Compare commits

...

82 commits

Author SHA1 Message Date
sfan5
7892541383 Various random code cleanups 2025-03-04 19:53:01 +01:00
sfan5
358658fa34 Fix cloud-related bugs
First, this reverts 56123b2fbe,
which un-fixes #15031 but fixes #15798 and #15854.

Then we disable culling for the cloud scene node which fixes #15031 again.
2025-03-04 19:53:01 +01:00
sfan5
68602b2eaf Fix shadow flicker on camera offset update (take 2)
The previous fix never did what it was supposed to, so let's do this.
2025-03-04 19:53:01 +01:00
sfan5
e84ac56e35 Don't try to update uninitialized shadow frustum 2025-03-04 19:53:01 +01:00
sfan5
47c000a293 Add unittest that lints builtin JSON files 2025-03-04 19:53:01 +01:00
sfan5
304ce4cd54 Fix syntax error in credits.json
reported at <https://forum.luanti.org/viewtopic.php?p=442729>

As it happens this didn't affect most users as jsoncpp allows trailing commas
by default since 2019.
2025-03-04 19:53:01 +01:00
sfan5
d54646d342 Improve error handling of map database creation 2025-03-04 19:53:01 +01:00
sfan5
7abaa8d4cd Make Irrlicht identity material const 2025-03-04 19:53:01 +01:00
sfan5
2796283550 Remove broken fall bobbing 2025-03-04 19:53:01 +01:00
sfan5
7602308835 Revert "Restrict relative mouse mode to Wayland users (#15697)"
see #15761
SDL is the only device that supports relative mode and
mouse input is actually somewhat broken if it's *not* enabled.

This reverts commit 45c5ef8798
and 88b007907a.
2025-03-04 19:53:01 +01:00
sfan5
bc43019467 Fix TerminalChatConsole crash
this setting was removed in #15633
2025-03-04 19:53:01 +01:00
sfan5
8449f5f6db Make devtest grass use overlay tiles 2025-03-04 19:53:01 +01:00
Medley
0eb047ca33
Disable debug-breaking locale workaround when debugging (#15859) 2025-03-03 20:33:42 +01:00
wrrrzr
98048cb06d
Fix missing includes in skyparams.h 2025-03-03 20:33:19 +01:00
Erich Schubert
6e995972bb check y limits early 2025-03-03 20:33:05 +01:00
Erich Schubert
08fad862aa Code cleanups. Function does not return deco count. 2025-03-03 20:33:05 +01:00
sfan5
c3477a4d08 Adjust Android default view range and mapblock limit 2025-03-01 22:40:10 +01:00
sfan5
062207e696 Enforce minimum client_mapblock_limit depending on view range 2025-03-01 22:40:10 +01:00
SmallJoker
24c1230c7b Client: fix disappearing node inventories on older servers
ee9258ce introduced a logic error, which caused clients to lose
node metadata when they should not and vice-versa.
See also: server.cpp / Server::sendAddNode
2025-03-01 21:05:17 +01:00
sfan5
eb79a76742
Android: update SDL support code (#15853) 2025-03-01 18:27:46 +01:00
millennIumAMbiguity
c0328e5363
Centered title in README.md and added icon 2025-03-01 12:27:43 +01:00
Joshua Gerrish
8d822d8231
Fix compile error with MSVC: string is not a member of std 2025-03-01 12:26:33 +01:00
y5nw
a11b25f3f5 Use fallback font correctly for fonts provided by the server 2025-03-01 12:25:24 +01:00
Lars Mueller
90121dc66f Fix & improve glTF loader matrix decomposition 2025-02-27 12:31:04 +01:00
Lars Mueller
d74af2f1a7 Use matrix4::getRotationRadians 2025-02-27 12:31:04 +01:00
Lars Mueller
b6c71b2379 Improve matrix4::getRotationDegrees a bit, radians 2025-02-27 12:31:04 +01:00
Lars Mueller
c261c26456 Add Irrlicht rotation consistency unit tests 2025-02-27 12:31:04 +01:00
Lars Mueller
5abf220979 Fix random usage in matrix4 tests 2025-02-27 12:31:04 +01:00
Lars Mueller
1ceeea34f4 Extend quaternion tests 2025-02-27 12:31:04 +01:00
Lars Mueller
3ae1fd459a Add quaternion conversion unit tests 2025-02-27 12:31:04 +01:00
Lars Mueller
0e86366324 Add test for matrix4::getRotationDegrees 2025-02-27 12:31:04 +01:00
Erich Schubert
58ad604a4b
Note that core.hash_node_position is not a hash function 2025-02-27 12:30:55 +01:00
guinea7pig
415e96184d
Update copyright date in README 2025-02-26 12:22:19 +01:00
sfan5
8654e16725 Disable shadow force updates with performance_tradeoffs 2025-02-26 12:22:06 +01:00
sfan5
eb8b449817 Fix shadow performance regression due to force update
broken by: b861f0c5c5
2025-02-26 12:22:06 +01:00
sfan5
22c81e5292 Print if sdl2-compat is in use 2025-02-26 12:21:57 +01:00
sfan5
42a35cec83 Allow looking straight up or down 2025-02-26 12:21:57 +01:00
sfan5
fc8c6742c4 Update Wireshark dissector 2025-02-26 12:21:57 +01:00
sfan5
ee9258cefd Clean up some packet-related code 2025-02-26 12:21:57 +01:00
grorp
5e89371ecd
TouchControls: touch_use_crosshair, dig/place simulation refactoring (#15800)
-   get rid of simulated mouse events for digging/placing, use keyboard events
    instead
    -   consistent with other simulated events, less code, no need for a
        pointer position
    -   more correct: touch controls no longer break if you have custom
        dig/place keybindings set
-   move reading of "touch_use_crosshair" setting from Game to TouchControls
2025-02-25 13:19:44 -05:00
Andrii Nemchenko
abcd2e0b81
Re-save active entities more often if they move a certain distance (#15605) 2025-02-22 16:19:19 +01:00
sfan5
d12ce68e64 Show unknown object visuals using unknown_object.png sprite 2025-02-22 16:19:04 +01:00
sfan5
83fd837d75 Clean up TileLayer::applyMaterialOptions 2025-02-22 16:19:04 +01:00
sfan5
7d3f0628c4 Use visual = "node" for builtin falling node entity
This greatly simplifies the code at the expense of some
falling nodes not showing up on older clients.
2025-02-22 16:19:04 +01:00
sfan5
27bbe3a873 CAO 'node' visual (#15683) 2025-02-22 16:19:04 +01:00
sfan5
5a8720a484 Change material sharing for CMeshSceneNode 2025-02-22 16:19:04 +01:00
Andrii Nemchenko
e51221d247
Implement metadata-aware version of InvRef:remove_item() (#15771) 2025-02-22 16:18:48 +01:00
DS
0890125962
SDL Irr device: Ignore +-0.0f y mouse wheel events (#15815)
our code often assumes that it's non-zero, e.g.: `event.MouseInput.Wheel < 0 ? -1 : 1`
2025-02-22 16:17:07 +01:00
DS
0667cbf5a2
Clang-Tidy config: Ignore performance-avoid-endl and performance-inefficient-string-concatenation 2025-02-22 16:16:41 +01:00
sfan5
ba62808fe8
Basic camera control API (#15796) 2025-02-19 18:45:45 +01:00
James Morey
50819ace8f
Move clickable_chat_weblinks to Advanced > Miscellaneous (#15799) 2025-02-19 18:45:31 +01:00
et
ef0219c2ed
Prevent accidental wallmounted_to_dir poisoning (#15810)
Prior to this commit, if you used a function like `core.wallmounted_to_dir`, and modified its output, it would modify all of the output in the future.
2025-02-18 21:51:33 +01:00
sfan5
f4bdf72aa4 Simplify SQLite3 schema types
see: <https://www.sqlite.org/datatype3.html>
2025-02-18 19:29:06 +01:00
sfan5
cc352f3b66 Add unit tests for MapDatabase implementations 2025-02-18 19:29:06 +01:00
sfan5
215b000793 Split blockpos into three columns in sqlite3 map database 2025-02-18 19:29:06 +01:00
sfan5
e8728acc5c Some cleanups in Database_SQLite3 2025-02-18 19:29:06 +01:00
Desour
166e02955e Decrease fps_max_unfocused from 20 to 10
This used to be the default for android.
There's not much issues now with using a lower value, so a lower default on all platforms
is reasonable.
The only downside I know of is that if you re-focus the window, it can up till the
next client step until it goes back to normal fps, but 10 Hz feels fast enough.
2025-02-15 18:21:01 +01:00
Desour
138111a542 Don't use fps_max_unfocused for server step time on non-singleplayer main-menu-hosted servers
It's unreasonable to change server step time when the hosting user unfocuses their window.
(m_is_paused is already not set if it's not singleplayer.)
2025-02-15 18:21:01 +01:00
Desour
191cb117f9 Don't use fps_max_unfocused for the pause menu
Nowadays, we have things like buttons that change appearance on hover, or scoll bars
in the pause menu. These do not work fine with low fps.
2025-02-15 18:21:01 +01:00
Miguel P.L
a57677120a
Correct keycode URL in settingtypes.txt/minetest.conf.example (#15784) 2025-02-15 18:20:45 +01:00
sfan5
75dcd94b90
Optimize add_area_node_boxes in collision code (#15719) 2025-02-15 12:19:17 +01:00
sfan5
d027fc9a88 Enable ipv6_server by default 2025-02-15 12:18:07 +01:00
sfan5
a11d526110 Rework socket IPV6_V6ONLY handling 2025-02-15 12:18:07 +01:00
siliconsniffer
eb797c502a
Tweak main menu server list behavior (#15736)
Co-authored-by: Lars Mueller <appgurulars@gmx.de>
2025-02-15 12:17:56 +01:00
Erich Schubert
567b9a997a
Collision: more accurate computation with acceleration and long dtime (#15408)
Co-authored-by: SmallJoker <mk939@ymail.com>
2025-02-15 12:17:44 +01:00
Lars Müller
319e270664
Clean up Irrlicht matrices a bit more (#15733) 2025-02-15 12:17:30 +01:00
sfan5
d015944f6c Revert "Disable SDL2 for 5.11.0"
This reverts commit 29cfb6efff.
2025-02-15 12:14:12 +01:00
Lars Müller
b7f01b0cc7
Don't save load_mod_* = false lines in world.mt (#15758) 2025-02-14 22:25:39 +01:00
sfan5
54bf5d62f2
Fix fgettext call in dlg_settings.lua
(#15614)
2025-02-14 22:17:10 +01:00
sfan5
849a583f66 Continue with 5.12.0-dev 2025-02-14 19:38:30 +01:00
sfan5
0cb7735125 Bump version to 5.11.0 2025-02-14 19:38:27 +01:00
sfan5
028949beca Delete empty languages 2025-02-14 19:13:14 +01:00
ninjum
6bdeb10c16 Translated using Weblate (Galician)
Currently translated at 99.9% (1391 of 1392 strings)
2025-02-14 19:11:16 +01:00
BlackImpostor
44cbae8fad Translated using Weblate (Russian)
Currently translated at 100.0% (1392 of 1392 strings)
2025-02-14 19:11:16 +01:00
waxtatect
f7b2d4760f Translated using Weblate (French)
Currently translated at 100.0% (1392 of 1392 strings)
2025-02-14 19:11:16 +01:00
109247019824
1ec19c2ad2 Translated using Weblate (Bulgarian)
Currently translated at 51.7% (721 of 1392 strings)
2025-02-14 19:11:12 +01:00
Linerly
9bfd39f036 Translated using Weblate (Indonesian)
Currently translated at 99.6% (1387 of 1392 strings)
2025-02-14 19:11:12 +01:00
Miguel
cfff6c4fd7 Translated using Weblate (Spanish)
Currently translated at 97.9% (1363 of 1392 strings)
2025-02-14 19:11:12 +01:00
Wuzzy
147dd3d372 Translated using Weblate (German)
Currently translated at 100.0% (1392 of 1392 strings)
2025-02-14 19:11:12 +01:00
sfan5
cda3dc08ca
Translated using Weblate (German)
Currently translated at 100.0% (1392 of 1392 strings)
2025-02-14 19:10:19 +01:00
mineplayer
78b4f929ce
Translated using Weblate (German)
Currently translated at 100.0% (1392 of 1392 strings)
2025-02-14 19:10:19 +01:00
Desour
2c50066c16 Keep the game paused in pause menu settings
The button_exit[]s were replaced by regular button[]s, to avoid a very short unpause when you
click the btn_settings (probably because it uses ClientEvent stuff).
2025-02-14 16:31:57 +01:00
202 changed files with 3119 additions and 15521 deletions

View file

@ -1,4 +1,4 @@
Checks: '-*,modernize-use-emplace,modernize-avoid-bind,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,performance-*' Checks: '-*,modernize-use-emplace,modernize-avoid-bind,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,performance-*,-performance-avoid-endl,performance-inefficient-string-concatenation'
WarningsAsErrors: '-*,modernize-use-emplace,performance-type-promotion-in-math-fn,performance-faster-string-find,performance-implicit-cast-in-loop' WarningsAsErrors: '-*,modernize-use-emplace,performance-type-promotion-in-math-fn,performance-faster-string-find,performance-implicit-cast-in-loop'
CheckOptions: CheckOptions:
- key: performance-unnecessary-value-param.AllowedTypes - key: performance-unnecessary-value-param.AllowedTypes

View file

@ -73,7 +73,7 @@ jobs:
env: env:
VCPKG_VERSION: 01f602195983451bc83e72f4214af2cbc495aa94 VCPKG_VERSION: 01f602195983451bc83e72f4214af2cbc495aa94
# 2024.05.24 # 2024.05.24
vcpkg_packages: zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp opengl-registry vcpkg_packages: zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp sdl2
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:

View file

@ -11,7 +11,7 @@ set(CLANG_MINIMUM_VERSION "7.0.1")
# You should not need to edit these manually, use util/bump_version.sh # You should not need to edit these manually, use util/bump_version.sh
set(VERSION_MAJOR 5) set(VERSION_MAJOR 5)
set(VERSION_MINOR 11) set(VERSION_MINOR 12)
set(VERSION_PATCH 0) set(VERSION_PATCH 0)
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")

View file

@ -1,13 +1,15 @@
Luanti (formerly Minetest) <div align="center">
========================== <img src="textures/base/pack/logo.png" width="32%">
<h1>Luanti (formerly Minetest)</h1>
![Build Status](https://github.com/luanti-org/luanti/workflows/build/badge.svg) <img src="https://github.com/luanti-org/luanti/workflows/build/badge.svg" alt="Build Status">
[![Translation status](https://hosted.weblate.org/widgets/minetest/-/svg-badge.svg)](https://hosted.weblate.org/engage/minetest/?utm_source=widget) <a href="https://hosted.weblate.org/engage/minetest/?utm_source=widget"><img src="https://hosted.weblate.org/widgets/minetest/-/svg-badge.svg" alt="Translation status"></a>
[![License](https://img.shields.io/badge/license-LGPLv2.1%2B-blue.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html) <a href="https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html"><img src="https://img.shields.io/badge/license-LGPLv2.1%2B-blue.svg" alt="License"></a>
</div>
<br><br>
Luanti is a free open-source voxel game engine with easy modding and game creation. Luanti is a free open-source voxel game engine with easy modding and game creation.
Copyright (C) 2010-2024 Perttu Ahola <celeron55@gmail.com> Copyright (C) 2010-2025 Perttu Ahola <celeron55@gmail.com>
and contributors (see source file comments and the version control log) and contributors (see source file comments and the version control log)
Table of Contents Table of Contents

View file

@ -1,5 +1,4 @@
diff --git a/android/app/src/main/java/org/libsdl/app/SDLActivity.java b/android/app/src/main/java/org/libsdl/app/SDLActivity.java diff --git a/android/app/src/main/java/org/libsdl/app/SDLActivity.java b/android/app/src/main/java/org/libsdl/app/SDLActivity.java
index fd5a056e3..83e3cf657 100644
--- a/android/app/src/main/java/org/libsdl/app/SDLActivity.java --- a/android/app/src/main/java/org/libsdl/app/SDLActivity.java
+++ b/android/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android/app/src/main/java/org/libsdl/app/SDLActivity.java
@@ -1345,7 +1345,12 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh @@ -1345,7 +1345,12 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
@ -9,7 +8,7 @@ index fd5a056e3..83e3cf657 100644
- if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) { - if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
+ if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE || + if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE ||
+ /* + /*
+ * CUSTOM ADDITION FOR MINETEST + * CUSTOM ADDITION FOR LUANTI
+ * should be upstreamed + * should be upstreamed
+ */ + */
+ (source & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE) { + (source & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE) {

View file

@ -60,8 +60,8 @@ import java.util.Locale;
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener { public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "SDL"; private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 2; private static final int SDL_MAJOR_VERSION = 2;
private static final int SDL_MINOR_VERSION = 30; private static final int SDL_MINOR_VERSION = 32;
private static final int SDL_MICRO_VERSION = 8; private static final int SDL_MICRO_VERSION = 0;
/* /*
// Display InputType.SOURCE/CLASS of events and devices // Display InputType.SOURCE/CLASS of events and devices
// //
@ -790,6 +790,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
SDLActivity.mFullscreenModeActive = false; SDLActivity.mFullscreenModeActive = false;
} }
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (Pie) */) {
window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
} }
} else { } else {
Log.e(TAG, "error handling message, getContext() returned no Activity"); Log.e(TAG, "error handling message, getContext() returned no Activity");
@ -1347,7 +1350,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE || if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE ||
/* /*
* CUSTOM ADDITION FOR MINETEST * CUSTOM ADDITION FOR LUANTI
* should be upstreamed * should be upstreamed
*/ */
(source & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE) { (source & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE) {

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="label">Luanti</string>
<string name="loading">Chargement…</string>
<string name="notification_channel_name">Notification générale</string>
<string name="notification_channel_description">Notifications de Luanti</string>
<string name="unzip_notification_title">Chargement de Luanti</string>
<string name="unzip_notification_description">Moins d\'une minute…</string>
<string name="ime_dialog_done">Terminé</string>
<string name="no_web_browser">Aucun navigateur web trouvé</string>
</resources>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="label">Luanti</string>
<string name="loading">Cargando…</string>
<string name="notification_channel_name">Notificación xeral</string>
<string name="notification_channel_description">Notificacións de Luanti</string>
<string name="unzip_notification_title">Cargando Luanti</string>
<string name="unzip_notification_description">Menos de 1 minuto…</string>
<string name="ime_dialog_done">Feito</string>
<string name="no_web_browser">Non se atopou ningún navegador web</string>
</resources>

View file

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
project.ext.set("versionMajor", 5) // Version Major project.ext.set("versionMajor", 5) // Version Major
project.ext.set("versionMinor", 11) // Version Minor project.ext.set("versionMinor", 12) // Version Minor
project.ext.set("versionPatch", 0) // Version Patch project.ext.set("versionPatch", 0) // Version Patch
// ^ keep in sync with cmake // ^ keep in sync with cmake

View file

@ -90,7 +90,7 @@ local facedir_to_dir_map = {
1, 4, 3, 2, 1, 4, 3, 2,
} }
function core.facedir_to_dir(facedir) function core.facedir_to_dir(facedir)
return facedir_to_dir[facedir_to_dir_map[facedir % 32]] return vector.copy(facedir_to_dir[facedir_to_dir_map[facedir % 32]])
end end
function core.dir_to_fourdir(dir) function core.dir_to_fourdir(dir)
@ -110,7 +110,7 @@ function core.dir_to_fourdir(dir)
end end
function core.fourdir_to_dir(fourdir) function core.fourdir_to_dir(fourdir)
return facedir_to_dir[facedir_to_dir_map[fourdir % 4]] return vector.copy(facedir_to_dir[facedir_to_dir_map[fourdir % 4]])
end end
function core.dir_to_wallmounted(dir) function core.dir_to_wallmounted(dir)
@ -147,7 +147,7 @@ local wallmounted_to_dir = {
vector.new( 0, -1, 0), vector.new( 0, -1, 0),
} }
function core.wallmounted_to_dir(wallmounted) function core.wallmounted_to_dir(wallmounted)
return wallmounted_to_dir[wallmounted % 8] return vector.copy(wallmounted_to_dir[wallmounted % 8])
end end
function core.dir_to_yaw(dir) function core.dir_to_yaw(dir)

View file

@ -159,7 +159,6 @@ local function load()
{ heading = fgettext_ne("Movement") }, { heading = fgettext_ne("Movement") },
"arm_inertia", "arm_inertia",
"view_bobbing_amount", "view_bobbing_amount",
"fall_bobbing_amount",
}, },
}) })
@ -517,7 +516,7 @@ local function get_formspec(dialogdata)
("button[0,%f;%f,0.8;back;%s]"):format( ("button[0,%f;%f,0.8;back;%s]"):format(
tabsize.height + 0.2, back_w, tabsize.height + 0.2, back_w,
fgettext(INIT == "pause_menu" and "Exit" or "Back")), INIT == "pause_menu" and fgettext("Exit") or fgettext("Back")),
("box[%f,%f;%f,0.8;#0000008C]"):format( ("box[%f,%f;%f,0.8;#0000008C]"):format(
back_w + 0.2, tabsize.height + 0.2, checkbox_w), back_w + 0.2, tabsize.height + 0.2, checkbox_w),

View file

@ -61,7 +61,7 @@ local function create_minetest_conf_example(settings)
end end
end end
if entry.type == "key" then if entry.type == "key" then
local line = "See https://github.com/minetest/irrlicht/blob/master/include/Keycodes.h" local line = "See https://github.com/luanti-org/luanti/blob/master/irr/include/Keycodes.h"
insert(result, "# " .. line .. "\n") insert(result, "# " .. line .. "\n")
end end
insert(result, "# type: " .. entry.type) insert(result, "# type: " .. entry.type)

View file

@ -1,5 +1,4 @@
local builtin_shared = ... local builtin_shared = ...
local SCALE = 0.667
local facedir_to_euler = { local facedir_to_euler = {
{y = 0, x = 0, z = 0}, {y = 0, x = 0, z = 0},
@ -36,9 +35,7 @@ local gravity = tonumber(core.settings:get("movement_gravity")) or 9.81
core.register_entity(":__builtin:falling_node", { core.register_entity(":__builtin:falling_node", {
initial_properties = { initial_properties = {
visual = "item", visual = "node",
visual_size = vector.new(SCALE, SCALE, SCALE),
textures = {},
physical = true, physical = true,
is_visible = false, is_visible = false,
collide_with_objects = true, collide_with_objects = true,
@ -80,41 +77,15 @@ core.register_entity(":__builtin:falling_node", {
-- Save liquidtype for falling water -- Save liquidtype for falling water
self.liquidtype = def.liquidtype self.liquidtype = def.liquidtype
-- Set entity visuals -- Set up entity visuals
if def.drawtype == "torchlike" or def.drawtype == "signlike" then -- For compatibility with older clients we continue to use "item" visual
local textures -- for simple situations.
if def.tiles and def.tiles[1] then local drawtypes = {normal=true, glasslike=true, allfaces=true, nodebox=true}
local tile = def.tiles[1] local p2types = {none=true, facedir=true, ["4dir"]=true}
if type(tile) == "table" then if drawtypes[def.drawtype] and p2types[def.paramtype2] and def.use_texture_alpha ~= "blend" then
tile = tile.name
end
if def.drawtype == "torchlike" then
textures = { "("..tile..")^[transformFX", tile }
else
textures = { tile, "("..tile..")^[transformFX" }
end
end
local vsize
if def.visual_scale then
local s = def.visual_scale
vsize = vector.new(s, s, s)
end
self.object:set_properties({
is_visible = true,
visual = "upright_sprite",
visual_size = vsize,
textures = textures,
glow = def.light_source,
})
elseif def.drawtype ~= "airlike" then
local itemstring = node.name
if core.is_colored_paramtype(def.paramtype2) then
itemstring = core.itemstring_with_palette(itemstring, node.param2)
end
-- FIXME: solution needed for paramtype2 == "leveled"
-- Calculate size of falling node -- Calculate size of falling node
local s = {} local s = vector.zero()
s.x = (def.visual_scale or 1) * SCALE s.x = (def.visual_scale or 1) * 0.667
s.y = s.x s.y = s.x
s.z = s.x s.z = s.x
-- Compensate for wield_scale -- Compensate for wield_scale
@ -125,10 +96,31 @@ core.register_entity(":__builtin:falling_node", {
end end
self.object:set_properties({ self.object:set_properties({
is_visible = true, is_visible = true,
wield_item = itemstring, visual = "item",
wield_item = node.name,
visual_size = s, visual_size = s,
glow = def.light_source, glow = def.light_source,
}) })
-- Rotate as needed
if def.paramtype2 == "facedir" then
local fdir = node.param2 % 32 % 24
local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler)
end
elseif def.paramtype2 == "4dir" then
local fdir = node.param2 % 4
local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler)
end
end
elseif def.drawtype ~= "airlike" then
self.object:set_properties({
is_visible = true,
node = node,
glow = def.light_source,
})
end end
-- Set collision box (certain nodeboxes only for now) -- Set collision box (certain nodeboxes only for now)
@ -148,111 +140,6 @@ core.register_entity(":__builtin:falling_node", {
}) })
end end
end end
-- Rotate entity
if def.drawtype == "torchlike" then
if (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted")
and node.param2 % 8 == 7 then
self.object:set_yaw(-math.pi*0.25)
else
self.object:set_yaw(math.pi*0.25)
end
elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh")
and (def.wield_image == "" or def.wield_image == nil))
or def.drawtype == "signlike"
or def.drawtype == "mesh"
or def.drawtype == "normal"
or def.drawtype == "nodebox" then
if (def.paramtype2 == "facedir" or def.paramtype2 == "colorfacedir") then
local fdir = node.param2 % 32 % 24
-- Get rotation from a precalculated lookup table
local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler)
end
elseif (def.paramtype2 == "4dir" or def.paramtype2 == "color4dir") then
local fdir = node.param2 % 4
-- Get rotation from a precalculated lookup table
local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler)
end
elseif (def.drawtype ~= "plantlike" and def.drawtype ~= "plantlike_rooted" and
(def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike")) then
local rot = node.param2 % 8
if (def.drawtype == "signlike" and def.paramtype2 ~= "wallmounted" and def.paramtype2 ~= "colorwallmounted") then
-- Change rotation to "floor" by default for non-wallmounted paramtype2
rot = 1
end
local pitch, yaw, roll = 0, 0, 0
if def.drawtype == "nodebox" or def.drawtype == "mesh" then
if rot == 0 then
pitch, yaw = math.pi/2, 0
elseif rot == 1 then
pitch, yaw = -math.pi/2, math.pi
elseif rot == 2 then
pitch, yaw = 0, math.pi/2
elseif rot == 3 then
pitch, yaw = 0, -math.pi/2
elseif rot == 4 then
pitch, yaw = 0, math.pi
elseif rot == 6 then
pitch, yaw = math.pi/2, 0
elseif rot == 7 then
pitch, yaw = -math.pi/2, math.pi
end
else
if rot == 1 then
pitch, yaw = math.pi, math.pi
elseif rot == 2 then
pitch, yaw = math.pi/2, math.pi/2
elseif rot == 3 then
pitch, yaw = math.pi/2, -math.pi/2
elseif rot == 4 then
pitch, yaw = math.pi/2, math.pi
elseif rot == 5 then
pitch, yaw = math.pi/2, 0
elseif rot == 6 then
pitch, yaw = math.pi, -math.pi/2
elseif rot == 7 then
pitch, yaw = 0, -math.pi/2
end
end
if def.drawtype == "signlike" then
pitch = pitch - math.pi/2
if rot == 0 then
yaw = yaw + math.pi/2
elseif rot == 1 then
yaw = yaw - math.pi/2
elseif rot == 6 then
yaw = yaw - math.pi/2
pitch = pitch + math.pi
elseif rot == 7 then
yaw = yaw + math.pi/2
pitch = pitch + math.pi
end
elseif def.drawtype == "mesh" or def.drawtype == "normal" or def.drawtype == "nodebox" then
if rot == 0 or rot == 1 then
roll = roll + math.pi
elseif rot == 6 or rot == 7 then
if def.drawtype ~= "normal" then
roll = roll - math.pi/2
end
else
yaw = yaw + math.pi
end
end
self.object:set_rotation({x=pitch, y=yaw, z=roll})
elseif (def.drawtype == "mesh" and def.paramtype2 == "degrotate") then
local p2 = (node.param2 - (def.place_param2 or 0)) % 240
local yaw = (p2 / 240) * (math.pi * 2)
self.object:set_yaw(yaw)
elseif (def.drawtype == "mesh" and def.paramtype2 == "colordegrotate") then
local p2 = (node.param2 % 32 - (def.place_param2 or 0) % 32) % 24
local yaw = (p2 / 24) * (math.pi * 2)
self.object:set_yaw(yaw)
end
end
end, end,
get_staticdata = function(self) get_staticdata = function(self)

View file

@ -45,6 +45,7 @@ core.features = {
abm_without_neighbors = true, abm_without_neighbors = true,
biome_weights = true, biome_weights = true,
particle_blend_clip = true, particle_blend_clip = true,
remove_item_match_meta = true,
} }
function core.has_feature(arg) function core.has_feature(arg)

View file

@ -57,7 +57,7 @@
"AFCMS", "AFCMS",
"siliconsniffer", "siliconsniffer",
"Wuzzy", "Wuzzy",
"Zemtzov7", "Zemtzov7"
], ],
"previous_contributors": [ "previous_contributors": [
"Ælla Chiana Moskopp (erle) <erle@dieweltistgarnichtso.net> [Logo]", "Ælla Chiana Moskopp (erle) <erle@dieweltistgarnichtso.net> [Logo]",

View file

@ -21,7 +21,7 @@ local function clients_list_formspec(dialogdata)
"size[6,9.5]", "size[6,9.5]",
TOUCH_GUI and "padding[0.01,0.01]" or "", TOUCH_GUI and "padding[0.01,0.01]" or "",
"hypertext[0,0;6,1.5;;<global margin=5 halign=center valign=middle>", "hypertext[0,0;6,1.5;;<global margin=5 halign=center valign=middle>",
fgettext("This is the list of clients connected to\n$1", fgettext("Players connected to\n$1",
"<b>" .. core.hypertext_escape(servername) .. "</b>") .. "]", "<b>" .. core.hypertext_escape(servername) .. "</b>") .. "]",
"textlist[0.5,1.5;5,6.8;;" .. fmt_formspec_list(clients_list) .. "]", "textlist[0.5,1.5;5,6.8;;" .. fmt_formspec_list(clients_list) .. "]",
"button[1.5,8.5;3,0.8;quit;OK]" "button[1.5,8.5;3,0.8;quit;OK]"

View file

@ -299,7 +299,7 @@ local function handle_buttons(this, fields)
worldfile:set("load_mod_" .. mod.name, mod.virtual_path) worldfile:set("load_mod_" .. mod.name, mod.virtual_path)
was_set[mod.name] = true was_set[mod.name] = true
elseif not was_set[mod.name] then elseif not was_set[mod.name] then
worldfile:set("load_mod_" .. mod.name, "false") worldfile:remove("load_mod_" .. mod.name)
end end
elseif mod.enabled then elseif mod.enabled then
gamedata.errormessage = fgettext_ne("Failed to enable mo" .. gamedata.errormessage = fgettext_ne("Failed to enable mo" ..

View file

@ -190,10 +190,10 @@ local function get_formspec(tabview, name, tabdata)
local max_clients = 5 local max_clients = 5
if #clients_list > max_clients then if #clients_list > max_clients then
retval = retval .. "tooltip[btn_view_clients;" .. retval = retval .. "tooltip[btn_view_clients;" ..
fgettext("Clients:\n$1", table.concat(clients_list, "\n", 1, max_clients)) .. "\n..." .. "]" fgettext("Players:\n$1", table.concat(clients_list, "\n", 1, max_clients)) .. "\n..." .. "]"
else else
retval = retval .. "tooltip[btn_view_clients;" .. retval = retval .. "tooltip[btn_view_clients;" ..
fgettext("Clients:\n$1", table.concat(clients_list, "\n")) .. "]" fgettext("Players:\n$1", table.concat(clients_list, "\n")) .. "]"
end end
retval = retval .. "style[btn_view_clients;padding=6]" retval = retval .. "style[btn_view_clients;padding=6]"
retval = retval .. "image_button[4.5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir .. retval = retval .. "image_button[4.5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
@ -391,12 +391,15 @@ local function matches_query(server, query)
return name_matches and 50 or description_matches and 0 return name_matches and 50 or description_matches and 0
end end
local function search_server_list(input) local function search_server_list(input, tabdata)
menudata.search_result = nil menudata.search_result = nil
if #serverlistmgr.servers < 2 then if #serverlistmgr.servers < 2 then
return return
end end
tabdata.pre_search_selection = tabdata.pre_search_selection or find_selected_server()
-- setup the search query -- setup the search query
local query = parse_search_input(input) local query = parse_search_input(input)
if not query then if not query then
@ -419,11 +422,23 @@ local function search_server_list(input)
return return
end end
local current_server = find_selected_server()
table.sort(search_result, function(a, b) table.sort(search_result, function(a, b)
return a.points > b.points return a.points > b.points
end) end)
menudata.search_result = search_result menudata.search_result = search_result
-- Keep current selection if it's in search results
if current_server then
for _, server in ipairs(search_result) do
if server.address == current_server.address and
server.port == current_server.port then
return
end
end
end
-- Find first compatible server (favorite or public) -- Find first compatible server (favorite or public)
for _, server in ipairs(search_result) do for _, server in ipairs(search_result) do
if is_server_protocol_compat(server.proto_min, server.proto_max) then if is_server_protocol_compat(server.proto_min, server.proto_max) then
@ -434,6 +449,7 @@ local function search_server_list(input)
-- If no compatible server found, clear selection -- If no compatible server found, clear selection
set_selected_server(nil) set_selected_server(nil)
end end
local function main_button_handler(tabview, fields, name, tabdata) local function main_button_handler(tabview, fields, name, tabdata)
if fields.te_name then if fields.te_name then
gamedata.playername = fields.te_name gamedata.playername = fields.te_name
@ -471,6 +487,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
end end
if event.type == "CHG" then if event.type == "CHG" then
set_selected_server(server) set_selected_server(server)
tabdata.pre_search_selection = nil
return true return true
end end
end end
@ -484,11 +501,9 @@ local function main_button_handler(tabview, fields, name, tabdata)
if fields.btn_delete_favorite then if fields.btn_delete_favorite then
local idx = core.get_table_index("servers") local idx = core.get_table_index("servers")
if not idx then return end if not idx then return end
local server = tabdata.lookup[idx]
if not server then return end
serverlistmgr.delete_favorite(server) serverlistmgr.delete_favorite(tabdata.lookup[idx])
set_selected_server(server) set_selected_server(tabdata.lookup[idx+1])
return true return true
end end
@ -516,13 +531,16 @@ local function main_button_handler(tabview, fields, name, tabdata)
if fields.btn_mp_clear then if fields.btn_mp_clear then
tabdata.search_for = "" tabdata.search_for = ""
menudata.search_result = nil menudata.search_result = nil
set_selected_server(nil) if tabdata.pre_search_selection then
set_selected_server(tabdata.pre_search_selection)
tabdata.pre_search_selection = nil
end
return true return true
end end
if fields.btn_mp_search or fields.key_enter_field == "te_search" then if fields.btn_mp_search or fields.key_enter_field == "te_search" then
tabdata.search_for = fields.te_search tabdata.search_for = fields.te_search
search_server_list(fields.te_search) search_server_list(fields.te_search, tabdata)
return true return true
end end

View file

@ -256,8 +256,8 @@ fps_max (Maximum FPS) int 60 1 4294967295
# Vertical screen synchronization. Your system may still force VSync on even if this is disabled. # Vertical screen synchronization. Your system may still force VSync on even if this is disabled.
vsync (VSync) bool false vsync (VSync) bool false
# Maximum FPS when the window is not focused, or when the game is paused. # Maximum FPS when the window is not focused.
fps_max_unfocused (FPS when unfocused or paused) int 20 1 4294967295 fps_max_unfocused (FPS when unfocused) int 10 1 4294967295
# View distance in nodes. # View distance in nodes.
viewing_range (Viewing range) int 190 20 4000 viewing_range (Viewing range) int 190 20 4000
@ -295,10 +295,6 @@ arm_inertia (Arm inertia) bool true
# For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double. # For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.
view_bobbing_amount (View bobbing factor) float 1.0 0.0 7.9 view_bobbing_amount (View bobbing factor) float 1.0 0.0 7.9
# Multiplier for fall bobbing.
# For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.
fall_bobbing_amount (Fall bobbing factor) float 0.03 0.0 100.0
[**Camera] [**Camera]
# Field of view in degrees. # Field of view in degrees.
@ -717,9 +713,6 @@ console_color (Console color) string (0,0,0)
# In-game chat console background alpha (opaqueness, between 0 and 255). # In-game chat console background alpha (opaqueness, between 0 and 255).
console_alpha (Console alpha) int 200 0 255 console_alpha (Console alpha) int 200 0 255
# Clickable weblinks (middle-click or Ctrl+left-click) enabled in chat console output.
clickable_chat_weblinks (Chat weblinks) bool true
# Optional override for chat weblink color. # Optional override for chat weblink color.
chat_weblink_color (Weblink color) string #8888FF chat_weblink_color (Weblink color) string #8888FF
@ -835,11 +828,12 @@ protocol_version_min (Protocol version minimum) int 1 1 65535
# Files that are not present will be fetched the usual way. # Files that are not present will be fetched the usual way.
remote_media (Remote media) string remote_media (Remote media) string
# Enable/disable running an IPv6 server. # Enable IPv6 support for server.
# Note that clients will be able to connect with both IPv4 and IPv6.
# Ignored if bind_address is set. # Ignored if bind_address is set.
# #
# Requires: enable_ipv6 # Requires: enable_ipv6
ipv6_server (IPv6 server) bool false ipv6_server (IPv6 server) bool true
[*Server Security] [*Server Security]
@ -1797,14 +1791,6 @@ profiler_print_interval (Engine profiling data print interval) int 0 0
[*Advanced] [*Advanced]
# Enable IPv6 support (for both client and server).
# Required for IPv6 connections to work at all.
enable_ipv6 (IPv6) bool true
# If enabled, invalid world data won't cause the server to shut down.
# Only enable this if you know what you are doing.
ignore_world_load_errors (Ignore world errors) bool false
[**Graphics] [**Graphics]
# Enables debug and error-checking in the OpenGL driver. # Enables debug and error-checking in the OpenGL driver.
@ -1990,6 +1976,10 @@ lighting_boost_spread (Light curve boost spread) float 0.2 0.0 0.4
[**Networking] [**Networking]
# Enable IPv6 support (for both client and server).
# Required for IPv6 connections to work at all.
enable_ipv6 (IPv6) bool true
# Prometheus listener address. # Prometheus listener address.
# If Luanti is compiled with ENABLE_PROMETHEUS option enabled, # If Luanti is compiled with ENABLE_PROMETHEUS option enabled,
# enable metrics listener for Prometheus on that address. # enable metrics listener for Prometheus on that address.
@ -2004,7 +1994,9 @@ max_out_chat_queue_size (Maximum size of the outgoing chat queue) int 20 -1 3276
client_unload_unused_data_timeout (Mapblock unload timeout) float 600.0 0.0 client_unload_unused_data_timeout (Mapblock unload timeout) float 600.0 0.0
# Maximum number of mapblocks for client to be kept in memory. # Maximum number of mapblocks for client to be kept in memory.
# Set to -1 for unlimited amount. # Note that there is an internal dynamic minimum number of blocks that
# won't be deleted, depending on the current view range.
# Set to -1 for no limit.
client_mapblock_limit (Mapblock limit) int 7500 -1 2147483647 client_mapblock_limit (Mapblock limit) int 7500 -1 2147483647
# Maximum number of blocks that are simultaneously sent per client. # Maximum number of blocks that are simultaneously sent per client.
@ -2192,6 +2184,13 @@ curl_file_download_timeout (cURL file download timeout) int 300000 5000 21474836
[**Miscellaneous] [**Miscellaneous]
# Clickable weblinks (middle-click or Ctrl+left-click) enabled in chat console output.
clickable_chat_weblinks (Chat weblinks) bool true
# If enabled, invalid world data won't cause the server to shut down.
# Only enable this if you know what you are doing.
ignore_world_load_errors (Ignore world errors) bool false
# Adjust the detected display density, used for scaling UI elements. # Adjust the detected display density, used for scaling UI elements.
display_density_factor (Display Density Scaling Factor) float 1 0.5 5.0 display_density_factor (Display Density Scaling Factor) float 1 0.5 5.0

View file

@ -1,4 +1,4 @@
Luanti Lua Client Modding API Reference 5.11.0 Luanti Lua Client Modding API Reference 5.12.0
============================================== ==============================================
**WARNING**: if you're looking for the `minetest` namespace (e.g. `minetest.something`), **WARNING**: if you're looking for the `minetest` namespace (e.g. `minetest.something`),

View file

@ -22,27 +22,27 @@
For Debian/Ubuntu users: For Debian/Ubuntu users:
sudo apt install g++ make libc6-dev cmake libpng-dev libjpeg-dev libxi-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev libluajit-5.1-dev gettext sudo apt install g++ make libc6-dev cmake libpng-dev libjpeg-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev libluajit-5.1-dev gettext libsdl2-dev
For Fedora users: For Fedora users:
sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libpng-devel libjpeg-devel libvorbis-devel libXi-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel libzstd-devel gettext sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libpng-devel libjpeg-devel libvorbis-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel libzstd-devel gettext SDL2-devel
For openSUSE users: For openSUSE users:
sudo zypper install gcc gcc-c++ cmake libjpeg8-devel libpng16-devel openal-soft-devel libcurl-devel sqlite3-devel luajit-devel libzstd-devel Mesa-libGL-devel libXi-devel libvorbis-devel freetype2-devel sudo zypper install gcc gcc-c++ cmake libjpeg8-devel libpng16-devel openal-soft-devel libcurl-devel sqlite3-devel luajit-devel libzstd-devel Mesa-libGL-devel libvorbis-devel freetype2-devel SDL2-devel
For Arch users: For Arch users:
sudo pacman -S --needed base-devel libcurl-gnutls cmake libxi libpng libjpeg-turbo sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses zstd gettext sudo pacman -S --needed base-devel libcurl-gnutls cmake libpng libjpeg-turbo sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses zstd gettext sdl2
For Alpine users: For Alpine users:
sudo apk add build-base cmake libpng-dev jpeg-dev libxi-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev zstd-dev gettext sudo apk add build-base cmake libpng-dev jpeg-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev zstd-dev gettext sdl2-dev
For Void users: For Void users:
sudo xbps-install cmake libpng-devel jpeg-devel libXi-devel mesa sqlite-devel libogg-devel libvorbis-devel libopenal-devel libcurl-devel freetype-devel zlib-devel gmp-devel jsoncpp-devel LuaJIT-devel zstd libzstd-devel gettext sudo xbps-install cmake libpng-devel jpeg-devel mesa sqlite-devel libogg-devel libvorbis-devel libopenal-devel libcurl-devel freetype-devel zlib-devel gmp-devel jsoncpp-devel LuaJIT-devel zstd libzstd-devel gettext SDL2-devel
## Download ## Download

View file

@ -13,9 +13,8 @@
It is highly recommended to use vcpkg as package manager. It is highly recommended to use vcpkg as package manager.
After you successfully built vcpkg you can easily install the required libraries: After you successfully built vcpkg you can easily install the required libraries:
```powershell ```powershell
vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp gettext[tools] opengl-registry --triplet x64-windows vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp gettext[tools] sdl2 --triplet x64-windows
``` ```
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store. - `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.

View file

@ -1522,7 +1522,7 @@ There are a bunch of different looking node types.
* `allfaces` * `allfaces`
* Often used for partially-transparent nodes. * Often used for partially-transparent nodes.
* External sides of textures, and unlike other drawtypes, the external sides * External sides of textures, and unlike other drawtypes, the external sides
of other blocks, are visible from the inside. of other nodes, are visible from the inside.
* `allfaces_optional` * `allfaces_optional`
* Often used for leaves nodes. * Often used for leaves nodes.
* This switches between `normal`, `glasslike` and `allfaces` according to * This switches between `normal`, `glasslike` and `allfaces` according to
@ -5689,6 +5689,8 @@ Utilities
biome_weights = true, biome_weights = true,
-- Particles can specify a "clip" blend mode (5.11.0) -- Particles can specify a "clip" blend mode (5.11.0)
particle_blend_clip = true, particle_blend_clip = true,
-- The `match_meta` optional parameter is available for `InvRef:remove_item()` (5.12.0)
remove_item_match_meta = true,
} }
``` ```
@ -7454,7 +7456,8 @@ Misc.
* This function can be overridden by mods to change the leave message. * This function can be overridden by mods to change the leave message.
* `core.hash_node_position(pos)`: returns a 48-bit integer * `core.hash_node_position(pos)`: returns a 48-bit integer
* `pos`: table {x=number, y=number, z=number}, * `pos`: table {x=number, y=number, z=number},
* Gives a unique hash number for a node position (16+16+16=48bit) * Gives a unique numeric encoding for a node position (16+16+16=48bit)
* Despite the name, this is not a hash function (so it doesn't mix or produce collisions).
* `core.get_position_from_hash(hash)`: returns a position * `core.get_position_from_hash(hash)`: returns a position
* Inverse transform of `core.hash_node_position` * Inverse transform of `core.hash_node_position`
* `core.get_item_group(name, group)`: returns a rating * `core.get_item_group(name, group)`: returns a rating
@ -7872,13 +7875,15 @@ An `InvRef` is a reference to an inventory.
can be fully added to the list can be fully added to the list
* `contains_item(listname, stack, [match_meta])`: returns `true` if * `contains_item(listname, stack, [match_meta])`: returns `true` if
the stack of items can be fully taken from the list. the stack of items can be fully taken from the list.
If `match_meta` is false, only the items' names are compared * If `match_meta` is `true`, item metadata is also considered when comparing
(default: `false`). items. Otherwise, only the items names are compared. Default: `false`
* `remove_item(listname, stack)`: take as many items as specified from the * The method ignores wear.
list, returns the items that were actually removed (as an `ItemStack`) * `remove_item(listname, stack, [match_meta])`: take as many items as specified from the
-- note that any item metadata is ignored, so attempting to remove a specific list, returns the items that were actually removed (as an `ItemStack`).
unique item this way will likely remove the wrong one -- to do that use * If `match_meta` is `true` (available since feature `remove_item_match_meta`),
`set_stack` with an empty `ItemStack`. item metadata is also considered when comparing items. Otherwise, only the
items names are compared. Default: `false`
* The method ignores wear.
* `get_location()`: returns a location compatible to * `get_location()`: returns a location compatible to
`core.get_inventory(location)`. `core.get_inventory(location)`.
* returns `{type="undefined"}` in case location is not known * returns `{type="undefined"}` in case location is not known
@ -8827,6 +8832,14 @@ child will follow movement and rotation of that bone.
Same limits as for `thirdperson_back` apply. Same limits as for `thirdperson_back` apply.
Defaults to `thirdperson_back` if unspecified. Defaults to `thirdperson_back` if unspecified.
* `get_eye_offset()`: Returns camera offset vectors as set via `set_eye_offset`. * `get_eye_offset()`: Returns camera offset vectors as set via `set_eye_offset`.
* `set_camera(params)`: Sets camera parameters.
* `mode`: Defines the camera mode used
- `any`: free choice between all modes (default)
- `first`: first-person camera
- `third`: third-person camera
- `third_front`: third-person camera, looking opposite of movement direction
* Supported by client since 5.12.0.
* `get_camera()`: Returns the camera parameters as a table as above.
* `send_mapblock(blockpos)`: * `send_mapblock(blockpos)`:
* Sends an already loaded mapblock to the player. * Sends an already loaded mapblock to the player.
* Returns `false` if nothing was sent (note that this can also mean that * Returns `false` if nothing was sent (note that this can also mean that
@ -9221,7 +9234,7 @@ Player properties need to be saved manually.
-- Clients older than 5.9.0 interpret `pointable = "blocking"` as `pointable = true`. -- Clients older than 5.9.0 interpret `pointable = "blocking"` as `pointable = true`.
-- Can be overridden by the `pointabilities` of the held item. -- Can be overridden by the `pointabilities` of the held item.
visual = "cube" / "sprite" / "upright_sprite" / "mesh" / "wielditem" / "item", visual = "",
-- "cube" is a node-sized cube. -- "cube" is a node-sized cube.
-- "sprite" is a flat texture always facing the player. -- "sprite" is a flat texture always facing the player.
-- "upright_sprite" is a vertical flat texture. -- "upright_sprite" is a vertical flat texture.
@ -9243,6 +9256,8 @@ Player properties need to be saved manually.
-- Wielditems are scaled a bit. If you want a wielditem to appear -- Wielditems are scaled a bit. If you want a wielditem to appear
-- to be as large as a node, use `0.667` in `visual_size` -- to be as large as a node, use `0.667` in `visual_size`
-- "item" is similar to "wielditem" but ignores the 'wield_image' parameter. -- "item" is similar to "wielditem" but ignores the 'wield_image' parameter.
-- "node" looks exactly like a node in-world (supported since 5.12.0)
-- Note that visual effects like waving or liquid reflections will not work.
visual_size = {x = 1, y = 1, z = 1}, visual_size = {x = 1, y = 1, z = 1},
-- Multipliers for the visual size. If `z` is not specified, `x` will be used -- Multipliers for the visual size. If `z` is not specified, `x` will be used
@ -9252,7 +9267,7 @@ Player properties need to be saved manually.
-- File name of mesh when using "mesh" visual -- File name of mesh when using "mesh" visual
textures = {}, textures = {},
-- Number of required textures depends on visual. -- Number of required textures depends on visual:
-- "cube" uses 6 textures just like a node, but all 6 must be defined. -- "cube" uses 6 textures just like a node, but all 6 must be defined.
-- "sprite" uses 1 texture. -- "sprite" uses 1 texture.
-- "upright_sprite" uses 2 textures: {front, back}. -- "upright_sprite" uses 2 textures: {front, back}.
@ -9262,11 +9277,14 @@ Player properties need to be saved manually.
colors = {}, colors = {},
-- Currently unused. -- Currently unused.
node = {name = "ignore", param1=0, param2=0},
-- Node to show when using the "node" visual
use_texture_alpha = false, use_texture_alpha = false,
-- Use texture's alpha channel. -- Use texture's alpha channel for transparency blending.
-- Excludes "upright_sprite" and "wielditem".
-- Note: currently causes visual issues when viewed through other -- Note: currently causes visual issues when viewed through other
-- semi-transparent materials such as water. -- semi-transparent materials such as water.
-- Note: ignored for "item", "wielditem" and "node" visual.
spritediv = {x = 1, y = 1}, spritediv = {x = 1, y = 1},
-- Used with spritesheet textures for animation and/or frame selection -- Used with spritesheet textures for animation and/or frame selection
@ -9283,7 +9301,7 @@ Player properties need to be saved manually.
-- If false, object is invisible and can't be pointed. -- If false, object is invisible and can't be pointed.
makes_footstep_sound = false, makes_footstep_sound = false,
-- If true, is able to make footstep sounds of nodes -- If true, object is able to make footstep sounds of nodes
-- (see node sound definition for details). -- (see node sound definition for details).
automatic_rotate = 0, automatic_rotate = 0,
@ -9306,6 +9324,7 @@ Player properties need to be saved manually.
backface_culling = true, backface_culling = true,
-- Set to false to disable backface_culling for model -- Set to false to disable backface_culling for model
-- Note: only used by "mesh" and "cube" visual
glow = 0, glow = 0,
-- Add this much extra lighting when calculating texture color. -- Add this much extra lighting when calculating texture color.
@ -9341,6 +9360,7 @@ Player properties need to be saved manually.
shaded = true, shaded = true,
-- Setting this to 'false' disables diffuse lighting of entity -- Setting this to 'false' disables diffuse lighting of entity
-- Note: ignored for "item", "wielditem" and "node" visual
show_on_minimap = false, show_on_minimap = false,
-- Defaults to true for players, false for other entities. -- Defaults to true for players, false for other entities.

View file

@ -1,4 +1,4 @@
Luanti Lua Mainmenu API Reference 5.11.0 Luanti Lua Mainmenu API Reference 5.12.0
======================================== ========================================
Introduction Introduction

View file

@ -281,15 +281,27 @@ storing coordinates separately), but the format has been kept unchanged for
that part. that part.
## `map.sqlite` ## `map.sqlite`
`map.sqlite` is a `SQLite3` database, containing a single table, called `map.sqlite` is an `SQLite3` database, containing a single table, called
`blocks`. It looks like this: `blocks`. It looks like this:
```sql
CREATE TABLE `blocks` (
`x` INTEGER, `y` INTEGER, `z` INTEGER,
`data` BLOB NOT NULL,
PRIMARY KEY (`x`, `z`, `y`)
);
```
Before 5.12.0 it looked like this:
```sql ```sql
CREATE TABLE `blocks` (`pos` INT NOT NULL PRIMARY KEY, `data` BLOB); CREATE TABLE `blocks` (`pos` INT NOT NULL PRIMARY KEY, `data` BLOB);
``` ```
## Position Hashing ## Position Hashing
Applies to the pre-5.12.0 schema:
`pos` (a node position hash) is created from the three coordinates of a `pos` (a node position hash) is created from the three coordinates of a
`MapBlock` using this algorithm, defined here in Python: `MapBlock` using this algorithm, defined here in Python:
@ -335,8 +347,8 @@ See below for description.
> * NOTE: Byte order is MSB first (big-endian). > * NOTE: Byte order is MSB first (big-endian).
> * NOTE: Zlib data is in such a format that Python's `zlib` at least can > * NOTE: Zlib data is in such a format that Python's `zlib` at least can
> directly decompress. > directly decompress.
> * NOTE: Since version 29 zstd is used instead of zlib. In addition, the entire > * NOTE: Since version 29 zstd is used instead of zlib. In addition, the
> block is first serialized and then compressed (except the version byte). > **entire block** is first serialized and then compressed (except version byte).
`u8` version `u8` version
* map format version number, see serialization.h for the latest number * map format version number, see serialization.h for the latest number

View file

@ -22,11 +22,15 @@ core.register_node("basenodes:desert_stone", {
core.register_node("basenodes:dirt_with_grass", { core.register_node("basenodes:dirt_with_grass", {
description = "Dirt with Grass", description = "Dirt with Grass",
tiles ={"default_grass.png", -- Using overlays here has no real merit here but we do it anyway so
-- overlay-related bugs become more apparent in devtest.
tiles = {"default_dirt.png"},
overlay_tiles = {
"default_grass.png",
-- a little dot on the bottom to distinguish it from dirt -- a little dot on the bottom to distinguish it from dirt
"default_dirt.png^basenodes_dirt_with_grass_bottom.png", "basenodes_dirt_with_grass_bottom.png",
{name = "default_dirt.png^default_grass_side.png", {name = "default_grass_side.png", tileable_vertical = false},
tileable_vertical = false}}, },
groups = {crumbly=3, soil=1}, groups = {crumbly=3, soil=1},
}) })

View file

@ -66,6 +66,15 @@ core.register_entity("testentities:mesh_unshaded", {
}, },
}) })
core.register_entity("testentities:node", {
initial_properties = {
visual = "node",
node = { name = "stairs:stair_stone" },
},
})
-- More complex meshes
core.register_entity("testentities:sam", { core.register_entity("testentities:sam", {
initial_properties = { initial_properties = {
visual = "mesh", visual = "mesh",

View file

@ -1,10 +1,11 @@
local function get_stack_with_meta(count)
local item_with_meta = ItemStack({name = "air", meta = {test = "abc"}}) return ItemStack({name = "air", count = count, meta = {test = "abc"}})
end
local test_list = { local test_list = {
ItemStack("air"), ItemStack("air"),
ItemStack(""), ItemStack(""),
ItemStack(item_with_meta), ItemStack(get_stack_with_meta(1)),
} }
local function compare_lists(a, b) local function compare_lists(a, b)
@ -34,12 +35,12 @@ local function test_inventory()
assert(not inv:set_width("test", -1)) assert(not inv:set_width("test", -1))
inv:set_stack("test", 1, "air") inv:set_stack("test", 1, "air")
inv:set_stack("test", 3, item_with_meta) inv:set_stack("test", 3, get_stack_with_meta(1))
assert(not inv:is_empty("test")) assert(not inv:is_empty("test"))
assert(compare_lists(inv:get_list("test"), test_list)) assert(compare_lists(inv:get_list("test"), test_list))
assert(inv:add_item("test", "air") == ItemStack()) assert(inv:add_item("test", "air") == ItemStack())
assert(inv:add_item("test", item_with_meta) == ItemStack()) assert(inv:add_item("test", get_stack_with_meta(1)) == ItemStack())
assert(inv:get_stack("test", 1) == ItemStack("air 2")) assert(inv:get_stack("test", 1) == ItemStack("air 2"))
assert(inv:room_for_item("test", "air 99")) assert(inv:room_for_item("test", "air 99"))
@ -48,16 +49,28 @@ local function test_inventory()
inv:set_stack("test", 2, "") inv:set_stack("test", 2, "")
assert(inv:contains_item("test", "air")) assert(inv:contains_item("test", "air"))
assert(inv:contains_item("test", "air 4"))
assert(not inv:contains_item("test", "air 5"))
assert(not inv:contains_item("test", "air 99")) assert(not inv:contains_item("test", "air 99"))
assert(inv:contains_item("test", item_with_meta, true)) assert(inv:contains_item("test", "air 2", true))
assert(not inv:contains_item("test", "air 3", true))
assert(inv:contains_item("test", get_stack_with_meta(2), true))
assert(not inv:contains_item("test", get_stack_with_meta(3), true))
-- Items should be removed in reverse and combine with first stack removed -- Items should be removed in reverse and combine with first stack removed
assert(inv:remove_item("test", "air") == item_with_meta) assert(inv:remove_item("test", "air") == get_stack_with_meta(1))
item_with_meta:set_count(2) assert(inv:remove_item("test", "air 2") == get_stack_with_meta(2))
assert(inv:remove_item("test", "air 2") == item_with_meta)
assert(inv:remove_item("test", "air") == ItemStack("air")) assert(inv:remove_item("test", "air") == ItemStack("air"))
assert(inv:is_empty("test")) assert(inv:is_empty("test"))
inv:set_stack("test", 1, "air 3")
inv:set_stack("test", 3, get_stack_with_meta(2))
assert(inv:remove_item("test", "air 4", true) == ItemStack("air 3"))
inv:set_stack("test", 1, "air 3")
assert(inv:remove_item("test", get_stack_with_meta(3), true) == get_stack_with_meta(2))
assert(inv:remove_item("test", "air 3", true) == ItemStack("air 3"))
assert(inv:is_empty("test"))
-- Failure of set_list(s) should not change inventory -- Failure of set_list(s) should not change inventory
local before = inv:get_list("test") local before = inv:get_list("test")
pcall(inv.set_lists, inv, {test = true}) pcall(inv.set_lists, inv, {test = true})

View file

@ -189,6 +189,29 @@ local function test_write_json()
end end
unittests.register("test_write_json", test_write_json) unittests.register("test_write_json", test_write_json)
local function lint_json_files()
-- Check that files we ship with Luanti are valid JSON
local stack = {core.get_builtin_path()}
local checked = 0
while #stack > 0 do
local path = table.remove(stack)
for _, name in ipairs(core.get_dir_list(path, true)) do
stack[#stack+1] = path .. "/" .. name
end
for _, name in ipairs(core.get_dir_list(path, false)) do
if name:match("%.json$") then
local f = io.open(path .. "/" .. name, "rb")
print(path .. "/" .. name)
assert(core.parse_json(f:read("*all"), -1) ~= nil)
f:close()
checked = checked + 1
end
end
end
assert(checked > 0, "no files found?!")
end
unittests.register("lint_json_files", lint_json_files)
local function test_game_info() local function test_game_info()
local info = core.get_game_info() local info = core.get_game_info()
local game_conf = Settings(info.path .. "/game.conf") local game_conf = Settings(info.path .. "/game.conf")

View file

@ -21,7 +21,7 @@ Aside from standard search options (`ZLIB_INCLUDE_DIR`, `ZLIB_LIBRARY`, ...) the
* `ENABLE_OPENGL` - Enable OpenGL driver * `ENABLE_OPENGL` - Enable OpenGL driver
* `ENABLE_OPENGL3` (default: `OFF`) - Enable OpenGL 3+ driver * `ENABLE_OPENGL3` (default: `OFF`) - Enable OpenGL 3+ driver
* `ENABLE_GLES2` - Enable OpenGL ES 2+ driver * `ENABLE_GLES2` - Enable OpenGL ES 2+ driver
* `USE_SDL2` (default: ON for Android, OFF for other platforms) - Use SDL2 instead of older native device code * `USE_SDL2` (default: platform-dependent, usually `ON`) - Use SDL2 instead of older native device code
However, IrrlichtMt cannot be built or installed separately. However, IrrlichtMt cannot be built or installed separately.

View file

@ -34,16 +34,16 @@ public:
/** \return Pointer to mesh which is displayed by this node. */ /** \return Pointer to mesh which is displayed by this node. */
virtual IMesh *getMesh(void) = 0; virtual IMesh *getMesh(void) = 0;
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them directly.
/** In this way it is possible to change the materials of a mesh /** In this way it is possible to change the materials of a mesh
causing all mesh scene nodes referencing this mesh to change, too. causing all mesh scene nodes referencing this mesh to change, too.
\param readonly Flag if the materials shall be read-only. */ \param shared Flag if the materials shall be shared. */
virtual void setReadOnlyMaterials(bool readonly) = 0; virtual void setSharedMaterials(bool shared) = 0;
//! Check if the scene node should not copy the materials of the mesh but use them in a read only style //! Check if the scene node does not copy the materials of the mesh but uses them directly.
/** This flag can be set by setReadOnlyMaterials(). /** This flag can be set by setSharedMaterials().
\return Whether the materials are read-only. */ \return Whether the materials are shared. */
virtual bool isReadOnlyMaterials() const = 0; virtual bool isSharedMaterials() const = 0;
}; };
} // end namespace scene } // end namespace scene

View file

@ -310,7 +310,11 @@ public:
\return The material at that index. */ \return The material at that index. */
virtual video::SMaterial &getMaterial(u32 num) virtual video::SMaterial &getMaterial(u32 num)
{ {
return video::IdentityMaterial; // We return a default material since a reference can't be null,
// but note that writing to this is a mistake either by a child class
// or the caller, because getMaterialCount() is zero.
// Doing so will helpfully cause a segfault.
return const_cast<video::SMaterial&>(video::IdentityMaterial);
} }
//! Get amount of materials used by this scene node. //! Get amount of materials used by this scene node.

View file

@ -198,9 +198,6 @@ public:
or similar. */ or similar. */
virtual bool supportsTouchEvents() const { return false; } virtual bool supportsTouchEvents() const { return false; }
//! Checks whether windowing uses the Wayland protocol.
virtual bool isUsingWayland() const { return false; }
//! Get the current color format of the window //! Get the current color format of the window
/** \return Color format of the window. */ /** \return Color format of the window. */
virtual video::ECOLOR_FORMAT getColorFormat() const = 0; virtual video::ECOLOR_FORMAT getColorFormat() const = 0;

View file

@ -472,7 +472,7 @@ public:
}; };
//! global const identity Material //! global const identity Material
IRRLICHT_API extern SMaterial IdentityMaterial; IRRLICHT_API extern const SMaterial IdentityMaterial;
} // end namespace video } // end namespace video
} // end namespace irr } // end namespace irr

View file

@ -18,47 +18,38 @@ namespace core
//! Rounding error constant often used when comparing f32 values. //! Rounding error constant often used when comparing f32 values.
const f32 ROUNDING_ERROR_f32 = 0.000001f; constexpr f32 ROUNDING_ERROR_f32 = 0.000001f;
const f64 ROUNDING_ERROR_f64 = 0.00000001; constexpr f64 ROUNDING_ERROR_f64 = 0.00000001;
#ifdef PI // make sure we don't collide with a define #ifdef PI // make sure we don't collide with a define
#undef PI #undef PI
#endif #endif
//! Constant for PI. //! Constant for PI.
const f32 PI = 3.14159265359f; constexpr f32 PI = M_PI;
//! Constant for reciprocal of PI.
const f32 RECIPROCAL_PI = 1.0f / PI;
//! Constant for half of PI.
const f32 HALF_PI = PI / 2.0f;
#ifdef PI64 // make sure we don't collide with a define #ifdef PI64 // make sure we don't collide with a define
#undef PI64 #undef PI64
#endif #endif
//! Constant for 64bit PI. //! Constant for 64bit PI.
const f64 PI64 = 3.1415926535897932384626433832795028841971693993751; constexpr f64 PI64 = M_PI;
//! Constant for 64bit reciprocal of PI.
const f64 RECIPROCAL_PI64 = 1.0 / PI64;
//! 32bit Constant for converting from degrees to radians //! 32bit Constant for converting from degrees to radians
const f32 DEGTORAD = PI / 180.0f; constexpr f32 DEGTORAD = PI / 180.0f;
//! 32bit constant for converting from radians to degrees (formally known as GRAD_PI) //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI)
const f32 RADTODEG = 180.0f / PI; constexpr f32 RADTODEG = 180.0f / PI;
//! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2) //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2)
const f64 DEGTORAD64 = PI64 / 180.0; constexpr f64 DEGTORAD64 = PI64 / 180.0;
//! 64bit constant for converting from radians to degrees //! 64bit constant for converting from radians to degrees
const f64 RADTODEG64 = 180.0 / PI64; constexpr f64 RADTODEG64 = 180.0 / PI64;
//! Utility function to convert a radian value to degrees //! Utility function to convert a radian value to degrees
/** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
\param radians The radians value to convert to degrees. \param radians The radians value to convert to degrees.
*/ */
inline f32 radToDeg(f32 radians) inline constexpr f32 radToDeg(f32 radians)
{ {
return RADTODEG * radians; return RADTODEG * radians;
} }
@ -67,7 +58,7 @@ inline f32 radToDeg(f32 radians)
/** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
\param radians The radians value to convert to degrees. \param radians The radians value to convert to degrees.
*/ */
inline f64 radToDeg(f64 radians) inline constexpr f64 radToDeg(f64 radians)
{ {
return RADTODEG64 * radians; return RADTODEG64 * radians;
} }
@ -76,7 +67,7 @@ inline f64 radToDeg(f64 radians)
/** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X
\param degrees The degrees value to convert to radians. \param degrees The degrees value to convert to radians.
*/ */
inline f32 degToRad(f32 degrees) inline constexpr f32 degToRad(f32 degrees)
{ {
return DEGTORAD * degrees; return DEGTORAD * degrees;
} }
@ -85,44 +76,44 @@ inline f32 degToRad(f32 degrees)
/** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X
\param degrees The degrees value to convert to radians. \param degrees The degrees value to convert to radians.
*/ */
inline f64 degToRad(f64 degrees) inline constexpr f64 degToRad(f64 degrees)
{ {
return DEGTORAD64 * degrees; return DEGTORAD64 * degrees;
} }
//! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems) //! returns minimum of two values.
template <class T> template <class T>
inline const T &min_(const T &a, const T &b) inline const T &min_(const T &a, const T &b)
{ {
return a < b ? a : b; return a < b ? a : b;
} }
//! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems) //! returns minimum of three values.
template <class T> template <class T>
inline const T &min_(const T &a, const T &b, const T &c) inline const T &min_(const T &a, const T &b, const T &c)
{ {
return a < b ? min_(a, c) : min_(b, c); return a < b ? min_(a, c) : min_(b, c);
} }
//! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems) //! returns maximum of two values.
template <class T> template <class T>
inline const T &max_(const T &a, const T &b) inline const T &max_(const T &a, const T &b)
{ {
return a < b ? b : a; return a < b ? b : a;
} }
//! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems) //! returns maximum of three values.
template <class T> template <class T>
inline const T &max_(const T &a, const T &b, const T &c) inline const T &max_(const T &a, const T &b, const T &c)
{ {
return a < b ? max_(b, c) : max_(a, c); return a < b ? max_(b, c) : max_(a, c);
} }
//! returns abs of two values. Own implementation to get rid of STL (VS6 problems) //! returns abs of two values.
template <class T> template <class T>
inline T abs_(const T &a) inline T abs_(const T &a)
{ {
return a < (T)0 ? -a : a; return std::abs(a);
} }
//! returns linear interpolation of a and b with ratio t //! returns linear interpolation of a and b with ratio t
@ -140,19 +131,6 @@ inline const T clamp(const T &value, const T &low, const T &high)
return min_(max_(value, low), high); return min_(max_(value, low), high);
} }
//! swaps the content of the passed parameters
// Note: We use the same trick as boost and use two template arguments to
// avoid ambiguity when swapping objects of an Irrlicht type that has not
// it's own swap overload. Otherwise we get conflicts with some compilers
// in combination with stl.
template <class T1, class T2>
inline void swap(T1 &a, T2 &b)
{
T1 c(a);
a = b;
b = c;
}
template <class T> template <class T>
inline T roundingError(); inline T roundingError();

View file

@ -162,21 +162,12 @@ public:
//! Returns true if the matrix is the identity matrix //! Returns true if the matrix is the identity matrix
inline bool isIdentity() const; inline bool isIdentity() const;
//! Returns true if the matrix is orthogonal
inline bool isOrthogonal() const;
//! Returns true if the matrix is the identity matrix
bool isIdentity_integer_base() const;
//! Set the translation of the current matrix. Will erase any previous values. //! Set the translation of the current matrix. Will erase any previous values.
CMatrix4<T> &setTranslation(const vector3d<T> &translation); CMatrix4<T> &setTranslation(const vector3d<T> &translation);
//! Gets the current translation //! Gets the current translation
vector3d<T> getTranslation() const; vector3d<T> getTranslation() const;
//! Set the inverse translation of the current matrix. Will erase any previous values.
CMatrix4<T> &setInverseTranslation(const vector3d<T> &translation);
//! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
//! NOTE: Rotation order is ZYX. This means that vectors are //! NOTE: Rotation order is ZYX. This means that vectors are
//! first rotated around the X, then the Y, and finally the Z axis. //! first rotated around the X, then the Y, and finally the Z axis.
@ -188,9 +179,7 @@ public:
CMatrix4<T> &setRotationDegrees(const vector3d<T> &rotation); CMatrix4<T> &setRotationDegrees(const vector3d<T> &rotation);
//! Get the rotation, as set by setRotation() when you already know the scale used to create the matrix //! Get the rotation, as set by setRotation() when you already know the scale used to create the matrix
/** NOTE: The scale needs to be the correct one used to create this matrix. /**
You can _not_ use the result of getScale(), but have to save your scale
variable in another place (like ISceneNode does).
NOTE: No scale value can be 0 or the result is undefined. NOTE: No scale value can be 0 or the result is undefined.
NOTE: It does not necessarily return the *same* Euler angles as those set by setRotationDegrees(), NOTE: It does not necessarily return the *same* Euler angles as those set by setRotationDegrees(),
but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node. but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node.
@ -198,24 +187,18 @@ public:
WARNING: There have been troubles with this function over the years and we may still have missed some corner cases. WARNING: There have been troubles with this function over the years and we may still have missed some corner cases.
It's generally safer to keep the rotation and scale you used to create the matrix around and work with those. It's generally safer to keep the rotation and scale you used to create the matrix around and work with those.
*/ */
core::vector3d<T> getRotationDegrees(const vector3d<T> &scale) const; vector3d<T> getRotationRadians(const vector3d<T> &scale) const;
//! Returns the rotation, as set by setRotation(). //! Returns the rotation, as set by setRotation().
/** NOTE: You will have the same end-rotation as used in setRotation, but it might not use the same axis values. /** NOTE: You will have the same end-rotation as used in setRotation, but it might not use the same axis values.
NOTE: This only works correct if no other matrix operations have been done on the inner 3x3 matrix besides NOTE: This only works correctly for TRS matrix products where S is a positive, component-wise scaling (see setScale).
setting rotation (so no scale/shear). Thought it (probably) works as long as scale doesn't flip handedness.
NOTE: It does not necessarily return the *same* Euler angles as those set by setRotationDegrees(), NOTE: It does not necessarily return the *same* Euler angles as those set by setRotationDegrees(),
but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node. but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node.
*/ */
core::vector3d<T> getRotationDegrees() const; vector3d<T> getRotationRadians() const;
//! Make an inverted rotation matrix from Euler angles. //! Same as getRotationRadians, but returns degrees.
/** The 4th row and column are unmodified. */ vector3d<T> getRotationDegrees() const;
inline CMatrix4<T> &setInverseRotationRadians(const vector3d<T> &rotation);
//! Make an inverted rotation matrix from Euler angles.
/** The 4th row and column are unmodified. */
inline CMatrix4<T> &setInverseRotationDegrees(const vector3d<T> &rotation);
//! Make a rotation matrix from angle and axis, assuming left handed rotation. //! Make a rotation matrix from angle and axis, assuming left handed rotation.
/** The 4th row and column are unmodified. */ /** The 4th row and column are unmodified. */
@ -225,10 +208,10 @@ public:
CMatrix4<T> &setScale(const vector3d<T> &scale); CMatrix4<T> &setScale(const vector3d<T> &scale);
//! Set Scale //! Set Scale
CMatrix4<T> &setScale(const T scale) { return setScale(core::vector3d<T>(scale, scale, scale)); } CMatrix4<T> &setScale(const T scale) { return setScale(vector3d<T>(scale, scale, scale)); }
//! Get Scale //! Get Scale
core::vector3d<T> getScale() const; vector3d<T> getScale() const;
//! Translate a vector by the inverse of the translation part of this matrix. //! Translate a vector by the inverse of the translation part of this matrix.
void inverseTranslateVect(vector3df &vect) const; void inverseTranslateVect(vector3df &vect) const;
@ -259,7 +242,7 @@ public:
//! An alternate transform vector method, writing into an array of 4 floats //! An alternate transform vector method, writing into an array of 4 floats
/** This operation is performed as if the vector was 4d with the 4th component =1. /** This operation is performed as if the vector was 4d with the 4th component =1.
NOTE: out[3] will be written to (4th vector component)*/ NOTE: out[3] will be written to (4th vector component)*/
void transformVect(T *out, const core::vector3df &in) const; void transformVect(T *out, const vector3df &in) const;
//! An alternate transform vector method, reading from and writing to an array of 3 floats //! An alternate transform vector method, reading from and writing to an array of 3 floats
/** This operation is performed as if the vector was 4d with the 4th component =1 /** This operation is performed as if the vector was 4d with the 4th component =1
@ -274,13 +257,13 @@ public:
void translateVect(vector3df &vect) const; void translateVect(vector3df &vect) const;
//! Transforms a plane by this matrix //! Transforms a plane by this matrix
void transformPlane(core::plane3d<f32> &plane) const; void transformPlane(plane3d<f32> &plane) const;
//! Transforms a plane by this matrix //! Transforms a plane by this matrix
void transformPlane(const core::plane3d<f32> &in, core::plane3d<f32> &out) const; void transformPlane(const plane3d<f32> &in, plane3d<f32> &out) const;
//! Transforms a axis aligned bounding box //! Transforms a axis aligned bounding box
void transformBoxEx(core::aabbox3d<f32> &box) const; void transformBoxEx(aabbox3d<f32> &box) const;
//! Multiplies this matrix by a 1x4 matrix //! Multiplies this matrix by a 1x4 matrix
void multiplyWith1x4Matrix(T *matrix) const; void multiplyWith1x4Matrix(T *matrix) const;
@ -338,16 +321,16 @@ public:
\param plane: plane into which the geometry if flattened into \param plane: plane into which the geometry if flattened into
\param point: value between 0 and 1, describing the light source. \param point: value between 0 and 1, describing the light source.
If this is 1, it is a point light, if it is 0, it is a directional light. */ If this is 1, it is a point light, if it is 0, it is a directional light. */
CMatrix4<T> &buildShadowMatrix(const core::vector3df &light, core::plane3df plane, f32 point = 1.0f); CMatrix4<T> &buildShadowMatrix(const vector3df &light, plane3df plane, f32 point = 1.0f);
//! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates. //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
/** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */ /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */
CMatrix4<T> &buildNDCToDCMatrix(const core::rect<s32> &area, f32 zScale); CMatrix4<T> &buildNDCToDCMatrix(const rect<s32> &area, f32 zScale);
//! Creates a new matrix as interpolated matrix from two other ones. //! Creates a new matrix as interpolated matrix from two other ones.
/** \param b: other matrix to interpolate with /** \param b: other matrix to interpolate with
\param time: Must be a value between 0 and 1. */ \param time: Must be a value between 0 and 1. */
CMatrix4<T> interpolate(const core::CMatrix4<T> &b, f32 time) const; CMatrix4<T> interpolate(const CMatrix4<T> &b, f32 time) const;
//! Gets transposed matrix //! Gets transposed matrix
CMatrix4<T> getTransposed() const; CMatrix4<T> getTransposed() const;
@ -359,13 +342,13 @@ public:
/** \param from: vector to rotate from /** \param from: vector to rotate from
\param to: vector to rotate to \param to: vector to rotate to
*/ */
CMatrix4<T> &buildRotateFromTo(const core::vector3df &from, const core::vector3df &to); CMatrix4<T> &buildRotateFromTo(const vector3df &from, const vector3df &to);
//! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards
/** \param center Position to rotate around /** \param center Position to rotate around
\param translate Translation applied after the rotation \param translate Translation applied after the rotation
*/ */
void setRotationCenter(const core::vector3df &center, const core::vector3df &translate); void setRotationCenter(const vector3df &center, const vector3df &translate);
//! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis
/** \param camPos: viewer position in world coo /** \param camPos: viewer position in world coo
@ -374,11 +357,11 @@ public:
\param axis: axis to rotate about \param axis: axis to rotate about
\param from: source vector to rotate from \param from: source vector to rotate from
*/ */
void buildAxisAlignedBillboard(const core::vector3df &camPos, void buildAxisAlignedBillboard(const vector3df &camPos,
const core::vector3df &center, const vector3df &center,
const core::vector3df &translation, const vector3df &translation,
const core::vector3df &axis, const vector3df &axis,
const core::vector3df &from); const vector3df &from);
/* /*
construct 2D Texture transformations construct 2D Texture transformations
@ -386,9 +369,9 @@ public:
*/ */
//! Set to a texture transformation matrix with the given parameters. //! Set to a texture transformation matrix with the given parameters.
CMatrix4<T> &buildTextureTransform(f32 rotateRad, CMatrix4<T> &buildTextureTransform(f32 rotateRad,
const core::vector2df &rotatecenter, const vector2df &rotatecenter,
const core::vector2df &translate, const vector2df &translate,
const core::vector2df &scale); const vector2df &scale);
//! Set texture transformation rotation //! Set texture transformation rotation
/** Rotate about z axis, recenter at (0.5,0.5). /** Rotate about z axis, recenter at (0.5,0.5).
@ -439,9 +422,12 @@ public:
CMatrix4<T> &setM(const T *data); CMatrix4<T> &setM(const T *data);
//! Compare two matrices using the equal method //! Compare two matrices using the equal method
bool equals(const core::CMatrix4<T> &other, const T tolerance = (T)ROUNDING_ERROR_f64) const; bool equals(const CMatrix4<T> &other, const T tolerance = (T)ROUNDING_ERROR_f64) const;
private: private:
template <bool degrees>
vector3d<T> getRotation(const vector3d<T> &scale) const;
//! Matrix data, stored in row-major order //! Matrix data, stored in row-major order
T M[16]; T M[16];
}; };
@ -645,21 +631,8 @@ inline CMatrix4<T> &CMatrix4<T>::operator*=(const T &scalar)
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::operator*=(const CMatrix4<T> &other) inline CMatrix4<T> &CMatrix4<T>::operator*=(const CMatrix4<T> &other)
{ {
#if defined(USE_MATRIX_TEST)
// do checks on your own in order to avoid copy creation
if (!other.isIdentity()) {
if (this->isIdentity()) {
return (*this = other);
} else {
CMatrix4<T> temp(*this);
return setbyproduct_nocheck(temp, other);
}
}
return *this;
#else
CMatrix4<T> temp(*this); CMatrix4<T> temp(*this);
return setbyproduct_nocheck(temp, other); return setbyproduct_nocheck(temp, other);
#endif
} }
//! multiply by another matrix //! multiply by another matrix
@ -699,30 +672,13 @@ inline CMatrix4<T> &CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T> &other_a
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::setbyproduct(const CMatrix4<T> &other_a, const CMatrix4<T> &other_b) inline CMatrix4<T> &CMatrix4<T>::setbyproduct(const CMatrix4<T> &other_a, const CMatrix4<T> &other_b)
{ {
#if defined(USE_MATRIX_TEST)
if (other_a.isIdentity())
return (*this = other_b);
else if (other_b.isIdentity())
return (*this = other_a);
else
return setbyproduct_nocheck(other_a, other_b);
#else
return setbyproduct_nocheck(other_a, other_b); return setbyproduct_nocheck(other_a, other_b);
#endif
} }
//! multiply by another matrix //! multiply by another matrix
template <class T> template <class T>
inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T> &m2) const inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T> &m2) const
{ {
#if defined(USE_MATRIX_TEST)
// Testing purpose..
if (this->isIdentity())
return m2;
if (m2.isIdentity())
return *this;
#endif
CMatrix4<T> m3(EM4CONST_NOTHING); CMatrix4<T> m3(EM4CONST_NOTHING);
const T *m1 = M; const T *m1 = M;
@ -764,15 +720,6 @@ inline CMatrix4<T> &CMatrix4<T>::setTranslation(const vector3d<T> &translation)
return *this; return *this;
} }
template <class T>
inline CMatrix4<T> &CMatrix4<T>::setInverseTranslation(const vector3d<T> &translation)
{
M[12] = -translation.X;
M[13] = -translation.Y;
M[14] = -translation.Z;
return *this;
}
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::setScale(const vector3d<T> &scale) inline CMatrix4<T> &CMatrix4<T>::setScale(const vector3d<T> &scale)
{ {
@ -805,13 +752,7 @@ inline vector3d<T> CMatrix4<T>::getScale() const
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::setRotationDegrees(const vector3d<T> &rotation) inline CMatrix4<T> &CMatrix4<T>::setRotationDegrees(const vector3d<T> &rotation)
{ {
return setRotationRadians(rotation * core::DEGTORAD); return setRotationRadians(rotation * DEGTORAD);
}
template <class T>
inline CMatrix4<T> &CMatrix4<T>::setInverseRotationDegrees(const vector3d<T> &rotation)
{
return setInverseRotationRadians(rotation * core::DEGTORAD);
} }
template <class T> template <class T>
@ -841,91 +782,60 @@ inline CMatrix4<T> &CMatrix4<T>::setRotationRadians(const vector3d<T> &rotation)
return *this; return *this;
} }
//! Returns a rotation which (mostly) works in combination with the given scale
/**
This code was originally written by by Chev (assuming no scaling back then,
we can be blamed for all problems added by regarding scale)
*/
template <class T> template <class T>
inline core::vector3d<T> CMatrix4<T>::getRotationDegrees(const vector3d<T> &scale_) const template <bool degrees>
inline vector3d<T> CMatrix4<T>::getRotation(const vector3d<T> &scale_) const
{ {
// Based on code by Chev
const CMatrix4<T> &mat = *this; const CMatrix4<T> &mat = *this;
const core::vector3d<f64> scale(core::iszero(scale_.X) ? FLT_MAX : scale_.X, core::iszero(scale_.Y) ? FLT_MAX : scale_.Y, core::iszero(scale_.Z) ? FLT_MAX : scale_.Z); const vector3d<f64> scale(iszero(scale_.X) ? FLT_MAX : scale_.X, iszero(scale_.Y) ? FLT_MAX : scale_.Y, iszero(scale_.Z) ? FLT_MAX : scale_.Z);
const core::vector3d<f64> invScale(core::reciprocal(scale.X), core::reciprocal(scale.Y), core::reciprocal(scale.Z)); const vector3d<f64> invScale(reciprocal(scale.X), reciprocal(scale.Y), reciprocal(scale.Z));
f64 Y = -asin(core::clamp(mat[2] * invScale.X, -1.0, 1.0)); f64 a = clamp(mat[2] * invScale.X, -1.0, 1.0);
const f64 C = cos(Y); f64 Y = -asin(a);
Y *= RADTODEG64;
f64 rotx, roty, X, Z; f64 rotx, roty, X, Z;
if (!core::iszero((T)C)) { if (!core::equals(std::abs(a), 1.0)) {
const f64 invC = core::reciprocal(C); // abs(a) = abs(sin(Y)) = 1 <=> cos(Y) = 0
rotx = mat[10] * invC * invScale.Z; rotx = mat[10] * invScale.Z;
roty = mat[6] * invC * invScale.Y; roty = mat[6] * invScale.Y;
X = atan2(roty, rotx) * RADTODEG64; X = atan2(roty, rotx);
rotx = mat[0] * invC * invScale.X; rotx = mat[0] * invScale.X;
roty = mat[1] * invC * invScale.X; roty = mat[1] * invScale.X;
Z = atan2(roty, rotx) * RADTODEG64; Z = atan2(roty, rotx);
} else { } else {
X = 0.0; X = 0.0;
rotx = mat[5] * invScale.Y; rotx = mat[5];
roty = -mat[4] * invScale.Y; roty = -mat[4];
Z = atan2(roty, rotx) * RADTODEG64; Z = atan2(roty, rotx);
} }
// fix values that get below zero if (degrees) {
if (X < 0.0) X *= core::RADTODEG64;
X += 360.0; Y *= core::RADTODEG64;
if (Y < 0.0) Z *= core::RADTODEG64;
Y += 360.0; }
if (Z < 0.0)
Z += 360.0;
return vector3d<T>((T)X, (T)Y, (T)Z); return vector3d<T>((T)X, (T)Y, (T)Z);
} }
//! Returns a rotation that is equivalent to that set by setRotationDegrees(). template <class T>
inline vector3d<T> CMatrix4<T>::getRotationRadians(const vector3d<T> &scale) const
{
return getRotation<false>(scale);
}
template <class T>
inline vector3d<T> CMatrix4<T>::getRotationRadians() const
{
return getRotationRadians(getScale());
}
template <class T> template <class T>
inline vector3d<T> CMatrix4<T>::getRotationDegrees() const inline vector3d<T> CMatrix4<T>::getRotationDegrees() const
{ {
// Note: Using getScale() here make it look like it could do matrix decomposition. return getRotation<true>(getScale());
// It can't! It works (or should work) as long as rotation doesn't flip the handedness
// aka scale swapping 1 or 3 axes. (I think we could catch that as well by comparing
// crossproduct of first 2 axes to direction of third axis, but TODO)
// And maybe it should also offer the solution for the simple calculation
// without regarding scaling as Irrlicht did before 1.7
vector3d<T> scale(getScale());
return getRotationDegrees(scale);
}
//! Sets matrix to rotation matrix of inverse angles given as parameters
template <class T>
inline CMatrix4<T> &CMatrix4<T>::setInverseRotationRadians(const vector3d<T> &rotation)
{
f64 cPitch = cos(rotation.X);
f64 sPitch = sin(rotation.X);
f64 cYaw = cos(rotation.Y);
f64 sYaw = sin(rotation.Y);
f64 cRoll = cos(rotation.Z);
f64 sRoll = sin(rotation.Z);
M[0] = (T)(cYaw * cRoll);
M[4] = (T)(cYaw * sRoll);
M[8] = (T)(-sYaw);
f64 sPitch_sYaw = sPitch * sYaw;
f64 cPitch_sYaw = cPitch * sYaw;
M[1] = (T)(sPitch_sYaw * cRoll - cPitch * sRoll);
M[5] = (T)(sPitch_sYaw * sRoll + cPitch * cRoll);
M[9] = (T)(sPitch * cYaw);
M[2] = (T)(cPitch_sYaw * cRoll + sPitch * sRoll);
M[6] = (T)(cPitch_sYaw * sRoll - sPitch * cRoll);
M[10] = (T)(cPitch * cYaw);
return *this;
} }
//! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation //! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation
@ -959,8 +869,6 @@ inline CMatrix4<T> &CMatrix4<T>::setRotationAxisRadians(const T &angle, const ve
return *this; return *this;
} }
/*!
*/
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::makeIdentity() inline CMatrix4<T> &CMatrix4<T>::makeIdentity()
{ {
@ -1002,77 +910,6 @@ inline bool CMatrix4<T>::isIdentity() const
return true; return true;
} }
/* Check orthogonality of matrix. */
template <class T>
inline bool CMatrix4<T>::isOrthogonal() const
{
T dp = M[0] * M[4] + M[1] * M[5] + M[2] * M[6] + M[3] * M[7];
if (!iszero(dp))
return false;
dp = M[0] * M[8] + M[1] * M[9] + M[2] * M[10] + M[3] * M[11];
if (!iszero(dp))
return false;
dp = M[0] * M[12] + M[1] * M[13] + M[2] * M[14] + M[3] * M[15];
if (!iszero(dp))
return false;
dp = M[4] * M[8] + M[5] * M[9] + M[6] * M[10] + M[7] * M[11];
if (!iszero(dp))
return false;
dp = M[4] * M[12] + M[5] * M[13] + M[6] * M[14] + M[7] * M[15];
if (!iszero(dp))
return false;
dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15];
return (iszero(dp));
}
/*
doesn't solve floating range problems..
but takes care on +/- 0 on translation because we are changing it..
reducing floating point branches
but it needs the floats in memory..
*/
template <class T>
inline bool CMatrix4<T>::isIdentity_integer_base() const
{
if (IR(M[0]) != F32_VALUE_1)
return false;
if (IR(M[1]) != 0)
return false;
if (IR(M[2]) != 0)
return false;
if (IR(M[3]) != 0)
return false;
if (IR(M[4]) != 0)
return false;
if (IR(M[5]) != F32_VALUE_1)
return false;
if (IR(M[6]) != 0)
return false;
if (IR(M[7]) != 0)
return false;
if (IR(M[8]) != 0)
return false;
if (IR(M[9]) != 0)
return false;
if (IR(M[10]) != F32_VALUE_1)
return false;
if (IR(M[11]) != 0)
return false;
if (IR(M[12]) != 0)
return false;
if (IR(M[13]) != 0)
return false;
if (IR(M[13]) != 0)
return false;
if (IR(M[15]) != F32_VALUE_1)
return false;
return true;
}
template <class T> template <class T>
inline vector3d<T> CMatrix4<T>::rotateAndScaleVect(const vector3d<T> &v) const inline vector3d<T> CMatrix4<T>::rotateAndScaleVect(const vector3d<T> &v) const
{ {
@ -1104,7 +941,7 @@ inline vector3d<T> CMatrix4<T>::transformVect(const vector3d<T> &v) const
} }
template <class T> template <class T>
inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const inline void CMatrix4<T>::transformVect(T *out, const vector3df &in) const
{ {
out[0] = in.X * M[0] + in.Y * M[4] + in.Z * M[8] + M[12]; out[0] = in.X * M[0] + in.Y * M[4] + in.Z * M[8] + M[12];
out[1] = in.X * M[1] + in.Y * M[5] + in.Z * M[9] + M[13]; out[1] = in.X * M[1] + in.Y * M[5] + in.Z * M[9] + M[13];
@ -1131,7 +968,7 @@ inline void CMatrix4<T>::transformVec4(T *out, const T *in) const
//! Transforms a plane by this matrix //! Transforms a plane by this matrix
template <class T> template <class T>
inline void CMatrix4<T>::transformPlane(core::plane3d<f32> &plane) const inline void CMatrix4<T>::transformPlane(plane3d<f32> &plane) const
{ {
vector3df member; vector3df member;
// Transform the plane member point, i.e. rotate, translate and scale it. // Transform the plane member point, i.e. rotate, translate and scale it.
@ -1145,7 +982,7 @@ inline void CMatrix4<T>::transformPlane(core::plane3d<f32> &plane) const
//! Transforms a plane by this matrix //! Transforms a plane by this matrix
template <class T> template <class T>
inline void CMatrix4<T>::transformPlane(const core::plane3d<f32> &in, core::plane3d<f32> &out) const inline void CMatrix4<T>::transformPlane(const plane3d<f32> &in, plane3d<f32> &out) const
{ {
out = in; out = in;
transformPlane(out); transformPlane(out);
@ -1153,13 +990,8 @@ inline void CMatrix4<T>::transformPlane(const core::plane3d<f32> &in, core::plan
//! Transforms a axis aligned bounding box more accurately than transformBox() //! Transforms a axis aligned bounding box more accurately than transformBox()
template <class T> template <class T>
inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32> &box) const inline void CMatrix4<T>::transformBoxEx(aabbox3d<f32> &box) const
{ {
#if defined(USE_MATRIX_TEST)
if (isIdentity())
return;
#endif
const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z}; const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z}; const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
@ -1242,12 +1074,6 @@ inline bool CMatrix4<T>::getInverse(CMatrix4<T> &out) const
/// The inverse is calculated using Cramers rule. /// The inverse is calculated using Cramers rule.
/// If no inverse exists then 'false' is returned. /// If no inverse exists then 'false' is returned.
#if defined(USE_MATRIX_TEST)
if (this->isIdentity()) {
out = *this;
return true;
}
#endif
const CMatrix4<T> &m = *this; const CMatrix4<T> &m = *this;
f32 d = (m[0] * m[5] - m[1] * m[4]) * (m[10] * m[15] - m[11] * m[14]) - f32 d = (m[0] * m[5] - m[1] * m[4]) * (m[10] * m[15] - m[11] * m[14]) -
@ -1257,10 +1083,10 @@ inline bool CMatrix4<T>::getInverse(CMatrix4<T> &out) const
(m[1] * m[7] - m[3] * m[5]) * (m[8] * m[14] - m[10] * m[12]) + (m[1] * m[7] - m[3] * m[5]) * (m[8] * m[14] - m[10] * m[12]) +
(m[2] * m[7] - m[3] * m[6]) * (m[8] * m[13] - m[9] * m[12]); (m[2] * m[7] - m[3] * m[6]) * (m[8] * m[13] - m[9] * m[12]);
if (core::iszero(d, FLT_MIN)) if (iszero(d, FLT_MIN))
return false; return false;
d = core::reciprocal(d); d = reciprocal(d);
out[0] = d * (m[5] * (m[10] * m[15] - m[11] * m[14]) + out[0] = d * (m[5] * (m[10] * m[15] - m[11] * m[14]) +
m[6] * (m[11] * m[13] - m[9] * m[15]) + m[6] * (m[11] * m[13] - m[9] * m[15]) +
@ -1642,7 +1468,7 @@ inline CMatrix4<T> &CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
// Builds a matrix that flattens geometry into a plane. // Builds a matrix that flattens geometry into a plane.
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::buildShadowMatrix(const core::vector3df &light, core::plane3df plane, f32 point) inline CMatrix4<T> &CMatrix4<T>::buildShadowMatrix(const vector3df &light, plane3df plane, f32 point)
{ {
plane.Normal.normalize(); plane.Normal.normalize();
const f32 d = plane.Normal.dotProduct(light); const f32 d = plane.Normal.dotProduct(light);
@ -1748,7 +1574,7 @@ inline CMatrix4<T> &CMatrix4<T>::buildCameraLookAtMatrixRH(
// creates a new matrix as interpolated matrix from this and the passed one. // creates a new matrix as interpolated matrix from this and the passed one.
template <class T> template <class T>
inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T> &b, f32 time) const inline CMatrix4<T> CMatrix4<T>::interpolate(const CMatrix4<T> &b, f32 time) const
{ {
CMatrix4<T> mat(EM4CONST_NOTHING); CMatrix4<T> mat(EM4CONST_NOTHING);
@ -1797,7 +1623,7 @@ inline void CMatrix4<T>::getTransposed(CMatrix4<T> &o) const
// used to scale <-1,-1><1,1> to viewport // used to scale <-1,-1><1,1> to viewport
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::buildNDCToDCMatrix(const core::rect<s32> &viewport, f32 zScale) inline CMatrix4<T> &CMatrix4<T>::buildNDCToDCMatrix(const rect<s32> &viewport, f32 zScale)
{ {
const f32 scaleX = (viewport.getWidth() - 0.75f) * 0.5f; const f32 scaleX = (viewport.getWidth() - 0.75f) * 0.5f;
const f32 scaleY = -(viewport.getHeight() - 0.75f) * 0.5f; const f32 scaleY = -(viewport.getHeight() - 0.75f) * 0.5f;
@ -1808,7 +1634,7 @@ inline CMatrix4<T> &CMatrix4<T>::buildNDCToDCMatrix(const core::rect<s32> &viewp
makeIdentity(); makeIdentity();
M[12] = (T)dx; M[12] = (T)dx;
M[13] = (T)dy; M[13] = (T)dy;
return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale)); return setScale(vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
} }
//! Builds a matrix that rotates from one vector to another //! Builds a matrix that rotates from one vector to another
@ -1818,25 +1644,25 @@ inline CMatrix4<T> &CMatrix4<T>::buildNDCToDCMatrix(const core::rect<s32> &viewp
http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm
*/ */
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::buildRotateFromTo(const core::vector3df &from, const core::vector3df &to) inline CMatrix4<T> &CMatrix4<T>::buildRotateFromTo(const vector3df &from, const vector3df &to)
{ {
// unit vectors // unit vectors
core::vector3df f(from); vector3df f(from);
core::vector3df t(to); vector3df t(to);
f.normalize(); f.normalize();
t.normalize(); t.normalize();
// axis multiplication by sin // axis multiplication by sin
core::vector3df vs(t.crossProduct(f)); vector3df vs(t.crossProduct(f));
// axis of rotation // axis of rotation
core::vector3df v(vs); vector3df v(vs);
v.normalize(); v.normalize();
// cosine angle // cosine angle
T ca = f.dotProduct(t); T ca = f.dotProduct(t);
core::vector3df vt(v * (1 - ca)); vector3df vt(v * (1 - ca));
M[0] = vt.X * v.X + ca; M[0] = vt.X * v.X + ca;
M[5] = vt.Y * v.Y + ca; M[5] = vt.Y * v.Y + ca;
@ -1875,29 +1701,29 @@ inline CMatrix4<T> &CMatrix4<T>::buildRotateFromTo(const core::vector3df &from,
*/ */
template <class T> template <class T>
inline void CMatrix4<T>::buildAxisAlignedBillboard( inline void CMatrix4<T>::buildAxisAlignedBillboard(
const core::vector3df &camPos, const vector3df &camPos,
const core::vector3df &center, const vector3df &center,
const core::vector3df &translation, const vector3df &translation,
const core::vector3df &axis, const vector3df &axis,
const core::vector3df &from) const vector3df &from)
{ {
// axis of rotation // axis of rotation
core::vector3df up = axis; vector3df up = axis;
up.normalize(); up.normalize();
const core::vector3df forward = (camPos - center).normalize(); const vector3df forward = (camPos - center).normalize();
const core::vector3df right = up.crossProduct(forward).normalize(); const vector3df right = up.crossProduct(forward).normalize();
// correct look vector // correct look vector
const core::vector3df look = right.crossProduct(up); const vector3df look = right.crossProduct(up);
// rotate from to // rotate from to
// axis multiplication by sin // axis multiplication by sin
const core::vector3df vs = look.crossProduct(from); const vector3df vs = look.crossProduct(from);
// cosine angle // cosine angle
const f32 ca = from.dotProduct(look); const f32 ca = from.dotProduct(look);
core::vector3df vt(up * (1.f - ca)); vector3df vt(up * (1.f - ca));
M[0] = static_cast<T>(vt.X * up.X + ca); M[0] = static_cast<T>(vt.X * up.X + ca);
M[5] = static_cast<T>(vt.Y * up.Y + ca); M[5] = static_cast<T>(vt.Y * up.Y + ca);
@ -1924,7 +1750,7 @@ inline void CMatrix4<T>::buildAxisAlignedBillboard(
//! Builds a combined matrix which translate to a center before rotation and translate afterward //! Builds a combined matrix which translate to a center before rotation and translate afterward
template <class T> template <class T>
inline void CMatrix4<T>::setRotationCenter(const core::vector3df &center, const core::vector3df &translation) inline void CMatrix4<T>::setRotationCenter(const vector3df &center, const vector3df &translation)
{ {
M[12] = -M[0] * center.X - M[4] * center.Y - M[8] * center.Z + (center.X - translation.X); M[12] = -M[0] * center.X - M[4] * center.Y - M[8] * center.Z + (center.X - translation.X);
M[13] = -M[1] * center.X - M[5] * center.Y - M[9] * center.Z + (center.Y - translation.Y); M[13] = -M[1] * center.X - M[5] * center.Y - M[9] * center.Z + (center.Y - translation.Y);
@ -1945,9 +1771,9 @@ inline void CMatrix4<T>::setRotationCenter(const core::vector3df &center, const
template <class T> template <class T>
inline CMatrix4<T> &CMatrix4<T>::buildTextureTransform(f32 rotateRad, inline CMatrix4<T> &CMatrix4<T>::buildTextureTransform(f32 rotateRad,
const core::vector2df &rotatecenter, const vector2df &rotatecenter,
const core::vector2df &translate, const vector2df &translate,
const core::vector2df &scale) const vector2df &scale)
{ {
const f32 c = cosf(rotateRad); const f32 c = cosf(rotateRad);
const f32 s = sinf(rotateRad); const f32 s = sinf(rotateRad);
@ -2052,7 +1878,7 @@ inline CMatrix4<T> &CMatrix4<T>::setM(const T *data)
//! Compare two matrices using the equal method //! Compare two matrices using the equal method
template <class T> template <class T>
inline bool CMatrix4<T>::equals(const core::CMatrix4<T> &other, const T tolerance) const inline bool CMatrix4<T>::equals(const CMatrix4<T> &other, const T tolerance) const
{ {
for (s32 i = 0; i < 16; ++i) for (s32 i = 0; i < 16; ++i)
if (!core::equals(M[i], other.M[i], tolerance)) if (!core::equals(M[i], other.M[i], tolerance))

View file

@ -33,6 +33,12 @@ public:
explicit constexpr vector3d(T n) : explicit constexpr vector3d(T n) :
X(n), Y(n), Z(n) {} X(n), Y(n), Z(n) {}
template <class U>
constexpr static vector3d<T> from(const vector3d<U> &other)
{
return {static_cast<T>(other.X), static_cast<T>(other.Y), static_cast<T>(other.Z)};
}
// operators // operators
vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); } vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); }

View file

@ -619,7 +619,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
// Code is slow, needs to be fixed up // Code is slow, needs to be fixed up
const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees() * core::DEGTORAD); const core::quaternion RotationStart(PretransitingSave[n].getRotationRadians());
const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation() * core::DEGTORAD); const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation() * core::DEGTORAD);
core::quaternion QRotation; core::quaternion QRotation;

View file

@ -546,16 +546,6 @@ void SelfType::MeshExtractor::deferAddMesh(
}); });
} }
// Base transformation between left & right handed coordinate systems.
// This just inverts the Z axis.
static const core::matrix4 leftToRight = core::matrix4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1
);
static const core::matrix4 rightToLeft = leftToRight;
static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, SkinnedMesh::SJoint *joint) static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, SkinnedMesh::SJoint *joint)
{ {
// Note: Under the hood, this casts these doubles to floats. // Note: Under the hood, this casts these doubles to floats.
@ -570,14 +560,7 @@ static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, SkinnedMes
auto scale = mat.getScale(); auto scale = mat.getScale();
joint->Animatedscale = scale; joint->Animatedscale = scale;
core::matrix4 inverseScale; joint->Animatedrotation = mat.getRotationRadians(scale);
inverseScale.setScale(core::vector3df(
scale.X == 0 ? 0 : 1 / scale.X,
scale.Y == 0 ? 0 : 1 / scale.Y,
scale.Z == 0 ? 0 : 1 / scale.Z));
core::matrix4 axisNormalizedMat = inverseScale * mat;
joint->Animatedrotation = axisNormalizedMat.getRotationDegrees();
// Invert the rotation because it is applied using `getMatrix_transposed`, // Invert the rotation because it is applied using `getMatrix_transposed`,
// which again inverts. // which again inverts.
joint->Animatedrotation.makeInverse(); joint->Animatedrotation.makeInverse();

View file

@ -308,8 +308,6 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters &param) :
if (SDL_Init(flags) < 0) { if (SDL_Init(flags) < 0) {
os::Printer::log("Unable to initialize SDL", SDL_GetError(), ELL_ERROR); os::Printer::log("Unable to initialize SDL", SDL_GetError(), ELL_ERROR);
Close = true; Close = true;
} else {
os::Printer::log("SDL initialized", ELL_INFORMATION);
} }
} }
@ -324,21 +322,27 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters &param) :
} }
} }
SDL_VERSION(&Info.version); core::stringc sdlver = "SDL ";
{
SDL_version v{};
SDL_GetVersion(&v);
sdlver += v.major;
sdlver += ".";
sdlver += v.minor;
sdlver += ".";
sdlver += v.patch;
// the SDL team seems to intentionally number sdl2-compat this way:
// <https://github.com/libsdl-org/sdl2-compat/tags>
if (v.patch >= 50)
sdlver += " (compat)";
#ifndef _IRR_EMSCRIPTEN_PLATFORM_ sdlver += " on ";
SDL_GetWindowWMInfo(Window, &Info); sdlver += SDL_GetPlatform();
#endif //_IRR_EMSCRIPTEN_PLATFORM_ }
core::stringc sdlversion = "SDL Version ";
sdlversion += Info.version.major;
sdlversion += ".";
sdlversion += Info.version.minor;
sdlversion += ".";
sdlversion += Info.version.patch;
Operator = new COSOperator(sdlversion); Operator = new COSOperator(sdlver);
if (SDLDeviceInstances == 1) { if (SDLDeviceInstances == 1) {
os::Printer::log(sdlversion.c_str(), ELL_INFORMATION); os::Printer::log(sdlver.c_str(), ELL_INFORMATION);
} }
// create cursor control // create cursor control
@ -706,6 +710,10 @@ bool CIrrDeviceSDL::run()
irrevent.MouseInput.X = MouseX; irrevent.MouseInput.X = MouseX;
irrevent.MouseInput.Y = MouseY; irrevent.MouseInput.Y = MouseY;
// wheel y can be 0 if scrolling sideways
if (irrevent.MouseInput.Wheel == 0.0f)
break;
postEventFromUser(irrevent); postEventFromUser(irrevent);
break; break;
} }
@ -1248,15 +1256,6 @@ bool CIrrDeviceSDL::supportsTouchEvents() const
return true; return true;
} }
//! Checks whether windowing uses the Wayland protocol.
bool CIrrDeviceSDL::isUsingWayland() const
{
if (!Window)
return false;
auto *name = SDL_GetCurrentVideoDriver();
return name && !strcmp(name, "wayland");
}
//! returns if window is active. if not, nothing need to be drawn //! returns if window is active. if not, nothing need to be drawn
bool CIrrDeviceSDL::isWindowActive() const bool CIrrDeviceSDL::isWindowActive() const
{ {

View file

@ -96,9 +96,6 @@ public:
//! Checks if the Irrlicht device supports touch events. //! Checks if the Irrlicht device supports touch events.
bool supportsTouchEvents() const override; bool supportsTouchEvents() const override;
//! Checks whether windowing uses the Wayland protocol.
bool isUsingWayland() const override;
//! Get the position of this window on screen //! Get the position of this window on screen
core::position2di getWindowPosition() override; core::position2di getWindowPosition() override;
@ -340,7 +337,6 @@ private:
}; };
core::array<SKeyMap> KeyMap; core::array<SKeyMap> KeyMap;
SDL_SysWMinfo Info;
s32 CurrentTouchCount; s32 CurrentTouchCount;
bool IsInBackground; bool IsInBackground;

View file

@ -1,6 +1,6 @@
# When enabling SDL2 by default on macOS, don't forget to change # When enabling SDL2 by default on macOS, don't forget to change
# "NSHighResolutionCapable" to true in "Info.plist". # "NSHighResolutionCapable" to true in "Info.plist".
if(ANDROID) if(NOT APPLE)
set(DEFAULT_SDL2 ON) set(DEFAULT_SDL2 ON)
endif() endif()
@ -33,6 +33,15 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
elseif(MSVC) elseif(MSVC)
string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " msvcrt.lib") # ???? fuck off string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " msvcrt.lib") # ???? fuck off
add_compile_definitions(
# Suppress some useless warnings
_CRT_SECURE_NO_DEPRECATE
# Get M_PI to work
_USE_MATH_DEFINES
# Don't define min/max macros in minwindef.h
NOMINMAX
)
add_compile_options(/Zl) add_compile_options(/Zl)
# Enable SSE for floating point math on 32-bit x86 by default # Enable SSE for floating point math on 32-bit x86 by default

View file

@ -21,7 +21,7 @@ CMeshSceneNode::CMeshSceneNode(IMesh *mesh, ISceneNode *parent, ISceneManager *m
const core::vector3df &scale) : const core::vector3df &scale) :
IMeshSceneNode(parent, mgr, id, position, rotation, scale), IMeshSceneNode(parent, mgr, id, position, rotation, scale),
Mesh(0), Mesh(0),
PassCount(0), ReadOnlyMaterials(false) PassCount(0), SharedMaterials(false)
{ {
setMesh(mesh); setMesh(mesh);
} }
@ -49,9 +49,9 @@ void CMeshSceneNode::OnRegisterSceneNode()
int solidCount = 0; int solidCount = 0;
// count transparent and solid materials in this scene node // count transparent and solid materials in this scene node
const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size(); const u32 numMaterials = SharedMaterials ? Mesh->getMeshBufferCount() : Materials.size();
for (u32 i = 0; i < numMaterials; ++i) { for (u32 i = 0; i < numMaterials; ++i) {
const video::SMaterial &material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i]; const auto &material = SharedMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
if (driver->needsTransparentRenderPass(material)) if (driver->needsTransparentRenderPass(material))
++transparentCount; ++transparentCount;
@ -93,7 +93,7 @@ void CMeshSceneNode::render()
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) {
scene::IMeshBuffer *mb = Mesh->getMeshBuffer(i); scene::IMeshBuffer *mb = Mesh->getMeshBuffer(i);
if (mb) { if (mb) {
const video::SMaterial &material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; const auto &material = SharedMaterials ? mb->getMaterial() : Materials[i];
const bool transparent = driver->needsTransparentRenderPass(material); const bool transparent = driver->needsTransparentRenderPass(material);
@ -164,14 +164,10 @@ const core::aabbox3d<f32> &CMeshSceneNode::getBoundingBox() const
//! returns the material based on the zero based index i. To get the amount //! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount(). //! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hierarchy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial &CMeshSceneNode::getMaterial(u32 i) video::SMaterial &CMeshSceneNode::getMaterial(u32 i)
{ {
if (Mesh && ReadOnlyMaterials && i < Mesh->getMeshBufferCount()) { if (Mesh && SharedMaterials && i < Mesh->getMeshBufferCount()) {
ReadOnlyMaterial = Mesh->getMeshBuffer(i)->getMaterial(); return Mesh->getMeshBuffer(i)->getMaterial();
return ReadOnlyMaterial;
} }
if (i >= Materials.size()) if (i >= Materials.size())
@ -183,7 +179,7 @@ video::SMaterial &CMeshSceneNode::getMaterial(u32 i)
//! returns amount of materials used by this scene node. //! returns amount of materials used by this scene node.
u32 CMeshSceneNode::getMaterialCount() const u32 CMeshSceneNode::getMaterialCount() const
{ {
if (Mesh && ReadOnlyMaterials) if (Mesh && SharedMaterials)
return Mesh->getMeshBufferCount(); return Mesh->getMeshBufferCount();
return Materials.size(); return Materials.size();
@ -206,9 +202,10 @@ void CMeshSceneNode::copyMaterials()
{ {
Materials.clear(); Materials.clear();
if (Mesh) { if (Mesh && !SharedMaterials) {
video::SMaterial mat; video::SMaterial mat;
Materials.reserve(Mesh->getMeshBufferCount());
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) {
IMeshBuffer *mb = Mesh->getMeshBuffer(i); IMeshBuffer *mb = Mesh->getMeshBuffer(i);
if (mb) if (mb)
@ -222,15 +219,18 @@ void CMeshSceneNode::copyMaterials()
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes /* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */ referencing this mesh to change too. */
void CMeshSceneNode::setReadOnlyMaterials(bool readonly) void CMeshSceneNode::setSharedMaterials(bool shared)
{ {
ReadOnlyMaterials = readonly; if (SharedMaterials != shared) {
SharedMaterials = shared;
copyMaterials();
}
} }
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
bool CMeshSceneNode::isReadOnlyMaterials() const bool CMeshSceneNode::isSharedMaterials() const
{ {
return ReadOnlyMaterials; return SharedMaterials;
} }
//! Creates a clone of this scene node and its children. //! Creates a clone of this scene node and its children.
@ -245,7 +245,7 @@ ISceneNode *CMeshSceneNode::clone(ISceneNode *newParent, ISceneManager *newManag
newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale); newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale);
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
nb->ReadOnlyMaterials = ReadOnlyMaterials; nb->SharedMaterials = SharedMaterials;
nb->Materials = Materials; nb->Materials = Materials;
if (newParent) if (newParent)

View file

@ -52,13 +52,16 @@ public:
//! Returns the current mesh //! Returns the current mesh
IMesh *getMesh(void) override { return Mesh; } IMesh *getMesh(void) override { return Mesh; }
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them directly.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes /** In this way it is possible to change the materials of a mesh
referencing this mesh to change too. */ causing all mesh scene nodes referencing this mesh to change, too.
void setReadOnlyMaterials(bool readonly) override; \param shared Flag if the materials shall be shared. */
void setSharedMaterials(bool shared) override;
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style //! Check if the scene node does not copy the materials of the mesh but uses them directly.
bool isReadOnlyMaterials() const override; /** This flag can be set by setSharedMaterials().
\return Whether the materials are shared. */
bool isSharedMaterials() const override;
//! Creates a clone of this scene node and its children. //! Creates a clone of this scene node and its children.
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override; ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
@ -71,14 +74,13 @@ public:
protected: protected:
void copyMaterials(); void copyMaterials();
core::array<video::SMaterial> Materials; std::vector<video::SMaterial> Materials;
core::aabbox3d<f32> Box{{0, 0, 0}}; core::aabbox3d<f32> Box{{0, 0, 0}};
video::SMaterial ReadOnlyMaterial;
IMesh *Mesh; IMesh *Mesh;
s32 PassCount; s32 PassCount;
bool ReadOnlyMaterials; bool SharedMaterials;
}; };
} // end namespace scene } // end namespace scene

View file

@ -1455,9 +1455,9 @@ void CNullDriver::setMaterialRendererName(u32 idx, const char *name)
void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames)
{ {
if (idx1 < MaterialRenderers.size() && idx2 < MaterialRenderers.size()) { if (idx1 < MaterialRenderers.size() && idx2 < MaterialRenderers.size()) {
irr::core::swap(MaterialRenderers[idx1].Renderer, MaterialRenderers[idx2].Renderer); std::swap(MaterialRenderers[idx1].Renderer, MaterialRenderers[idx2].Renderer);
if (swapNames) if (swapNames)
irr::core::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name); std::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
} }
} }

View file

@ -1526,8 +1526,6 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(SkinnedMesh::SJoint *joint)
os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
} }
// core::vector3df rotation = mat.getRotationDegrees();
AnimatedMesh->addRotationKey(joint, time, core::quaternion(mat.getTransposed())); AnimatedMesh->addRotationKey(joint, time, core::quaternion(mat.getTransposed()));
AnimatedMesh->addPositionKey(joint, time, mat.getTranslation()); AnimatedMesh->addPositionKey(joint, time, mat.getTranslation());

View file

@ -88,7 +88,7 @@ const matrix4 IdentityMatrix(matrix4::EM4CONST_IDENTITY);
namespace video namespace video
{ {
SMaterial IdentityMaterial; const SMaterial IdentityMaterial;
extern "C" IRRLICHT_API bool IRRCALLCONV isDriverSupported(E_DRIVER_TYPE driver) extern "C" IRRLICHT_API bool IRRCALLCONV isDriverSupported(E_DRIVER_TYPE driver)
{ {

View file

@ -149,6 +149,6 @@
<update_contact>celeron55@gmail.com</update_contact> <update_contact>celeron55@gmail.com</update_contact>
<releases> <releases>
<release date="2024-11-10" version="5.10.0"/> <release date="2025-02-14" version="5.11.0"/>
</releases> </releases>
</component> </component>

View file

@ -3,9 +3,9 @@ msgstr ""
"Project-Id-Version: minetest\n" "Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2025-01-27 06:02+0000\n" "PO-Revision-Date: 2025-02-11 02:02+0000\n"
"Last-Translator: 109247019824 " "Last-Translator: 109247019824 <109247019824@users.noreply.hosted.weblate.org>"
"<109247019824@users.noreply.hosted.weblate.org>\n" "\n"
"Language-Team: Bulgarian <https://hosted.weblate.org/projects/minetest/" "Language-Team: Bulgarian <https://hosted.weblate.org/projects/minetest/"
"minetest/bg/>\n" "minetest/bg/>\n"
"Language: bg\n" "Language: bg\n"
@ -264,13 +264,12 @@ msgid "Show technical names"
msgstr "Технически наименования" msgstr "Технически наименования"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Сензорен екран" msgstr "Подредба на сензорния екран"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
msgid "pause_menu" msgid "pause_menu"
msgstr "" msgstr "pause_menu"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -612,6 +611,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Това е списък на клиентите свързани с\n"
"$1"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: German (Minetest)\n" "Project-Id-Version: German (Minetest)\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2025-02-05 11:03+0000\n" "PO-Revision-Date: 2025-02-11 02:02+0000\n"
"Last-Translator: Wuzzy <Wuzzy@disroot.org>\n" "Last-Translator: Wuzzy <Wuzzy@disroot.org>\n"
"Language-Team: German <https://hosted.weblate.org/projects/minetest/minetest/" "Language-Team: German <https://hosted.weblate.org/projects/minetest/minetest/"
"de/>\n" "de/>\n"
@ -263,14 +263,12 @@ msgid "Show technical names"
msgstr "Technische Namen zeigen" msgstr "Technische Namen zeigen"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Touchscreen" msgstr "Touchscreen-Layout"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "pause_menu" msgid "pause_menu"
msgstr "Bildwiederholrate im Pausenmenü" msgstr "pause_menu"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -436,7 +434,7 @@ msgstr "Mods"
#: builtin/mainmenu/content/dlg_contentdb.lua #: builtin/mainmenu/content/dlg_contentdb.lua
#: builtin/mainmenu/content/dlg_package.lua #: builtin/mainmenu/content/dlg_package.lua
msgid "No packages could be retrieved" msgid "No packages could be retrieved"
msgstr "Es konnten keine Pakete abgerufen werden" msgstr "Es konnten keine Pakete empfangen werden"
#: builtin/mainmenu/content/dlg_contentdb.lua #: builtin/mainmenu/content/dlg_contentdb.lua
msgid "No updates" msgid "No updates"
@ -610,6 +608,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Dies ist die Liste der Clients, die zu\n"
"$1 verbunden sind"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"
@ -975,25 +975,24 @@ msgstr ""
"der jede Umbennenung hier überschreiben wird." "der jede Umbennenung hier überschreiben wird."
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
#, fuzzy
msgid "Expand all" msgid "Expand all"
msgstr "Alle aktivieren" msgstr "Alle ausklappen"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "Group by prefix" msgid "Group by prefix"
msgstr "" msgstr "Nach Präfix gruppieren"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses a game called $2 and the following mods:" msgid "The $1 server uses a game called $2 and the following mods:"
msgstr "" msgstr "Der Server $1 nutzt ein Spiel namens $2 und die folgenden Mods:"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses the following mods:" msgid "The $1 server uses the following mods:"
msgstr "" msgstr "Der Server $1 nutzt folgende Mods:"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "A new $1 version is available" msgid "A new $1 version is available"
msgstr "Eine neue $1-Version ist verfügbar" msgstr "Eine neue Version von $1 ist verfügbar"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "" msgid ""
@ -1203,20 +1202,20 @@ msgstr ""
"Sie müssen ein Spiel installieren, bevor Sie eine Welt erstellen können." "Sie müssen ein Spiel installieren, bevor Sie eine Welt erstellen können."
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Add favorite" msgid "Add favorite"
msgstr "Favorit entfernen" msgstr "Favorit hinzufügen"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Address" msgid "Address"
msgstr "Adresse" msgstr "Adresse"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Clients:\n" "Clients:\n"
"$1" "$1"
msgstr "Client" msgstr ""
"Clients:\n"
"$1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Creative mode" msgid "Creative mode"
@ -1232,9 +1231,8 @@ msgid "Favorites"
msgstr "Favoriten" msgstr "Favoriten"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Game: $1" msgid "Game: $1"
msgstr "Spiel" msgstr "Spiel: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Incompatible Servers" msgid "Incompatible Servers"
@ -1249,14 +1247,12 @@ msgid "Login"
msgstr "Einloggen" msgstr "Einloggen"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Number of mods: $1" msgid "Number of mods: $1"
msgstr "Anzahl der Erzeugerthreads" msgstr "Anzahl der Mods: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Open server website" msgid "Open server website"
msgstr "Taktung dedizierter Server" msgstr "Server-Webseite besuchen"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Ping" msgid "Ping"
@ -1269,6 +1265,10 @@ msgid ""
"mod:<name>\n" "mod:<name>\n"
"player:<name>" "player:<name>"
msgstr "" msgstr ""
"Mögliche Filter\n"
"game:<Name>\n"
"mod:<Name>\n"
"player:<Name>"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Public Servers" msgid "Public Servers"
@ -1364,9 +1364,8 @@ msgid "Access denied. Reason: %s"
msgstr "Zugriff verweigert. Grund: %s" msgstr "Zugriff verweigert. Grund: %s"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "All debug info hidden" msgid "All debug info hidden"
msgstr "Debug-Infos angezeigt" msgstr "Alle Debug-Infos verborgen"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Automatic forward disabled" msgid "Automatic forward disabled"
@ -1390,7 +1389,7 @@ msgstr "Blockgrenzen für Blöcke in Nähe angezeigt"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Bounding boxes shown" msgid "Bounding boxes shown"
msgstr "" msgstr "Grenzboxen angezeigt"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Camera update disabled" msgid "Camera update disabled"
@ -1632,9 +1631,8 @@ msgid "Volume changed to %d%%"
msgstr "Lautstärke auf %d%% gesetzt" msgstr "Lautstärke auf %d%% gesetzt"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "Wireframe not supported by video driver" msgid "Wireframe not supported by video driver"
msgstr "Shader sind aktiviert, aber GLSL wird vom Treiber nicht unterstützt." msgstr "Drahtmodell vom Treiber nicht unterstützt"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Wireframe shown" msgid "Wireframe shown"
@ -2067,9 +2065,8 @@ msgid "Failed to compile the \"%s\" shader."
msgstr "Fehler beim Kompilieren des „%s“-Shaders." msgstr "Fehler beim Kompilieren des „%s“-Shaders."
#: src/client/shader.cpp #: src/client/shader.cpp
#, fuzzy
msgid "GLSL is not supported by the driver" msgid "GLSL is not supported by the driver"
msgstr "Shader sind aktiviert, aber GLSL wird vom Treiber nicht unterstützt." msgstr "GLSL wird vom Treiber nicht unterstützt"
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3" #. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2306,35 +2303,32 @@ msgid "Sound Volume: %d%%"
msgstr "Tonlautstärke: %d%%" msgstr "Tonlautstärke: %d%%"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Add button" msgid "Add button"
msgstr "Mittlere Taste" msgstr "Button hinzufügen"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Done" msgid "Done"
msgstr "Fertig!" msgstr "Fertig"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Remove" msgid "Remove"
msgstr "Entfernter Server" msgstr "Entfernen"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Zurücksetzen"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Start dragging a button to add. Tap outside to cancel." msgid "Start dragging a button to add. Tap outside to cancel."
msgstr "" msgstr "Button ziehen zum Hinzufügen. Außerhalb antippen zum Abbrechen."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap a button to select it. Drag a button to move it." msgid "Tap a button to select it. Drag a button to move it."
msgstr "" msgstr "Button antippen zum Auswählen. Button ziehen zum Verschieben."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap outside to deselect." msgid "Tap outside to deselect."
msgstr "" msgstr "Außerhalb antippen zum Abwählen."
#: src/gui/touchscreenlayout.cpp #: src/gui/touchscreenlayout.cpp
msgid "Joystick" msgid "Joystick"
@ -2576,7 +2570,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
msgstr "3-D-Rauschen, welches die Anzahl der Verliese je Mapchunk festlegt." msgstr "3-D-Rauschen, welches die Anzahl der Verliese je Mapchunk festlegt."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"3D support.\n" "3D support.\n"
"Currently supported:\n" "Currently supported:\n"
@ -2595,9 +2588,7 @@ msgstr ""
"zeilenbasierte Polarisation.\n" "zeilenbasierte Polarisation.\n"
"- topbottom: Bildschirm horizontal teilen.\n" "- topbottom: Bildschirm horizontal teilen.\n"
"- sidebyside: Bildschirm vertikal teilen.\n" "- sidebyside: Bildschirm vertikal teilen.\n"
"- crossview: Schieläugiges 3-D\n" "- crossview: Schieläugiges 3-D"
"Beachten Sie, dass der „interlaced“-Modus erfordert, dass Shader aktiviert "
"sind."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -2692,11 +2683,13 @@ msgid ""
"All mesh buffers with less than this number of vertices will be merged\n" "All mesh buffers with less than this number of vertices will be merged\n"
"during map rendering. This improves rendering performance." "during map rendering. This improves rendering performance."
msgstr "" msgstr ""
"Alle Mesh-Puffer, die weniger als diese Anzahl Punkte haben, werden während\n"
"des Renderns der Karte zusammengeführt. Dies verbessert die Performanz\n"
"des Renderns."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Allow clouds to look 3D instead of flat." msgid "Allow clouds to look 3D instead of flat."
msgstr "Wolken blockförmig statt flach aussehen lassen." msgstr "Erlaubt, dass Wolken ein 3-D-Aussehen statt ein flaches Aussehen haben."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Allows liquids to be translucent." msgid "Allows liquids to be translucent."
@ -3107,7 +3100,7 @@ msgstr "Wolken im Menü"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Color depth for post-processing texture" msgid "Color depth for post-processing texture"
msgstr "" msgstr "Farbtiefe für Nachbearbeitungstextur"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Colored fog" msgid "Colored fog"
@ -3127,7 +3120,6 @@ msgstr ""
"für Details." "für Details."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Comma-separated list of flags to hide in the content repository.\n" "Comma-separated list of flags to hide in the content repository.\n"
"\"nonfree\" can be used to hide packages which do not qualify as 'free " "\"nonfree\" can be used to hide packages which do not qualify as 'free "
@ -3145,7 +3137,7 @@ msgstr ""
"Sie können auch Inhaltseinstufungen festlegen.\n" "Sie können auch Inhaltseinstufungen festlegen.\n"
"Diese Flags sind von Luanti-Versionen unabhängig,\n" "Diese Flags sind von Luanti-Versionen unabhängig,\n"
"für eine vollständige Liste gehen Sie auf:\n" "für eine vollständige Liste gehen Sie auf:\n"
"https://content.minetest.net/help/content_flags/" "https://content.luanti.org/help/content_flags/"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -3316,6 +3308,11 @@ msgid ""
"Reducing this can improve performance, but some effects (e.g. debanding)\n" "Reducing this can improve performance, but some effects (e.g. debanding)\n"
"require more than 8 bits to work." "require more than 8 bits to work."
msgstr "" msgstr ""
"Die Farbtiefe der Textur, die für die Nachbearbeitungs-Pipeline benutzt "
"wird, festlegen.\n"
"Wird der Wert verringert, kann dies die Performanz verbessern, aber einige "
"Effekte (z.B. Debanding)\n"
"brauchen mehr als 8 Bit, um zu funktionieren."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dedicated server step" msgid "Dedicated server step"
@ -3544,6 +3541,10 @@ msgid ""
"situations\n" "situations\n"
"where transparency sorting would be very slow otherwise." "where transparency sorting would be very slow otherwise."
msgstr "" msgstr ""
"Transparenzsortierte Dreiecke nach ihren Meshpuffern gruppiert zeichnen.\n"
"Dies macht die Transparenzsortierung zwischen Meshpuffern kaputt, aber "
"vermeidet\n"
"Situationen, wo die Transparenzsortierung sonst sehr langsam wäre."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dump the mapgen debug information." msgid "Dump the mapgen debug information."
@ -3628,14 +3629,12 @@ msgstr ""
"Verhalten des menschlichen Auges simuliert." "Verhalten des menschlichen Auges simuliert."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable colored shadows for transculent nodes.\n" "Enable colored shadows for transculent nodes.\n"
"This is expensive." "This is expensive."
msgstr "" msgstr ""
"Aktiviert gefärbte Schatten. \n" "Aktiviert gefärbte Schatten für transluzente Blöcke.\n"
"Falls aktiv, werden transluzente Blöcke gefärbte Schatten werfen. Dies ist " "Dies ist rechenintensiv."
"rechenintensiv."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable console window" msgid "Enable console window"
@ -3721,14 +3720,12 @@ msgstr ""
"1.0 für den Standardwert, 2.0 für doppelte Geschwindigkeit." "1.0 für den Standardwert, 2.0 für doppelte Geschwindigkeit."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable/disable running an IPv6 server.\n" "Enable/disable running an IPv6 server.\n"
"Ignored if bind_address is set." "Ignored if bind_address is set."
msgstr "" msgstr ""
"Server als IPv6 laufen lassen (oder nicht).\n" "Server als IPv6 laufen lassen (oder nicht).\n"
"Wird ignoriert, falls bind_address gesetzt ist.\n" "Wird ignoriert, falls bind_address gesetzt ist."
"Dafür muss außerdem enable_ipv6 aktiviert sein."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -4399,15 +4396,15 @@ msgstr ""
"ihr Passwort zu ein leeres Passwort ändern." "ihr Passwort zu ein leeres Passwort ändern."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"If enabled, server account registration is separate from login in the UI.\n" "If enabled, server account registration is separate from login in the UI.\n"
"If disabled, connecting to a server will automatically register a new " "If disabled, connecting to a server will automatically register a new "
"account." "account."
msgstr "" msgstr ""
"Falls aktiviert, wird die Kontoregistrierung vom Einloggen in der " "Falls aktiviert, wird die Serverkontoregistrierung in der Benutzeroberfläche "
"Benutzeroberfläche getrennt behandelt.\n" "getrennt vom Einloggen behandelt.\n"
"Falls deaktiviert, werden neue Konten beim Einloggen automatisch registriert." "Falls deaktiviert, werden neue Konten beim Verbindungsaufbau zu einem Server "
"automatisch registriert."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5313,7 +5310,7 @@ msgstr "Untergrenze der zufälligen Anzahl kleiner Höhlen je Mapchunk."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Minimum vertex count for mesh buffers" msgid "Minimum vertex count for mesh buffers"
msgstr "" msgstr "Minimale Punktanzahl für Meshpuffer"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Mipmapping" msgid "Mipmapping"
@ -5409,16 +5406,15 @@ msgstr ""
"- Die optionalen Schwebeländer von v7 (standardmäßig deaktiviert)." "- Die optionalen Schwebeländer von v7 (standardmäßig deaktiviert)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Name of the player.\n" "Name of the player.\n"
"When running a server, a client connecting with this name is admin.\n" "When running a server, a client connecting with this name is admin.\n"
"When starting from the main menu, this is overridden." "When starting from the main menu, this is overridden."
msgstr "" msgstr ""
"Name des Spielers.\n" "Name des Spielers.\n"
"Wenn ein Server gestartet wird, werden Clients mit diesem Namen zu " "Wenn ein Server gestartet wird, wird ein Client mit diesem Namen zum "
"Administratoren.\n" "Administrator.\n"
"Wird vom Hauptmenü aus gestartet, wird diese Einstellung überschrieben." "Wenn vom Hauptmenü aus gestartet, wird diese Einstellung überschrieben."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5938,7 +5934,6 @@ msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
msgstr "Siehe https://www.sqlite.org/pragma.html#pragma_synchronous" msgstr "Siehe https://www.sqlite.org/pragma.html#pragma_synchronous"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Select the antialiasing method to apply.\n" "Select the antialiasing method to apply.\n"
"\n" "\n"
@ -5965,20 +5960,22 @@ msgstr ""
"\n" "\n"
"* None Keine Kantenglättung (Standard)\n" "* None Keine Kantenglättung (Standard)\n"
"\n" "\n"
"* FSAA Von der Hardware bereitgestellte Vollbildkantenglättung (nicht\n" "* FSAA Von der Hardware bereitgestellte Vollbildkantenglättung\n"
"kompatibel mit Nachbearbeitung und Unterabtastung), auch bekannt\n" "Auch bekannt als „Multi-Sample Antialiasing“ (MSAA)\n"
"als Multi-Sample Antialiasing (MSAA). Glättet Blockkanten aus, " "Glättet Blockkanten, aber hat keine Auswirkung auf das Innere von Texturen.\n"
"beeinträchtigt\n"
"aber nicht die Innenseiten der Texturen.\n"
"Um diese Option zu ändern, ist ein Neustart erforderlich.\n"
"\n" "\n"
"* FXAA Schnelle annähende Kantenglättung (benötigt Shader).\n" "Wenn die Nachbearbeitung deaktiviert ist, benötigt das Ändern von FSAA\n"
"einen Neustart. Außerdem wird, wenn die Nachbearbeitung deaktiviert ist,\n"
"FSAA nicht zusammen mit einer Unterabtastung oder einer\n"
"Nicht-Standard-„3d_mode“-Einstellung funktionieren.\n"
"\n"
"* FXAA Schnelle annähende Kantenglättung\n"
"Wendet einen Nachbearbeitungsfilter an, um kontrastreiche Kanten zu " "Wendet einen Nachbearbeitungsfilter an, um kontrastreiche Kanten zu "
"erkennen\n" "erkennen\n"
"und zu glätten. Bietet eine Balance zwischen Geschwindigkeit und " "und zu glätten. Bietet eine Balance zwischen Geschwindigkeit und "
"Bildqualität.\n" "Bildqualität.\n"
"\n" "\n"
"* SSAA Super-Sampling-Kantenglättung (benötigt Shader).\n" "* SSAA Super-Sampling-Kantenglättung\n"
"Rendert ein hochauflösendes Bild der Szene, dann skaliert es herunter, um\n" "Rendert ein hochauflösendes Bild der Szene, dann skaliert es herunter, um\n"
"die Aliasing-Effekte zu reduzieren. Dies ist die langsamste und genaueste " "die Aliasing-Effekte zu reduzieren. Dies ist die langsamste und genaueste "
"Methode." "Methode."
@ -6419,7 +6416,6 @@ msgstr ""
"(oder alle) Gegenstände setzen kann." "(oder alle) Gegenstände setzen kann."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Spread a complete update of the shadow map over a given number of frames.\n" "Spread a complete update of the shadow map over a given number of frames.\n"
"Higher values might make shadows laggy, lower values\n" "Higher values might make shadows laggy, lower values\n"
@ -6427,8 +6423,7 @@ msgid ""
msgstr "" msgstr ""
"Eine vollständige Aktualisierung der Schattenkarte über die angegebene\n" "Eine vollständige Aktualisierung der Schattenkarte über die angegebene\n"
"Anzahl Frames verteilen. Höhere Werte können dazu führen, dass\n" "Anzahl Frames verteilen. Höhere Werte können dazu führen, dass\n"
"Schatten langsamer reagieren, niedrigere Werte sind rechenintensiver.\n" "Schatten langsamer reagieren, niedrigere Werte sind rechenintensiver."
"Minimalwert: 1; Maximalwert: 16"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6876,9 +6871,8 @@ msgid "Transparency Sorting Distance"
msgstr "Transparenzsortierungsdistanz" msgstr "Transparenzsortierungsdistanz"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Transparency Sorting Group by Buffers" msgid "Transparency Sorting Group by Buffers"
msgstr "Transparenzsortierungsdistanz" msgstr "Transparenzsortierung nach Puffer gruppieren"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Trees noise" msgid "Trees noise"
@ -6942,7 +6936,6 @@ msgid "Undersampling"
msgstr "Unterabtastung" msgstr "Unterabtastung"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Undersampling is similar to using a lower screen resolution, but it applies\n" "Undersampling is similar to using a lower screen resolution, but it applies\n"
"to the game world only, keeping the GUI intact.\n" "to the game world only, keeping the GUI intact.\n"
@ -6954,11 +6947,14 @@ msgid ""
"to a non-default value." "to a non-default value."
msgstr "" msgstr ""
"Unterabtastung ist ähnlich der Verwendung einer niedrigeren " "Unterabtastung ist ähnlich der Verwendung einer niedrigeren "
"Bildschirmauflösung, aber sie wird nur auf die Spielwelt angewandt, während " "Bildschirmauflösung,\n"
"die GUI intakt bleibt.\n" "aber sie wird nur auf die Spielwelt angewandt, während die GUI intakt bleibt."
"\n"
"Dies sollte einen beträchtlichen Performanzschub auf Kosten einer weniger " "Dies sollte einen beträchtlichen Performanzschub auf Kosten einer weniger "
"detaillierten Grafik geben.\n" "detaillierten Grafik geben.\n"
"Hohe Werte führen zu einer weniger detaillierten Grafik." "Hohe Werte führen zu einer weniger detaillierten Grafik.\n"
"Anmerkung: Unterabtastung wird im Moment nicht unterstützt, falls die\n"
"„3d_mode“-Einstellung auf einen Nicht-Standardwert gesetzt ist."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Unlimited player transfer distance" msgid "Unlimited player transfer distance"
@ -6985,13 +6981,14 @@ msgid "Use a cloud animation for the main menu background."
msgstr "Eine Wolkenanimation für den Hintergrund im Hauptmenü benutzen." msgstr "Eine Wolkenanimation für den Hintergrund im Hauptmenü benutzen."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Use anisotropic filtering when looking at textures from an angle.\n" "Use anisotropic filtering when looking at textures from an angle.\n"
"This provides a significant improvement when used together with mipmapping." "This provides a significant improvement when used together with mipmapping."
msgstr "" msgstr ""
"Anisotrope Filterung verwenden, wenn auf Texturen aus einem gewissen Winkel " "Anisotrope Filterung verwenden, wenn auf Texturen aus einem gewissen Winkel "
"heraus geschaut wird." "heraus geschaut wird.\n"
"Dies bietet eine signifikante Verbesserung, wenn es gemeinsam mit Mipmapping "
"verwendet wird."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Use bilinear filtering when scaling textures." msgid "Use bilinear filtering when scaling textures."
@ -7268,7 +7265,6 @@ msgstr ""
"die Inventarbilder von Blöcken)." "die Inventarbilder von Blöcken)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"When using bilinear/trilinear filtering, low-resolution textures\n" "When using bilinear/trilinear filtering, low-resolution textures\n"
"can be blurred, so this option automatically upscales them to preserve\n" "can be blurred, so this option automatically upscales them to preserve\n"
@ -7279,14 +7275,14 @@ msgid ""
"This is also used as the base node texture size for world-aligned\n" "This is also used as the base node texture size for world-aligned\n"
"texture autoscaling." "texture autoscaling."
msgstr "" msgstr ""
"Wenn bilineare, trilineare oder anisotrope Filter benutzt werden, können\n" "Wenn bilineare/trilineare Filter benutzt werden, können\n"
"niedrigauflösende Texturen verschwommen sein, also werden sie automatisch\n" "niedrigauflösende Texturen verschwommen sein, also werden sie automatisch\n"
"mit Pixelwiederholung vergrößert, um scharfe Pixel zu behalten. Dies setzt " "mit Pixelwiederholung vergrößert, um scharfe Pixel zu behalten. Dies setzt "
"die\n" "die\n"
"minimale Texturengröße für die vergrößerten Texturen; höhere Werte führen\n" "minimale Texturengröße für die vergrößerten Texturen; höhere Werte führen\n"
"zu einem schärferen Aussehen, aber erfordern mehr Speicher. Zweierpotenzen\n" "zu einem schärferen Aussehen, aber erfordern mehr Speicher.\n"
"werden empfohlen. Diese Einstellung trifft NUR dann in Kraft, falls\n" "Diese Einstellung trifft NUR dann in Kraft, falls\n"
"der bilineare/trilineare/anisotrope Filter aktiviert ist.\n" "einer der genannten Filter aktiviert ist.\n"
"Dies wird außerdem verwendet als die Basisblocktexturengröße für\n" "Dies wird außerdem verwendet als die Basisblocktexturengröße für\n"
"welt-ausgerichtete automatische Texturenskalierung." "welt-ausgerichtete automatische Texturenskalierung."
@ -7326,17 +7322,15 @@ msgid "Whether to fog out the end of the visible area."
msgstr "Ob das Ende des sichtbaren Gebietes im Nebel verschwinden soll." msgstr "Ob das Ende des sichtbaren Gebietes im Nebel verschwinden soll."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Whether to mute sounds. You can unmute sounds at any time.\n" "Whether to mute sounds. You can unmute sounds at any time.\n"
"In-game, you can toggle the mute state with the mute key or by using the\n" "In-game, you can toggle the mute state with the mute key or by using the\n"
"pause menu." "pause menu."
msgstr "" msgstr ""
"Ob die Töne stummgeschaltet werden. Man kann die Töne jederzeit " "Ob die Töne stummgeschaltet werden. Man kann die Töne jederzeit "
"stummschalten,\n" "stummschalten.\n"
"außer, wenn das Tonsystem ausgeschaltet wurde (enable_sound=false).\n"
"Im Spiel können die Töne mit der Stummtaste oder mit Hilfe des\n" "Im Spiel können die Töne mit der Stummtaste oder mit Hilfe des\n"
"Pausemenüs stummgeschaltet werden." "Pausenmenüs stummgeschaltet werden."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: Spanish (Minetest)\n" "Project-Id-Version: Spanish (Minetest)\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2025-01-23 21:01+0000\n" "PO-Revision-Date: 2025-02-14 12:19+0000\n"
"Last-Translator: Miguel <mp0187595@tutamail.com>\n" "Last-Translator: Miguel <mp0187595@tutamail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/minetest/" "Language-Team: Spanish <https://hosted.weblate.org/projects/minetest/"
"minetest/es/>\n" "minetest/es/>\n"
@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10-dev\n" "X-Generator: Weblate 5.10\n"
#: builtin/client/chatcommands.lua #: builtin/client/chatcommands.lua
msgid "Clear the out chat queue" msgid "Clear the out chat queue"
@ -263,14 +263,12 @@ msgid "Show technical names"
msgstr "Mostrar los nombres técnicos" msgstr "Mostrar los nombres técnicos"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Pantalla táctil" msgstr "Diseño de pantalla táctil"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "pause_menu" msgid "pause_menu"
msgstr "FPS (cuadros/s) en el menú de pausa" msgstr "pause_menu"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -610,6 +608,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Esta es la lista de clientes conectados a\n"
"$1"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"
@ -974,21 +974,20 @@ msgstr ""
"cual sobreescribirá cualquier renombrado desde aquí." "cual sobreescribirá cualquier renombrado desde aquí."
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
#, fuzzy
msgid "Expand all" msgid "Expand all"
msgstr "Activar todos" msgstr "Expandir todo"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "Group by prefix" msgid "Group by prefix"
msgstr "" msgstr "Grupo por prefijo"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses a game called $2 and the following mods:" msgid "The $1 server uses a game called $2 and the following mods:"
msgstr "" msgstr "El servidor $1 utiliza un juego llamado $2 y los siguientes mods:"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses the following mods:" msgid "The $1 server uses the following mods:"
msgstr "" msgstr "El servidor $1 usa los siguientes mods:"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "A new $1 version is available" msgid "A new $1 version is available"
@ -1201,20 +1200,20 @@ msgid "You need to install a game before you can create a world."
msgstr "Necesitas instalar un juego antes de poder crear un mundo." msgstr "Necesitas instalar un juego antes de poder crear un mundo."
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Add favorite" msgid "Add favorite"
msgstr "Eliminar el favorito" msgstr "Añadir a favorito"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Address" msgid "Address"
msgstr "Dirección" msgstr "Dirección"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Clients:\n" "Clients:\n"
"$1" "$1"
msgstr "Cliente" msgstr ""
"Clientes:\n"
"$1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Creative mode" msgid "Creative mode"
@ -1230,9 +1229,8 @@ msgid "Favorites"
msgstr "Favoritos" msgstr "Favoritos"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Game: $1" msgid "Game: $1"
msgstr "Juego" msgstr "Juego: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Incompatible Servers" msgid "Incompatible Servers"
@ -1247,26 +1245,29 @@ msgid "Login"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Number of mods: $1" msgid "Number of mods: $1"
msgstr "Número de hilos emergentes" msgstr "Número de mods: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Open server website" msgid "Open server website"
msgstr "Intervalo de servidor dedicado" msgstr "Abrir sitio web del servidor"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Ping" msgid "Ping"
msgstr "Ping" msgstr "Ping"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Possible filters\n" "Possible filters\n"
"game:<name>\n" "game:<name>\n"
"mod:<name>\n" "mod:<name>\n"
"player:<name>" "player:<name>"
msgstr "" msgstr ""
"Posibles filtros\n"
"game:<nombre>\n"
"mod:<nombre>\n"
"player:<nombre>"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Public Servers" msgid "Public Servers"
@ -1274,7 +1275,7 @@ msgstr "Servidores Públicos"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Refresh" msgid "Refresh"
msgstr "Actualizar" msgstr "Refrescar"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Remove favorite" msgid "Remove favorite"
@ -1364,9 +1365,8 @@ msgid "Access denied. Reason: %s"
msgstr "Acceso denegado. Razón: %s" msgstr "Acceso denegado. Razón: %s"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "All debug info hidden" msgid "All debug info hidden"
msgstr "Info de depuración mostrada" msgstr "Toda la información de depuración oculta"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Automatic forward disabled" msgid "Automatic forward disabled"
@ -1390,7 +1390,7 @@ msgstr "Límites de bloque mostrados para bloques cercanos"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Bounding boxes shown" msgid "Bounding boxes shown"
msgstr "" msgstr "Cajas delimitadoras mostradas"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Camera update disabled" msgid "Camera update disabled"
@ -1633,9 +1633,8 @@ msgid "Volume changed to %d%%"
msgstr "Volumen cambiado a %d%%" msgstr "Volumen cambiado a %d%%"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "Wireframe not supported by video driver" msgid "Wireframe not supported by video driver"
msgstr "Los shaders están activados pero el driver no soporta GLSL." msgstr "El controlador de vídeo no admite la estructura alámbrica"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Wireframe shown" msgid "Wireframe shown"
@ -2068,9 +2067,8 @@ msgid "Failed to compile the \"%s\" shader."
msgstr "Fallo al compilar el shader \"%s\"." msgstr "Fallo al compilar el shader \"%s\"."
#: src/client/shader.cpp #: src/client/shader.cpp
#, fuzzy
msgid "GLSL is not supported by the driver" msgid "GLSL is not supported by the driver"
msgstr "Los shaders están activados pero el driver no soporta GLSL." msgstr "El controlador no admite GLSL"
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3" #. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2235,11 +2233,11 @@ msgstr "Alternar el registro del chat"
#: src/gui/guiKeyChangeMenu.cpp src/gui/touchscreenlayout.cpp #: src/gui/guiKeyChangeMenu.cpp src/gui/touchscreenlayout.cpp
msgid "Toggle fast" msgid "Toggle fast"
msgstr "Activar rápido" msgstr "Alternar rápido"
#: src/gui/guiKeyChangeMenu.cpp src/gui/touchscreenlayout.cpp #: src/gui/guiKeyChangeMenu.cpp src/gui/touchscreenlayout.cpp
msgid "Toggle fly" msgid "Toggle fly"
msgstr "Activar volar" msgstr "Alternar volar"
#: src/gui/guiKeyChangeMenu.cpp #: src/gui/guiKeyChangeMenu.cpp
msgid "Toggle fog" msgid "Toggle fog"
@ -2307,35 +2305,33 @@ msgid "Sound Volume: %d%%"
msgstr "Volumen del sonido: %d%%" msgstr "Volumen del sonido: %d%%"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Add button" msgid "Add button"
msgstr "Botón central" msgstr "Agregar botón"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Done" msgid "Done"
msgstr "¡Completado!" msgstr "Hecho"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Remove" msgid "Remove"
msgstr "Servidor remoto" msgstr "Eliminar"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Reiniciar"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Start dragging a button to add. Tap outside to cancel." msgid "Start dragging a button to add. Tap outside to cancel."
msgstr "" msgstr ""
"Comienza arrastrando un botón para agregarlo. Toca afuera para cancelar."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap a button to select it. Drag a button to move it." msgid "Tap a button to select it. Drag a button to move it."
msgstr "" msgstr "Toca un botón para seleccionarlo. Arrastra un botón para moverlo."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap outside to deselect." msgid "Tap outside to deselect."
msgstr "" msgstr "Toca afuera para anular la selección."
#: src/gui/touchscreenlayout.cpp #: src/gui/touchscreenlayout.cpp
msgid "Joystick" msgid "Joystick"
@ -2575,7 +2571,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
msgstr "Ruido 3D que determina la cantidad de mazmorras por chunk." msgstr "Ruido 3D que determina la cantidad de mazmorras por chunk."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"3D support.\n" "3D support.\n"
"Currently supported:\n" "Currently supported:\n"
@ -2588,14 +2583,13 @@ msgid ""
msgstr "" msgstr ""
"Soporte 3D.\n" "Soporte 3D.\n"
"Soportado actualmente:\n" "Soportado actualmente:\n"
"- Ninguno (none): sin salida 3D.\n" "- Ninguno: sin salida 3D.\n"
"- Anaglifo (anaglyph): 3D en colores cían y magenta.\n" "- Anaglifo: 3D en colores cían y magenta.\n"
"- Entrelazado (interlaced): soporte para pantallas con polarización " "- Entrelazado: soporte para pantallas con polarización basada en filas "
"basada en filas impar/par.\n" "impar/par.\n"
"- Arriba-abajo (topbottom): dividir pantalla arriba y abajo.\n" "- Arriba-abajo: dividir pantalla arriba y abajo.\n"
"- Lado a lado (sidebyside): dividir pantalla lado a lado.\n" "- Lado a lado: dividir pantalla lado a lado.\n"
"- Vista cruzada (crossview): visión 3D cruzada.\n" "- Vista cruzada: visión 3D cruzada"
"Nota: el modo entrelazado requiere que los sombreadores estén activados."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -2687,11 +2681,14 @@ msgid ""
"All mesh buffers with less than this number of vertices will be merged\n" "All mesh buffers with less than this number of vertices will be merged\n"
"during map rendering. This improves rendering performance." "during map rendering. This improves rendering performance."
msgstr "" msgstr ""
"Se fusionarán todos los buffers de malla con menos de este número de "
"vértices\n"
"Durante la representación del mapa. Esto mejora el rendimiento de "
"renderizado."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Allow clouds to look 3D instead of flat." msgid "Allow clouds to look 3D instead of flat."
msgstr "Usar nubes 3D en lugar de planas." msgstr "Permitir que las nubes se vean en 3D en lugar de planas."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Allows liquids to be translucent." msgid "Allows liquids to be translucent."
@ -3105,7 +3102,7 @@ msgstr "Nubes en el menú"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Color depth for post-processing texture" msgid "Color depth for post-processing texture"
msgstr "" msgstr "Profundidad de color para la textura post-procesamiento"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Colored fog" msgid "Colored fog"
@ -3125,7 +3122,6 @@ msgstr ""
"Útil para pruebas. Ver al_extensions.[h,cpp] para más detalles." "Útil para pruebas. Ver al_extensions.[h,cpp] para más detalles."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Comma-separated list of flags to hide in the content repository.\n" "Comma-separated list of flags to hide in the content repository.\n"
"\"nonfree\" can be used to hide packages which do not qualify as 'free " "\"nonfree\" can be used to hide packages which do not qualify as 'free "
@ -3142,7 +3138,7 @@ msgstr ""
"según lo definido por la Free Software Foundation.\n" "según lo definido por la Free Software Foundation.\n"
"También puedes especificar clasificaciones de contenido.\n" "También puedes especificar clasificaciones de contenido.\n"
"Estas banderas son independientes de las versiones de Luanti,\n" "Estas banderas son independientes de las versiones de Luanti,\n"
"así que consulta una lista completa en https://content.minetest.net/help/" "así que consulta una lista completa en https://content.luanti.org/help/"
"content_flags/" "content_flags/"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -3313,6 +3309,11 @@ msgid ""
"Reducing this can improve performance, but some effects (e.g. debanding)\n" "Reducing this can improve performance, but some effects (e.g. debanding)\n"
"require more than 8 bits to work." "require more than 8 bits to work."
msgstr "" msgstr ""
"Decide la profundidad de color de la textura utilizada para la canalización "
"post-procesamiento.\n"
"Reducir esto puede mejorar el rendimiento, pero algunos efectos (por "
"ejemplo, tramado)\n"
"requieren más de 8 bits para trabajar."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dedicated server step" msgid "Dedicated server step"
@ -3537,6 +3538,11 @@ msgid ""
"situations\n" "situations\n"
"where transparency sorting would be very slow otherwise." "where transparency sorting would be very slow otherwise."
msgstr "" msgstr ""
"Dibuja los triángulos clasificados por transparencia agrupados por sus "
"buffers de malla.\n"
"Esto rompe la clasificación de transparencia entre los buffers de malla, "
"pero evita situaciones\n"
"donde la clasificación de transparencia sería muy lenta de lo contrario."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dump the mapgen debug information." msgid "Dump the mapgen debug information."
@ -3621,14 +3627,12 @@ msgstr ""
"el comportamiento del ojo humano." "el comportamiento del ojo humano."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable colored shadows for transculent nodes.\n" "Enable colored shadows for transculent nodes.\n"
"This is expensive." "This is expensive."
msgstr "" msgstr ""
"Habilitar las sombras coloreadas.\n" "Habilita las sombras de colores para nodos translúcidos.\n"
"Si el valor es verdadero los nodos traslúcidos proyectarán sombras " "Esto es costoso."
"coloreadas. Esta opción usa muchos recursos."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable console window" msgid "Enable console window"
@ -3712,14 +3716,12 @@ msgstr ""
"Por ejemplo: 0 para balanceo sin vista; 1.0 para normal; 2.0 para doble." "Por ejemplo: 0 para balanceo sin vista; 1.0 para normal; 2.0 para doble."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable/disable running an IPv6 server.\n" "Enable/disable running an IPv6 server.\n"
"Ignored if bind_address is set." "Ignored if bind_address is set."
msgstr "" msgstr ""
"Habilita/deshabilita la ejecución de un servidor IPv6.\n" "Activa/desactiva la ejecución de un servidor IPv6.\n"
"Ignorado si se establece bind_address.\n" "Se ignora si bind_address está establecido."
"Necesita habilitar enable_ipv6 para ser activado."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -3749,7 +3751,7 @@ msgstr "Activar el desplazamiento suave."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enables the post processing pipeline." msgid "Enables the post processing pipeline."
msgstr "Habilita la canalización para el posprocesamiento." msgstr "Habilita la canalización posterior al procesamiento."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -4384,7 +4386,6 @@ msgstr ""
"la suya por una contraseña vacía." "la suya por una contraseña vacía."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"If enabled, server account registration is separate from login in the UI.\n" "If enabled, server account registration is separate from login in the UI.\n"
"If disabled, connecting to a server will automatically register a new " "If disabled, connecting to a server will automatically register a new "
@ -4392,8 +4393,8 @@ msgid ""
msgstr "" msgstr ""
"Si está activado, el registro de la cuenta es independiente del inicio de " "Si está activado, el registro de la cuenta es independiente del inicio de "
"sesión en la interfaz de usuario.\n" "sesión en la interfaz de usuario.\n"
"Si está deshabilitado, las cuentas nuevas se registrarán automáticamente al " "Si está desactivado, la conexión a un servidor registrará automáticamente "
"iniciar sesión." "una nueva cuenta."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5298,7 +5299,7 @@ msgstr ""
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Minimum vertex count for mesh buffers" msgid "Minimum vertex count for mesh buffers"
msgstr "" msgstr "Recuento mínimo de vértices para buffers de malla"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Mipmapping" msgid "Mipmapping"
@ -5393,15 +5394,14 @@ msgstr ""
"- Las islas flotantes opcionales de v7 (desactivadas por defecto)." "- Las islas flotantes opcionales de v7 (desactivadas por defecto)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Name of the player.\n" "Name of the player.\n"
"When running a server, a client connecting with this name is admin.\n" "When running a server, a client connecting with this name is admin.\n"
"When starting from the main menu, this is overridden." "When starting from the main menu, this is overridden."
msgstr "" msgstr ""
"Nombre del jugador.\n" "Nombre del jugador.\n"
"Cuando se ejecuta un servidor, los clientes que se conecten con este nombre " "Al ejecutar un servidor, el cliente que se conecta con este nombre es "
"son administradores.\n" "administrador.\n"
"Al comenzar desde el menú principal, esto se anula." "Al comenzar desde el menú principal, esto se anula."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -5927,7 +5927,6 @@ msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
msgstr "Ver https://www.sqlite.org/pragma.html#pragma_synchronous" msgstr "Ver https://www.sqlite.org/pragma.html#pragma_synchronous"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Select the antialiasing method to apply.\n" "Select the antialiasing method to apply.\n"
"\n" "\n"
@ -5950,26 +5949,28 @@ msgid ""
"Renders higher-resolution image of the scene, then scales down to reduce\n" "Renders higher-resolution image of the scene, then scales down to reduce\n"
"the aliasing effects. This is the slowest and the most accurate method." "the aliasing effects. This is the slowest and the most accurate method."
msgstr "" msgstr ""
"Seleccione el método de antialiasing a aplicar.\n" "Seleccione el método de suavizado a aplicar.\n"
"\n" "\n"
"* Ninguno - Sin antialiasing (por defecto)\n" "* Ninguno - Sin suavizado (por defecto)\n"
"\n" "\n"
"* FSAA - Antialiasing de pantalla completa por hardware\n" "* FSAA - Suavizado de pantalla completa por hardware\n"
"(incompatible con Postprocesado y Submuestreo)\n" "También conocido como suavizado multimuestra (MSAA)\n"
"También conocido como antialiasing multimuestra (MSAA)\n" "Suaviza los bordes de los bloques pero no afecta al interior de las texturas."
"Suaviza los bordes de los bloques pero no afecta al interior de las "
"texturas.\n"
"Es necesario reiniciar para cambiar esta opción.\n"
"\n" "\n"
"* FXAA - Antialiasing rápido aproximado (requiere shaders)\n" "\n"
"Aplica un filtro de postprocesado para detectar y suavizar los bordes de " "Si el posprocesamiento está desactivado, cambiar FSAA requiere reiniciar.\n"
"Además, si se desactiva el posprocesamiento, FSAA no funcionará con\n"
"submuestreo o una configuración no predeterminada de \"3d_mode\".\n"
"\n"
"* FXAA - Suavizado aproximado rápido\n"
"Aplica un filtro de pos-procesamiento para detectar y suavizar los bordes de "
"alto contraste.\n" "alto contraste.\n"
"Proporciona un equilibrio entre velocidad y calidad de imagen.\n" "Proporciona un equilibrio entre velocidad y calidad de imagen.\n"
"\n" "\n"
"* SSAA - Antialiasing de supermuestreo (requiere shaders)\n" "* SSAA - Suavizado de supermuestreo\n"
"Renderiza una imagen de mayor resolución de la escena y, a continuación, " "Renderiza una imagen de mayor resolución de la escena y, a continuación, "
"reduce la escala para reducir los efectos de aliasing.\n" "reduce la escala para reducir\n"
"los efectos del aliasing. Es el método más lento y preciso." "los efectos de distorsión. Es el método más lento y preciso."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Selection box border color (R,G,B)." msgid "Selection box border color (R,G,B)."
@ -6410,7 +6411,6 @@ msgstr ""
"pila para ciertos ítems (o para todos)." "pila para ciertos ítems (o para todos)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Spread a complete update of the shadow map over a given number of frames.\n" "Spread a complete update of the shadow map over a given number of frames.\n"
"Higher values might make shadows laggy, lower values\n" "Higher values might make shadows laggy, lower values\n"
@ -6420,8 +6420,7 @@ msgstr ""
"determinado de fotogramas.\n" "determinado de fotogramas.\n"
"Los valores más altos pueden hacer que las sombras se retrasen, los valores " "Los valores más altos pueden hacer que las sombras se retrasen, los valores "
"más bajos\n" "más bajos\n"
"consumirán más recursos.\n" "consumirán más recursos."
"Valor mínimo: 1; valor máximo: 16"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6872,9 +6871,8 @@ msgid "Transparency Sorting Distance"
msgstr "Distancia de Clasificación de Transparencia" msgstr "Distancia de Clasificación de Transparencia"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Transparency Sorting Group by Buffers" msgid "Transparency Sorting Group by Buffers"
msgstr "Distancia de Clasificación de Transparencia" msgstr "Grupo de Clasificación de Transparencia por búferes"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Trees noise" msgid "Trees noise"
@ -6978,11 +6976,13 @@ msgid "Use a cloud animation for the main menu background."
msgstr "Usar nubes con animaciones para el fondo del menú principal." msgstr "Usar nubes con animaciones para el fondo del menú principal."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Use anisotropic filtering when looking at textures from an angle.\n" "Use anisotropic filtering when looking at textures from an angle.\n"
"This provides a significant improvement when used together with mipmapping." "This provides a significant improvement when used together with mipmapping."
msgstr "Usar filtrado anisotrópico al mirar texturas desde un ángulo." msgstr ""
"Usar filtrado anisotrópico al mirar texturas desde un ángulo.\n"
"Esto proporciona una mejora significativa cuando se utiliza junto con el "
"mapeo MIP."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Use bilinear filtering when scaling textures." msgid "Use bilinear filtering when scaling textures."
@ -7319,18 +7319,16 @@ msgid "Whether to fog out the end of the visible area."
msgstr "Si se debe nublar el final del área visible." msgstr "Si se debe nublar el final del área visible."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Whether to mute sounds. You can unmute sounds at any time.\n" "Whether to mute sounds. You can unmute sounds at any time.\n"
"In-game, you can toggle the mute state with the mute key or by using the\n" "In-game, you can toggle the mute state with the mute key or by using the\n"
"pause menu." "pause menu."
msgstr "" msgstr ""
"Si deseas silenciar los sonidos. Puedes activar el sonido en cualquier " "Si deseas silenciar los sonidos. Puedes activar el sonido en cualquier "
"momento,\n" "momento.\n"
"a menos que el sistema de sonido esté desactivado (enable_sound=false).\n" "En el juego, puedes alternar el estado de silencio con la tecla de silenciar "
"En el juego, puedes alternar el estado de silencio con la tecla de silencio " "o usando el\n"
"o\n" "menú de pausa."
"usando el menú de pausa."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: French (Minetest)\n" "Project-Id-Version: French (Minetest)\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2024-11-06 18:04+0000\n" "PO-Revision-Date: 2025-02-12 12:18+0000\n"
"Last-Translator: waxtatect <piero@live.ie>\n" "Last-Translator: waxtatect <piero@live.ie>\n"
"Language-Team: French <https://hosted.weblate.org/projects/minetest/minetest/" "Language-Team: French <https://hosted.weblate.org/projects/minetest/minetest/"
"fr/>\n" "fr/>\n"
@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.8.2\n" "X-Generator: Weblate 5.10-dev\n"
#: builtin/client/chatcommands.lua #: builtin/client/chatcommands.lua
msgid "Clear the out chat queue" msgid "Clear the out chat queue"
@ -263,14 +263,12 @@ msgid "Show technical names"
msgstr "Montrer les noms techniques" msgstr "Montrer les noms techniques"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Écran tactile" msgstr "Disposition de l'écran tactile"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "pause_menu" msgid "pause_menu"
msgstr "FPS maximum sur le menu pause" msgstr "pause_menu"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -319,7 +317,7 @@ msgstr "Très basses"
#: builtin/fstk/ui.lua #: builtin/fstk/ui.lua
msgid "<none available>" msgid "<none available>"
msgstr "< aucun disponible >" msgstr "<non disponible>"
#: builtin/fstk/ui.lua #: builtin/fstk/ui.lua
msgid "An error occurred in a Lua script:" msgid "An error occurred in a Lua script:"
@ -610,6 +608,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Voici la liste des clients connectés à\n"
"$1"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"
@ -977,21 +977,20 @@ msgstr ""
"remplace tout renommage effectué ici." "remplace tout renommage effectué ici."
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
#, fuzzy
msgid "Expand all" msgid "Expand all"
msgstr "Tout activer" msgstr "Tout développer"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "Group by prefix" msgid "Group by prefix"
msgstr "" msgstr "Grouper par préfixe"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses a game called $2 and the following mods:" msgid "The $1 server uses a game called $2 and the following mods:"
msgstr "" msgstr "Le serveur $1 utilise un jeu appelé $2 et les mods suivants :"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses the following mods:" msgid "The $1 server uses the following mods:"
msgstr "" msgstr "Le serveur $1 utilise les mods suivants :"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "A new $1 version is available" msgid "A new $1 version is available"
@ -1205,20 +1204,20 @@ msgid "You need to install a game before you can create a world."
msgstr "Vous devez en installer un pour créer un nouveau monde." msgstr "Vous devez en installer un pour créer un nouveau monde."
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Add favorite" msgid "Add favorite"
msgstr "Supprimer le favori" msgstr "Ajouter aux favoris"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Address" msgid "Address"
msgstr "Adresse" msgstr "Adresse"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Clients:\n" "Clients:\n"
"$1" "$1"
msgstr "Client" msgstr ""
"Clients : \n"
"$1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Creative mode" msgid "Creative mode"
@ -1234,9 +1233,8 @@ msgid "Favorites"
msgstr "Favoris" msgstr "Favoris"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Game: $1" msgid "Game: $1"
msgstr "Jeu" msgstr "Jeu : $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Incompatible Servers" msgid "Incompatible Servers"
@ -1251,14 +1249,12 @@ msgid "Login"
msgstr "Connexion" msgstr "Connexion"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Number of mods: $1" msgid "Number of mods: $1"
msgstr "Nombre de fils émergents" msgstr "Nombre de mods : $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Open server website" msgid "Open server website"
msgstr "Intervalle de mise à jour des objets sur le serveur" msgstr "Visiter le site web du serveur"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Ping" msgid "Ping"
@ -1271,6 +1267,10 @@ msgid ""
"mod:<name>\n" "mod:<name>\n"
"player:<name>" "player:<name>"
msgstr "" msgstr ""
"Filtres possibles :\n"
"game:<nom>\n"
"mod:<nom>\n"
"player:<nom>"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Public Servers" msgid "Public Servers"
@ -1366,9 +1366,8 @@ msgid "Access denied. Reason: %s"
msgstr "Accès refusé. Raison : %s" msgstr "Accès refusé. Raison : %s"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "All debug info hidden" msgid "All debug info hidden"
msgstr "Informations de débogage affichées" msgstr "Informations de débogage cachées"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Automatic forward disabled" msgid "Automatic forward disabled"
@ -1392,7 +1391,7 @@ msgstr "Limites des blocs affichées pour les blocs voisins"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Bounding boxes shown" msgid "Bounding boxes shown"
msgstr "" msgstr "Limites des boîtes affichées"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Camera update disabled" msgid "Camera update disabled"
@ -1635,10 +1634,8 @@ msgid "Volume changed to %d%%"
msgstr "Volume réglé sur %d %%" msgstr "Volume réglé sur %d %%"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "Wireframe not supported by video driver" msgid "Wireframe not supported by video driver"
msgstr "" msgstr "Fils de fer non pris en charge par le pilote vidéo"
"Les nuanceurs sont activés mais GLSL n'est pas pris en charge par le pilote."
#: src/client/game.cpp #: src/client/game.cpp
msgid "Wireframe shown" msgid "Wireframe shown"
@ -2068,10 +2065,8 @@ msgid "Failed to compile the \"%s\" shader."
msgstr "Échec de la compilation du nuanceur « %s »." msgstr "Échec de la compilation du nuanceur « %s »."
#: src/client/shader.cpp #: src/client/shader.cpp
#, fuzzy
msgid "GLSL is not supported by the driver" msgid "GLSL is not supported by the driver"
msgstr "" msgstr "GLSL n'est pas pris en charge par le pilote vidéo"
"Les nuanceurs sont activés mais GLSL n'est pas pris en charge par le pilote."
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3" #. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2091,7 +2086,7 @@ msgid ""
"Note: this may be caused by a dependency cycle, in which case try updating " "Note: this may be caused by a dependency cycle, in which case try updating "
"the mods." "the mods."
msgstr "" msgstr ""
"Note : ceci peut être dû à un cycle de dépendances, dans ce cas essayer de " "Note : cela peut être dû à un cycle de dépendances, dans ce cas essayer de "
"mettre à jour les mods." "mettre à jour les mods."
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2308,35 +2303,35 @@ msgid "Sound Volume: %d%%"
msgstr "Volume du son : %d %%" msgstr "Volume du son : %d %%"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Add button" msgid "Add button"
msgstr "Clic central" msgstr "Ajouter un bouton"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Done" msgid "Done"
msgstr "Terminé !" msgstr "Terminé"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Remove" msgid "Remove"
msgstr "Serveur distant" msgstr "Supprimer"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Réinitialiser"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Start dragging a button to add. Tap outside to cancel." msgid "Start dragging a button to add. Tap outside to cancel."
msgstr "" msgstr ""
"Faire glisser un bouton pour ajouter. Appuyer à l'extérieur pour annuler."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap a button to select it. Drag a button to move it." msgid "Tap a button to select it. Drag a button to move it."
msgstr "" msgstr ""
"Appuyer sur un bouton pour le sélectionner. Faire glisser un bouton pour le "
"déplacer."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap outside to deselect." msgid "Tap outside to deselect."
msgstr "" msgstr "Appuyer à l'extérieur pour désélectionner."
#: src/gui/touchscreenlayout.cpp #: src/gui/touchscreenlayout.cpp
msgid "Joystick" msgid "Joystick"
@ -2524,7 +2519,7 @@ msgstr "Nuages 3D"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "3D mode" msgid "3D mode"
msgstr "Mode écran 3D" msgstr "Mode 3D"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "3D mode parallax strength" msgid "3D mode parallax strength"
@ -2573,7 +2568,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
msgstr "Bruit 3D qui détermine le nombre de donjons par tranche de carte." msgstr "Bruit 3D qui détermine le nombre de donjons par tranche de carte."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"3D support.\n" "3D support.\n"
"Currently supported:\n" "Currently supported:\n"
@ -2592,8 +2586,7 @@ msgstr ""
"lignes paires/impaires.\n" "lignes paires/impaires.\n"
" haut-bas : partage haut et bas de l'écran.\n" " haut-bas : partage haut et bas de l'écran.\n"
" côte-à-côte : partage côte à côte de l'écran.\n" " côte-à-côte : partage côte à côte de l'écran.\n"
" vision croisée : vision croisée 3D.\n" " vision croisée : vision croisée 3D."
"Noter que le mode entrelacé nécessite que les nuanceurs soient activés."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -2683,11 +2676,13 @@ msgid ""
"All mesh buffers with less than this number of vertices will be merged\n" "All mesh buffers with less than this number of vertices will be merged\n"
"during map rendering. This improves rendering performance." "during map rendering. This improves rendering performance."
msgstr "" msgstr ""
"Tous les tampons de maillage ayant moins de ce nombre de sommets sont "
"fusionnés lors du rendu de la carte.\n"
"Cela améliore les performances de rendu."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Allow clouds to look 3D instead of flat." msgid "Allow clouds to look 3D instead of flat."
msgstr "Activer les nuages 3D au lieu des nuages 2D (plats)." msgstr "Permet aux nuages de paraître en 3D au lieu de plats."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Allows liquids to be translucent." msgid "Allows liquids to be translucent."
@ -2705,7 +2700,7 @@ msgstr ""
"Des valeurs plus élevées rendent les niveaux de lumière moyens et inférieurs " "Des valeurs plus élevées rendent les niveaux de lumière moyens et inférieurs "
"plus lumineux.\n" "plus lumineux.\n"
"La valeur « 1,0 » laisse la courbe de lumière intacte.\n" "La valeur « 1,0 » laisse la courbe de lumière intacte.\n"
"Ceci a un effet significatif seulement sur la lumière du jour et la lumière " "Cela a un effet significatif seulement sur la lumière du jour et la lumière "
"artificielle, et a très peu d'effet sur la lumière naturelle nocturne." "artificielle, et a très peu d'effet sur la lumière naturelle nocturne."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -2777,7 +2772,7 @@ msgstr ""
"effectue un tramage supplémentaire ou si les canaux de couleur ne sont pas " "effectue un tramage supplémentaire ou si les canaux de couleur ne sont pas "
"quantifiés à 8 bits.\n" "quantifiés à 8 bits.\n"
"Avec OpenGL ES, le tramage fonctionne seulement si les nuanceurs prennent en " "Avec OpenGL ES, le tramage fonctionne seulement si les nuanceurs prennent en "
"charge une précision élevée en virgule flottante et ceci peut avoir un " "charge une précision élevée en virgule flottante et cela peut avoir un "
"impact plus important sur les performances." "impact plus important sur les performances."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -2836,8 +2831,8 @@ msgstr ""
"Des valeurs plus faibles peuvent augmenter la performance du serveur, mais " "Des valeurs plus faibles peuvent augmenter la performance du serveur, mais "
"peut provoquer l'apparition de problèmes de rendu (certains blocs ne sont " "peut provoquer l'apparition de problèmes de rendu (certains blocs ne sont "
"pas visibles).\n" "pas visibles).\n"
"Ceci est particulièrement utile pour les très grandes distances de vue (plus " "C'est particulièrement utile pour les très grandes distances de vue (plus de "
"de 500).\n" "500).\n"
"Établie en blocs de carte (16 nœuds)." "Établie en blocs de carte (16 nœuds)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -3099,7 +3094,7 @@ msgstr "Nuages dans le menu"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Color depth for post-processing texture" msgid "Color depth for post-processing texture"
msgstr "" msgstr "Profondeur de couleur pour la texture de post-traitement"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Colored fog" msgid "Colored fog"
@ -3119,7 +3114,6 @@ msgstr ""
"Utile pour les tests. Voir « al_extensions.[h, cpp] » pour plus de détails." "Utile pour les tests. Voir « al_extensions.[h, cpp] » pour plus de détails."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Comma-separated list of flags to hide in the content repository.\n" "Comma-separated list of flags to hide in the content repository.\n"
"\"nonfree\" can be used to hide packages which do not qualify as 'free " "\"nonfree\" can be used to hide packages which do not qualify as 'free "
@ -3272,7 +3266,7 @@ msgid ""
"This also applies to the object crosshair." "This also applies to the object crosshair."
msgstr "" msgstr ""
"Opacité du réticule (entre 0 et 255).\n" "Opacité du réticule (entre 0 et 255).\n"
"Ceci s'applique également au réticule de l'objet." "Cela s'applique également au réticule de l'objet."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Crosshair color" msgid "Crosshair color"
@ -3284,7 +3278,7 @@ msgid ""
"Also controls the object crosshair color" "Also controls the object crosshair color"
msgstr "" msgstr ""
"Couleur du réticule (R,V,B).\n" "Couleur du réticule (R,V,B).\n"
"Ceci s'applique également à la couleur du réticule de l'objet." "Cela s'applique également à la couleur du réticule de l'objet."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Debug log file size threshold" msgid "Debug log file size threshold"
@ -3305,6 +3299,10 @@ msgid ""
"Reducing this can improve performance, but some effects (e.g. debanding)\n" "Reducing this can improve performance, but some effects (e.g. debanding)\n"
"require more than 8 bits to work." "require more than 8 bits to work."
msgstr "" msgstr ""
"Détermine la profondeur de couleur de la texture utilisée pour les "
"opérations de post-traitement.\n"
"Réduire cette valeur peut améliorer les performances, mais certains effets ("
"ex. : le tramage) nécessitent plus de 8 bits pour fonctionner."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dedicated server step" msgid "Dedicated server step"
@ -3345,8 +3343,8 @@ msgid ""
"but also uses more resources." "but also uses more resources."
msgstr "" msgstr ""
"Définir la qualité du filtrage des ombres.\n" "Définir la qualité du filtrage des ombres.\n"
"Ceci simule l'effet d'ombres douces en appliquant un disque PCF ou Poisson " "Cela simule l'effet d'ombres douces en appliquant le PCF ou le disque de "
"mais utilise également plus de ressources." "Poisson mais utilise également plus de ressources."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -3364,10 +3362,10 @@ msgstr ""
"Les anciens clients sont compatibles dans le sens où ils ne plantent pas " "Les anciens clients sont compatibles dans le sens où ils ne plantent pas "
"lors de la connexion aux serveurs récents,\n" "lors de la connexion aux serveurs récents,\n"
"mais ils peuvent ne pas prendre en charge certaines fonctionnalités.\n" "mais ils peuvent ne pas prendre en charge certaines fonctionnalités.\n"
"Ceci permet un contrôle plus précis que " "Cela permet un contrôle plus précis que « strict_protocol_version_checking »."
"« strict_protocol_version_checking ».\n" "\n"
"Luanti applique toujours son propre minimum interne, activer " "Luanti applique toujours son propre minimum interne, activer « "
"« strict_protocol_version_checking » le remplace." "strict_protocol_version_checking » le remplace."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Defines areas where trees have apples." msgid "Defines areas where trees have apples."
@ -3441,7 +3439,7 @@ msgid ""
"down the rate of mesh updates, thus reducing jitter on slower clients." "down the rate of mesh updates, thus reducing jitter on slower clients."
msgstr "" msgstr ""
"Délai entre les mises à jour du maillage du client en ms.\n" "Délai entre les mises à jour du maillage du client en ms.\n"
"Augmenter ceci ralentit le taux de mise à jour et réduit donc les " "Augmenter cela ralentit le taux de mise à jour et réduit donc les "
"tremblements sur les clients lents." "tremblements sur les clients lents."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -3528,6 +3526,10 @@ msgid ""
"situations\n" "situations\n"
"where transparency sorting would be very slow otherwise." "where transparency sorting would be very slow otherwise."
msgstr "" msgstr ""
"Dessine les triangles triés par transparence regroupés par leurs tampons de "
"maillage.\n"
"Cela empêche le tri par transparence entre les tampons de maillage, mais "
"évite les situations où le tri par transparence serait très lent autrement."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dump the mapgen debug information." msgid "Dump the mapgen debug information."
@ -3589,7 +3591,7 @@ msgid ""
msgstr "" msgstr ""
"Activer le filtrage par disque de Poisson.\n" "Activer le filtrage par disque de Poisson.\n"
"Si activé, utilise le disque de Poisson pour créer des « ombres douces ». " "Si activé, utilise le disque de Poisson pour créer des « ombres douces ». "
"Sinon, utilise le filtrage PCF." "Sinon, utilise le PCF."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable Post Processing" msgid "Enable Post Processing"
@ -3597,7 +3599,7 @@ msgstr "Activer le post-traitement"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable Raytraced Culling" msgid "Enable Raytraced Culling"
msgstr "Activer l'élimination des blocs invisibles par Ray Tracing" msgstr "Activer l'élimination des blocs invisibles par lancer de rayons"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -3613,14 +3615,12 @@ msgstr ""
"simulant le comportement de lœil humain." "simulant le comportement de lœil humain."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable colored shadows for transculent nodes.\n" "Enable colored shadows for transculent nodes.\n"
"This is expensive." "This is expensive."
msgstr "" msgstr ""
"Activer les ombres colorées.\n" "Activer les ombres colorées pour les nœuds translucides.\n"
"Sur les nœuds vraiment transparents, projette des ombres colorées. Ceci est " "Cela utilise beaucoup de ressources."
"coûteux."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable console window" msgid "Enable console window"
@ -3707,14 +3707,12 @@ msgstr ""
"double." "double."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable/disable running an IPv6 server.\n" "Enable/disable running an IPv6 server.\n"
"Ignored if bind_address is set." "Ignored if bind_address is set."
msgstr "" msgstr ""
"Activer/désactiver l'usage d'un serveur IPv6.\n" "Activer/désactiver l'usage d'un serveur IPv6.\n"
"Ignoré si « bind_address » est activé.\n" "Ignoré si « bind_address » est activé."
"A besoin de « enable_ipv6 » pour être activé."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -3978,7 +3976,7 @@ msgid ""
"be\n" "be\n"
"sized 16, 32, 48, etc., so a mod requesting a size of 25 will get 32." "sized 16, 32, 48, etc., so a mod requesting a size of 25 will get 32."
msgstr "" msgstr ""
"Pour les polices de style pixel qui ne s'adaptent pas bien, ceci garantit " "Pour les polices de style pixel qui ne s'adaptent pas bien, cela garantit "
"que les tailles de police utilisées avec cette police sont toujours " "que les tailles de police utilisées avec cette police sont toujours "
"divisibles par cette valeur, en pixels.\n" "divisibles par cette valeur, en pixels.\n"
"Par exemple une police de style pixel de 16 pixels de haut doit avoir cette " "Par exemple une police de style pixel de 16 pixels de haut doit avoir cette "
@ -4057,7 +4055,7 @@ msgstr ""
"Distance maximale à laquelle les clients ont connaissance des objets, " "Distance maximale à laquelle les clients ont connaissance des objets, "
"établie en blocs de carte (16 nœuds).\n" "établie en blocs de carte (16 nœuds).\n"
"\n" "\n"
"Définir ceci plus grand que « active_block_range », ainsi le serveur " "Définir cela plus grand que « active_block_range », ainsi le serveur "
"maintient les objets actifs jusquà cette distance dans la direction où un " "maintient les objets actifs jusquà cette distance dans la direction où un "
"joueur regarde (cela peut éviter que des mobs disparaissent soudainement de " "joueur regarde (cela peut éviter que des mobs disparaissent soudainement de "
"la vue)." "la vue)."
@ -4288,7 +4286,7 @@ msgid ""
"Decrease this to increase liquid resistance to movement." "Decrease this to increase liquid resistance to movement."
msgstr "" msgstr ""
"Ralentissement lors du déplacement dans un liquide.\n" "Ralentissement lors du déplacement dans un liquide.\n"
"Réduire ceci pour augmenter la résistance au mouvement." "Réduire cette valeur pour augmenter la résistance au mouvement."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "How wide to make rivers." msgid "How wide to make rivers."
@ -4376,16 +4374,15 @@ msgstr ""
"de le remplacer par un mot de passe vide." "de le remplacer par un mot de passe vide."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"If enabled, server account registration is separate from login in the UI.\n" "If enabled, server account registration is separate from login in the UI.\n"
"If disabled, connecting to a server will automatically register a new " "If disabled, connecting to a server will automatically register a new "
"account." "account."
msgstr "" msgstr ""
"Si activé, l'enregistrement du compte est séparé de la connexion dans " "Si activé, l'enregistrement du compte sur le serveur est séparé de la "
"l'interface utilisateur.\n" "connexion dans l'interface utilisateur.\n"
"Si désactivé, les nouveaux comptes sont enregistrés automatiquement lors de " "Si désactivé, la connexion à un serveur entraîne automatiquement "
"la connexion." "l'enregistrement d'un nouveau compte."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -4396,7 +4393,7 @@ msgid ""
msgstr "" msgstr ""
"Si activé, le serveur effectue la détermination des blocs de carte " "Si activé, le serveur effectue la détermination des blocs de carte "
"invisibles selon la position des yeux du joueur.\n" "invisibles selon la position des yeux du joueur.\n"
"Ceci peut réduire le nombre de blocs envoyés au client de 50 à 80 %.\n" "Cela peut réduire le nombre de blocs envoyés au client de 50 à 80 %.\n"
"Les clients ne reçoivent plus la plupart des blocs invisibles, de sorte que " "Les clients ne reçoivent plus la plupart des blocs invisibles, de sorte que "
"l'utilité du mode sans collisions est réduite." "l'utilité du mode sans collisions est réduite."
@ -4473,7 +4470,7 @@ msgid ""
"This is usually only needed by core/builtin contributors" "This is usually only needed by core/builtin contributors"
msgstr "" msgstr ""
"Instrumenter « Intégré » (« builtin »).\n" "Instrumenter « Intégré » (« builtin »).\n"
"Ceci est habituellement nécessaire seulement pour les développeurs " "Cela est habituellement nécessaire seulement pour les développeurs "
"principaux." "principaux."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -4752,7 +4749,7 @@ msgid ""
"- trace" "- trace"
msgstr "" msgstr ""
"Niveau de journalisation à écrire dans « debug.txt » :\n" "Niveau de journalisation à écrire dans « debug.txt » :\n"
" < rien > (pas de journalisation)\n" " <vide> (pas de journalisation)\n"
" aucun (messages sans niveau)\n" " aucun (messages sans niveau)\n"
" erreur\n" " erreur\n"
" avertissement\n" " avertissement\n"
@ -5282,7 +5279,7 @@ msgstr ""
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Minimum vertex count for mesh buffers" msgid "Minimum vertex count for mesh buffers"
msgstr "" msgstr "Nombre minimal de sommets pour les tampons de maillage"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Mipmapping" msgid "Mipmapping"
@ -5378,15 +5375,14 @@ msgstr ""
" les terrains flottants optionnels du générateur v7 (désactivé par défaut)." " les terrains flottants optionnels du générateur v7 (désactivé par défaut)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Name of the player.\n" "Name of the player.\n"
"When running a server, a client connecting with this name is admin.\n" "When running a server, a client connecting with this name is admin.\n"
"When starting from the main menu, this is overridden." "When starting from the main menu, this is overridden."
msgstr "" msgstr ""
"Nom du joueur.\n" "Nom du joueur.\n"
"Lorsqu'un serveur est lancé, les clients se connectant avec ce nom sont " "Lorsqu'un serveur est lancé, le client se connectant avec ce nom est "
"administrateurs.\n" "administrateur.\n"
"Lors du démarrage à partir du menu principal, celui-ci est remplacé." "Lors du démarrage à partir du menu principal, celui-ci est remplacé."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -5614,7 +5610,7 @@ msgstr ""
"des boutons de la souris.\n" "des boutons de la souris.\n"
"Activer cette option lorsque vous creusez ou placez trop souvent par " "Activer cette option lorsque vous creusez ou placez trop souvent par "
"accident.\n" "accident.\n"
"Sur écrans tactiles, ceci a un effet seulement pour creuser." "Sur écrans tactiles, cela a un effet seulement pour le minage."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Prevent mods from doing insecure things like running shell commands." msgid "Prevent mods from doing insecure things like running shell commands."
@ -5847,9 +5843,9 @@ msgid ""
"edge pixels when images are scaled by non-integer sizes." "edge pixels when images are scaled by non-integer sizes."
msgstr "" msgstr ""
"Met à l'échelle l'interface graphique par une valeur spécifiée par " "Met à l'échelle l'interface graphique par une valeur spécifiée par "
"l'utilisateur, à l'aide d'un filtre au plus proche voisin avec " "l'utilisateur, à l'aide d'un filtre au plus proche voisin avec anticrénelage."
"anticrénelage.\n" "\n"
"Ceci lisse certains bords grossiers, et mélange les pixels en réduisant " "Cela lisse certains bords grossiers, et mélange les pixels en réduisant "
"l'échelle.\n" "l'échelle.\n"
"Au détriment d'un effet de flou sur des pixels en bordure quand les images " "Au détriment d'un effet de flou sur des pixels en bordure quand les images "
"sont mises à l'échelle par des valeurs fractionnelles." "sont mises à l'échelle par des valeurs fractionnelles."
@ -5911,7 +5907,6 @@ msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
msgstr "Voir http://www.sqlite.org/pragma.html#pragma_synchronous" msgstr "Voir http://www.sqlite.org/pragma.html#pragma_synchronous"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Select the antialiasing method to apply.\n" "Select the antialiasing method to apply.\n"
"\n" "\n"
@ -5938,17 +5933,22 @@ msgstr ""
"\n" "\n"
"* Aucun Pas d'anticrénelage (par défaut)\n" "* Aucun Pas d'anticrénelage (par défaut)\n"
"\n" "\n"
"* FSAA Anticrénelage de la scène complète (incompatible avec « Post-" "* FSAA Anticrénelage matériel de la scène complète\n"
"traitement » et « Sous-échantillonnage »)\n"
"Alias anticrénelage multi-échantillon (MSAA), lisse les bords des blocs mais " "Alias anticrénelage multi-échantillon (MSAA), lisse les bords des blocs mais "
"n'affecte pas l'intérieur des textures.\n" "n'affecte pas l'intérieur des textures.\n"
"Un redémarrage est nécessaire pour modifier cette option.\n"
"\n" "\n"
"* FXAA Anticrénelage approximatif rapide (nécessite des nuanceurs)\n" "Si le post-traitement est désactivé, la modification de FSAA nécessite un "
"redémarrage.\n"
"De même, si le post-traitement est désactivé, le FSAA ne fonctionne pas avec "
"le sous-échantillonnage,\n"
"pour un paramètre « Mode 3D » défini sur une autre valeur que celle par "
"défaut.\n"
"\n"
"* FXAA Anticrénelage approximatif rapide\n"
"Applique un filtre de post-traitement pour détecter et lisser les bords à " "Applique un filtre de post-traitement pour détecter et lisser les bords à "
"contraste élevé, fournit un équilibre entre vitesse et qualité d'image.\n" "contraste élevé, fournit un équilibre entre vitesse et qualité d'image.\n"
"\n" "\n"
"* SSAA Anticrénelage par super-échantillonnage (nécessite des nuanceurs)\n" "* SSAA Anticrénelage par super-échantillonnage\n"
"Rendu d'une image haute résolution de la scène, puis réduit l'échelle pour " "Rendu d'une image haute résolution de la scène, puis réduit l'échelle pour "
"diminuer le crénelage. C'est la méthode la plus lente et la plus précise." "diminuer le crénelage. C'est la méthode la plus lente et la plus précise."
@ -6187,7 +6187,7 @@ msgid ""
msgstr "" msgstr ""
"Définit la qualité de la texture de l'ombre sur 32 bits.\n" "Définit la qualité de la texture de l'ombre sur 32 bits.\n"
"Si désactivé, une texture de 16 bits est utilisée.\n" "Si désactivé, une texture de 16 bits est utilisée.\n"
"Ceci peut causer beaucoup plus d'artefacts sur l'ombre." "Cela peut causer beaucoup plus d'artefacts sur l'ombre."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Shader path" msgid "Shader path"
@ -6389,7 +6389,6 @@ msgstr ""
"certains (ou tous) objets." "certains (ou tous) objets."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Spread a complete update of the shadow map over a given number of frames.\n" "Spread a complete update of the shadow map over a given number of frames.\n"
"Higher values might make shadows laggy, lower values\n" "Higher values might make shadows laggy, lower values\n"
@ -6398,8 +6397,7 @@ msgstr ""
"Répartit une mise à jour complète de la carte des ombres sur un nombre donné " "Répartit une mise à jour complète de la carte des ombres sur un nombre donné "
"d'images.\n" "d'images.\n"
"Des valeurs plus élevées peuvent rendre les ombres plus lentes, des valeurs " "Des valeurs plus élevées peuvent rendre les ombres plus lentes, des valeurs "
"plus faibles consomment plus de ressources.\n" "plus faibles consomment plus de ressources."
"Valeur minimale : 1 ; valeur maximale : 16"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6666,11 +6664,11 @@ msgid ""
msgstr "" msgstr ""
"Le rayon du volume de blocs autour de chaque joueur soumis au bloc actif, " "Le rayon du volume de blocs autour de chaque joueur soumis au bloc actif, "
"établi en blocs de carte (16 nœuds).\n" "établi en blocs de carte (16 nœuds).\n"
"Dans les blocs actifs, les objets sont chargés et les « ABMs » sont " "Dans les blocs actifs, les objets sont chargés et les « ABMs » sont exécutés."
"exécutés.\n" "\n"
"C'est également la distance minimale dans laquelle les objets actifs (mobs) " "C'est également la distance minimale dans laquelle les objets actifs (mobs) "
"sont conservés.\n" "sont conservés.\n"
"Ceci doit être configuré avec « active_object_send_range_blocks »." "Cela doit être configuré avec « active_object_send_range_blocks »."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6701,7 +6699,7 @@ msgstr ""
"Intensité (obscurité) de l'ombrage des blocs avec l'occlusion ambiante.\n" "Intensité (obscurité) de l'ombrage des blocs avec l'occlusion ambiante.\n"
"Les valeurs plus faibles sont plus sombres, les valeurs plus hautes sont " "Les valeurs plus faibles sont plus sombres, les valeurs plus hautes sont "
"plus claires.\n" "plus claires.\n"
"Une plage valide de valeurs pour ceci se situe entre 0,25 et 4,0.\n" "Une plage valide de valeurs pour cela se situe entre 0,25 et 4,0.\n"
"Si la valeur est en dehors de cette plage alors elle est définie à la plus " "Si la valeur est en dehors de cette plage alors elle est définie à la plus "
"proche des valeurs valides." "proche des valeurs valides."
@ -6798,7 +6796,7 @@ msgid ""
msgstr "" msgstr ""
"Pour réduire le décalage, le transfert des blocs est ralenti quand un joueur " "Pour réduire le décalage, le transfert des blocs est ralenti quand un joueur "
"construit quelque chose.\n" "construit quelque chose.\n"
"Ceci détermine la durée du ralentissement après placement ou destruction " "Cela détermine la durée du ralentissement après placement ou destruction "
"d'un nœud." "d'un nœud."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -6843,12 +6841,11 @@ msgstr "Liquides translucides"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Transparency Sorting Distance" msgid "Transparency Sorting Distance"
msgstr "Distance de tri de la transparence" msgstr "Tri de la transparence par distance"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Transparency Sorting Group by Buffers" msgid "Transparency Sorting Group by Buffers"
msgstr "Distance de tri de la transparence" msgstr "Tri de la transparence regroupés par tampons"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Trees noise" msgid "Trees noise"
@ -6912,7 +6909,6 @@ msgid "Undersampling"
msgstr "Sous-échantillonnage" msgstr "Sous-échantillonnage"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Undersampling is similar to using a lower screen resolution, but it applies\n" "Undersampling is similar to using a lower screen resolution, but it applies\n"
"to the game world only, keeping the GUI intact.\n" "to the game world only, keeping the GUI intact.\n"
@ -6926,9 +6922,12 @@ msgstr ""
"Le sous-échantillonnage ressemble à l'utilisation d'une résolution d'écran " "Le sous-échantillonnage ressemble à l'utilisation d'une résolution d'écran "
"inférieure.\n" "inférieure.\n"
"Il ne s'applique qu'au rendu 3D, gardant l'interface graphique intacte.\n" "Il ne s'applique qu'au rendu 3D, gardant l'interface graphique intacte.\n"
"Ceci doit donner un bonus de performance conséquent, au détriment de la " "Cela doit donner un bonus de performance conséquent, au détriment de la "
"qualité d'image.\n" "qualité d'image.\n"
"Les valeurs plus élevées réduisent la qualité du détail des images." "Les valeurs plus élevées réduisent la qualité du détail des images.\n"
"Note : le sous-échantillonnage n'est actuellement pas pris en charge,\n"
"si le paramètre « Mode 3D » est définie sur une autre valeur que celle par "
"défaut."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Unlimited player transfer distance" msgid "Unlimited player transfer distance"
@ -6955,13 +6954,14 @@ msgid "Use a cloud animation for the main menu background."
msgstr "Utiliser l'animation des nuages pour l'arrière-plan du menu principal." msgstr "Utiliser l'animation des nuages pour l'arrière-plan du menu principal."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Use anisotropic filtering when looking at textures from an angle.\n" "Use anisotropic filtering when looking at textures from an angle.\n"
"This provides a significant improvement when used together with mipmapping." "This provides a significant improvement when used together with mipmapping."
msgstr "" msgstr ""
"Utiliser le filtrage anisotrope lorsque l'on regarde les textures sous un " "Utiliser le filtrage anisotrope lorsque l'on regarde les textures sous un "
"certain angle." "certain angle.\n"
"Cela apporte une amélioration significative lorsqu'il est utilisé avec le "
"mip-mapping."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Use bilinear filtering when scaling textures." msgid "Use bilinear filtering when scaling textures."
@ -6998,10 +6998,10 @@ msgid ""
"This flag enables use of raytraced occlusion culling test for\n" "This flag enables use of raytraced occlusion culling test for\n"
"client mesh sizes smaller than 4x4x4 map blocks." "client mesh sizes smaller than 4x4x4 map blocks."
msgstr "" msgstr ""
"Utiliser l'élimination des blocs invisibles par Ray Tracing avec le nouvel " "Utiliser l'élimination des blocs invisibles par lancer de rayons avec le "
"algorithme.\n" "nouvel algorithme.\n"
"Cette option active l'utilisation du test d'élimination des blocs invisibles " "Cette option active l'utilisation du test d'élimination des blocs invisibles "
"par Ray Tracing,\n" "par lancer de rayons,\n"
"pour les maillages clients de taille inférieure à 4 × 4 × 4 blocs de carte." "pour les maillages clients de taille inférieure à 4 × 4 × 4 blocs de carte."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -7237,7 +7237,6 @@ msgstr ""
"directement par le matériel (ex. : textures des blocs dans l'inventaire)." "directement par le matériel (ex. : textures des blocs dans l'inventaire)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"When using bilinear/trilinear filtering, low-resolution textures\n" "When using bilinear/trilinear filtering, low-resolution textures\n"
"can be blurred, so this option automatically upscales them to preserve\n" "can be blurred, so this option automatically upscales them to preserve\n"
@ -7248,16 +7247,16 @@ msgid ""
"This is also used as the base node texture size for world-aligned\n" "This is also used as the base node texture size for world-aligned\n"
"texture autoscaling." "texture autoscaling."
msgstr "" msgstr ""
"En utilisant le filtrage bilinéaire/trilinéaire/anisotrope, les textures de " "En utilisant le filtrage bilinéaire/trilinéaire, les textures de basse "
"basse résolution peuvent être floues.\n" "résolution peuvent être floues.\n"
"Elles sont donc agrandies avec l'interpolation au plus proche voisin pour " "Cette option les agrandies automatiquement afin de préserver des pixels nets."
"préserver des pixels nets.\n" "\n"
"Ceci détermine la taille minimale pour les textures agrandies;\n" "Cela définit la taille minimale pour les textures agrandies;\n"
"les valeurs plus élevées ont un rendu plus net, mais nécessitent plus de " "les valeurs plus élevées ont un rendu plus net, mais nécessitent plus de "
"mémoire. Les puissances de 2 sont recommandées.\n" "mémoire.\n"
"Ce paramètre est appliqué seulement si le filtrage bilinéaire/trilinéaire/" "Ce paramètre est appliqué UNIQUEMENT si l'un des filtres mentionnés est "
"anisotrope est activé.\n" "activé.\n"
"Ceci est également utilisé comme taille de texture de nœud de base pour " "Cela est également utilisé comme taille de texture de nœud de base pour "
"l'agrandissement automatique des textures alignées sur le monde." "l'agrandissement automatique des textures alignées sur le monde."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -7293,14 +7292,12 @@ msgid "Whether to fog out the end of the visible area."
msgstr "Détermine la visibilité du brouillard au bout de l'aire visible." msgstr "Détermine la visibilité du brouillard au bout de l'aire visible."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Whether to mute sounds. You can unmute sounds at any time.\n" "Whether to mute sounds. You can unmute sounds at any time.\n"
"In-game, you can toggle the mute state with the mute key or by using the\n" "In-game, you can toggle the mute state with the mute key or by using the\n"
"pause menu." "pause menu."
msgstr "" msgstr ""
"S'il faut couper le son. Vous pouvez réactiver le son à tout moment, sauf si " "S'il faut couper le son. Vous pouvez réactiver le son à tout moment.\n"
"le système audio est désactivé (« enable_sound=false »).\n"
"Dans le jeu, vous pouvez basculer l'état du son avec la touche « Muet » ou " "Dans le jeu, vous pouvez basculer l'état du son avec la touche « Muet » ou "
"en utilisant le menu pause." "en utilisant le menu pause."
@ -7399,7 +7396,7 @@ msgstr ""
"Distance Y sur laquelle les terrains flottants passent d'une densité " "Distance Y sur laquelle les terrains flottants passent d'une densité "
"maximale à une densité nulle.\n" "maximale à une densité nulle.\n"
"L'effilage commence à cette distance, depuis la limite en Y.\n" "L'effilage commence à cette distance, depuis la limite en Y.\n"
"Pour une couche solide de terrain flottant, ceci contrôle la hauteur des " "Pour une couche solide de terrain flottant, cela contrôle la hauteur des "
"collines et des montagnes.\n" "collines et des montagnes.\n"
"Doit être inférieure ou égale à la moitié de la distance entre les limites Y." "Doit être inférieure ou égale à la moitié de la distance entre les limites Y."

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: minetest\n" "Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2024-11-24 10:00+0000\n" "PO-Revision-Date: 2025-02-13 12:44+0000\n"
"Last-Translator: ninjum <ninhum@gmx.com>\n" "Last-Translator: ninjum <ninhum@gmx.com>\n"
"Language-Team: Galician <https://hosted.weblate.org/projects/minetest/" "Language-Team: Galician <https://hosted.weblate.org/projects/minetest/"
"minetest/gl/>\n" "minetest/gl/>\n"
@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.9-dev\n" "X-Generator: Weblate 5.10-dev\n"
#: builtin/client/chatcommands.lua #: builtin/client/chatcommands.lua
msgid "Clear the out chat queue" msgid "Clear the out chat queue"
@ -263,13 +263,12 @@ msgid "Show technical names"
msgstr "Mostrar nomes técnicos" msgstr "Mostrar nomes técnicos"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Pantalla táctil" msgstr "Disposición da pantalla táctil"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
msgid "pause_menu" msgid "pause_menu"
msgstr "" msgstr "_menú de pausa"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -609,6 +608,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Esta é a lista de clientes conectados a\n"
"$1"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"
@ -882,7 +883,7 @@ msgstr "Desexa eliminar \"$1\"?"
#: builtin/mainmenu/dlg_delete_content.lua #: builtin/mainmenu/dlg_delete_content.lua
#: builtin/mainmenu/dlg_delete_world.lua builtin/mainmenu/tab_local.lua #: builtin/mainmenu/dlg_delete_world.lua builtin/mainmenu/tab_local.lua
msgid "Delete" msgid "Delete"
msgstr "Eliminar" msgstr "Borrar"
#: builtin/mainmenu/dlg_delete_content.lua #: builtin/mainmenu/dlg_delete_content.lua
msgid "pkgmgr: failed to delete \"$1\"" msgid "pkgmgr: failed to delete \"$1\""
@ -971,21 +972,20 @@ msgstr ""
"non permitirá cambios de nome aquí." "non permitirá cambios de nome aquí."
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
#, fuzzy
msgid "Expand all" msgid "Expand all"
msgstr "Activar todo" msgstr "Expandir todo"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "Group by prefix" msgid "Group by prefix"
msgstr "" msgstr "Agrupar por prefixo"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses a game called $2 and the following mods:" msgid "The $1 server uses a game called $2 and the following mods:"
msgstr "" msgstr "O servidor $1 usa un xogo chamado $2 e as seguintes modificacións:"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses the following mods:" msgid "The $1 server uses the following mods:"
msgstr "" msgstr "O servidor $1 usa as seguintes modificacións:"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "A new $1 version is available" msgid "A new $1 version is available"
@ -1199,20 +1199,20 @@ msgid "You need to install a game before you can create a world."
msgstr "Tes que instalar un xogo antes de poder crear un mundo." msgstr "Tes que instalar un xogo antes de poder crear un mundo."
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Add favorite" msgid "Add favorite"
msgstr "Favorito remoto" msgstr "Engadir aos favoritos"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Address" msgid "Address"
msgstr "Enderezo" msgstr "Enderezo"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Clients:\n" "Clients:\n"
"$1" "$1"
msgstr "Cliente" msgstr ""
"Clientes:\n"
"$1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Creative mode" msgid "Creative mode"
@ -1228,9 +1228,8 @@ msgid "Favorites"
msgstr "Favoritos" msgstr "Favoritos"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Game: $1" msgid "Game: $1"
msgstr "Xogo" msgstr "Xogo: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Incompatible Servers" msgid "Incompatible Servers"
@ -1245,14 +1244,12 @@ msgid "Login"
msgstr "Identificarse" msgstr "Identificarse"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Number of mods: $1" msgid "Number of mods: $1"
msgstr "Número de fíos emerxentes" msgstr "Número de modificacións: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Open server website" msgid "Open server website"
msgstr "Intervalo de servidor dedicado" msgstr "Abrir o sitio web do servidor"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Ping" msgid "Ping"
@ -1265,6 +1262,10 @@ msgid ""
"mod:<name>\n" "mod:<name>\n"
"player:<name>" "player:<name>"
msgstr "" msgstr ""
"Filtros posibles\n"
"xogo:<nome>\n"
"mod:<nome>\"\n"
"xogador:<nome"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Public Servers" msgid "Public Servers"
@ -1360,9 +1361,8 @@ msgid "Access denied. Reason: %s"
msgstr "Acceso negado. Motivo: %s" msgstr "Acceso negado. Motivo: %s"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "All debug info hidden" msgid "All debug info hidden"
msgstr "Info de depuración mostrada" msgstr "Toda a información de depuración oculta"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Automatic forward disabled" msgid "Automatic forward disabled"
@ -1386,7 +1386,7 @@ msgstr "Límites de bloques mostrados para bloques pretos"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Bounding boxes shown" msgid "Bounding boxes shown"
msgstr "" msgstr "Caixas delimitadoras amosadas"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Camera update disabled" msgid "Camera update disabled"
@ -1627,9 +1627,8 @@ msgid "Volume changed to %d%%"
msgstr "Volume cambiado a %d%%" msgstr "Volume cambiado a %d%%"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "Wireframe not supported by video driver" msgid "Wireframe not supported by video driver"
msgstr "Os sombreadores están habilitados pero o controlador non admite GLSL." msgstr "O wireframe non é compatible co controlador de vídeo"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Wireframe shown" msgid "Wireframe shown"
@ -2062,9 +2061,8 @@ msgid "Failed to compile the \"%s\" shader."
msgstr "Produciuse un erro ao compilar o sombreador \"%s\"." msgstr "Produciuse un erro ao compilar o sombreador \"%s\"."
#: src/client/shader.cpp #: src/client/shader.cpp
#, fuzzy
msgid "GLSL is not supported by the driver" msgid "GLSL is not supported by the driver"
msgstr "Os sombreadores están habilitados pero o controlador non admite GLSL." msgstr "GLSL non é compatible co controlador"
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3" #. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2301,35 +2299,32 @@ msgid "Sound Volume: %d%%"
msgstr "Son: %d%%" msgstr "Son: %d%%"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Add button" msgid "Add button"
msgstr "Botón central" msgstr "Engadir botón"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Done" msgid "Done"
msgstr "Feito!" msgstr "Feito"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Remove" msgid "Remove"
msgstr "Servidor remoto" msgstr "Eliminar"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Restablecer"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Start dragging a button to add. Tap outside to cancel." msgid "Start dragging a button to add. Tap outside to cancel."
msgstr "" msgstr "Comeza a arrastrar un botón para engadir. Toca fóra para cancelar."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap a button to select it. Drag a button to move it." msgid "Tap a button to select it. Drag a button to move it."
msgstr "" msgstr "Toca un botón para seccionalo. Arrastra un botón para movelo."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap outside to deselect." msgid "Tap outside to deselect."
msgstr "" msgstr "Toca fóra para deseleccionar."
#: src/gui/touchscreenlayout.cpp #: src/gui/touchscreenlayout.cpp
msgid "Joystick" msgid "Joystick"
@ -2565,7 +2560,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
msgstr "Ruído 3D que determina a cantidade de calabozos por chunk." msgstr "Ruído 3D que determina a cantidade de calabozos por chunk."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"3D support.\n" "3D support.\n"
"Currently supported:\n" "Currently supported:\n"
@ -2578,14 +2572,13 @@ msgid ""
msgstr "" msgstr ""
"Soporte 3D.\n" "Soporte 3D.\n"
"Soportado actualmente:\n" "Soportado actualmente:\n"
"- none: sen saída 3D.\n" "- ningún: sen saída 3D.\n"
"- anaglyph: 3D en cor ciano/maxenta.\n" "- anáglifo: 3D en cor ciano/maxenta.\n"
"- interlaced: soporte de pantalla polarizada baseada en liñas par/ímpar.\n" "- entrelazado: soporte de pantalla polarizada baseada en liñas par/ímpar."
"- topbottom: pantalla dividida superior/inferior.\n" "\n"
"- sidebyside: pantalla dividida lado a lado.\n" "- arriba-abaixo: pantalla dividida superior/inferior.\n"
" - crossview: 3D para ver cruzado\n" "- lado a lado: pantalla dividida lado a lado.\n"
"Teña en conta que o modo entrelazado require cos sombreadores estean " "- vista cruzada: 3D para ver cruzado"
"activados."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -2674,11 +2667,13 @@ msgid ""
"All mesh buffers with less than this number of vertices will be merged\n" "All mesh buffers with less than this number of vertices will be merged\n"
"during map rendering. This improves rendering performance." "during map rendering. This improves rendering performance."
msgstr "" msgstr ""
"Todos os buffers de malla con menos de este número de vértices serán "
"fusionados\n"
"durante o renderizado do mapa. Isto mellora o rendemento do renderizado."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Allow clouds to look 3D instead of flat." msgid "Allow clouds to look 3D instead of flat."
msgstr "Activa as nubes 3D en lugar de nubes 2D (planas)." msgstr "Permitir que as nubes se vexan en 3D en vez de planas."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Allows liquids to be translucent." msgid "Allows liquids to be translucent."
@ -3089,7 +3084,7 @@ msgstr "Nubes no menú"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Color depth for post-processing texture" msgid "Color depth for post-processing texture"
msgstr "" msgstr "Profundidade de cor para a textura de post-procesamento"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Colored fog" msgid "Colored fog"
@ -3108,7 +3103,6 @@ msgstr ""
"Útil para probas. Vexa al_extensions.[h,cpp] para máis detalles." "Útil para probas. Vexa al_extensions.[h,cpp] para máis detalles."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Comma-separated list of flags to hide in the content repository.\n" "Comma-separated list of flags to hide in the content repository.\n"
"\"nonfree\" can be used to hide packages which do not qualify as 'free " "\"nonfree\" can be used to hide packages which do not qualify as 'free "
@ -3294,6 +3288,11 @@ msgid ""
"Reducing this can improve performance, but some effects (e.g. debanding)\n" "Reducing this can improve performance, but some effects (e.g. debanding)\n"
"require more than 8 bits to work." "require more than 8 bits to work."
msgstr "" msgstr ""
"Decide a profundidade de cor da textura utilizada para o proceso de post-"
"procesamento.\n"
"Reducir isto pode mellorar o rendemento, pero algúns efectos (por exemplo, "
"tramado)\n"
"require máis de 8 bits para funcionar."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dedicated server step" msgid "Dedicated server step"
@ -3518,6 +3517,11 @@ msgid ""
"situations\n" "situations\n"
"where transparency sorting would be very slow otherwise." "where transparency sorting would be very slow otherwise."
msgstr "" msgstr ""
"Debuxar triángulos ordenados por transparencia agrupados polos seus buffers "
"de malla.\n"
"Isto rompe a orde de transparencia entre os buffers de malla, pero evita "
"situacións\n"
"onde a orde de transparencia sería moi lenta noutro caso."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dump the mapgen debug information." msgid "Dump the mapgen debug information."
@ -3602,14 +3606,12 @@ msgstr ""
"simulando o comportamento do ollo humano." "simulando o comportamento do ollo humano."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable colored shadows for transculent nodes.\n" "Enable colored shadows for transculent nodes.\n"
"This is expensive." "This is expensive."
msgstr "" msgstr ""
"Activar sombras coloridas.\n" "Activar sombras coloreadas para nós translúcidos.\n"
"Se o valor é verdadeiro, os bloques traslúcidos proxectarán sombras " "Isto é custoso."
"coloridas. Esta opción precisa de moitos recursos."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable console window" msgid "Enable console window"
@ -3695,14 +3697,12 @@ msgstr ""
"Por exemplo: 0 para nada de balanceo; 1.0 para o normal; 2.0 para o dobre." "Por exemplo: 0 para nada de balanceo; 1.0 para o normal; 2.0 para o dobre."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable/disable running an IPv6 server.\n" "Enable/disable running an IPv6 server.\n"
"Ignored if bind_address is set." "Ignored if bind_address is set."
msgstr "" msgstr ""
"Activa/desactiva a execución dun servidor IPv6.\n" "Activar/desactivar a execución dun servidor IPv6.\n"
"Ignorado se establécese bind_address.\n" "Ignorado se está configurada a bind_address."
"É preciso enable_ipv6 para activalo."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -4364,14 +4364,15 @@ msgstr ""
"cambiar o seu contrasinal a un contrasinal baleiro." "cambiar o seu contrasinal a un contrasinal baleiro."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"If enabled, server account registration is separate from login in the UI.\n" "If enabled, server account registration is separate from login in the UI.\n"
"If disabled, connecting to a server will automatically register a new " "If disabled, connecting to a server will automatically register a new "
"account." "account."
msgstr "" msgstr ""
"Activar confirmación de rexistro ao se conectar ao servidor\n" "Se está activado, o rexistro da conta do servidor é separado do inicio de "
"Se está desactivado, rexistrarase unha nova conta automáticamente." "sesión na interface de usuario.\n"
"Se está desactivado, conectar a un servidor rexistrará automaticamente unha "
"nova conta."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5262,7 +5263,7 @@ msgstr "Límite mínimo do número aleatorio de covas pequenas por chunk."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Minimum vertex count for mesh buffers" msgid "Minimum vertex count for mesh buffers"
msgstr "" msgstr "Contaxe mínima de vértices para os buffers de malla"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Mipmapping" msgid "Mipmapping"
@ -5357,16 +5358,15 @@ msgstr ""
"- Os terreos flotantes opcionais de v7 (desactivados por defecto)." "- Os terreos flotantes opcionais de v7 (desactivados por defecto)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Name of the player.\n" "Name of the player.\n"
"When running a server, a client connecting with this name is admin.\n" "When running a server, a client connecting with this name is admin.\n"
"When starting from the main menu, this is overridden." "When starting from the main menu, this is overridden."
msgstr "" msgstr ""
"Nome do xogador.\n" "Nome do xogador.\n"
"Cando se executa un servidor, os clientes que se conectan con este nome son " "Cando se executa un servidor, un cliente que se conecte con este nome será "
"administradores.\n" "administrador.\n"
"Ao comezar desde o menú principal, isto substitúese." "Cando se inicie desde o menú principal, isto será substituído."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6356,18 +6356,16 @@ msgstr ""
"cantidade na que agrupar algúns (ou todos) os obxectos." "cantidade na que agrupar algúns (ou todos) os obxectos."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Spread a complete update of the shadow map over a given number of frames.\n" "Spread a complete update of the shadow map over a given number of frames.\n"
"Higher values might make shadows laggy, lower values\n" "Higher values might make shadows laggy, lower values\n"
"will consume more resources." "will consume more resources."
msgstr "" msgstr ""
"Distribuír unha actualización completa do mapa de sombras sobre unha " "Espallar unha actualización completa do mapa de sombras ao longo dun número "
"determinada cantidade de fotogramas.\n" "determinado de fotogramas.\n"
"Os valores máis altos poden facer cas sombras sexan lentas e os valores máis " "Valores máis altos poden facer que as sombras vaian con retardo, mentres que "
"baixos\n" "valores máis baixos\n"
"consumirán máis recursos.\n" "consumirán máis recursos."
"Valor mínimo: 1; Valor máximo 16"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6650,7 +6648,7 @@ msgid ""
msgstr "" msgstr ""
"O backend de renderizado.\n" "O backend de renderizado.\n"
"Nota: É necesario reiniciar despois de cambiar isto!\n" "Nota: É necesario reiniciar despois de cambiar isto!\n"
"OpenGL é o predeterminado para escritorio, e OGLES2 para Android" "OpenGL é o predeterminado para escritorio, e OGLES2 para Android."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6814,9 +6812,8 @@ msgid "Transparency Sorting Distance"
msgstr "Distancia de ordenación de transparencias" msgstr "Distancia de ordenación de transparencias"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Transparency Sorting Group by Buffers" msgid "Transparency Sorting Group by Buffers"
msgstr "Distancia de ordenación de transparencias" msgstr "Grupo de orde de transparencia por buffers"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Trees noise" msgid "Trees noise"
@ -6876,7 +6873,6 @@ msgid "Undersampling"
msgstr "Submostraxe" msgstr "Submostraxe"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Undersampling is similar to using a lower screen resolution, but it applies\n" "Undersampling is similar to using a lower screen resolution, but it applies\n"
"to the game world only, keeping the GUI intact.\n" "to the game world only, keeping the GUI intact.\n"
@ -6892,7 +6888,10 @@ msgstr ""
"só para o mundo, mantendo a GUI intacta.\n" "só para o mundo, mantendo a GUI intacta.\n"
"Debería dar un aumento máis significativo do rendemento a costa dunha imaxe " "Debería dar un aumento máis significativo do rendemento a costa dunha imaxe "
"menos detallada.\n" "menos detallada.\n"
"Os valores máis altos dan como resultado unha imaxe menos detallada." "Os valores máis altos dan como resultado unha imaxe menos detallada.\n"
"Nota: A submostraxe actualmente non está soportada se a configuración "
"'3d_mode' está establecida\n"
"cun valor non predeterminado."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Unlimited player transfer distance" msgid "Unlimited player transfer distance"
@ -6919,11 +6918,13 @@ msgid "Use a cloud animation for the main menu background."
msgstr "Usa unha animación de nube para o fondo do menú principal." msgstr "Usa unha animación de nube para o fondo do menú principal."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Use anisotropic filtering when looking at textures from an angle.\n" "Use anisotropic filtering when looking at textures from an angle.\n"
"This provides a significant improvement when used together with mipmapping." "This provides a significant improvement when used together with mipmapping."
msgstr "Usar filtrado anisotrópico ao observar texturas desde un ángulo." msgstr ""
"Usar filtrado anisotrópico ao observar texturas desde un ángulo.\n"
"Isto proporciona unha mellora significativa cando se usa xunto con "
"mipmapping."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Use bilinear filtering when scaling textures." msgid "Use bilinear filtering when scaling textures."
@ -7195,7 +7196,6 @@ msgstr ""
"ao hardware (por exemplo, renderizado en textura para nós do inventario)." "ao hardware (por exemplo, renderizado en textura para nós do inventario)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"When using bilinear/trilinear filtering, low-resolution textures\n" "When using bilinear/trilinear filtering, low-resolution textures\n"
"can be blurred, so this option automatically upscales them to preserve\n" "can be blurred, so this option automatically upscales them to preserve\n"
@ -7206,17 +7206,16 @@ msgid ""
"This is also used as the base node texture size for world-aligned\n" "This is also used as the base node texture size for world-aligned\n"
"texture autoscaling." "texture autoscaling."
msgstr "" msgstr ""
"Cando se usan filtros bilineais/trilineais/anisótropos, texturas de baixa " "Cando se usa filtrado bilineal/trilineal, as texturas de baixa resolución\n"
"resolución\n" "poden quedar borrosas, polo que esta opción amplía automaticamente as "
"poden ser borrosas, polo que amplíaos automaticamente co veciño máis " "texturas para preservar\n"
"próximo\n" "píxeles nítidos. Isto define o tamaño mínimo da textura para as texturas "
"interpolación para preservar píxeles nítidos. Isto establece o tamaño mínimo " "ampliadas;\n"
"de textura\n" "valores máis altos son máis nítidos, pero requiren máis memoria.\n"
"para as texturas mejoradas; valores máis altos parecen máis nítidos, pero " "Esta configuración APLÍCASE SÓ se algún dos filtros mencionados está "
"requiren máis\n" "habilitado.\n"
"memoria. Recoméndase potencias de 2. Esta configuración só se aplica se\n" "Este tamén se usa como tamaño de textura do nodo base para aliñados ao "
"O filtrado bilineal/trilineal/anisótropo está activado.\n" "mundo\n"
"Tamén se usa como tamaño de textura do nodo base para aliñados ao mundo\n"
"autoescalado de texturas." "autoescalado de texturas."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -7253,17 +7252,16 @@ msgid "Whether to fog out the end of the visible area."
msgstr "Indica se hai que poñar néboa ao final da zona visible." msgstr "Indica se hai que poñar néboa ao final da zona visible."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Whether to mute sounds. You can unmute sounds at any time.\n" "Whether to mute sounds. You can unmute sounds at any time.\n"
"In-game, you can toggle the mute state with the mute key or by using the\n" "In-game, you can toggle the mute state with the mute key or by using the\n"
"pause menu." "pause menu."
msgstr "" msgstr ""
"Indica se hai que silenciar os sons. Podes activar o son en calquera " "Se activar ou desactivar os sons. Pódese reactivar o son en calquera momento."
"momento, a non ser que\n" "\n"
"esté desactivado (enable_sound=false).\n" "No xogo, podes alternar o estado de silencio coa tecla de silencio ou "
"No xogo podes cambiar o estado de silencio coa tecla de silencio ou no\n" "utilizando\n"
"menú de pausa." "o menú de pausa."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: Indonesian (Minetest)\n" "Project-Id-Version: Indonesian (Minetest)\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2024-12-22 16:00+0000\n" "PO-Revision-Date: 2025-02-11 02:02+0000\n"
"Last-Translator: Linerly <linerly@proton.me>\n" "Last-Translator: Linerly <linerly@proton.me>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/minetest/" "Language-Team: Indonesian <https://hosted.weblate.org/projects/minetest/"
"minetest/id/>\n" "minetest/id/>\n"
@ -263,14 +263,12 @@ msgid "Show technical names"
msgstr "Tampilkan nama teknis" msgstr "Tampilkan nama teknis"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Layar Sentuh" msgstr "Tata letak layar sentuh"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "pause_menu" msgid "pause_menu"
msgstr "FPS (bingkai per detik) pada menu jeda" msgstr "pause_menu"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -608,6 +606,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Ini daftar klien yang terhubung ke\n"
"$1"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"
@ -967,21 +967,20 @@ msgstr ""
"akan menimpa penggantian nama yang ada." "akan menimpa penggantian nama yang ada."
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
#, fuzzy
msgid "Expand all" msgid "Expand all"
msgstr "Nyalakan semua" msgstr "Buka semua"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "Group by prefix" msgid "Group by prefix"
msgstr "" msgstr "Kelompokkan berdasarkan awalan"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses a game called $2 and the following mods:" msgid "The $1 server uses a game called $2 and the following mods:"
msgstr "" msgstr "Server $1 menggunakan permainan bernama $2 dan mod berikut:"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses the following mods:" msgid "The $1 server uses the following mods:"
msgstr "" msgstr "Server $1 menggunakan mod berikut:"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "A new $1 version is available" msgid "A new $1 version is available"
@ -1193,20 +1192,20 @@ msgid "You need to install a game before you can create a world."
msgstr "Anda perlu pasang sebuah permainan sebelum bisa membuat dunia." msgstr "Anda perlu pasang sebuah permainan sebelum bisa membuat dunia."
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Add favorite" msgid "Add favorite"
msgstr "Hapus favorit" msgstr "Tambahkan favorit"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Address" msgid "Address"
msgstr "Alamat" msgstr "Alamat"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Clients:\n" "Clients:\n"
"$1" "$1"
msgstr "Klien" msgstr ""
"Klien:\n"
"$1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Creative mode" msgid "Creative mode"
@ -1222,9 +1221,8 @@ msgid "Favorites"
msgstr "Favorit" msgstr "Favorit"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Game: $1" msgid "Game: $1"
msgstr "Permainan" msgstr "Permainan: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Incompatible Servers" msgid "Incompatible Servers"
@ -1239,14 +1237,12 @@ msgid "Login"
msgstr "Masuk" msgstr "Masuk"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Number of mods: $1" msgid "Number of mods: $1"
msgstr "Jumlah utas kemunculan" msgstr "Jumlah mod: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Open server website" msgid "Open server website"
msgstr "Langkah server khusus" msgstr "Buka situs web server"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Ping" msgid "Ping"
@ -1259,6 +1255,10 @@ msgid ""
"mod:<name>\n" "mod:<name>\n"
"player:<name>" "player:<name>"
msgstr "" msgstr ""
"Filter yang memungkinkan\n"
"game:<nama>\n"
"mod:<nama>\n"
"player:<name>"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Public Servers" msgid "Public Servers"
@ -1354,9 +1354,8 @@ msgid "Access denied. Reason: %s"
msgstr "Akses ditolak. Alasan: %s" msgstr "Akses ditolak. Alasan: %s"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "All debug info hidden" msgid "All debug info hidden"
msgstr "Info awakutu ditampilkan" msgstr "Semua info awakutu disembunyikan"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Automatic forward disabled" msgid "Automatic forward disabled"
@ -1380,7 +1379,7 @@ msgstr "Batasan blok ditampilkan untuk blok sekitar"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Bounding boxes shown" msgid "Bounding boxes shown"
msgstr "" msgstr "Kotak ikatan ditampilkan"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Camera update disabled" msgid "Camera update disabled"
@ -1623,9 +1622,8 @@ msgid "Volume changed to %d%%"
msgstr "Volume diubah ke %d%%" msgstr "Volume diubah ke %d%%"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "Wireframe not supported by video driver" msgid "Wireframe not supported by video driver"
msgstr "Shader dinyalakan, tetapi GLSL tidak didukung oleh pengandar." msgstr "Kerangka tidak didukung oleh pengandar video"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Wireframe shown" msgid "Wireframe shown"
@ -2058,9 +2056,8 @@ msgid "Failed to compile the \"%s\" shader."
msgstr "Gagal mengompilasi shader \"%s\"." msgstr "Gagal mengompilasi shader \"%s\"."
#: src/client/shader.cpp #: src/client/shader.cpp
#, fuzzy
msgid "GLSL is not supported by the driver" msgid "GLSL is not supported by the driver"
msgstr "Shader dinyalakan, tetapi GLSL tidak didukung oleh pengandar." msgstr "GLSL tidak didukung oleh pengandar"
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3" #. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2297,35 +2294,33 @@ msgid "Sound Volume: %d%%"
msgstr "Volume Suara: %d%%" msgstr "Volume Suara: %d%%"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Add button" msgid "Add button"
msgstr "Klik Tengah" msgstr "Tambahkan tombol"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Done" msgid "Done"
msgstr "Selesai!" msgstr "Selesai"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Remove" msgid "Remove"
msgstr "Server jarak jauh" msgstr "Hapus"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Atur ulang"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Start dragging a button to add. Tap outside to cancel." msgid "Start dragging a button to add. Tap outside to cancel."
msgstr "" msgstr ""
"Mulai menarik tombol untuk menambahkan. Ketuk di luar untuk membatalkan."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap a button to select it. Drag a button to move it." msgid "Tap a button to select it. Drag a button to move it."
msgstr "" msgstr "Ketuk tombol untuk memilih. Tarik tombol untuk memindahkan."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap outside to deselect." msgid "Tap outside to deselect."
msgstr "" msgstr "Ketuk di luar untuk membatalkan pilihan."
#: src/gui/touchscreenlayout.cpp #: src/gui/touchscreenlayout.cpp
msgid "Joystick" msgid "Joystick"
@ -2553,7 +2548,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
msgstr "Noise 3D yang mengatur jumlah dungeon per potongan peta." msgstr "Noise 3D yang mengatur jumlah dungeon per potongan peta."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"3D support.\n" "3D support.\n"
"Currently supported:\n" "Currently supported:\n"
@ -2571,8 +2565,7 @@ msgstr ""
"- interlaced: garis ganjil/genap berdasarkan polarisasi layar.\n" "- interlaced: garis ganjil/genap berdasarkan polarisasi layar.\n"
"- topbottom: pisahkan layar atas/bawah.\n" "- topbottom: pisahkan layar atas/bawah.\n"
"- sidebyside: pisahkan layar kiri/kanan.\n" "- sidebyside: pisahkan layar kiri/kanan.\n"
"- crossview: 3d dengan pandang silang\n" "- crossview: 3d dengan pandang silang"
"Catat bahwa mode interlaced memerlukan penggunaan shader."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -2661,11 +2654,12 @@ msgid ""
"All mesh buffers with less than this number of vertices will be merged\n" "All mesh buffers with less than this number of vertices will be merged\n"
"during map rendering. This improves rendering performance." "during map rendering. This improves rendering performance."
msgstr "" msgstr ""
"Semua penyangga jaring kurang dari jumlah verteks ini akan digabungkan\n"
"saat perenderan peta. Ini meningkatkan performa perenderan."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Allow clouds to look 3D instead of flat." msgid "Allow clouds to look 3D instead of flat."
msgstr "Gunakan tampilan awan 3D alih-alih datar." msgstr "Perbolehkan awan terlihat 3D daripada datar."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Allows liquids to be translucent." msgid "Allows liquids to be translucent."
@ -3075,7 +3069,7 @@ msgstr "Awan dalam menu"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Color depth for post-processing texture" msgid "Color depth for post-processing texture"
msgstr "" msgstr "Kedalaman warna untuk tekstur pasca-pemrosesan"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Colored fog" msgid "Colored fog"
@ -3095,7 +3089,6 @@ msgstr ""
"Berguna untuk pengujian. Lihat al_extensions.[h,cpp] untuk detailnya." "Berguna untuk pengujian. Lihat al_extensions.[h,cpp] untuk detailnya."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Comma-separated list of flags to hide in the content repository.\n" "Comma-separated list of flags to hide in the content repository.\n"
"\"nonfree\" can be used to hide packages which do not qualify as 'free " "\"nonfree\" can be used to hide packages which do not qualify as 'free "
@ -3281,6 +3274,11 @@ msgid ""
"Reducing this can improve performance, but some effects (e.g. debanding)\n" "Reducing this can improve performance, but some effects (e.g. debanding)\n"
"require more than 8 bits to work." "require more than 8 bits to work."
msgstr "" msgstr ""
"Tentukan kedalaman warna tekstur yang digunakan untuk alur pasca-pemrosesan."
"\n"
"Mengurangi ini dapat meningkatkan performa, tetapi beberapa efek (mis. "
"debanding)\n"
"memerlukan lebih dari 8 bit supaya bekerja."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dedicated server step" msgid "Dedicated server step"
@ -3500,6 +3498,11 @@ msgid ""
"situations\n" "situations\n"
"where transparency sorting would be very slow otherwise." "where transparency sorting would be very slow otherwise."
msgstr "" msgstr ""
"Gambar segitiga diurutkan berdasarkan transparansi berdasarkan penyangga "
"jaringnya.\n"
"Ini merusak pengurutan transparansi antara penyangga jaring, tetapi "
"menghindari situasi\n"
"di mana pengurutan transparansi akan menjadi lebih lambat."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dump the mapgen debug information." msgid "Dump the mapgen debug information."
@ -3584,14 +3587,12 @@ msgstr ""
"menyimulasikan perilaku mata manusia." "menyimulasikan perilaku mata manusia."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable colored shadows for transculent nodes.\n" "Enable colored shadows for transculent nodes.\n"
"This is expensive." "This is expensive."
msgstr "" msgstr ""
"Menyalakan bayangan berwarna.\n" "Aktif kan bayangan berwarna untuk nodus translusen.\n"
"Nilai true berarti nodus agak tembus pandang memiliki bayangan berwarna. Ini " "Ini komputasi mahal."
"memerlukan sumber daya besar."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable console window" msgid "Enable console window"
@ -3670,14 +3671,12 @@ msgstr ""
"Contoh: 0 untuk tanpa view bobbing; 1.0 untuk normal; 2.0 untuk 2x lipat." "Contoh: 0 untuk tanpa view bobbing; 1.0 untuk normal; 2.0 untuk 2x lipat."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable/disable running an IPv6 server.\n" "Enable/disable running an IPv6 server.\n"
"Ignored if bind_address is set." "Ignored if bind_address is set."
msgstr "" msgstr ""
"Nyalakan/matikan server IPv6.\n" "Aktif kan/nonaktifkan menjalankan server IPv6.\n"
"Diabaikan jika bind_address telah diatur.\n" "Diabaikan jika bind_address telah diatur."
"Perlu menyalakan enable_ipv6."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -4323,14 +4322,14 @@ msgstr ""
"menggantinya dengan kata sandi kosong." "menggantinya dengan kata sandi kosong."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"If enabled, server account registration is separate from login in the UI.\n" "If enabled, server account registration is separate from login in the UI.\n"
"If disabled, connecting to a server will automatically register a new " "If disabled, connecting to a server will automatically register a new "
"account." "account."
msgstr "" msgstr ""
"Jika dinyalakan, tampilan pendaftaran akun dan masuk akan dipisah.\n" "Jika diaktifkan, pendaftaran akun server terpisah dari log masuk dalam UI.\n"
"Jika dimatikan, akun baru akan didaftarkan secara otomatis saat masuk." "Jika dinonaktifkan, menghubungkan ke server akan mendaftarkan akun secara "
"otomatis."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5204,7 +5203,7 @@ msgstr "Batas minimal nilai acak untuk gua kecil per potongan peta."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Minimum vertex count for mesh buffers" msgid "Minimum vertex count for mesh buffers"
msgstr "" msgstr "Jumlah verteks minimum untuk penyangga jaring"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Mipmapping" msgid "Mipmapping"
@ -5299,16 +5298,15 @@ msgstr ""
"- \"floatlands\" pada pembuat peta v7 (dimatikan secara bawaan)." "- \"floatlands\" pada pembuat peta v7 (dimatikan secara bawaan)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Name of the player.\n" "Name of the player.\n"
"When running a server, a client connecting with this name is admin.\n" "When running a server, a client connecting with this name is admin.\n"
"When starting from the main menu, this is overridden." "When starting from the main menu, this is overridden."
msgstr "" msgstr ""
"Nama si pemain.\n" "Nama pemain.\n"
"Saat menjalankan server, klien yang tersambung dengan nama ini adalah " "Saat menjalankan server, klien yang tersambung dengan nama ini adalah admin."
"pengurus.\n" "\n"
"Saat menjalankan dari menu utama, nilai ini ditimpa." "Saat memulai dari menu utama, ini ditimpa."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5814,7 +5812,6 @@ msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
msgstr "Lihat https://www.sqlite.org/pragma.html#pragma_synchronous" msgstr "Lihat https://www.sqlite.org/pragma.html#pragma_synchronous"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Select the antialiasing method to apply.\n" "Select the antialiasing method to apply.\n"
"\n" "\n"
@ -5837,26 +5834,46 @@ msgid ""
"Renders higher-resolution image of the scene, then scales down to reduce\n" "Renders higher-resolution image of the scene, then scales down to reduce\n"
"the aliasing effects. This is the slowest and the most accurate method." "the aliasing effects. This is the slowest and the most accurate method."
msgstr "" msgstr ""
"Pilih metode antialiasing yang akan diterapkan.\n" "Pilih metode antialiasing untuk diterapkan.\n"
"\n" "\n"
"* Tidak ada - Tidak ada antialiasing (bawaan)\n"
"\n" "\n"
"* FSAA - Antialiasing layar penuh yang disediakan perangkat keras\n"
"(tidak kompatibel dengan Post Processing dan Undersampling)\n"
"Antialiasing multi-sampel (MSAA)\n"
"Menghaluskan tepi blok, tetapi tidak memengaruhi bagian dalam tekstur.\n"
"Diperlukan pengaktifan ulang untuk mengubah opsi ini.\n"
"\n" "\n"
"* FXAA - Antialiasing perkiraan cepat (memerlukan shader)\n" "* Tidak ada - tidak ada antialiasing (default)\n"
"Menerapkan filter pasca-pemrosesan untuk mendeteksi dan memperhalus tepi " "\n"
"yang sangat kontras.\n" "\n"
"\n"
"* FSAA-Antialiasing layar penuh yang disediakan perangkat keras\n"
"\n"
"A.k.a antialiasing multi-sampel (MSAA)\n"
"\n"
"Menghancur tepi blok tetapi tidak mempengaruhi bagian dalam tekstur.\n"
"\n"
"\n"
"\n"
"Jika pemrosesan pos dinonaktifkan, mengubah FSAA memerlukan restart.\n"
"\n"
"Juga, jika pemrosesan pos dinonaktifkan, FSAA tidak akan bekerja sama "
"dengannya\n"
"\n"
"pengaturan undersampling atau non-default \"3D_MODE\".\n"
"\n"
"\n"
"\n"
"* Fxaa - perkiraan cepat antialiasing\n"
"\n"
"Menerapkan filter pasca pemrosesan untuk mendeteksi dan menghaluskan tepi "
"kontras tinggi.\n"
"\n"
"Memberikan keseimbangan antara kecepatan dan kualitas gambar.\n" "Memberikan keseimbangan antara kecepatan dan kualitas gambar.\n"
"\n" "\n"
"* SSAA - Antialiasing super-sampling (memerlukan shader)\n" "\n"
"Merender gambar pemandangan dengan resolusi lebih tinggi, kemudian " "\n"
"memperkecil skala untuk mengurangi\n" "* SSAA - Antialiasing Super -Sampling\n"
"mengurangi efek aliasing. Ini adalah metode yang paling lambat dan paling " "\n"
"akurat." "Membuat gambar resolusi yang lebih tinggi dari pemandangan itu, lalu "
"berskala ke bawah untuk mengurangi\n"
"\n"
"Efek aliasing. Ini adalah metode paling lambat dan paling akurat."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Selection box border color (R,G,B)." msgid "Selection box border color (R,G,B)."
@ -6283,16 +6300,15 @@ msgstr ""
"semua) barang." "semua) barang."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Spread a complete update of the shadow map over a given number of frames.\n" "Spread a complete update of the shadow map over a given number of frames.\n"
"Higher values might make shadows laggy, lower values\n" "Higher values might make shadows laggy, lower values\n"
"will consume more resources." "will consume more resources."
msgstr "" msgstr ""
"Menyebarkan pembaruan peta bayangan dalam jumlah bingkai yang diberikan.\n" "Sebarkan pembaruan lengkap peta bayangan pada sejumlah bingkai tertentu.\n"
"Nilai tinggi bisa membuat bayangan patah-patah, nilai rendah akan perlu\n" "Nilai yang lebih tinggi mungkin membuat bayangan lambat, nilai yang lebih "
"sumber daya lebih banyak.\n" "rendah\n"
"Nilai minimum: 1; nilai maksimum: 16" "akan mengkonsumsi lebih banyak sumber daya."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6721,9 +6737,8 @@ msgid "Transparency Sorting Distance"
msgstr "Jarak Pengurutan Transparansi" msgstr "Jarak Pengurutan Transparansi"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Transparency Sorting Group by Buffers" msgid "Transparency Sorting Group by Buffers"
msgstr "Jarak Pengurutan Transparansi" msgstr "Jarak Pengurutan Transparansi berdasarkan Penyangga"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Trees noise" msgid "Trees noise"
@ -6783,7 +6798,6 @@ msgid "Undersampling"
msgstr "Undersampling(Pengambilan sampel yang terlalu rendah)" msgstr "Undersampling(Pengambilan sampel yang terlalu rendah)"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Undersampling is similar to using a lower screen resolution, but it applies\n" "Undersampling is similar to using a lower screen resolution, but it applies\n"
"to the game world only, keeping the GUI intact.\n" "to the game world only, keeping the GUI intact.\n"
@ -6794,10 +6808,13 @@ msgid ""
"set\n" "set\n"
"to a non-default value." "to a non-default value."
msgstr "" msgstr ""
"Undersampling seperti menggunakan resolusi layar yang lebih rendah, tetapi\n" "Undersampling hampir mirip seperti menggunakan resolusi layer yang lebih "
"hanya berlaku untuk dunia permainan saja, antarmuka grafis tetap.\n" "rendah, tetapi hanya diterapkan ke dunia permainan saja sambil menjaga GUI.\n"
"Seharusnya memberikan dorongan kinerja dengan gambar yang kurang detail.\n" "Ini seharusnya memberikan peningkatan performa dengan mengurangi detail "
"Nilai yang lebih tinggi menghasilkan gambar yang kurang detail." "gambar.\n"
"Nilai yang lebih tinggi membuat detail gambar lebih sedikit.\n"
"Catatan: Undersampling saat ini tidak didukung jika pengaturan \"3d_mode\" "
"ditetapkan ke nilai non-bawaan."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Unlimited player transfer distance" msgid "Unlimited player transfer distance"
@ -6824,12 +6841,13 @@ msgid "Use a cloud animation for the main menu background."
msgstr "Gunakan animasi awan untuk latar belakang menu utama." msgstr "Gunakan animasi awan untuk latar belakang menu utama."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Use anisotropic filtering when looking at textures from an angle.\n" "Use anisotropic filtering when looking at textures from an angle.\n"
"This provides a significant improvement when used together with mipmapping." "This provides a significant improvement when used together with mipmapping."
msgstr "" msgstr ""
"Gunakan pemfilteran anisotropik saat melihat tekstur pada sudut tertentu." "Gunakan pemfilteran anisotropik saat melihat tekstur pada sudut tertentu.\n"
"Ini menyediakan peningkatan yang lebih baik ketika digunakan bersama dengan "
"mipmapping."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Use bilinear filtering when scaling textures." msgid "Use bilinear filtering when scaling textures."
@ -7102,7 +7120,6 @@ msgstr ""
"perangkat keras (misal gambar ke tekstur untuk nodus dalam inventaris)." "perangkat keras (misal gambar ke tekstur untuk nodus dalam inventaris)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"When using bilinear/trilinear filtering, low-resolution textures\n" "When using bilinear/trilinear filtering, low-resolution textures\n"
"can be blurred, so this option automatically upscales them to preserve\n" "can be blurred, so this option automatically upscales them to preserve\n"
@ -7113,15 +7130,18 @@ msgid ""
"This is also used as the base node texture size for world-aligned\n" "This is also used as the base node texture size for world-aligned\n"
"texture autoscaling." "texture autoscaling."
msgstr "" msgstr ""
"Saat menggunakan filter bilinear/trilinear/anisotropik, tekstur resolusi\n" "Saat menggunakan pemfilteran bilinear/trilinear, tekstur resolusi rendah\n"
"rendah dapat dikaburkan sehingga diperbesar otomatis dengan interpolasi\n" "bisa dikaburkan, jadi opsi ini secara otomatis meningkatkannya untuk "
"nearest-neighbor untuk menjaga ketajaman piksel. Ini mengatur ukuran\n" "menjaga\n"
"tekstur minimum untuk tekstur yang diperbesar; semakin tinggi semakin\n" "piksel tajam. Ini mendefinisikan ukuran tekstur minimum untuk tekstur yang "
"tajam, tetapi butuh memori lebih. Perpangkatan dua disarankan. Pengaturan\n" "ditingkatkan;\n"
"ini HANYA diterapkan jika menggunakan filter bilinear/trilinear/" "Nilai yang lebih tinggi terlihat lebih tajam, tetapi membutuhkan lebih "
"anisotropik.\n" "banyak memori.\n"
"Ini juga digunakan sebagai ukuran dasar tekstur nodus untuk penyekalaan\n" "Pengaturan ini hanya diterapkan jika salah satu filter yang disebutkan "
"otomatis tekstur yang sejajar dengan dunia." "diaktifkan.\n"
"Ini juga digunakan sebagai ukuran tekstur simpul dasar untuk dunia yang "
"selaras\n"
"Tekstur Autoscaling."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -7156,16 +7176,15 @@ msgid "Whether to fog out the end of the visible area."
msgstr "Apakah harus memberi kabut pada akhir daerah yang terlihat." msgstr "Apakah harus memberi kabut pada akhir daerah yang terlihat."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Whether to mute sounds. You can unmute sounds at any time.\n" "Whether to mute sounds. You can unmute sounds at any time.\n"
"In-game, you can toggle the mute state with the mute key or by using the\n" "In-game, you can toggle the mute state with the mute key or by using the\n"
"pause menu." "pause menu."
msgstr "" msgstr ""
"Apakah akan membisukan suara atau tidak. Anda dapat membunyikan\n" "Apakah suara dibisukan atau tidak. Kamu bisa membunyikan suara kapan pun.\n"
"suara kapan pun, kecuali sistem suara dimatikan (enable_sound = false).\n" "Dalam permainan, kamu bisa sakelar keadaan bisu dengan tombol bisikan atau "
"Dalam permainan, Anda dapat beralih mode bisu dengan tombol bisu\n" "menggunakan\n"
"atau melalui menu jeda." "menu jeda."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: Russian (Minetest)\n" "Project-Id-Version: Russian (Minetest)\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-09 13:23+0100\n" "POT-Creation-Date: 2025-02-09 13:23+0100\n"
"PO-Revision-Date: 2025-01-27 06:02+0000\n" "PO-Revision-Date: 2025-02-12 12:18+0000\n"
"Last-Translator: BlackImpostor <SkyBuilderOFFICAL@yandex.ru>\n" "Last-Translator: BlackImpostor <SkyBuilderOFFICAL@yandex.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/minetest/" "Language-Team: Russian <https://hosted.weblate.org/projects/minetest/"
"minetest/ru/>\n" "minetest/ru/>\n"
@ -264,14 +264,12 @@ msgid "Show technical names"
msgstr "Показывать технические названия" msgstr "Показывать технические названия"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "Touchscreen layout" msgid "Touchscreen layout"
msgstr "Сенсорный экран" msgstr "Pазложение сенсорного экрана"
#: builtin/common/settings/dlg_settings.lua #: builtin/common/settings/dlg_settings.lua
#, fuzzy
msgid "pause_menu" msgid "pause_menu"
msgstr "Кадровая частота во время паузы" msgstr "меню_паузы"
#: builtin/common/settings/settingtypes.lua #: builtin/common/settings/settingtypes.lua
msgid "Client Mods" msgid "Client Mods"
@ -609,6 +607,8 @@ msgid ""
"This is the list of clients connected to\n" "This is the list of clients connected to\n"
"$1" "$1"
msgstr "" msgstr ""
"Это список подключённых клиентов к\n"
"$1"
#: builtin/mainmenu/dlg_config_world.lua #: builtin/mainmenu/dlg_config_world.lua
msgid "(Enabled, has error)" msgid "(Enabled, has error)"
@ -972,21 +972,21 @@ msgstr ""
"перезапишет указанное здесь значение." "перезапишет указанное здесь значение."
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
#, fuzzy
msgid "Expand all" msgid "Expand all"
msgstr "Включить всё" msgstr "Расширить всё"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "Group by prefix" msgid "Group by prefix"
msgstr "" msgstr "Сгруппировать по префиксу"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses a game called $2 and the following mods:" msgid "The $1 server uses a game called $2 and the following mods:"
msgstr "" msgstr ""
"На сервере $1 используется игра под названием $2 со следующими дополнениями:"
#: builtin/mainmenu/dlg_server_list_mods.lua #: builtin/mainmenu/dlg_server_list_mods.lua
msgid "The $1 server uses the following mods:" msgid "The $1 server uses the following mods:"
msgstr "" msgstr "Сервер $1 использует следующие дополнения:"
#: builtin/mainmenu/dlg_version_info.lua #: builtin/mainmenu/dlg_version_info.lua
msgid "A new $1 version is available" msgid "A new $1 version is available"
@ -1198,20 +1198,20 @@ msgid "You need to install a game before you can create a world."
msgstr "Вам требуется установить игру, прежде чем вы сможете создать мир." msgstr "Вам требуется установить игру, прежде чем вы сможете создать мир."
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Add favorite" msgid "Add favorite"
msgstr "Удалить избранное" msgstr "Добавить избранное"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Address" msgid "Address"
msgstr "Адрес" msgstr "Адрес"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "" msgid ""
"Clients:\n" "Clients:\n"
"$1" "$1"
msgstr "Клиент" msgstr ""
"Клиенты:\n"
"$1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Creative mode" msgid "Creative mode"
@ -1227,9 +1227,8 @@ msgid "Favorites"
msgstr "Избранное" msgstr "Избранное"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Game: $1" msgid "Game: $1"
msgstr "Игра" msgstr "Игра: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Incompatible Servers" msgid "Incompatible Servers"
@ -1244,14 +1243,12 @@ msgid "Login"
msgstr "Войти" msgstr "Войти"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Number of mods: $1" msgid "Number of mods: $1"
msgstr "Количество потоков подгрузки" msgstr "Количество модов: $1"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
#, fuzzy
msgid "Open server website" msgid "Open server website"
msgstr "Шаг выделенного сервера" msgstr "Открыть веб-сайт сервера"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Ping" msgid "Ping"
@ -1264,6 +1261,10 @@ msgid ""
"mod:<name>\n" "mod:<name>\n"
"player:<name>" "player:<name>"
msgstr "" msgstr ""
"Возможные фильтры\n"
"игра:<имя>\n"
"дополнение:<имя>\n"
"игрок:<имя>"
#: builtin/mainmenu/tab_online.lua #: builtin/mainmenu/tab_online.lua
msgid "Public Servers" msgid "Public Servers"
@ -1359,9 +1360,8 @@ msgid "Access denied. Reason: %s"
msgstr "Доступ запрещён. Причина: %s" msgstr "Доступ запрещён. Причина: %s"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "All debug info hidden" msgid "All debug info hidden"
msgstr "Отладочные сведения отображены" msgstr "Все отладочные сведения скрыты"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Automatic forward disabled" msgid "Automatic forward disabled"
@ -1385,7 +1385,7 @@ msgstr "Границы показаны для ближайших мапблок
#: src/client/game.cpp #: src/client/game.cpp
msgid "Bounding boxes shown" msgid "Bounding boxes shown"
msgstr "" msgstr "Показаны ограничивающие рамки"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Camera update disabled" msgid "Camera update disabled"
@ -1623,9 +1623,8 @@ msgid "Volume changed to %d%%"
msgstr "Громкость установлена на %d%%" msgstr "Громкость установлена на %d%%"
#: src/client/game.cpp #: src/client/game.cpp
#, fuzzy
msgid "Wireframe not supported by video driver" msgid "Wireframe not supported by video driver"
msgstr "Шейдеры включены, но GLSL не поддерживается драйвером." msgstr "Полигоны не доступны этим видео драйвером"
#: src/client/game.cpp #: src/client/game.cpp
msgid "Wireframe shown" msgid "Wireframe shown"
@ -2058,9 +2057,8 @@ msgid "Failed to compile the \"%s\" shader."
msgstr "Не удалось скомпилировать шейдер «%s»." msgstr "Не удалось скомпилировать шейдер «%s»."
#: src/client/shader.cpp #: src/client/shader.cpp
#, fuzzy
msgid "GLSL is not supported by the driver" msgid "GLSL is not supported by the driver"
msgstr "Шейдеры включены, но GLSL не поддерживается драйвером." msgstr "GLSL не поддерживается драйвером"
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3" #. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
#: src/content/mod_configuration.cpp #: src/content/mod_configuration.cpp
@ -2296,35 +2294,35 @@ msgid "Sound Volume: %d%%"
msgstr "Громкость звука: %d%%" msgstr "Громкость звука: %d%%"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Add button" msgid "Add button"
msgstr "Средняя кнопка" msgstr "Добавить кнопку"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Done" msgid "Done"
msgstr "Готово!" msgstr "Готово"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
#, fuzzy
msgid "Remove" msgid "Remove"
msgstr "Удалённый сервер" msgstr "Убрать"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Сбросить"
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Start dragging a button to add. Tap outside to cancel." msgid "Start dragging a button to add. Tap outside to cancel."
msgstr "" msgstr ""
"Начните перетаскивать кнопку, чтобы добавить. Нажмите \"За пределами\", "
"чтобы отменить."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap a button to select it. Drag a button to move it." msgid "Tap a button to select it. Drag a button to move it."
msgstr "" msgstr ""
"Нажмите на кнопку, чтобы выбрать её. Перетащите кнопку, чтобы перемещать её."
#: src/gui/touchscreeneditor.cpp #: src/gui/touchscreeneditor.cpp
msgid "Tap outside to deselect." msgid "Tap outside to deselect."
msgstr "" msgstr "Нажмите \"Снаружи\", чтобы отменить выбор."
#: src/gui/touchscreenlayout.cpp #: src/gui/touchscreenlayout.cpp
msgid "Joystick" msgid "Joystick"
@ -2555,7 +2553,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
msgstr "3D-шум, определяющий количество подземелий на мапчанк карты." msgstr "3D-шум, определяющий количество подземелий на мапчанк карты."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"3D support.\n" "3D support.\n"
"Currently supported:\n" "Currently supported:\n"
@ -2566,15 +2563,14 @@ msgid ""
"- sidebyside: split screen side by side.\n" "- sidebyside: split screen side by side.\n"
"- crossview: Cross-eyed 3d" "- crossview: Cross-eyed 3d"
msgstr "" msgstr ""
"3D-анаглиф.\n" "Поддержка 3D.\n"
"Сейчас поддерживаются:\n" "Сейчас поддерживаются:\n"
"- none: без 3D.\n" "- none: без 3d выхода.\n"
"- anaglyph: для красно/синих очков.\n" "- anaglyph: для красно/синих очков.\n"
"- interlaced: поляризация с чётными/нечётными линиями.\n" "- interlaced: поляризация с чётными/нечётными линиями.\n"
"- topbottom: горизонтальное разделение экрана.\n" "- topbottom: горизонтальное разделение экрана.\n"
"- sidebyside: вертикальное разделение экрана.\n" "- sidebyside: вертикальное разделение экрана.\n"
"- crossview: перекрёстная стереопара.\n" "- crossview: перекрёстная стереопара 3d"
"Примечание: для режима «interlaced» должны быть включены шейдеры."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -2663,11 +2659,12 @@ msgid ""
"All mesh buffers with less than this number of vertices will be merged\n" "All mesh buffers with less than this number of vertices will be merged\n"
"during map rendering. This improves rendering performance." "during map rendering. This improves rendering performance."
msgstr "" msgstr ""
"Все буферы мешей с меньшим количеством вершин будут объединены\n"
"во время рендера карты. Это повышает производительность рендеринга."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Allow clouds to look 3D instead of flat." msgid "Allow clouds to look 3D instead of flat."
msgstr "Объёмные облака вместо плоских." msgstr "Позволяет облакам выглядеть больше 3D, чем плоскими."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Allows liquids to be translucent." msgid "Allows liquids to be translucent."
@ -3080,7 +3077,7 @@ msgstr "Облака в меню"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Color depth for post-processing texture" msgid "Color depth for post-processing texture"
msgstr "" msgstr "Глубина цвета для постобработки текстуры"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Colored fog" msgid "Colored fog"
@ -3101,7 +3098,6 @@ msgstr ""
"[h,cpp]." "[h,cpp]."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Comma-separated list of flags to hide in the content repository.\n" "Comma-separated list of flags to hide in the content repository.\n"
"\"nonfree\" can be used to hide packages which do not qualify as 'free " "\"nonfree\" can be used to hide packages which do not qualify as 'free "
@ -3112,12 +3108,12 @@ msgid ""
"so see a full list at https://content.luanti.org/help/content_flags/" "so see a full list at https://content.luanti.org/help/content_flags/"
msgstr "" msgstr ""
"Список разделенных запятыми флажков для скрытия в хранилище контента.\n" "Список разделенных запятыми флажков для скрытия в хранилище контента.\n"
"\"nonfree\" может использоваться для скрытия пакетов,\n" "«несвободный» может использоваться для скрытия пакетов, которые не подпадают "
"которые не подпадают под категорию Free Software Foundation,\n" "под категорию «свободного программного обеспечения»,\n"
"как это определено Фондом свободного программного обеспечения.\n" "как это определено Фондом Свободного Программного Обеспечения.\n"
"Вы также можете указать рейтинг контента. Эти флаги не зависят от версий " "Вы также можете указать рейтинг контента.\n"
"Luanti,\n" "Эти флаги не зависят от версий Luanti,\n"
"поэтому смотрите полный список по адресу https://content.minetest.net/help/" "поэтому смотрите полный список по адресу https://content.luanti.org/help/"
"content_flags/" "content_flags/"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
@ -3287,6 +3283,11 @@ msgid ""
"Reducing this can improve performance, but some effects (e.g. debanding)\n" "Reducing this can improve performance, but some effects (e.g. debanding)\n"
"require more than 8 bits to work." "require more than 8 bits to work."
msgstr "" msgstr ""
"Определить глубину цвета текстуры, используемой для конвейера постобработки."
"\n"
"Уменьшение этого параметра может повысить производительность, но для работы "
"некоторых эффектов (например, для удаления пятен)\n"
"требуется более 8 бит."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dedicated server step" msgid "Dedicated server step"
@ -3507,6 +3508,11 @@ msgid ""
"situations\n" "situations\n"
"where transparency sorting would be very slow otherwise." "where transparency sorting would be very slow otherwise."
msgstr "" msgstr ""
"Рисовать треугольники, отсортированные по прозрачности, сгруппированные по "
"их меш буферам.\n"
"Это нарушает сортировку по прозрачности между меш буферами, но позволяет "
"избежать ситуаций,\n"
"когда в противном случае сортировка по прозрачности была бы очень медленной."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Dump the mapgen debug information." msgid "Dump the mapgen debug information."
@ -3591,14 +3597,12 @@ msgstr ""
"имитируя поведение человеческого глаза." "имитируя поведение человеческого глаза."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable colored shadows for transculent nodes.\n" "Enable colored shadows for transculent nodes.\n"
"This is expensive." "This is expensive."
msgstr "" msgstr ""
"Включить цветные тени.\n" "Включите цветные тени для трансгенных блоков.\n"
"Когда включено, прозрачные ноды отбрасывают цветные тени. Это " "Это дорого."
"ресурсозатратно."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Enable console window" msgid "Enable console window"
@ -3681,14 +3685,12 @@ msgstr ""
"Например: 0 отключает покачивание, 1.0 для обычного, 2.0 для двойного." "Например: 0 отключает покачивание, 1.0 для обычного, 2.0 для двойного."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Enable/disable running an IPv6 server.\n" "Enable/disable running an IPv6 server.\n"
"Ignored if bind_address is set." "Ignored if bind_address is set."
msgstr "" msgstr ""
"Включить/отключить запуск IPv6-сервера.\n" "Включить/отключить запуск сервера IPv6.\n"
"Игнорируется, если задан «bind_address».\n" "Игнорируется, если задан параметр bind_address."
"Для включения необходим «enable_ipv6»."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -4333,16 +4335,15 @@ msgstr ""
"Если включено, то новые игроки не смогут подключаться с пустым паролем." "Если включено, то новые игроки не смогут подключаться с пустым паролем."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"If enabled, server account registration is separate from login in the UI.\n" "If enabled, server account registration is separate from login in the UI.\n"
"If disabled, connecting to a server will automatically register a new " "If disabled, connecting to a server will automatically register a new "
"account." "account."
msgstr "" msgstr ""
"Если включено, регистрация аккаунта выполняется в интерфейсе отдельно от " "Если этот параметр включен, регистрация учетной записи сервера выполняется "
"входа.\n" "отдельно от входа в пользовательский интерфейс.\n"
"Если отключено, новые учётные записи будут регистрироваться автоматически " "Если он отключен, при подключении к серверу автоматически регистрируется "
"при входе." "новая учетная запись."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5212,7 +5213,7 @@ msgstr "Минимум малых пещер на мапчанк."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Minimum vertex count for mesh buffers" msgid "Minimum vertex count for mesh buffers"
msgstr "" msgstr "Минимальное количество вершин для меш буферов"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Mipmapping" msgid "Mipmapping"
@ -5307,15 +5308,15 @@ msgstr ""
"- Дополнительные парящие острова из v7 (выключено по умолчанию)." "- Дополнительные парящие острова из v7 (выключено по умолчанию)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Name of the player.\n" "Name of the player.\n"
"When running a server, a client connecting with this name is admin.\n" "When running a server, a client connecting with this name is admin.\n"
"When starting from the main menu, this is overridden." "When starting from the main menu, this is overridden."
msgstr "" msgstr ""
"Имя игрока.\n" "Имя игрока.\n"
"При запуске сервера клиенты с этим именем будут администраторами.\n" "При запуске сервера клиент, подключающийся под этим именем, является "
"Будет переопределено при запуске из главного меню." "администратором.\n"
"При запуске из главного меню это значение переопределяется."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -5824,7 +5825,6 @@ msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
msgstr "См. http://www.sqlite.org/pragma.html#pragma_synchronous" msgstr "См. http://www.sqlite.org/pragma.html#pragma_synchronous"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Select the antialiasing method to apply.\n" "Select the antialiasing method to apply.\n"
"\n" "\n"
@ -5849,25 +5849,27 @@ msgid ""
msgstr "" msgstr ""
"Выберите метод сглаживания, который необходимо применить.\n" "Выберите метод сглаживания, который необходимо применить.\n"
"\n" "\n"
"* * Нет - сглаживание отсутствует (по умолчанию).\n" "* None - Нет сглаживания (по умолчанию)\n"
"\n" "\n"
"* FSAA - Аппаратное полноэкранное сглаживание\n" "* FSAA - Аппаратное полноэкранное сглаживание,\n"
"(несовместимое с постобработкой и недостаточной дискретизацией)\n" "аналогичное сглаживанию с несколькими выборками (MSAA).\n"
", аналогичное сглаживанию с несколькими выборками (MSAA)\n"
"Сглаживает края блоков, но не влияет на внутреннюю часть текстур.\n" "Сглаживает края блоков, но не влияет на внутреннюю часть текстур.\n"
"Для изменения этого параметра требуется перезагрузка.\n"
"\n" "\n"
"* FXAA - Быстрое приблизительное сглаживание (требуется использование " "Если постобработка отключена, для изменения FSAA требуется перезапуск.\n"
"шейдеров)\n" "Кроме того, если постобработка отключена, FSAA не будет работать в сочетании "
"Применяется фильтр последующей обработки для обнаружения и сглаживания " "с\n"
"недостаточной дискретизацией или настройкой \"3d_mode\", не используемой по "
"умолчанию.\n"
"\n"
"* FXAA - Быстрое приблизительное сглаживание\n"
"Применяет фильтр последующей обработки для обнаружения и сглаживания "
"высококонтрастных краев.\n" "высококонтрастных краев.\n"
"Обеспечивает баланс между скоростью и качеством изображения.\n" "Обеспечивает баланс между скоростью и качеством изображения.\n"
"\n" "\n"
"* SSAA - сглаживание с использованием суперсэмплирования (требуются " "* SSAA - Сглаживание с использованием суперсэмплирования\n"
"шейдеры)\n" "Позволяет получить изображение сцены с более высоким разрешением, а затем "
"Визуализирует изображение сцены с более высоким разрешением, затем уменьшает " "уменьшить масштаб, чтобы уменьшить\n"
"масштаб, чтобы уменьшить\n" "эффекты сглаживания. Это самый медленный и точный метод."
"эффекты наложения. Это самый медленный и точный метод."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Selection box border color (R,G,B)." msgid "Selection box border color (R,G,B)."
@ -6300,17 +6302,14 @@ msgstr ""
"(или всех) предметов." "(или всех) предметов."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Spread a complete update of the shadow map over a given number of frames.\n" "Spread a complete update of the shadow map over a given number of frames.\n"
"Higher values might make shadows laggy, lower values\n" "Higher values might make shadows laggy, lower values\n"
"will consume more resources." "will consume more resources."
msgstr "" msgstr ""
"Распространяет полное обновление карты теней на заданное количество кадров.\n" "Распространить полное обновление карты теней на заданное количество кадров.\n"
"Более высокие значения могут сделать тени нестабильными, более низкие " "Более высокие значения могут привести к запаздыванию теней,\n"
"значения\n" "более низкие значения потребляют больше ресурсов."
"будут потреблять больше ресурсов.\n"
"Минимум: 1; максимум: 16"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -6753,9 +6752,8 @@ msgid "Transparency Sorting Distance"
msgstr "Дальность сортировки по прозрачности" msgstr "Дальность сортировки по прозрачности"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "Transparency Sorting Group by Buffers" msgid "Transparency Sorting Group by Buffers"
msgstr "Дальность сортировки по прозрачности" msgstr "Прозрачность Сортировки Групп по Буферам"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Trees noise" msgid "Trees noise"
@ -6816,7 +6814,6 @@ msgid "Undersampling"
msgstr "Субдискретизация" msgstr "Субдискретизация"
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Undersampling is similar to using a lower screen resolution, but it applies\n" "Undersampling is similar to using a lower screen resolution, but it applies\n"
"to the game world only, keeping the GUI intact.\n" "to the game world only, keeping the GUI intact.\n"
@ -6827,12 +6824,15 @@ msgid ""
"set\n" "set\n"
"to a non-default value." "to a non-default value."
msgstr "" msgstr ""
"Субдискретизация аналогична использованию низкого разрешения экрана,\n" "Недостаточная дискретизация аналогична использованию более низкого "
"но она применяется только к игровому миру, графический интерфейс не " "разрешения экрана, но применяется\n"
"затрагивается.\n" "только к игровому миру, сохраняя графический интерфейс без изменений.\n"
"Значительно увеличивает производительность за счёт вывода менее подробного " "Это должно значительно повысить производительность за счет снижения "
"изображения.\n" "детализации изображения.\n"
"Высокие значения приводят к менее проработанному изображению." "Более высокие значения приводят к снижению детализации изображения.\n"
"Примечание: В настоящее время недостаточная дискретизация не поддерживается, "
"если для параметра \"3d_mode\" установлено\n"
"значение, отличное от значения по умолчанию."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Unlimited player transfer distance" msgid "Unlimited player transfer distance"
@ -6859,12 +6859,13 @@ msgid "Use a cloud animation for the main menu background."
msgstr "Анимированные облака в главном меню." msgstr "Анимированные облака в главном меню."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Use anisotropic filtering when looking at textures from an angle.\n" "Use anisotropic filtering when looking at textures from an angle.\n"
"This provides a significant improvement when used together with mipmapping." "This provides a significant improvement when used together with mipmapping."
msgstr "" msgstr ""
"Использовать анизотропную фильтрацию при взгляде на текстуры под углом." "Использовать анизотропную фильтрацию при просмотре текстур под углом.\n"
"Это обеспечивает значительное улучшение при использовании в сочетании с "
"мип-картированием."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "Use bilinear filtering when scaling textures." msgid "Use bilinear filtering when scaling textures."
@ -7138,7 +7139,6 @@ msgstr ""
"аппаратно (прим. render-to-texture для нод в инвентаре)." "аппаратно (прим. render-to-texture для нод в инвентаре)."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"When using bilinear/trilinear filtering, low-resolution textures\n" "When using bilinear/trilinear filtering, low-resolution textures\n"
"can be blurred, so this option automatically upscales them to preserve\n" "can be blurred, so this option automatically upscales them to preserve\n"
@ -7149,17 +7149,17 @@ msgid ""
"This is also used as the base node texture size for world-aligned\n" "This is also used as the base node texture size for world-aligned\n"
"texture autoscaling." "texture autoscaling."
msgstr "" msgstr ""
"Когда используются билинейный/трилинейный/анизотропный фильтры, то текстуры " "При использовании билинейной/трилинейной фильтрации текстуры с низким "
"низкого разрешения\n" "разрешением\n"
"могут быть размытыми, поэтому они автоматически увеличиваются ближайшей\n" "могут быть размыты, поэтому этот параметр автоматически увеличивает их "
"интерполяцией для сохранения четкости пикселей. Это устанавливает " "масштаб, чтобы сохранить\n"
"минимальный размер текстуры\n" "четкие пиксели. Это определяет минимальный размер текстуры для текстур в "
"для увеличенных текстур; большие значения выглядят чётче, но требуют больше\n" "увеличенном масштабе;\n"
"памяти. Рекомендуются степени числа 2. Эта настройки применяется ТОЛЬКО " "более высокие значения выглядят четче, но требуют больше памяти.\n"
"если\n" "Этот параметр применяется ТОЛЬКО в том случае, если включен любой из "
"билинейный/трилинейный/анизотропный фильтр включен.\n" "упомянутых фильтров.\n"
"Это также используется для автомасштабирования как основной размер для\n" "Он также используется в качестве базового размера текстуры узла для\n"
"повёрнутых по сторонам света текстур блока." "автоматического масштабирования текстуры, выровненной по окружности."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""
@ -7194,16 +7194,15 @@ msgid "Whether to fog out the end of the visible area."
msgstr "Затуманивает конец видимой области." msgstr "Затуманивает конец видимой области."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
#, fuzzy
msgid "" msgid ""
"Whether to mute sounds. You can unmute sounds at any time.\n" "Whether to mute sounds. You can unmute sounds at any time.\n"
"In-game, you can toggle the mute state with the mute key or by using the\n" "In-game, you can toggle the mute state with the mute key or by using the\n"
"pause menu." "pause menu."
msgstr "" msgstr ""
"Заглушает звуки. Вы можете включить звуки в любое время, если\n" "Следует ли отключать звук. Вы можете включить звук в любое время.\n"
"звуковая система не отключена (enable_sound=false).\n" "В игре вы можете переключать режим отключения звука с помощью клавиши "
"Внутри игры, вы можете включить переключать звуки, нажав на клавишу\n" "отключения звука\n"
"заглушения звука или используя меню паузы." "или с помощью меню паузы."
#: src/settings_translation_file.cpp #: src/settings_translation_file.cpp
msgid "" msgid ""

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@ static constexpr f32 CAMERA_OFFSET_STEP = 200;
#define WIELDMESH_AMPLITUDE_Y 10.0f #define WIELDMESH_AMPLITUDE_Y 10.0f
static const char *setting_names[] = { static const char *setting_names[] = {
"fall_bobbing_amount", "view_bobbing_amount", "fov", "arm_inertia", "view_bobbing_amount", "fov", "arm_inertia",
"show_nametag_backgrounds", "show_nametag_backgrounds",
}; };
@ -78,7 +78,6 @@ void Camera::readSettings()
* (as opposed to the this local caching). This can be addressed in * (as opposed to the this local caching). This can be addressed in
* a later release. * a later release.
*/ */
m_cache_fall_bobbing_amount = g_settings->getFloat("fall_bobbing_amount", 0.0f, 100.0f);
m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount", 0.0f, 7.9f); m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount", 0.0f, 7.9f);
// 45 degrees is the lowest FOV that doesn't cause the server to treat this // 45 degrees is the lowest FOV that doesn't cause the server to treat this
// as a zoom FOV and load world beyond the set server limits. // as a zoom FOV and load world beyond the set server limits.
@ -130,13 +129,6 @@ inline f32 my_modf(f32 x)
void Camera::step(f32 dtime) void Camera::step(f32 dtime)
{ {
if(m_view_bobbing_fall > 0)
{
m_view_bobbing_fall -= 3 * dtime;
if(m_view_bobbing_fall <= 0)
m_view_bobbing_fall = -1; // Mark the effect as finished
}
bool was_under_zero = m_wield_change_timer < 0; bool was_under_zero = m_wield_change_timer < 0;
m_wield_change_timer = MYMIN(m_wield_change_timer + dtime, 0.125); m_wield_change_timer = MYMIN(m_wield_change_timer + dtime, 0.125);
@ -351,30 +343,13 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
// Get camera tilt timer (hurt animation) // Get camera tilt timer (hurt animation)
float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75); float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75);
// Fall bobbing animation
float fall_bobbing = 0;
if(player->camera_impact >= 1 && m_camera_mode < CAMERA_MODE_THIRD)
{
if(m_view_bobbing_fall == -1) // Effect took place and has finished
player->camera_impact = m_view_bobbing_fall = 0;
else if(m_view_bobbing_fall == 0) // Initialize effect
m_view_bobbing_fall = 1;
// Convert 0 -> 1 to 0 -> 1 -> 0
fall_bobbing = m_view_bobbing_fall < 0.5 ? m_view_bobbing_fall * 2 : -(m_view_bobbing_fall - 0.5) * 2 + 1;
// Smoothen and invert the above
fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1;
// Amplify according to the intensity of the impact
if (player->camera_impact > 0.0f)
fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5;
fall_bobbing *= m_cache_fall_bobbing_amount;
}
// Calculate and translate the head SceneNode offsets // Calculate and translate the head SceneNode offsets
{ {
v3f eye_offset = player->getEyeOffset(); v3f eye_offset = player->getEyeOffset();
switch(m_camera_mode) { switch(m_camera_mode) {
case CAMERA_MODE_ANY:
assert(false);
break;
case CAMERA_MODE_FIRST: case CAMERA_MODE_FIRST:
eye_offset += player->eye_offset_first; eye_offset += player->eye_offset_first;
break; break;
@ -389,7 +364,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
} }
// Set head node transformation // Set head node transformation
eye_offset.Y += cameratilt * -player->hurt_tilt_strength + fall_bobbing; eye_offset.Y += cameratilt * -player->hurt_tilt_strength;
m_headnode->setPosition(eye_offset); m_headnode->setPosition(eye_offset);
m_headnode->setRotation(v3f(pitch, 0, m_headnode->setRotation(v3f(pitch, 0,
cameratilt * player->hurt_tilt_strength)); cameratilt * player->hurt_tilt_strength));

View file

@ -57,8 +57,6 @@ struct Nametag
} }
}; };
enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT};
/* /*
Client camera class, manages the player and camera scene nodes, the viewing distance Client camera class, manages the player and camera scene nodes, the viewing distance
and performs view bobbing etc. It also displays the wielded tool in front of the and performs view bobbing etc. It also displays the wielded tool in front of the
@ -169,7 +167,8 @@ public:
void drawWieldedTool(irr::core::matrix4* translation=NULL); void drawWieldedTool(irr::core::matrix4* translation=NULL);
// Toggle the current camera mode // Toggle the current camera mode
void toggleCameraMode() { void toggleCameraMode()
{
if (m_camera_mode == CAMERA_MODE_FIRST) if (m_camera_mode == CAMERA_MODE_FIRST)
m_camera_mode = CAMERA_MODE_THIRD; m_camera_mode = CAMERA_MODE_THIRD;
else if (m_camera_mode == CAMERA_MODE_THIRD) else if (m_camera_mode == CAMERA_MODE_THIRD)
@ -185,7 +184,7 @@ public:
} }
//read the current camera mode //read the current camera mode
inline CameraMode getCameraMode() inline CameraMode getCameraMode() const
{ {
return m_camera_mode; return m_camera_mode;
} }
@ -257,8 +256,6 @@ private:
s32 m_view_bobbing_state = 0; s32 m_view_bobbing_state = 0;
// Speed of view bobbing animation // Speed of view bobbing animation
f32 m_view_bobbing_speed = 0.0f; f32 m_view_bobbing_speed = 0.0f;
// Fall view bobbing
f32 m_view_bobbing_fall = 0.0f;
// Digging animation frame (0 <= m_digging_anim < 1) // Digging animation frame (0 <= m_digging_anim < 1)
f32 m_digging_anim = 0.0f; f32 m_digging_anim = 0.0f;
@ -273,7 +270,6 @@ private:
CameraMode m_camera_mode = CAMERA_MODE_FIRST; CameraMode m_camera_mode = CAMERA_MODE_FIRST;
f32 m_cache_fall_bobbing_amount;
f32 m_cache_view_bobbing_amount; f32 m_cache_view_bobbing_amount;
bool m_arm_inertia; bool m_arm_inertia;

View file

@ -398,11 +398,7 @@ void Client::step(float dtime)
if (dtime > DTIME_LIMIT) if (dtime > DTIME_LIMIT)
dtime = DTIME_LIMIT; dtime = DTIME_LIMIT;
m_animation_time += dtime; m_animation_time = fmodf(m_animation_time + dtime, 60.0f);
if(m_animation_time > 60.0)
m_animation_time -= 60.0;
m_time_of_day_update_timer += dtime;
ReceiveAll(); ReceiveAll();
@ -450,20 +446,43 @@ void Client::step(float dtime)
/* /*
Run Map's timers and unload unused data Run Map's timers and unload unused data
*/ */
const float map_timer_and_unload_dtime = 5.25; constexpr float map_timer_and_unload_dtime = 5.25f;
constexpr s32 mapblock_limit_enforce_distance = 200;
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) { if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) {
std::vector<v3s16> deleted_blocks; std::vector<v3s16> deleted_blocks;
// Determine actual block limit to use
const s32 configured_limit = g_settings->getS32("client_mapblock_limit");
s32 mapblock_limit;
if (configured_limit < 0) {
mapblock_limit = -1;
} else {
s32 view_range = g_settings->getS16("viewing_range");
// Up to a certain limit we want to guarantee that the client can keep
// a full 360° view loaded in memory without blocks vanishing behind
// the players back.
// We use a sphere volume to approximate this. In practice far less
// blocks will be needed due to occlusion/culling.
float blocks_range = ceilf(std::min(mapblock_limit_enforce_distance, view_range)
/ (float) MAP_BLOCKSIZE);
mapblock_limit = (4.f/3.f) * M_PI * powf(blocks_range, 3);
assert(mapblock_limit > 0);
mapblock_limit = std::max(mapblock_limit, configured_limit);
if (mapblock_limit > std::max(configured_limit, m_mapblock_limit_logged)) {
infostream << "Client: using block limit of " << mapblock_limit
<< " rather than configured " << configured_limit
<< " due to view range." << std::endl;
m_mapblock_limit_logged = mapblock_limit;
}
}
m_env.getMap().timerUpdate(map_timer_and_unload_dtime, m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
std::max(g_settings->getFloat("client_unload_unused_data_timeout"), 0.0f), std::max(g_settings->getFloat("client_unload_unused_data_timeout"), 0.0f),
g_settings->getS32("client_mapblock_limit"), mapblock_limit, &deleted_blocks);
&deleted_blocks);
/* // Send info to server
Send info to server
NOTE: This loop is intentionally iterated the way it is.
*/
std::vector<v3s16>::iterator i = deleted_blocks.begin(); auto i = deleted_blocks.begin();
std::vector<v3s16> sendlist; std::vector<v3s16> sendlist;
for(;;) { for(;;) {
if(sendlist.size() == 255 || i == deleted_blocks.end()) { if(sendlist.size() == 255 || i == deleted_blocks.end()) {
@ -644,9 +663,11 @@ void Client::step(float dtime)
if (num_processed_meshes > 0) if (num_processed_meshes > 0)
g_profiler->graphAdd("num_processed_meshes", num_processed_meshes); g_profiler->graphAdd("num_processed_meshes", num_processed_meshes);
auto shadow_renderer = RenderingEngine::get_shadow_renderer(); if (force_update_shadows && !g_settings->getFlag("performance_tradeoffs")) {
if (shadow_renderer && force_update_shadows) auto shadow = RenderingEngine::get_shadow_renderer();
shadow_renderer->setForceUpdateShadowMap(); if (shadow)
shadow->setForceUpdateShadowMap();
};
} }
/* /*
@ -873,14 +894,6 @@ void Client::deletingPeer(con::IPeer *peer, bool timeout)
m_access_denied_reason = gettext("Connection aborted (protocol error?)."); m_access_denied_reason = gettext("Connection aborted (protocol error?).");
} }
/*
u16 command
u16 number of files requested
for each file {
u16 length of name
string name
}
*/
void Client::request_media(const std::vector<std::string> &file_requests) void Client::request_media(const std::vector<std::string> &file_requests)
{ {
std::ostringstream os(std::ios_base::binary); std::ostringstream os(std::ios_base::binary);
@ -1031,8 +1044,8 @@ void Client::Send(NetworkPacket* pkt)
// Will fill up 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4 bytes // Will fill up 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4 bytes
void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt, bool camera_inverted) void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt, bool camera_inverted)
{ {
v3f pf = myplayer->getPosition() * 100; v3s32 position = v3s32::from(myplayer->getPosition() * 100);
v3f sf = myplayer->getSpeed() * 100; v3s32 speed = v3s32::from(myplayer->getSpeed() * 100);
s32 pitch = myplayer->getPitch() * 100; s32 pitch = myplayer->getPitch() * 100;
s32 yaw = myplayer->getYaw() * 100; s32 yaw = myplayer->getYaw() * 100;
u32 keyPressed = myplayer->control.getKeysPressed(); u32 keyPressed = myplayer->control.getKeysPressed();
@ -1043,9 +1056,6 @@ void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *
f32 movement_speed = myplayer->control.movement_speed; f32 movement_speed = myplayer->control.movement_speed;
f32 movement_dir = myplayer->control.movement_direction; f32 movement_dir = myplayer->control.movement_direction;
v3s32 position(pf.X, pf.Y, pf.Z);
v3s32 speed(sf.X, sf.Y, sf.Z);
/* /*
Format: Format:
[0] v3s32 position*100 [0] v3s32 position*100
@ -1742,12 +1752,7 @@ void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server, bool
void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool urgent) void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool urgent)
{ {
{ infostream << "Client::addUpdateMeshTaskForNode(): " << nodepos << std::endl;
v3s16 p = nodepos;
infostream<<"Client::addUpdateMeshTaskForNode(): "
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
<<std::endl;
}
v3s16 blockpos = getNodeBlockPos(nodepos); v3s16 blockpos = getNodeBlockPos(nodepos);
v3s16 blockpos_relative = blockpos * MAP_BLOCKSIZE; v3s16 blockpos_relative = blockpos * MAP_BLOCKSIZE;

View file

@ -217,6 +217,7 @@ public:
void handleCommand_MediaPush(NetworkPacket *pkt); void handleCommand_MediaPush(NetworkPacket *pkt);
void handleCommand_MinimapModes(NetworkPacket *pkt); void handleCommand_MinimapModes(NetworkPacket *pkt);
void handleCommand_SetLighting(NetworkPacket *pkt); void handleCommand_SetLighting(NetworkPacket *pkt);
void handleCommand_Camera(NetworkPacket* pkt);
void ProcessData(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt);
@ -485,23 +486,18 @@ private:
u8 m_server_ser_ver; u8 m_server_ser_ver;
// Used version of the protocol with server // Used version of the protocol with server
// Values smaller than 25 only mean they are smaller than 25,
// and aren't accurate. We simply just don't know, because
// the server didn't send the version back then.
// If 0, server init hasn't been received yet. // If 0, server init hasn't been received yet.
u16 m_proto_ver = 0; u16 m_proto_ver = 0;
bool m_update_wielded_item = false; bool m_update_wielded_item = false;
Inventory *m_inventory_from_server = nullptr; Inventory *m_inventory_from_server = nullptr;
float m_inventory_from_server_age = 0.0f; float m_inventory_from_server_age = 0.0f;
s32 m_mapblock_limit_logged = 0;
PacketCounter m_packetcounter; PacketCounter m_packetcounter;
// Block mesh animation parameters // Block mesh animation parameters
float m_animation_time = 0.0f; float m_animation_time = 0.0f;
int m_crack_level = -1; int m_crack_level = -1;
v3s16 m_crack_pos; v3s16 m_crack_pos;
// 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
//s32 m_daynight_i;
//u32 m_daynight_ratio;
std::queue<std::wstring> m_out_chat_queue; std::queue<std::wstring> m_out_chat_queue;
u32 m_last_chat_message_sent; u32 m_last_chat_message_sent;
float m_chat_message_allowance = 5.0f; float m_chat_message_allowance = 5.0f;
@ -537,11 +533,6 @@ private:
// Pending downloads of dynamic media (key: token) // Pending downloads of dynamic media (key: token)
std::vector<std::pair<u32, std::shared_ptr<SingleMediaDownloader>>> m_pending_media_downloads; std::vector<std::pair<u32, std::shared_ptr<SingleMediaDownloader>>> m_pending_media_downloads;
// time_of_day speed approximation for old protocol
bool m_time_of_day_set = false;
float m_last_time_of_day_f = -1.0f;
float m_time_of_day_update_timer = 0.0f;
// An interval for generally sending object positions and stuff // An interval for generally sending object positions and stuff
float m_recommended_send_interval = 0.1f; float m_recommended_send_interval = 0.1f;

View file

@ -441,8 +441,8 @@ void ClientEnvironment::getSelectedActiveObjects(
GenericCAO* gcao = dynamic_cast<GenericCAO*>(obj); GenericCAO* gcao = dynamic_cast<GenericCAO*>(obj);
if (gcao != nullptr && gcao->getProperties().rotate_selectionbox) { if (gcao != nullptr && gcao->getProperties().rotate_selectionbox) {
gcao->getSceneNode()->updateAbsolutePosition(); gcao->getSceneNode()->updateAbsolutePosition();
const v3f deg = obj->getSceneNode()->getAbsoluteTransformation().getRotationDegrees(); const v3f rad = obj->getSceneNode()->getAbsoluteTransformation().getRotationRadians();
collision = boxLineCollision(selection_box, deg, collision = boxLineCollision(selection_box, rad,
rel_pos, line_vector, &current_intersection, &current_normal, &current_raw_normal); rel_pos, line_vector, &current_intersection, &current_normal, &current_raw_normal);
} else { } else {
collision = boxLineCollision(selection_box, rel_pos, line_vector, collision = boxLineCollision(selection_box, rel_pos, line_vector,

View file

@ -36,6 +36,7 @@ enum ClientEventType : u8
CE_SET_STARS, CE_SET_STARS,
CE_OVERRIDE_DAY_NIGHT_RATIO, CE_OVERRIDE_DAY_NIGHT_RATIO,
CE_CLOUD_PARAMS, CE_CLOUD_PARAMS,
CE_UPDATE_CAMERA,
CLIENTEVENT_MAX, CLIENTEVENT_MAX,
}; };
@ -66,11 +67,14 @@ struct ClientEventHudChange
struct ClientEvent struct ClientEvent
{ {
// TODO: should get rid of this ctor
ClientEvent() : type(CE_NONE) {}
ClientEvent(ClientEventType type) : type(type) {}
ClientEventType type; ClientEventType type;
union union
{ {
// struct{
//} none;
struct struct
{ {
u16 amount; u16 amount;
@ -86,8 +90,6 @@ struct ClientEvent
std::string *formspec; std::string *formspec;
std::string *formname; std::string *formname;
} show_formspec; } show_formspec;
// struct{
//} textures_updated;
ParticleParameters *spawn_particle; ParticleParameters *spawn_particle;
struct struct
{ {

View file

@ -52,6 +52,13 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc,
updateBox(); updateBox();
// Neither EAC_BOX (the default) nor EAC_FRUSTUM_BOX will correctly cull
// the clouds.
// And yes, the bounding box is correct. You can check using the #if 0'd
// code in render() and see for yourself.
// So I give up and let's disable culling.
setAutomaticCulling(scene::EAC_OFF);
m_meshbuffer.reset(new scene::SMeshBuffer()); m_meshbuffer.reset(new scene::SMeshBuffer());
m_meshbuffer->setHardwareMappingHint(scene::EHM_DYNAMIC); m_meshbuffer->setHardwareMappingHint(scene::EHM_DYNAMIC);
} }
@ -366,6 +373,19 @@ void Clouds::render()
if (SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT) if (SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
return; return;
#if 0
{
video::SMaterial tmp;
tmp.Thickness = 1.f;
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
driver->setMaterial(tmp);
aabb3f tmpbox = m_box;
tmpbox.MinEdge.X = tmpbox.MinEdge.Z = -1000 * BS;
tmpbox.MaxEdge.X = tmpbox.MaxEdge.Z = 1000 * BS;
driver->draw3DBox(tmpbox, video::SColor(255, 255, 0x4d, 0));
}
#endif
updateMesh(); updateMesh();
// Update position // Update position
@ -425,14 +445,14 @@ void Clouds::update(const v3f &camera_p, const video::SColorf &color_diffuse)
// is the camera inside the cloud mesh? // is the camera inside the cloud mesh?
m_camera_pos = camera_p; m_camera_pos = camera_p;
m_camera_inside_cloud = false; // default m_camera_inside_cloud = false;
if (is3D()) { if (is3D()) {
float camera_height = camera_p.Y - BS * m_camera_offset.Y; float camera_height = camera_p.Y - BS * m_camera_offset.Y;
if (camera_height >= m_box.MinEdge.Y && if (camera_height >= m_box.MinEdge.Y &&
camera_height <= m_box.MaxEdge.Y) { camera_height <= m_box.MaxEdge.Y) {
v2f camera_in_noise; v2f camera_in_noise;
camera_in_noise.X = floor((camera_p.X - m_origin.X) / cloud_size + 0.5); camera_in_noise.X = floorf((camera_p.X - m_origin.X) / cloud_size + 0.5f);
camera_in_noise.Y = floor((camera_p.Z - m_origin.Y) / cloud_size + 0.5); camera_in_noise.Y = floorf((camera_p.Z - m_origin.Y) / cloud_size + 0.5f);
bool filled = gridFilled(camera_in_noise.X, camera_in_noise.Y); bool filled = gridFilled(camera_in_noise.X, camera_in_noise.Y);
m_camera_inside_cloud = filled; m_camera_inside_cloud = filled;
} }

View file

@ -134,8 +134,11 @@ private:
{ {
float height_bs = m_params.height * BS; float height_bs = m_params.height * BS;
float thickness_bs = m_params.thickness * BS; float thickness_bs = m_params.thickness * BS;
m_box = aabb3f(-BS * 1000000.0f, height_bs, -BS * 1000000.0f, float far_bs = 1000000.0f * BS;
BS * 1000000.0f, height_bs + thickness_bs, BS * 1000000.0f); m_box = aabb3f(-far_bs, height_bs, -far_bs,
far_bs, height_bs + thickness_bs, far_bs);
m_box.MinEdge -= v3f::from(m_camera_offset) * BS;
m_box.MaxEdge -= v3f::from(m_camera_offset) * BS;
} }
void updateMesh(); void updateMesh();

View file

@ -12,6 +12,8 @@
#include "client/sound.h" #include "client/sound.h"
#include "client/texturesource.h" #include "client/texturesource.h"
#include "client/mapblock_mesh.h" #include "client/mapblock_mesh.h"
#include "client/content_mapblock.h"
#include "client/meshgen/collector.h"
#include "util/basic_macros.h" #include "util/basic_macros.h"
#include "util/numeric.h" #include "util/numeric.h"
#include "util/serialize.h" #include "util/serialize.h"
@ -180,6 +182,55 @@ static void setColorParam(scene::ISceneNode *node, video::SColor color)
node->getMaterial(i).ColorParam = color; node->getMaterial(i).ColorParam = color;
} }
static scene::SMesh *generateNodeMesh(Client *client, MapNode n,
std::vector<MeshAnimationInfo> &animation)
{
auto *ndef = client->ndef();
auto *shdsrc = client->getShaderSource();
MeshCollector collector(v3f(0), v3f());
{
MeshMakeData mmd(ndef, 1, MeshGrid{1});
n.setParam1(0xff);
mmd.fillSingleNode(n);
MapblockMeshGenerator(&mmd, &collector).generate();
}
auto mesh = make_irr<scene::SMesh>();
animation.clear();
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
for (PreMeshBuffer &p : collector.prebuffers[layer]) {
// reset the pre-computed light data stored in the vertex color,
// since we do that ourselves via updateLight().
for (auto &v : p.vertices)
v.Color.set(0xFFFFFFFF);
// but still apply the tile color
p.applyTileColor();
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
const FrameSpec &frame = (*p.layer.frames)[0];
p.layer.texture = frame.texture;
animation.emplace_back(MeshAnimationInfo{mesh->getMeshBufferCount(), 0, p.layer});
}
auto buf = make_irr<scene::SMeshBuffer>();
buf->append(&p.vertices[0], p.vertices.size(),
&p.indices[0], p.indices.size());
// Set up material
auto &mat = buf->Material;
u32 shader_id = shdsrc->getShader("object_shader", p.layer.material_type, NDT_NORMAL);
mat.MaterialType = shdsrc->getShaderInfo(shader_id).material;
p.layer.applyMaterialOptions(mat, layer);
mesh->addMeshBuffer(buf.get());
}
}
mesh->recalculateBoundingBox();
return mesh.release();
}
/* /*
TestCAO TestCAO
*/ */
@ -572,6 +623,8 @@ void GenericCAO::removeFromScene(bool permanent)
m_spritenode = nullptr; m_spritenode = nullptr;
} }
m_meshnode_animation.clear();
if (m_matrixnode) { if (m_matrixnode) {
m_matrixnode->remove(); m_matrixnode->remove();
m_matrixnode->drop(); m_matrixnode->drop();
@ -602,8 +655,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
infostream << "GenericCAO::addToScene(): " << m_prop.visual << std::endl; infostream << "GenericCAO::addToScene(): " << m_prop.visual << std::endl;
m_material_type_param = 0.5f; // May cut off alpha < 128 depending on m_material_type if (m_prop.visual != "node" && m_prop.visual != "wielditem" && m_prop.visual != "item")
{ {
IShaderSource *shader_source = m_client->getShaderSource(); IShaderSource *shader_source = m_client->getShaderSource();
MaterialType material_type; MaterialType material_type;
@ -617,15 +669,17 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
u32 shader_id = shader_source->getShader("object_shader", material_type, NDT_NORMAL); u32 shader_id = shader_source->getShader("object_shader", material_type, NDT_NORMAL);
m_material_type = shader_source->getShaderInfo(shader_id).material; m_material_type = shader_source->getShaderInfo(shader_id).material;
} else {
// Not used, so make sure it's not valid
m_material_type = EMT_INVALID;
} }
auto grabMatrixNode = [this] { m_matrixnode = m_smgr->addDummyTransformationSceneNode();
m_matrixnode = m_smgr->addDummyTransformationSceneNode(); m_matrixnode->grab();
m_matrixnode->grab();
};
auto setMaterial = [this] (video::SMaterial &mat) { auto setMaterial = [this] (video::SMaterial &mat) {
mat.MaterialType = m_material_type; if (m_material_type != EMT_INVALID)
mat.MaterialType = m_material_type;
mat.FogEnable = true; mat.FogEnable = true;
mat.forEachTexture([] (auto &tex) { mat.forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
@ -637,28 +691,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
node->forEachMaterial(setMaterial); node->forEachMaterial(setMaterial);
}; };
if (m_prop.visual == "sprite") { if (m_prop.visual == "upright_sprite") {
grabMatrixNode();
m_spritenode = m_smgr->addBillboardSceneNode(
m_matrixnode, v2f(1, 1), v3f(0,0,0), -1);
m_spritenode->grab();
video::ITexture *tex = tsrc->getTextureForMesh("no_texture.png");
m_spritenode->forEachMaterial([tex] (auto &mat) {
mat.setTexture(0, tex);
});
setSceneNodeMaterials(m_spritenode);
m_spritenode->setSize(v2f(m_prop.visual_size.X,
m_prop.visual_size.Y) * BS);
{
const float txs = 1.0 / 1;
const float tys = 1.0 / 1;
setBillboardTextureMatrix(m_spritenode,
txs, tys, 0, 0);
}
} else if (m_prop.visual == "upright_sprite") {
grabMatrixNode();
auto mesh = make_irr<scene::SMesh>(); auto mesh = make_irr<scene::SMesh>();
f32 dx = BS * m_prop.visual_size.X / 2; f32 dx = BS * m_prop.visual_size.X / 2;
f32 dy = BS * m_prop.visual_size.Y / 2; f32 dy = BS * m_prop.visual_size.Y / 2;
@ -700,7 +733,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
m_meshnode = m_smgr->addMeshSceneNode(mesh.get(), m_matrixnode); m_meshnode = m_smgr->addMeshSceneNode(mesh.get(), m_matrixnode);
m_meshnode->grab(); m_meshnode->grab();
} else if (m_prop.visual == "cube") { } else if (m_prop.visual == "cube") {
grabMatrixNode();
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS)); scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode); m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode);
m_meshnode->grab(); m_meshnode->grab();
@ -714,7 +746,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
mat.BackfaceCulling = m_prop.backface_culling; mat.BackfaceCulling = m_prop.backface_culling;
}); });
} else if (m_prop.visual == "mesh") { } else if (m_prop.visual == "mesh") {
grabMatrixNode();
scene::IAnimatedMesh *mesh = m_client->getMesh(m_prop.mesh, true); scene::IAnimatedMesh *mesh = m_client->getMesh(m_prop.mesh, true);
if (mesh) { if (mesh) {
if (!checkMeshNormals(mesh)) { if (!checkMeshNormals(mesh)) {
@ -741,7 +772,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
} else } else
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl; errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
} else if (m_prop.visual == "wielditem" || m_prop.visual == "item") { } else if (m_prop.visual == "wielditem" || m_prop.visual == "item") {
grabMatrixNode();
ItemStack item; ItemStack item;
if (m_prop.wield_item.empty()) { if (m_prop.wield_item.empty()) {
// Old format, only textures are specified. // Old format, only textures are specified.
@ -761,9 +791,35 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
(m_prop.visual == "wielditem")); (m_prop.visual == "wielditem"));
m_wield_meshnode->setScale(m_prop.visual_size / 2.0f); m_wield_meshnode->setScale(m_prop.visual_size / 2.0f);
} else if (m_prop.visual == "node") {
auto *mesh = generateNodeMesh(m_client, m_prop.node, m_meshnode_animation);
assert(mesh);
m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode);
m_meshnode->setSharedMaterials(true);
m_meshnode->grab();
mesh->drop();
m_meshnode->setScale(m_prop.visual_size);
setSceneNodeMaterials(m_meshnode);
} else { } else {
infostream<<"GenericCAO::addToScene(): \""<<m_prop.visual m_spritenode = m_smgr->addBillboardSceneNode(m_matrixnode);
<<"\" not supported"<<std::endl; m_spritenode->grab();
setSceneNodeMaterials(m_spritenode);
m_spritenode->setSize(v2f(m_prop.visual_size.X,
m_prop.visual_size.Y) * BS);
setBillboardTextureMatrix(m_spritenode, 1, 1, 0, 0);
// This also serves as fallback for unknown visual types
if (m_prop.visual != "sprite") {
infostream << "GenericCAO::addToScene(): \"" << m_prop.visual
<< "\" not supported" << std::endl;
m_spritenode->getMaterial(0).setTexture(0,
tsrc->getTextureForMesh("unknown_object.png"));
}
} }
/* Set VBO hint */ /* Set VBO hint */
@ -789,8 +845,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
updateTextures(m_current_texture_modifier); updateTextures(m_current_texture_modifier);
if (scene::ISceneNode *node = getSceneNode()) { if (scene::ISceneNode *node = getSceneNode()) {
if (m_matrixnode) node->setParent(m_matrixnode);
node->setParent(m_matrixnode);
if (auto shadow = RenderingEngine::get_shadow_renderer()) if (auto shadow = RenderingEngine::get_shadow_renderer())
shadow->addNodeToShadowList(node); shadow->addNodeToShadowList(node);
@ -861,8 +916,7 @@ void GenericCAO::updateLight(u32 day_night_ratio)
if (!pos_ok) if (!pos_ok)
light_at_pos = LIGHT_SUN; light_at_pos = LIGHT_SUN;
// Initialize with full alpha, otherwise entity won't be visible video::SColor light;
video::SColor light{0xFFFFFFFF};
// Encode light into color, adding a small boost // Encode light into color, adding a small boost
// based on the entity glow. // based on the entity glow.
@ -965,6 +1019,7 @@ void GenericCAO::updateNodePos()
scene::ISceneNode *node = getSceneNode(); scene::ISceneNode *node = getSceneNode();
if (node) { if (node) {
assert(m_matrixnode);
v3s16 camera_offset = m_env->getCameraOffset(); v3s16 camera_offset = m_env->getCameraOffset();
v3f pos = pos_translator.val_current - v3f pos = pos_translator.val_current -
intToFloat(camera_offset, BS); intToFloat(camera_offset, BS);
@ -1153,7 +1208,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
m_anim_frame = 0; m_anim_frame = 0;
} }
updateTexturePos(); updateTextureAnim();
if(m_reset_textures_timer >= 0) if(m_reset_textures_timer >= 0)
{ {
@ -1214,7 +1269,7 @@ static void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u
buf->setDirty(scene::EBT_VERTEX); buf->setDirty(scene::EBT_VERTEX);
} }
void GenericCAO::updateTexturePos() void GenericCAO::updateTextureAnim()
{ {
if(m_spritenode) if(m_spritenode)
{ {
@ -1279,6 +1334,23 @@ void GenericCAO::updateTexturePos()
auto mesh = m_meshnode->getMesh(); auto mesh = m_meshnode->getMesh();
setMeshBufferTextureCoords(mesh->getMeshBuffer(0), t, 4); setMeshBufferTextureCoords(mesh->getMeshBuffer(0), t, 4);
setMeshBufferTextureCoords(mesh->getMeshBuffer(1), t, 4); setMeshBufferTextureCoords(mesh->getMeshBuffer(1), t, 4);
} else if (m_prop.visual == "node") {
// same calculation as MapBlockMesh::animate() with a global timer
const float time = m_client->getAnimationTime();
for (auto &it : m_meshnode_animation) {
const TileLayer &tile = it.tile;
int frameno = (int)(time * 1000 / tile.animation_frame_length_ms)
% tile.animation_frame_count;
if (frameno == it.frame)
continue;
it.frame = frameno;
auto *buf = m_meshnode->getMesh()->getMeshBuffer(it.i);
const FrameSpec &frame = (*tile.frames)[frameno];
buf->getMaterial().setTexture(0, frame.texture);
}
} }
} }
} }
@ -1304,7 +1376,6 @@ void GenericCAO::updateTextures(std::string mod)
video::SMaterial &material = m_spritenode->getMaterial(0); video::SMaterial &material = m_spritenode->getMaterial(0);
material.MaterialType = m_material_type; material.MaterialType = m_material_type;
material.MaterialTypeParam = m_material_type_param;
material.setTexture(0, tsrc->getTextureForMesh(texturestring)); material.setTexture(0, tsrc->getTextureForMesh(texturestring));
material.forEachTexture([=] (auto &tex) { material.forEachTexture([=] (auto &tex) {
@ -1333,7 +1404,6 @@ void GenericCAO::updateTextures(std::string mod)
// Set material flags and texture // Set material flags and texture
video::SMaterial &material = m_animated_meshnode->getMaterial(i); video::SMaterial &material = m_animated_meshnode->getMaterial(i);
material.MaterialType = m_material_type; material.MaterialType = m_material_type;
material.MaterialTypeParam = m_material_type_param;
material.TextureLayers[0].Texture = texture; material.TextureLayers[0].Texture = texture;
material.BackfaceCulling = m_prop.backface_culling; material.BackfaceCulling = m_prop.backface_culling;
@ -1365,7 +1435,6 @@ void GenericCAO::updateTextures(std::string mod)
// Set material flags and texture // Set material flags and texture
video::SMaterial &material = m_meshnode->getMaterial(i); video::SMaterial &material = m_meshnode->getMaterial(i);
material.MaterialType = m_material_type; material.MaterialType = m_material_type;
material.MaterialTypeParam = m_material_type_param;
material.setTexture(0, tsrc->getTextureForMesh(texturestring)); material.setTexture(0, tsrc->getTextureForMesh(texturestring));
material.getTextureMatrix(0).makeIdentity(); material.getTextureMatrix(0).makeIdentity();
@ -1532,7 +1601,7 @@ bool GenericCAO::visualExpiryRequired(const ObjectProperties &new_) const
/* Visuals do not need to be expired for: /* Visuals do not need to be expired for:
* - nametag props: handled by updateNametag() * - nametag props: handled by updateNametag()
* - textures: handled by updateTextures() * - textures: handled by updateTextures()
* - sprite props: handled by updateTexturePos() * - sprite props: handled by updateTextureAnim()
* - glow: handled by updateLight() * - glow: handled by updateLight()
* - any other properties that do not change appearance * - any other properties that do not change appearance
*/ */
@ -1542,9 +1611,10 @@ bool GenericCAO::visualExpiryRequired(const ObjectProperties &new_) const
// Ordered to compare primitive types before std::vectors // Ordered to compare primitive types before std::vectors
return old.backface_culling != new_.backface_culling || return old.backface_culling != new_.backface_culling ||
old.is_visible != new_.is_visible || old.is_visible != new_.is_visible ||
old.mesh != new_.mesh ||
old.shaded != new_.shaded || old.shaded != new_.shaded ||
old.use_texture_alpha != new_.use_texture_alpha || old.use_texture_alpha != new_.use_texture_alpha ||
old.node != new_.node ||
old.mesh != new_.mesh ||
old.visual != new_.visual || old.visual != new_.visual ||
old.visual_size != new_.visual_size || old.visual_size != new_.visual_size ||
old.wield_item != new_.wield_item || old.wield_item != new_.wield_item ||
@ -1655,7 +1725,7 @@ void GenericCAO::processMessage(const std::string &data)
m_anim_framelength = framelength; m_anim_framelength = framelength;
m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch; m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
updateTexturePos(); updateTextureAnim();
} else if (cmd == AO_CMD_SET_PHYSICS_OVERRIDE) { } else if (cmd == AO_CMD_SET_PHYSICS_OVERRIDE) {
float override_speed = readF32(is); float override_speed = readF32(is);
float override_jump = readF32(is); float override_jump = readF32(is);

View file

@ -12,6 +12,7 @@
#include "clientobject.h" #include "clientobject.h"
#include "constants.h" #include "constants.h"
#include "itemgroup.h" #include "itemgroup.h"
#include "client/tile.h"
#include <cassert> #include <cassert>
#include <map> #include <map>
#include <memory> #include <memory>
@ -27,7 +28,7 @@ struct Nametag;
struct MinimapMarker; struct MinimapMarker;
/* /*
SmoothTranslator SmoothTranslator and other helpers
*/ */
template<typename T> template<typename T>
@ -60,9 +61,21 @@ struct SmoothTranslatorWrappedv3f : SmoothTranslator<v3f>
void translate(f32 dtime); void translate(f32 dtime);
}; };
struct MeshAnimationInfo {
u32 i; /// index of mesh buffer
int frame; /// last animation frame
TileLayer tile;
};
/*
GenericCAO
*/
class GenericCAO : public ClientActiveObject class GenericCAO : public ClientActiveObject
{ {
private: private:
static constexpr auto EMT_INVALID = video::EMT_FORCE_32BIT;
// Only set at initialization // Only set at initialization
std::string m_name = ""; std::string m_name = "";
bool m_is_player = false; bool m_is_player = false;
@ -73,6 +86,8 @@ private:
scene::ISceneManager *m_smgr = nullptr; scene::ISceneManager *m_smgr = nullptr;
Client *m_client = nullptr; Client *m_client = nullptr;
aabb3f m_selection_box = aabb3f(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.); aabb3f m_selection_box = aabb3f(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.);
// Visuals
scene::IMeshSceneNode *m_meshnode = nullptr; scene::IMeshSceneNode *m_meshnode = nullptr;
scene::IAnimatedMeshSceneNode *m_animated_meshnode = nullptr; scene::IAnimatedMeshSceneNode *m_animated_meshnode = nullptr;
WieldMeshSceneNode *m_wield_meshnode = nullptr; WieldMeshSceneNode *m_wield_meshnode = nullptr;
@ -80,6 +95,15 @@ private:
scene::IDummyTransformationSceneNode *m_matrixnode = nullptr; scene::IDummyTransformationSceneNode *m_matrixnode = nullptr;
Nametag *m_nametag = nullptr; Nametag *m_nametag = nullptr;
MinimapMarker *m_marker = nullptr; MinimapMarker *m_marker = nullptr;
bool m_visuals_expired = false;
video::SColor m_last_light = video::SColor(0xFFFFFFFF);
bool m_is_visible = false;
std::vector<MeshAnimationInfo> m_meshnode_animation;
// Material
video::E_MATERIAL_TYPE m_material_type = EMT_INVALID;
// Movement
v3f m_position = v3f(0.0f, 10.0f * BS, 0); v3f m_position = v3f(0.0f, 10.0f * BS, 0);
v3f m_velocity; v3f m_velocity;
v3f m_acceleration; v3f m_acceleration;
@ -87,18 +111,25 @@ private:
u16 m_hp = 1; u16 m_hp = 1;
SmoothTranslator<v3f> pos_translator; SmoothTranslator<v3f> pos_translator;
SmoothTranslatorWrappedv3f rot_translator; SmoothTranslatorWrappedv3f rot_translator;
// Spritesheet/animation stuff
// Spritesheet stuff
v2f m_tx_size = v2f(1,1); v2f m_tx_size = v2f(1,1);
v2s16 m_tx_basepos; v2s16 m_tx_basepos;
bool m_initial_tx_basepos_set = false; bool m_initial_tx_basepos_set = false;
bool m_tx_select_horiz_by_yawpitch = false; bool m_tx_select_horiz_by_yawpitch = false;
bool m_animation_loop = true;
v2f m_animation_range; v2f m_animation_range;
float m_animation_speed = 15.0f; float m_animation_speed = 15.0f;
float m_animation_blend = 0.0f; float m_animation_blend = 0.0f;
bool m_animation_loop = true; int m_anim_frame = 0;
int m_anim_num_frames = 1;
float m_anim_framelength = 0.2f;
float m_anim_timer = 0.0f;
// stores position and rotation for each bone name // stores position and rotation for each bone name
BoneOverrideMap m_bone_override; BoneOverrideMap m_bone_override;
// Attachments
object_t m_attachment_parent_id = 0; object_t m_attachment_parent_id = 0;
std::unordered_set<object_t> m_attachment_child_ids; std::unordered_set<object_t> m_attachment_child_ids;
std::string m_attachment_bone = ""; std::string m_attachment_bone = "";
@ -107,23 +138,13 @@ private:
bool m_attached_to_local = false; bool m_attached_to_local = false;
bool m_force_visible = false; bool m_force_visible = false;
int m_anim_frame = 0;
int m_anim_num_frames = 1;
float m_anim_framelength = 0.2f;
float m_anim_timer = 0.0f;
ItemGroupList m_armor_groups; ItemGroupList m_armor_groups;
float m_reset_textures_timer = -1.0f; float m_reset_textures_timer = -1.0f;
// stores texture modifier before punch update // stores texture modifier before punch update
std::string m_previous_texture_modifier = ""; std::string m_previous_texture_modifier = "";
// last applied texture modifier // last applied texture modifier
std::string m_current_texture_modifier = ""; std::string m_current_texture_modifier = "";
bool m_visuals_expired = false;
float m_step_distance_counter = 0.0f; float m_step_distance_counter = 0.0f;
video::SColor m_last_light = video::SColor(0xFFFFFFFF);
bool m_is_visible = false;
// Material
video::E_MATERIAL_TYPE m_material_type;
f32 m_material_type_param;
bool visualExpiryRequired(const ObjectProperties &newprops) const; bool visualExpiryRequired(const ObjectProperties &newprops) const;
@ -255,7 +276,7 @@ public:
void step(float dtime, ClientEnvironment *env) override; void step(float dtime, ClientEnvironment *env) override;
void updateTexturePos(); void updateTextureAnim();
// ffs this HAS TO BE a string copy! See #5739 if you think otherwise // ffs this HAS TO BE a string copy! See #5739 if you think otherwise
// Reason: updateTextures(m_previous_texture_modifier); // Reason: updateTextures(m_previous_texture_modifier);

View file

@ -121,7 +121,7 @@ void MapblockMeshGenerator::drawQuad(const TileSpec &tile, v3f *coords, const v3
v2f(1.0, vertical_tiling), v2f(0.0, vertical_tiling)}; v2f(1.0, vertical_tiling), v2f(0.0, vertical_tiling)};
video::S3DVertex vertices[4]; video::S3DVertex vertices[4];
bool shade_face = !cur_node.f->light_source && (normal != v3s16(0, 0, 0)); bool shade_face = !cur_node.f->light_source && (normal != v3s16(0, 0, 0));
v3f normal2(normal.X, normal.Y, normal.Z); v3f normal2 = v3f::from(normal);
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
vertices[j].Pos = coords[j] + cur_node.origin; vertices[j].Pos = coords[j] + cur_node.origin;
vertices[j].Normal = normal2; vertices[j].Normal = normal2;

View file

@ -33,7 +33,7 @@ public:
void put(MtEvent *e) override void put(MtEvent *e) override
{ {
std::map<MtEvent::Type, Dest>::iterator i = m_dest.find(e->getType()); auto i = m_dest.find(e->getType());
if (i != m_dest.end()) { if (i != m_dest.end()) {
std::list<FuncSpec> &funcs = i->second.funcs; std::list<FuncSpec> &funcs = i->second.funcs;
for (FuncSpec &func : funcs) { for (FuncSpec &func : funcs) {
@ -44,7 +44,7 @@ public:
} }
void reg(MtEvent::Type type, event_receive_func f, void *data) override void reg(MtEvent::Type type, event_receive_func f, void *data) override
{ {
std::map<MtEvent::Type, Dest>::iterator i = m_dest.find(type); auto i = m_dest.find(type);
if (i != m_dest.end()) { if (i != m_dest.end()) {
i->second.funcs.emplace_back(f, data); i->second.funcs.emplace_back(f, data);
} else { } else {

View file

@ -278,7 +278,7 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
}; };
auto it = m_media_faces.find(media_name); auto it = m_media_faces.find(media_name);
if (it != m_media_faces.end()) { if (spec.mode != _FM_Fallback && it != m_media_faces.end()) {
auto *face = it->second.get(); auto *face = it->second.get();
if (auto *font = createFont(face)) if (auto *font = createFont(face))
return font; return font;

View file

@ -564,6 +564,7 @@ protected:
void updatePauseState(); void updatePauseState();
void step(f32 dtime); void step(f32 dtime);
void processClientEvents(CameraOrientation *cam); void processClientEvents(CameraOrientation *cam);
void updateCameraMode(); // call after changing it
void updateCameraOffset(); void updateCameraOffset();
void updateCamera(f32 dtime); void updateCamera(f32 dtime);
void updateSound(f32 dtime); void updateSound(f32 dtime);
@ -665,6 +666,7 @@ private:
void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event, void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
CameraOrientation *cam); CameraOrientation *cam);
void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_UpdateCamera(ClientEvent *event, CameraOrientation *cam);
void updateChat(f32 dtime); void updateChat(f32 dtime);
@ -754,7 +756,6 @@ private:
f32 m_repeat_dig_time; f32 m_repeat_dig_time;
f32 m_cache_cam_smoothing; f32 m_cache_cam_smoothing;
bool m_enable_relative_mode = false;
bool m_invert_mouse; bool m_invert_mouse;
bool m_enable_hotbar_mouse_wheel; bool m_enable_hotbar_mouse_wheel;
bool m_invert_hotbar_mouse_wheel; bool m_invert_hotbar_mouse_wheel;
@ -770,9 +771,10 @@ private:
bool m_is_paused = false; bool m_is_paused = false;
bool m_touch_simulate_aux1 = false; bool m_touch_simulate_aux1 = false;
bool m_touch_use_crosshair; inline bool isTouchShootlineUsed()
inline bool isTouchCrosshairDisabled() { {
return !m_touch_use_crosshair && camera->getCameraMode() == CAMERA_MODE_FIRST; return g_touchcontrols && g_touchcontrols->isShootlineAvailable() &&
camera->getCameraMode() == CAMERA_MODE_FIRST;
} }
#ifdef __ANDROID__ #ifdef __ANDROID__
bool m_android_chat_open; bool m_android_chat_open;
@ -821,8 +823,6 @@ Game::Game() :
&settingChangedCallback, this); &settingChangedCallback, this);
g_settings->registerChangedCallback("pause_on_lost_focus", g_settings->registerChangedCallback("pause_on_lost_focus",
&settingChangedCallback, this); &settingChangedCallback, this);
g_settings->registerChangedCallback("touch_use_crosshair",
&settingChangedCallback, this);
readSettings(); readSettings();
} }
@ -899,15 +899,6 @@ bool Game::startup(bool *kill,
m_first_loop_after_window_activation = true; m_first_loop_after_window_activation = true;
// In principle we could always enable relative mouse mode, but it causes weird
// bugs on some setups (e.g. #14932), so we enable it only when it's required.
// That is: on Wayland or Android, because it does not support mouse repositioning
#ifdef __ANDROID__
m_enable_relative_mode = true;
#else
m_enable_relative_mode = device->isUsingWayland();
#endif
g_client_translations->clear(); g_client_translations->clear();
// address can change if simple_singleplayer_mode // address can change if simple_singleplayer_mode
@ -968,7 +959,7 @@ void Game::run()
// Calculate dtime = // Calculate dtime =
// m_rendering_engine->run() from this iteration // m_rendering_engine->run() from this iteration
// + Sleep time until the wanted FPS are reached // + Sleep time until the wanted FPS are reached
draw_times.limit(device, &dtime, g_menumgr.pausesGame()); draw_times.limit(device, &dtime);
framemarker.start(); framemarker.start();
@ -1378,10 +1369,8 @@ bool Game::initGui()
gui_chat_console = make_irr<GUIChatConsole>(guienv, guienv->getRootGUIElement(), gui_chat_console = make_irr<GUIChatConsole>(guienv, guienv->getRootGUIElement(),
-1, chat_backend, client, &g_menumgr); -1, chat_backend, client, &g_menumgr);
if (shouldShowTouchControls()) { if (shouldShowTouchControls())
g_touchcontrols = new TouchControls(device, texture_src); g_touchcontrols = new TouchControls(device, texture_src);
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
}
return true; return true;
} }
@ -1921,6 +1910,9 @@ void Game::processKeyInput()
toggleFog(); toggleFog();
} else if (wasKeyDown(KeyType::TOGGLE_UPDATE_CAMERA)) { } else if (wasKeyDown(KeyType::TOGGLE_UPDATE_CAMERA)) {
toggleUpdateCamera(); toggleUpdateCamera();
} else if (wasKeyPressed(KeyType::CAMERA_MODE)) {
camera->toggleCameraMode();
updateCameraMode();
} else if (wasKeyPressed(KeyType::TOGGLE_DEBUG)) { } else if (wasKeyPressed(KeyType::TOGGLE_DEBUG)) {
toggleDebug(); toggleDebug();
} else if (wasKeyPressed(KeyType::TOGGLE_PROFILER)) { } else if (wasKeyPressed(KeyType::TOGGLE_PROFILER)) {
@ -2359,10 +2351,8 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime)
Since Minetest has its own code to synthesize mouse events from touch events, Since Minetest has its own code to synthesize mouse events from touch events,
this results in duplicated input. To avoid that, we don't enable relative this results in duplicated input. To avoid that, we don't enable relative
mouse mode if we're in touchscreen mode. */ mouse mode if we're in touchscreen mode. */
if (cur_control) { if (cur_control)
cur_control->setRelativeMode(m_enable_relative_mode && cur_control->setRelativeMode(!g_touchcontrols && !isMenuActive());
!g_touchcontrols && !isMenuActive());
}
if ((device->isWindowActive() && device->isWindowFocused() if ((device->isWindowActive() && device->isWindowFocused()
&& !isMenuActive()) || input->isRandom()) { && !isMenuActive()) || input->isRandom()) {
@ -2433,7 +2423,7 @@ void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) * c; cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) * c;
} }
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5); cam->camera_pitch = rangelim(cam->camera_pitch, -90, 90);
} }
@ -2504,7 +2494,7 @@ inline void Game::step(f32 dtime)
ZoneScoped; ZoneScoped;
if (server) { if (server) {
float fps_max = (!device->isWindowFocused() || g_menumgr.pausesGame()) ? float fps_max = !device->isWindowFocused() && simple_singleplayer_mode ?
g_settings->getFloat("fps_max_unfocused") : g_settings->getFloat("fps_max_unfocused") :
g_settings->getFloat("fps_max"); g_settings->getFloat("fps_max");
fps_max = std::max(fps_max, 1.0f); fps_max = std::max(fps_max, 1.0f);
@ -2575,6 +2565,7 @@ const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
{&Game::handleClientEvent_SetStars}, {&Game::handleClientEvent_SetStars},
{&Game::handleClientEvent_OverrideDayNigthRatio}, {&Game::handleClientEvent_OverrideDayNigthRatio},
{&Game::handleClientEvent_CloudParams}, {&Game::handleClientEvent_CloudParams},
{&Game::handleClientEvent_UpdateCamera},
}; };
void Game::handleClientEvent_None(ClientEvent *event, CameraOrientation *cam) void Game::handleClientEvent_None(ClientEvent *event, CameraOrientation *cam)
@ -2879,6 +2870,13 @@ void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *
clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y)); clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y));
} }
void Game::handleClientEvent_UpdateCamera(ClientEvent *event, CameraOrientation *cam)
{
// no parameters to update here, this just makes sure the camera is in the
// state it should be after something was changed.
updateCameraMode();
}
void Game::processClientEvents(CameraOrientation *cam) void Game::processClientEvents(CameraOrientation *cam)
{ {
while (client->hasClientEvents()) { while (client->hasClientEvents()) {
@ -2935,12 +2933,7 @@ void Game::updateCamera(f32 dtime)
ClientEnvironment &env = client->getEnv(); ClientEnvironment &env = client->getEnv();
LocalPlayer *player = env.getLocalPlayer(); LocalPlayer *player = env.getLocalPlayer();
/* // For interaction purposes, get info about the held item
For interaction purposes, get info about the held item
- What item is it?
- Is it a usable item?
- Can it point to liquids?
*/
ItemStack playeritem; ItemStack playeritem;
{ {
ItemStack selected, hand; ItemStack selected, hand;
@ -2950,23 +2943,6 @@ void Game::updateCamera(f32 dtime)
ToolCapabilities playeritem_toolcap = ToolCapabilities playeritem_toolcap =
playeritem.getToolCapabilities(itemdef_manager); playeritem.getToolCapabilities(itemdef_manager);
if (wasKeyPressed(KeyType::CAMERA_MODE)) {
GenericCAO *playercao = player->getCAO();
// If playercao not loaded, don't change camera
if (!playercao)
return;
camera->toggleCameraMode();
if (g_touchcontrols)
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
// Make the player visible depending on camera mode.
playercao->updateMeshCulling();
playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
}
float full_punch_interval = playeritem_toolcap.full_punch_interval; float full_punch_interval = playeritem_toolcap.full_punch_interval;
float tool_reload_ratio = runData.time_from_last_punch / full_punch_interval; float tool_reload_ratio = runData.time_from_last_punch / full_punch_interval;
@ -2981,6 +2957,22 @@ void Game::updateCamera(f32 dtime)
} }
} }
void Game::updateCameraMode()
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
// Obey server choice
if (player->allowed_camera_mode != CAMERA_MODE_ANY)
camera->setCameraMode(player->allowed_camera_mode);
GenericCAO *playercao = player->getCAO();
if (playercao) {
// Make the player visible depending on camera mode.
playercao->updateMeshCulling();
playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
}
}
void Game::updateCameraOffset() void Game::updateCameraOffset()
{ {
ClientEnvironment &env = client->getEnv(); ClientEnvironment &env = client->getEnv();
@ -2997,8 +2989,13 @@ void Game::updateCameraOffset()
if (!m_flags.disable_camera_update) { if (!m_flags.disable_camera_update) {
auto *shadow = RenderingEngine::get_shadow_renderer(); auto *shadow = RenderingEngine::get_shadow_renderer();
if (shadow) if (shadow) {
shadow->getDirectionalLight().updateCameraOffset(camera); shadow->getDirectionalLight().updateCameraOffset(camera);
// FIXME: I bet we can be smarter about this and don't need to redraw
// the shadow map at all, but this is for someone else to figure out.
if (!g_settings->getFlag("performance_tradeoffs"))
shadow->setForceUpdateShadowMap();
}
env.getClientMap().updateCamera(camera->getPosition(), env.getClientMap().updateCamera(camera->getPosition(),
camera->getDirection(), camera->getFovMax(), camera_offset, camera->getDirection(), camera->getFovMax(), camera_offset,
@ -3057,6 +3054,9 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
core::line3d<f32> shootline; core::line3d<f32> shootline;
switch (camera->getCameraMode()) { switch (camera->getCameraMode()) {
case CAMERA_MODE_ANY:
assert(false);
break;
case CAMERA_MODE_FIRST: case CAMERA_MODE_FIRST:
// Shoot from camera position, with bobbing // Shoot from camera position, with bobbing
shootline.start = camera->getPosition(); shootline.start = camera->getPosition();
@ -3073,7 +3073,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
} }
shootline.end = shootline.start + camera_direction * BS * d; shootline.end = shootline.start + camera_direction * BS * d;
if (g_touchcontrols && isTouchCrosshairDisabled()) { if (isTouchShootlineUsed()) {
shootline = g_touchcontrols->getShootline(); shootline = g_touchcontrols->getShootline();
// Scale shootline to the acual distance the player can reach // Scale shootline to the acual distance the player can reach
shootline.end = shootline.start + shootline.end = shootline.start +
@ -3232,9 +3232,10 @@ PointedThing Game::updatePointedThing(
hud->setSelectionPos(pos, camera_offset); hud->setSelectionPos(pos, camera_offset);
GenericCAO* gcao = dynamic_cast<GenericCAO*>(runData.selected_object); GenericCAO* gcao = dynamic_cast<GenericCAO*>(runData.selected_object);
if (gcao != nullptr && gcao->getProperties().rotate_selectionbox) if (gcao != nullptr && gcao->getProperties().rotate_selectionbox)
hud->setSelectionRotation(gcao->getSceneNode()->getAbsoluteTransformation().getRotationDegrees()); hud->setSelectionRotationRadians(gcao->getSceneNode()
->getAbsoluteTransformation().getRotationRadians());
else else
hud->setSelectionRotation(v3f()); hud->setSelectionRotationRadians(v3f());
} }
hud->setSelectedFaceNormal(result.raw_intersection_normal); hud->setSelectedFaceNormal(result.raw_intersection_normal);
} else if (result.type == POINTEDTHING_NODE) { } else if (result.type == POINTEDTHING_NODE) {
@ -3244,17 +3245,15 @@ PointedThing Game::updatePointedThing(
n.getSelectionBoxes(nodedef, &boxes, n.getSelectionBoxes(nodedef, &boxes,
n.getNeighbors(result.node_undersurface, &map)); n.getNeighbors(result.node_undersurface, &map));
f32 d = 0.002 * BS; f32 d = 0.002f * BS;
for (std::vector<aabb3f>::const_iterator i = boxes.begin(); for (aabb3f box : boxes) {
i != boxes.end(); ++i) {
aabb3f box = *i;
box.MinEdge -= v3f(d, d, d); box.MinEdge -= v3f(d, d, d);
box.MaxEdge += v3f(d, d, d); box.MaxEdge += v3f(d, d, d);
selectionboxes->push_back(box); selectionboxes->push_back(box);
} }
hud->setSelectionPos(intToFloat(result.node_undersurface, BS), hud->setSelectionPos(intToFloat(result.node_undersurface, BS),
camera_offset); camera_offset);
hud->setSelectionRotation(v3f()); hud->setSelectionRotationRadians(v3f());
hud->setSelectedFaceNormal(result.intersection_normal); hud->setSelectedFaceNormal(result.intersection_normal);
} }
@ -3449,9 +3448,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
u8 predicted_param2 = dir.Y < 0 ? 1 : 0; u8 predicted_param2 = dir.Y < 0 ? 1 : 0;
if (selected_def.wallmounted_rotate_vertical) { if (selected_def.wallmounted_rotate_vertical) {
bool rotate90 = false; bool rotate90 = false;
v3f fnodepos = v3f(neighborpos.X, neighborpos.Y, neighborpos.Z);
v3f ppos = client->getEnv().getLocalPlayer()->getPosition() / BS; v3f ppos = client->getEnv().getLocalPlayer()->getPosition() / BS;
v3f pdir = fnodepos - ppos; v3f pdir = v3f::from(neighborpos) - ppos;
switch (predicted_f.drawtype) { switch (predicted_f.drawtype) {
case NDT_TORCHLIKE: { case NDT_TORCHLIKE: {
rotate90 = !((pdir.X < 0 && pdir.Z > 0) || rotate90 = !((pdir.X < 0 && pdir.Z > 0) ||
@ -4046,7 +4044,7 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) && (player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
(this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT)); (this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
if (g_touchcontrols && isTouchCrosshairDisabled()) if (isTouchShootlineUsed())
draw_crosshair = false; draw_crosshair = false;
this->m_rendering_engine->draw_scene(sky_color, this->m_game_ui->m_flags.show_hud, this->m_rendering_engine->draw_scene(sky_color, this->m_game_ui->m_flags.show_hud,
@ -4126,10 +4124,6 @@ void Game::readSettings()
m_invert_hotbar_mouse_wheel = g_settings->getBool("invert_hotbar_mouse_wheel"); m_invert_hotbar_mouse_wheel = g_settings->getBool("invert_hotbar_mouse_wheel");
m_does_lost_focus_pause_game = g_settings->getBool("pause_on_lost_focus"); m_does_lost_focus_pause_game = g_settings->getBool("pause_on_lost_focus");
m_touch_use_crosshair = g_settings->getBool("touch_use_crosshair");
if (g_touchcontrols)
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
} }
/****************************************************************************/ /****************************************************************************/

View file

@ -283,9 +283,7 @@ void GameFormSpec::showPauseMenuFormSpec(const std::string &formspec, const std:
&m_input->joystick, fs_src, txt_dst, "", &m_input->joystick, fs_src, txt_dst, "",
m_client->getSoundManager()); m_client->getSoundManager());
// FIXME: can't enable this for now because "fps_max_unfocused" also applies m_formspec->doPause = true;
// when the game is paused, making the settings menu much less enjoyable.
// m_formspec->doPause = true;
} }
void GameFormSpec::showNodeFormspec(const std::string &formspec, const v3s16 &nodepos) void GameFormSpec::showNodeFormspec(const std::string &formspec, const v3s16 &nodepos)
@ -376,18 +374,18 @@ void GameFormSpec::showPauseMenu()
<< strgettext("Continue") << "]"; << strgettext("Continue") << "]";
if (!simple_singleplayer_mode) { if (!simple_singleplayer_mode) {
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;" os << "button[4," << (ypos++) << ";3,0.5;btn_change_password;"
<< strgettext("Change Password") << "]"; << strgettext("Change Password") << "]";
} else { } else {
os << "field[4.95,0;5,1.5;;" << strgettext("Game paused") << ";]"; os << "field[4.95,0;5,1.5;;" << strgettext("Game paused") << ";]";
} }
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_settings;" os << "button[4," << (ypos++) << ";3,0.5;btn_settings;"
<< strgettext("Settings") << "]"; << strgettext("Settings") << "]";
#ifndef __ANDROID__ #ifndef __ANDROID__
#if USE_SOUND #if USE_SOUND
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" os << "button[4," << (ypos++) << ";3,0.5;btn_sound;"
<< strgettext("Sound Volume") << "]"; << strgettext("Sound Volume") << "]";
#endif #endif
#endif #endif

View file

@ -880,7 +880,7 @@ void Hud::drawSelectionMesh()
core::matrix4 translate; core::matrix4 translate;
translate.setTranslation(m_selection_pos_with_offset); translate.setTranslation(m_selection_pos_with_offset);
core::matrix4 rotation; core::matrix4 rotation;
rotation.setRotationDegrees(m_selection_rotation); rotation.setRotationRadians(m_selection_rotation_radians);
driver->setTransform(video::ETS_WORLD, translate * rotation); driver->setTransform(video::ETS_WORLD, translate * rotation);
if (m_mode == HIGHLIGHT_BOX) { if (m_mode == HIGHLIGHT_BOX) {
@ -965,8 +965,8 @@ void Hud::drawBlockBounds()
v3f pmax = v3f(x, y, 1 + radius) * MAP_BLOCKSIZE * BS; v3f pmax = v3f(x, y, 1 + radius) * MAP_BLOCKSIZE * BS;
driver->draw3DLine( driver->draw3DLine(
base_corner + v3f(pmin.X, pmin.Y, pmin.Z), base_corner + pmin,
base_corner + v3f(pmax.X, pmax.Y, pmax.Z), base_corner + pmax,
choose_color(block_pos.X, block_pos.Y) choose_color(block_pos.X, block_pos.Y)
); );
driver->draw3DLine( driver->draw3DLine(

View file

@ -74,9 +74,15 @@ public:
v3f getSelectionPos() const { return m_selection_pos; } v3f getSelectionPos() const { return m_selection_pos; }
void setSelectionRotation(v3f rotation) { m_selection_rotation = rotation; } void setSelectionRotationRadians(v3f rotation)
{
m_selection_rotation_radians = rotation;
}
v3f getSelectionRotation() const { return m_selection_rotation; } v3f getSelectionRotationRadians() const
{
return m_selection_rotation_radians;
}
void setSelectionMeshColor(const video::SColor &color) void setSelectionMeshColor(const video::SColor &color)
{ {
@ -129,7 +135,7 @@ private:
std::vector<aabb3f> m_halo_boxes; std::vector<aabb3f> m_halo_boxes;
v3f m_selection_pos; v3f m_selection_pos;
v3f m_selection_pos_with_offset; v3f m_selection_pos_with_offset;
v3f m_selection_rotation; v3f m_selection_rotation_radians;
scene::IMesh *m_selection_mesh = nullptr; scene::IMesh *m_selection_mesh = nullptr;
video::SColor m_selection_mesh_color; video::SColor m_selection_mesh_color;

View file

@ -285,13 +285,13 @@ void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::I
maxsx = minsx + sw / dim.Width; maxsx = minsx + sw / dim.Width;
maxsx = rangelim(maxsx, 0, sox + sw); maxsx = rangelim(maxsx, 0, sox + sw);
if (minsx > maxsx) if (minsx > maxsx)
SWAP(double, minsx, maxsx); std::swap(minsx, maxsx);
minsy = soy + (dy * sh / dim.Height); minsy = soy + (dy * sh / dim.Height);
minsy = rangelim(minsy, 0, soy + sh); minsy = rangelim(minsy, 0, soy + sh);
maxsy = minsy + sh / dim.Height; maxsy = minsy + sh / dim.Height;
maxsy = rangelim(maxsy, 0, soy + sh); maxsy = rangelim(maxsy, 0, soy + sh);
if (minsy > maxsy) if (minsy > maxsy)
SWAP(double, minsy, maxsy); std::swap(minsy, maxsy);
// Total area, and integral of r, g, b values over that area, // Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops. // initialized to zero, to be summed up in next loops.

View file

@ -426,20 +426,6 @@ void getNodeTile(MapNode mn, const v3s16 &p, const v3s16 &dir, MeshMakeData *dat
tile.rotation = tile.world_aligned ? TileRotation::None : dir_to_tile[facedir][dir_i].rotation; tile.rotation = tile.world_aligned ? TileRotation::None : dir_to_tile[facedir][dir_i].rotation;
} }
static void applyTileColor(PreMeshBuffer &pmb)
{
video::SColor tc = pmb.layer.color;
if (tc == video::SColor(0xFFFFFFFF))
return;
for (video::S3DVertex &vertex : pmb.vertices) {
video::SColor *c = &vertex.Color;
c->set(c->getAlpha(),
c->getRed() * tc.getRed() / 255,
c->getGreen() * tc.getGreen() / 255,
c->getBlue() * tc.getBlue() / 255);
}
}
/* /*
MapBlockBspTree MapBlockBspTree
*/ */
@ -668,7 +654,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
{ {
PreMeshBuffer &p = collector.prebuffers[layer][i]; PreMeshBuffer &p = collector.prebuffers[layer][i];
applyTileColor(p); p.applyTileColor();
// Generate animation data // Generate animation data
// - Cracks // - Cracks
@ -701,28 +687,16 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
// Create material // Create material
video::SMaterial material; video::SMaterial material;
material.BackfaceCulling = true;
material.FogEnable = true; material.FogEnable = true;
material.setTexture(0, p.layer.texture);
material.forEachTexture([] (auto &tex) { material.forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
tex.MagFilter = video::ETMAGF_NEAREST; tex.MagFilter = video::ETMAGF_NEAREST;
}); });
/*
* The second layer is for overlays, but uses the same vertex positions
* as the first, which quickly leads to z-fighting.
* To fix this we can offset the polygons in the direction of the camera.
* This only affects the depth buffer and leads to no visual gaps in geometry.
*/
if (layer == 1) {
material.PolygonOffsetSlopeScale = -1;
material.PolygonOffsetDepthBias = -1;
}
{ {
material.MaterialType = m_shdrsrc->getShaderInfo( material.MaterialType = m_shdrsrc->getShaderInfo(
p.layer.shader_id).material; p.layer.shader_id).material;
p.layer.applyMaterialOptionsWithShaders(material); p.layer.applyMaterialOptions(material, layer);
} }
scene::SMeshBuffer *buf = new scene::SMeshBuffer(); scene::SMeshBuffer *buf = new scene::SMeshBuffer();

View file

@ -145,8 +145,7 @@ QueuedMeshUpdate *MeshUpdateQueue::pop()
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
bool must_be_urgent = !m_urgents.empty(); bool must_be_urgent = !m_urgents.empty();
for (std::vector<QueuedMeshUpdate*>::iterator i = m_queue.begin(); for (auto i = m_queue.begin(); i != m_queue.end(); ++i) {
i != m_queue.end(); ++i) {
QueuedMeshUpdate *q = *i; QueuedMeshUpdate *q = *i;
if (must_be_urgent && m_urgents.count(q->p) == 0) if (must_be_urgent && m_urgents.count(q->p) == 0)
continue; continue;
@ -264,8 +263,8 @@ void MeshUpdateManager::updateBlock(Map *map, v3s16 p, bool ack_block_to_server,
g_settings->getBool("smooth_lighting") g_settings->getBool("smooth_lighting")
&& !g_settings->getFlag("performance_tradeoffs"); && !g_settings->getFlag("performance_tradeoffs");
if (!m_queue_in.addBlock(map, p, ack_block_to_server, urgent)) { if (!m_queue_in.addBlock(map, p, ack_block_to_server, urgent)) {
warningstream << "Update requested for non-existent block at (" warningstream << "Update requested for non-existent block at "
<< p.X << ", " << p.Y << ", " << p.Z << ")" << std::endl; << p << std::endl;
return; return;
} }
if (update_neighbors) { if (update_neighbors) {

View file

@ -18,6 +18,21 @@ struct PreMeshBuffer
PreMeshBuffer() = default; PreMeshBuffer() = default;
explicit PreMeshBuffer(const TileLayer &layer) : layer(layer) {} explicit PreMeshBuffer(const TileLayer &layer) : layer(layer) {}
/// @brief Colorizes vertices as indicated by tile layer
void applyTileColor()
{
video::SColor tc = layer.color;
if (tc == video::SColor(0xFFFFFFFF))
return;
for (auto &vertex : vertices) {
video::SColor *c = &vertex.Color;
c->set(c->getAlpha(),
c->getRed() * tc.getRed() / 255U,
c->getGreen() * tc.getGreen() / 255U,
c->getBlue() * tc.getBlue() / 255U);
}
}
}; };
struct MeshCollector struct MeshCollector

View file

@ -78,15 +78,13 @@ void MinimapUpdateThread::doUpdate()
while (popBlockUpdate(&update)) { while (popBlockUpdate(&update)) {
if (update.data) { if (update.data) {
// Swap two values in the map using single lookup // Swap two values in the map using single lookup
std::pair<std::map<v3s16, MinimapMapblock*>::iterator, bool> auto result = m_blocks_cache.insert(std::make_pair(update.pos, update.data));
result = m_blocks_cache.insert(std::make_pair(update.pos, update.data));
if (!result.second) { if (!result.second) {
delete result.first->second; delete result.first->second;
result.first->second = update.data; result.first->second = update.data;
} }
} else { } else {
std::map<v3s16, MinimapMapblock *>::iterator it; auto it = m_blocks_cache.find(update.pos);
it = m_blocks_cache.find(update.pos);
if (it != m_blocks_cache.end()) { if (it != m_blocks_cache.end()) {
delete it->second; delete it->second;
m_blocks_cache.erase(it); m_blocks_cache.erase(it);
@ -124,8 +122,7 @@ void MinimapUpdateThread::getMap(v3s16 pos, s16 size, s16 height)
for (blockpos.Z = blockpos_min.Z; blockpos.Z <= blockpos_max.Z; ++blockpos.Z) for (blockpos.Z = blockpos_min.Z; blockpos.Z <= blockpos_max.Z; ++blockpos.Z)
for (blockpos.Y = blockpos_min.Y; blockpos.Y <= blockpos_max.Y; ++blockpos.Y) for (blockpos.Y = blockpos_min.Y; blockpos.Y <= blockpos_max.Y; ++blockpos.Y)
for (blockpos.X = blockpos_min.X; blockpos.X <= blockpos_max.X; ++blockpos.X) { for (blockpos.X = blockpos_min.X; blockpos.X <= blockpos_max.X; ++blockpos.X) {
std::map<v3s16, MinimapMapblock *>::const_iterator pblock = auto pblock = m_blocks_cache.find(blockpos);
m_blocks_cache.find(blockpos);
if (pblock == m_blocks_cache.end()) if (pblock == m_blocks_cache.end())
continue; continue;
const MinimapMapblock &block = *pblock->second; const MinimapMapblock &block = *pblock->second;
@ -647,8 +644,7 @@ void Minimap::drawMinimap(core::rect<s32> rect)
f32 sin_angle = std::sin(m_angle * core::DEGTORAD); f32 sin_angle = std::sin(m_angle * core::DEGTORAD);
f32 cos_angle = std::cos(m_angle * core::DEGTORAD); f32 cos_angle = std::cos(m_angle * core::DEGTORAD);
s32 marker_size2 = 0.025 * (float)rect.getWidth();; s32 marker_size2 = 0.025 * (float)rect.getWidth();;
for (std::list<v2f>::const_iterator for (auto i = m_active_markers.begin();
i = m_active_markers.begin();
i != m_active_markers.end(); ++i) { i != m_active_markers.end(); ++i) {
v2f posf = *i; v2f posf = *i;
if (data->minimap_shape_round) { if (data->minimap_shape_round) {

View file

@ -193,7 +193,7 @@ void Particle::updateVertices(ClientEnvironment *env, video::SColor color)
video::S3DVertex *vertices = m_buffer->getVertices(m_index); video::S3DVertex *vertices = m_buffer->getVertices(m_index);
if (m_texture.tex != nullptr) if (m_texture.tex != nullptr)
scale = m_texture.tex -> scale.blend(m_time / (m_expiration+0.1)); scale = m_texture.tex -> scale.blend(m_time / (m_expiration+0.1f));
else else
scale = v2f(1.f, 1.f); scale = v2f(1.f, 1.f);
@ -203,7 +203,7 @@ void Particle::updateVertices(ClientEnvironment *env, video::SColor color)
v2u32 framesize; v2u32 framesize;
texcoord = m_p.animation.getTextureCoords(texsize, m_animation_frame); texcoord = m_p.animation.getTextureCoords(texsize, m_animation_frame);
m_p.animation.determineParams(texsize, NULL, NULL, &framesize); m_p.animation.determineParams(texsize, NULL, NULL, &framesize);
framesize_f = v2f(framesize.X / (float) texsize.X, framesize.Y / (float) texsize.Y); framesize_f = v2f::from(framesize) / v2f::from(texsize);
tx0 = m_texpos.X + texcoord.X; tx0 = m_texpos.X + texcoord.X;
tx1 = m_texpos.X + texcoord.X + framesize_f.X * m_texsize.X; tx1 = m_texpos.X + texcoord.X + framesize_f.X * m_texsize.X;

View file

@ -34,9 +34,9 @@ void FpsControl::reset()
last_time = porting::getTimeUs(); last_time = porting::getTimeUs();
} }
void FpsControl::limit(IrrlichtDevice *device, f32 *dtime, bool assume_paused) void FpsControl::limit(IrrlichtDevice *device, f32 *dtime)
{ {
const float fps_limit = (device->isWindowFocused() && !assume_paused) const float fps_limit = device->isWindowFocused()
? g_settings->getFloat("fps_max") ? g_settings->getFloat("fps_max")
: g_settings->getFloat("fps_max_unfocused"); : g_settings->getFloat("fps_max_unfocused");
const u64 frametime_min = 1000000.0f / std::max(fps_limit, 1.0f); const u64 frametime_min = 1000000.0f / std::max(fps_limit, 1.0f);

View file

@ -45,7 +45,7 @@ struct FpsControl {
void reset(); void reset();
void limit(IrrlichtDevice *device, f32 *dtime, bool assume_paused = false); void limit(IrrlichtDevice *device, f32 *dtime);
u32 getBusyMs() const { return busy_time / 1000; } u32 getBusyMs() const { return busy_time / 1000; }

View file

@ -32,6 +32,7 @@ void DirectionalLight::createSplitMatrices(const Camera *cam)
// adjusted frustum boundaries // adjusted frustum boundaries
float sfNear = future_frustum.zNear; float sfNear = future_frustum.zNear;
float sfFar = adjustDist(future_frustum.zFar, cam->getFovY()); float sfFar = adjustDist(future_frustum.zFar, cam->getFovY());
assert(sfFar - sfNear > 0);
// adjusted camera positions // adjusted camera positions
v3f cam_pos_world = cam->getPosition(); v3f cam_pos_world = cam->getPosition();
@ -74,7 +75,6 @@ void DirectionalLight::createSplitMatrices(const Camera *cam)
future_frustum.ViewMat.buildCameraLookAtMatrixLH(eye, center_scene, v3f(0.0f, 1.0f, 0.0f)); future_frustum.ViewMat.buildCameraLookAtMatrixLH(eye, center_scene, v3f(0.0f, 1.0f, 0.0f));
future_frustum.ProjOrthMat.buildProjectionMatrixOrthoLH(radius, radius, future_frustum.ProjOrthMat.buildProjectionMatrixOrthoLH(radius, radius,
0.0f, length, false); 0.0f, length, false);
future_frustum.camera_offset = cam->getOffset();
} }
DirectionalLight::DirectionalLight(const u32 shadowMapResolution, DirectionalLight::DirectionalLight(const u32 shadowMapResolution,
@ -86,6 +86,8 @@ DirectionalLight::DirectionalLight(const u32 shadowMapResolution,
void DirectionalLight::updateCameraOffset(const Camera *cam) void DirectionalLight::updateCameraOffset(const Camera *cam)
{ {
if (future_frustum.zFar == 0.0f) // not initialized
return;
createSplitMatrices(cam); createSplitMatrices(cam);
should_update_map_shadow = true; should_update_map_shadow = true;
dirty = true; dirty = true;

View file

@ -22,7 +22,6 @@ struct shadowFrustum
core::matrix4 ViewMat; core::matrix4 ViewMat;
v3f position; v3f position;
v3f player; v3f player;
v3s16 camera_offset;
}; };
class DirectionalLight class DirectionalLight
@ -85,6 +84,7 @@ public:
return mapRes; return mapRes;
} }
/// If true, shadow map needs to be invalidated due to frustum change
bool should_update_map_shadow{true}; bool should_update_map_shadow{true};
void commitFrustum(); void commitFrustum();

View file

@ -177,14 +177,15 @@ void ShadowRenderer::removeNodeFromShadowList(scene::ISceneNode *node)
node->forEachMaterial([] (auto &mat) { node->forEachMaterial([] (auto &mat) {
mat.setTexture(TEXTURE_LAYER_SHADOW, nullptr); mat.setTexture(TEXTURE_LAYER_SHADOW, nullptr);
}); });
for (auto it = m_shadow_node_array.begin(); it != m_shadow_node_array.end();) {
if (it->node == node) { auto it = std::find(m_shadow_node_array.begin(), m_shadow_node_array.end(), node);
it = m_shadow_node_array.erase(it); if (it == m_shadow_node_array.end()) {
break; infostream << "removeNodeFromShadowList: " << node << " not found" << std::endl;
} else { return;
++it;
}
} }
// swap with last, then remove
*it = m_shadow_node_array.back();
m_shadow_node_array.pop_back();
} }
void ShadowRenderer::updateSMTextures() void ShadowRenderer::updateSMTextures()
@ -254,17 +255,14 @@ void ShadowRenderer::updateSMTextures()
if (!m_shadow_node_array.empty()) { if (!m_shadow_node_array.empty()) {
bool reset_sm_texture = false; bool reset_sm_texture = false;
// detect if SM should be regenerated // clear texture if requested
for (DirectionalLight &light : m_light_list) { for (DirectionalLight &light : m_light_list) {
if (light.should_update_map_shadow) reset_sm_texture |= light.should_update_map_shadow;
m_force_update_shadow_map = true;
light.should_update_map_shadow = false; light.should_update_map_shadow = false;
} }
if (m_force_update_shadow_map) { if (reset_sm_texture || m_force_update_shadow_map)
m_current_frame = 0; m_current_frame = 0;
reset_sm_texture = true;
}
video::ITexture* shadowMapTargetTexture = shadowMapClientMapFuture; video::ITexture* shadowMapTargetTexture = shadowMapClientMapFuture;
if (shadowMapTargetTexture == nullptr) if (shadowMapTargetTexture == nullptr)
@ -273,7 +271,7 @@ void ShadowRenderer::updateSMTextures()
// Update SM incrementally: // Update SM incrementally:
for (DirectionalLight &light : m_light_list) { for (DirectionalLight &light : m_light_list) {
// Static shader values. // Static shader values.
for (auto cb : {m_shadow_depth_cb, m_shadow_depth_entity_cb, m_shadow_depth_trans_cb}) for (auto cb : {m_shadow_depth_cb, m_shadow_depth_entity_cb, m_shadow_depth_trans_cb}) {
if (cb) { if (cb) {
cb->MapRes = (f32)m_shadow_map_texture_size; cb->MapRes = (f32)m_shadow_map_texture_size;
cb->MaxFar = (f32)m_shadow_map_max_distance * BS; cb->MaxFar = (f32)m_shadow_map_max_distance * BS;
@ -281,12 +279,9 @@ void ShadowRenderer::updateSMTextures()
cb->PerspectiveBiasZ = getPerspectiveBiasZ(); cb->PerspectiveBiasZ = getPerspectiveBiasZ();
cb->CameraPos = light.getFuturePlayerPos(); cb->CameraPos = light.getFuturePlayerPos();
} }
}
// set the Render Target // Note that force_update means we're drawing everything one go.
// right now we can only render in usual RTT, not
// Depth texture is available in irrlicth maybe we
// should put some gl* fn here
if (m_current_frame < m_map_shadow_update_frames || m_force_update_shadow_map) { if (m_current_frame < m_map_shadow_update_frames || m_force_update_shadow_map) {
m_driver->setRenderTarget(shadowMapTargetTexture, reset_sm_texture, true, m_driver->setRenderTarget(shadowMapTargetTexture, reset_sm_texture, true,

View file

@ -28,7 +28,8 @@ struct NodeToApply
E_SHADOW_MODE m = E_SHADOW_MODE::ESM_BOTH) : E_SHADOW_MODE m = E_SHADOW_MODE::ESM_BOTH) :
node(n), node(n),
shadowMode(m){}; shadowMode(m){};
bool operator<(const NodeToApply &other) const { return node < other.node; };
bool operator==(scene::ISceneNode *n) const { return node == n; }
scene::ISceneNode *node; scene::ISceneNode *node;
@ -68,6 +69,7 @@ public:
void removeNodeFromShadowList(scene::ISceneNode *node); void removeNodeFromShadowList(scene::ISceneNode *node);
void update(video::ITexture *outputTarget = nullptr); void update(video::ITexture *outputTarget = nullptr);
/// Force shadow map to be re-drawn in one go next frame
void setForceUpdateShadowMap() { m_force_update_shadow_map = true; } void setForceUpdateShadowMap() { m_force_update_shadow_map = true; }
void drawDebug(); void drawDebug();

View file

@ -4,41 +4,10 @@
#include "tile.h" #include "tile.h"
// Sets everything else except the texture in the material void TileLayer::applyMaterialOptions(video::SMaterial &material, int layer) const
void TileLayer::applyMaterialOptions(video::SMaterial &material) const
{ {
switch (material_type) { material.setTexture(0, texture);
case TILE_MATERIAL_OPAQUE:
case TILE_MATERIAL_LIQUID_OPAQUE:
case TILE_MATERIAL_WAVING_LIQUID_OPAQUE:
material.MaterialType = video::EMT_SOLID;
break;
case TILE_MATERIAL_BASIC:
case TILE_MATERIAL_WAVING_LEAVES:
case TILE_MATERIAL_WAVING_PLANTS:
case TILE_MATERIAL_WAVING_LIQUID_BASIC:
material.MaterialTypeParam = 0.5;
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
break;
case TILE_MATERIAL_ALPHA:
case TILE_MATERIAL_LIQUID_TRANSPARENT:
case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
break;
default:
break;
}
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0;
if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
}
if (!(material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) {
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
}
}
void TileLayer::applyMaterialOptionsWithShaders(video::SMaterial &material) const
{
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0; material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0;
if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) { if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
@ -48,4 +17,15 @@ void TileLayer::applyMaterialOptionsWithShaders(video::SMaterial &material) cons
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
material.TextureLayers[1].TextureWrapV = video::ETC_CLAMP_TO_EDGE; material.TextureLayers[1].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
} }
/*
* The second layer is for overlays, but uses the same vertex positions
* as the first, which easily leads to Z-fighting.
* To fix this we can offset the polygons in the direction of the camera.
* This only affects the depth buffer and leads to no visual gaps in geometry.
*/
if (layer == 1) {
material.PolygonOffsetSlopeScale = -1;
material.PolygonOffsetDepthBias = -1;
}
} }

View file

@ -9,7 +9,7 @@
#include <vector> #include <vector>
#include <SMaterial.h> #include <SMaterial.h>
enum MaterialType{ enum MaterialType : u8 {
TILE_MATERIAL_BASIC, TILE_MATERIAL_BASIC,
TILE_MATERIAL_ALPHA, TILE_MATERIAL_ALPHA,
TILE_MATERIAL_LIQUID_TRANSPARENT, TILE_MATERIAL_LIQUID_TRANSPARENT,
@ -84,9 +84,13 @@ struct TileLayer
return !(*this == other); return !(*this == other);
} }
void applyMaterialOptions(video::SMaterial &material) const; /**
* Set some material parameters accordingly.
void applyMaterialOptionsWithShaders(video::SMaterial &material) const; * @note does not set `MaterialType`
* @param material material to mody
* @param layer index of this layer in the `TileSpec`
*/
void applyMaterialOptions(video::SMaterial &material, int layer) const;
/// @return is this layer semi-transparent? /// @return is this layer semi-transparent?
bool isTransparent() const bool isTransparent() const
@ -98,8 +102,9 @@ struct TileLayer
case TILE_MATERIAL_LIQUID_TRANSPARENT: case TILE_MATERIAL_LIQUID_TRANSPARENT:
case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
return true; return true;
default:
return false;
} }
return false;
} }
// Ordered for size, please do not reorder // Ordered for size, please do not reorder
@ -113,13 +118,14 @@ struct TileLayer
u16 animation_frame_length_ms = 0; u16 animation_frame_length_ms = 0;
u16 animation_frame_count = 1; u16 animation_frame_count = 1;
u8 material_type = TILE_MATERIAL_BASIC; MaterialType material_type = TILE_MATERIAL_BASIC;
u8 material_flags = u8 material_flags =
//0 // <- DEBUG, Use the one below //0 // <- DEBUG, Use the one below
MATERIAL_FLAG_BACKFACE_CULLING | MATERIAL_FLAG_BACKFACE_CULLING |
MATERIAL_FLAG_TILEABLE_HORIZONTAL| MATERIAL_FLAG_TILEABLE_HORIZONTAL|
MATERIAL_FLAG_TILEABLE_VERTICAL; MATERIAL_FLAG_TILEABLE_VERTICAL;
/// @note not owned by this struct
std::vector<FrameSpec> *frames = nullptr; std::vector<FrameSpec> *frames = nullptr;
/*! /*!

View file

@ -154,8 +154,7 @@ public:
int maxdim = MYMAX(dim.Width, dim.Height); int maxdim = MYMAX(dim.Width, dim.Height);
std::map<int, scene::IMesh*>::iterator auto it = m_extrusion_meshes.lower_bound(maxdim);
it = m_extrusion_meshes.lower_bound(maxdim);
if (it == m_extrusion_meshes.end()) { if (it == m_extrusion_meshes.end()) {
// no viable resolution found; use largest one // no viable resolution found; use largest one
@ -204,7 +203,6 @@ WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id):
// Create the child scene node // Create the child scene node
scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube(); scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube();
m_meshnode = SceneManager->addMeshSceneNode(dummymesh, this, -1); m_meshnode = SceneManager->addMeshSceneNode(dummymesh, this, -1);
m_meshnode->setReadOnlyMaterials(false);
m_meshnode->setVisible(false); m_meshnode->setVisible(false);
dummymesh->drop(); // m_meshnode grabbed it dummymesh->drop(); // m_meshnode grabbed it
@ -327,13 +325,8 @@ static scene::SMesh *createGenericNodeMesh(Client *client, MapNode n,
buf->append(&p.vertices[0], p.vertices.size(), buf->append(&p.vertices[0], p.vertices.size(),
&p.indices[0], p.indices.size()); &p.indices[0], p.indices.size());
// Set up material // note: material type is left unset, overriden later
buf->Material.setTexture(0, p.layer.texture); p.layer.applyMaterialOptions(buf->Material, layer);
if (layer == 1) {
buf->Material.PolygonOffsetSlopeScale = -1;
buf->Material.PolygonOffsetDepthBias = -1;
}
p.layer.applyMaterialOptions(buf->Material);
mesh->addMeshBuffer(buf.get()); mesh->addMeshBuffer(buf.get());
colors->emplace_back(p.layer.has_color, p.layer.color); colors->emplace_back(p.layer.has_color, p.layer.color);
@ -433,7 +426,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
u32 material_count = m_meshnode->getMaterialCount(); u32 material_count = m_meshnode->getMaterialCount();
for (u32 i = 0; i < material_count; ++i) { for (u32 i = 0; i < material_count; ++i) {
video::SMaterial &material = m_meshnode->getMaterial(i); video::SMaterial &material = m_meshnode->getMaterial(i);
// FIXME: overriding this breaks different alpha modes the mesh may have // FIXME: we should take different alpha modes of the mesh into account here
material.MaterialType = m_material_type; material.MaterialType = m_material_type;
material.MaterialTypeParam = 0.5f; material.MaterialTypeParam = 0.5f;
material.forEachTexture([this] (auto &tex) { material.forEachTexture([this] (auto &tex) {

View file

@ -72,6 +72,14 @@ inline v3f truncate(const v3f vec, const f32 factor)
); );
} }
inline v3f rangelimv(const v3f vec, const f32 low, const f32 high)
{
return v3f(
rangelim(vec.X, low, high),
rangelim(vec.Y, low, high),
rangelim(vec.Z, low, high)
);
}
} }
// Helper function: // Helper function:
@ -101,6 +109,8 @@ CollisionAxis axisAlignedCollision(
if (speed.Y) { if (speed.Y) {
distance = relbox.MaxEdge.Y - relbox.MinEdge.Y; distance = relbox.MaxEdge.Y - relbox.MinEdge.Y;
// FIXME: The dtime calculation is inaccurate without acceleration information.
// Exact formula: `dtime = (-vel ± sqrt(vel² + 2 * acc * distance)) / acc`
*dtime = distance / std::abs(speed.Y); *dtime = distance / std::abs(speed.Y);
time = std::max(*dtime, 0.0f); time = std::max(*dtime, 0.0f);
@ -214,16 +224,50 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
thread_local std::vector<aabb3f> nodeboxes; thread_local std::vector<aabb3f> nodeboxes;
Map *map = &env->getMap(); Map *map = &env->getMap();
const bool air_walkable = nodedef->get(CONTENT_AIR).walkable;
v3s16 last_bp(S16_MAX);
MapBlock *last_block = nullptr;
// Note: as the area used here is usually small, iterating entire blocks
// would actually be slower by factor of 10.
v3s16 p; v3s16 p;
for (p.Z = min.Z; p.Z <= max.Z; p.Z++) for (p.Z = min.Z; p.Z <= max.Z; p.Z++)
for (p.Y = min.Y; p.Y <= max.Y; p.Y++) for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
for (p.X = min.X; p.X <= max.X; p.X++) { for (p.X = min.X; p.X <= max.X; p.X++) {
bool is_position_valid; v3s16 bp, relp;
MapNode n = map->getNode(p, &is_position_valid); getNodeBlockPosWithOffset(p, bp, relp);
if (bp != last_bp) {
last_block = map->getBlockNoCreateNoEx(bp);
last_bp = bp;
}
MapBlock *const block = last_block;
if (is_position_valid && n.getContent() != CONTENT_IGNORE) { if (!block) {
// Object collides into walkable nodes // Since we iterate with node precision we can only safely skip
// ahead in the "innermost" axis of the MapBlock (X).
// This still worth it as it reduces the number of nodes to look at
// and entries in `cinfo`.
v3s16 rowend(bp.X * MAP_BLOCKSIZE + MAP_BLOCKSIZE - 1, p.Y, p.Z);
aabb3f box = getNodeBox(p, BS);
box.addInternalBox(getNodeBox(rowend, BS));
// Collide with unloaded block
cinfo.emplace_back(true, 0, p, box);
p.X = rowend.X;
continue;
}
if (!air_walkable && block->isAir()) {
// Skip ahead if air, like above
any_position_valid = true;
p.X = bp.X * MAP_BLOCKSIZE + MAP_BLOCKSIZE - 1;
continue;
}
const MapNode n = block->getNodeNoCheck(relp);
if (n.getContent() != CONTENT_IGNORE) {
any_position_valid = true; any_position_valid = true;
const ContentFeatures &f = nodedef->get(n); const ContentFeatures &f = nodedef->get(n);
@ -238,7 +282,6 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
nodeboxes.clear(); nodeboxes.clear();
n.getCollisionBoxes(nodedef, &nodeboxes, neighbors); n.getCollisionBoxes(nodedef, &nodeboxes, neighbors);
// Calculate float position only once
v3f posf = intToFloat(p, BS); v3f posf = intToFloat(p, BS);
for (auto box : nodeboxes) { for (auto box : nodeboxes) {
box.MinEdge += posf; box.MinEdge += posf;
@ -246,12 +289,12 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
cinfo.emplace_back(false, n_bouncy_value, p, box); cinfo.emplace_back(false, n_bouncy_value, p, box);
} }
} else { } else {
// Collide with unloaded nodes (position invalid) and loaded // Collide with loaded CONTENT_IGNORE nodes
// CONTENT_IGNORE nodes (position valid)
aabb3f box = getNodeBox(p, BS); aabb3f box = getNodeBox(p, BS);
cinfo.emplace_back(true, 0, p, box); cinfo.emplace_back(true, 0, p, box);
} }
} }
return any_position_valid; return any_position_valid;
} }
@ -335,6 +378,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
collisionMoveResult result; collisionMoveResult result;
// Assume no collisions when no velocity and no acceleration
if (*speed_f == v3f() && accel_f == v3f())
return result;
/* /*
Calculate new velocity Calculate new velocity
*/ */
@ -350,30 +397,19 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
time_notification_done = false; time_notification_done = false;
} }
v3f dpos_f = (*speed_f + accel_f * 0.5f * dtime) * dtime; // Average speed
v3f newpos_f = *pos_f + dpos_f; v3f aspeed_f = *speed_f + accel_f * 0.5f * dtime;
*speed_f += accel_f * dtime;
// If the object is static, there are no collisions
if (dpos_f == v3f())
return result;
// Limit speed for avoiding hangs // Limit speed for avoiding hangs
speed_f->Y = rangelim(speed_f->Y, -5000, 5000); aspeed_f = truncate(rangelimv(aspeed_f, -5000.0f, 5000.0f), 10000.0f);
speed_f->X = rangelim(speed_f->X, -5000, 5000);
speed_f->Z = rangelim(speed_f->Z, -5000, 5000);
*speed_f = truncate(*speed_f, 10000.0f); // Collect node boxes in movement range
/*
Collect node boxes in movement range
*/
// cached allocation // cached allocation
thread_local std::vector<NearbyCollisionInfo> cinfo; thread_local std::vector<NearbyCollisionInfo> cinfo;
cinfo.clear(); cinfo.clear();
{ {
// Movement if no collisions
v3f newpos_f = *pos_f + aspeed_f * dtime;
v3f minpos_f( v3f minpos_f(
MYMIN(pos_f->X, newpos_f.X), MYMIN(pos_f->X, newpos_f.X),
MYMIN(pos_f->Y, newpos_f.Y) + 0.01f * BS, // bias rounding, player often at +/-n.5 MYMIN(pos_f->Y, newpos_f.Y) + 0.01f * BS, // bias rounding, player often at +/-n.5
@ -399,24 +435,14 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
} }
} }
/* // Collect object boxes in movement range
Collect object boxes in movement range
*/
if (collide_with_objects) { if (collide_with_objects) {
add_object_boxes(env, box_0, dtime, *pos_f, *speed_f, self, cinfo); add_object_boxes(env, box_0, dtime, *pos_f, aspeed_f, self, cinfo);
} }
/* // Collision detection
Collision detection
*/
f32 d = 0.0f; f32 d = 0.0f;
for (int loopcount = 0;; loopcount++) {
int loopcount = 0;
while(dtime > BS * 1e-10f) {
// Avoid infinite loop
loopcount++;
if (loopcount >= 100) { if (loopcount >= 100) {
warningstream << "collisionMoveSimple: Loop count exceeded, aborting to avoid infinite loop" << std::endl; warningstream << "collisionMoveSimple: Loop count exceeded, aborting to avoid infinite loop" << std::endl;
g_collision_problems_encountered = true; g_collision_problems_encountered = true;
@ -431,9 +457,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
f32 nearest_dtime = dtime; f32 nearest_dtime = dtime;
int nearest_boxindex = -1; int nearest_boxindex = -1;
/* // Go through every nodebox, find nearest collision
Go through every nodebox, find nearest collision
*/
for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) { for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
const NearbyCollisionInfo &box_info = cinfo[boxindex]; const NearbyCollisionInfo &box_info = cinfo[boxindex];
// Ignore if already stepped up this nodebox. // Ignore if already stepped up this nodebox.
@ -443,8 +467,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
// Find nearest collision of the two boxes (raytracing-like) // Find nearest collision of the two boxes (raytracing-like)
f32 dtime_tmp = nearest_dtime; f32 dtime_tmp = nearest_dtime;
CollisionAxis collided = axisAlignedCollision(box_info.box, CollisionAxis collided = axisAlignedCollision(box_info.box,
movingbox, *speed_f, &dtime_tmp); movingbox, aspeed_f, &dtime_tmp);
if (collided == -1 || dtime_tmp >= nearest_dtime) if (collided == -1 || dtime_tmp >= nearest_dtime)
continue; continue;
@ -455,95 +478,119 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
if (nearest_collided == COLLISION_AXIS_NONE) { if (nearest_collided == COLLISION_AXIS_NONE) {
// No collision with any collision box. // No collision with any collision box.
*pos_f += truncate(*speed_f * dtime, 100.0f); *pos_f += aspeed_f * dtime;
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers // Final speed:
} else { *speed_f += accel_f * dtime;
// Otherwise, a collision occurred. // Limit speed for avoiding hangs
NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex]; *speed_f = truncate(rangelimv(*speed_f, -5000.0f, 5000.0f), 10000.0f);
const aabb3f& cbox = nearest_info.box; break;
}
// Otherwise, a collision occurred.
NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
const aabb3f& cbox = nearest_info.box;
//movingbox except moved to the horizontal position it would be after step up //movingbox except moved to the horizontal position it would be after step up
bool step_up = false;
if (nearest_collided != COLLISION_AXIS_Y) {
aabb3f stepbox = movingbox; aabb3f stepbox = movingbox;
stepbox.MinEdge.X += speed_f->X * dtime; // Look slightly ahead for checking the height when stepping
stepbox.MinEdge.Z += speed_f->Z * dtime; // to ensure we also check above the node we collided with
stepbox.MaxEdge.X += speed_f->X * dtime; // otherwise, might allow glitches such as a stack of stairs
stepbox.MaxEdge.Z += speed_f->Z * dtime; float extra_dtime = nearest_dtime + 0.1f * fabsf(dtime - nearest_dtime);
stepbox.MinEdge.X += aspeed_f.X * extra_dtime;
stepbox.MinEdge.Z += aspeed_f.Z * extra_dtime;
stepbox.MaxEdge.X += aspeed_f.X * extra_dtime;
stepbox.MaxEdge.Z += aspeed_f.Z * extra_dtime;
// Check for stairs. // Check for stairs.
bool step_up = (nearest_collided != COLLISION_AXIS_Y) && // must not be Y direction step_up = (movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) && (movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) && (!wouldCollideWithCeiling(cinfo, stepbox,
(!wouldCollideWithCeiling(cinfo, stepbox, cbox.MaxEdge.Y - movingbox.MinEdge.Y,
cbox.MaxEdge.Y - movingbox.MinEdge.Y, d));
d)); }
// Get bounce multiplier // Get bounce multiplier
float bounce = -(float)nearest_info.bouncy / 100.0f; float bounce = -(float)nearest_info.bouncy / 100.0f;
// Move to the point of collision and reduce dtime by nearest_dtime // Move to the point of collision and reduce dtime by nearest_dtime
if (nearest_dtime < 0) { if (nearest_dtime < 0) {
// Handle negative nearest_dtime // Handle negative nearest_dtime
if (!step_up) { // This largely means an "instant" collision, e.g., with the floor.
if (nearest_collided == COLLISION_AXIS_X) // We use aspeed and nearest_dtime to be consistent with above and resolve this collision
pos_f->X += speed_f->X * nearest_dtime; if (!step_up) {
if (nearest_collided == COLLISION_AXIS_Y) if (nearest_collided == COLLISION_AXIS_X)
pos_f->Y += speed_f->Y * nearest_dtime; pos_f->X += aspeed_f.X * nearest_dtime;
if (nearest_collided == COLLISION_AXIS_Z) if (nearest_collided == COLLISION_AXIS_Y)
pos_f->Z += speed_f->Z * nearest_dtime; pos_f->Y += aspeed_f.Y * nearest_dtime;
} if (nearest_collided == COLLISION_AXIS_Z)
} else { pos_f->Z += aspeed_f.Z * nearest_dtime;
*pos_f += truncate(*speed_f * nearest_dtime, 100.0f);
dtime -= nearest_dtime;
} }
} else if (nearest_dtime > 0) {
// updated average speed for the sub-interval up to nearest_dtime
aspeed_f = *speed_f + accel_f * 0.5f * nearest_dtime;
*pos_f += aspeed_f * nearest_dtime;
// Speed at (approximated) collision:
*speed_f += accel_f * nearest_dtime;
// Limit speed for avoiding hangs
*speed_f = truncate(rangelimv(*speed_f, -5000.0f, 5000.0f), 10000.0f);
dtime -= nearest_dtime;
}
bool is_collision = true; v3f old_speed_f = *speed_f;
if (nearest_info.is_unloaded)
is_collision = false;
// Set the speed component that caused the collision to zero
if (step_up) {
// Special case: Handle stairs
nearest_info.is_step_up = true;
} else if (nearest_collided == COLLISION_AXIS_X) {
if (bounce < -1e-4 && fabsf(speed_f->X) > BS * 3) {
speed_f->X *= bounce;
} else {
speed_f->X = 0;
accel_f.X = 0; // avoid colliding in the next interations
}
} else if (nearest_collided == COLLISION_AXIS_Y) {
if (bounce < -1e-4 && fabsf(speed_f->Y) > BS * 3) {
speed_f->Y *= bounce;
} else {
if (speed_f->Y < 0.0f) {
// FIXME: This code is necessary until `axisAlignedCollision` takes acceleration
// into consideration for the time calculation. Otherwise, the colliding faces
// never line up, especially at high step (dtime) intervals.
result.touching_ground = true;
result.standing_on_object = nearest_info.isObject();
}
speed_f->Y = 0;
accel_f.Y = 0; // avoid colliding in the next interations
}
} else { /* nearest_collided == COLLISION_AXIS_Z */
if (bounce < -1e-4 && fabsf(speed_f->Z) > BS * 3) {
speed_f->Z *= bounce;
} else {
speed_f->Z = 0;
accel_f.Z = 0; // avoid colliding in the next interations
}
}
if (!nearest_info.is_unloaded && !step_up) {
CollisionInfo info; CollisionInfo info;
if (nearest_info.isObject()) info.axis = nearest_collided;
info.type = COLLISION_OBJECT; info.type = nearest_info.isObject() ? COLLISION_OBJECT : COLLISION_NODE;
else
info.type = COLLISION_NODE;
info.node_p = nearest_info.position; info.node_p = nearest_info.position;
info.object = nearest_info.obj; info.object = nearest_info.obj;
info.new_pos = *pos_f; info.new_pos = *pos_f;
info.old_speed = *speed_f; info.old_speed = old_speed_f;
// Set the speed component that caused the collision to zero
if (step_up) {
// Special case: Handle stairs
nearest_info.is_step_up = true;
is_collision = false;
} else if (nearest_collided == COLLISION_AXIS_X) {
if (fabs(speed_f->X) > BS * 3)
speed_f->X *= bounce;
else
speed_f->X = 0;
result.collides = true;
} else if (nearest_collided == COLLISION_AXIS_Y) {
if(fabs(speed_f->Y) > BS * 3)
speed_f->Y *= bounce;
else
speed_f->Y = 0;
result.collides = true;
} else if (nearest_collided == COLLISION_AXIS_Z) {
if (fabs(speed_f->Z) > BS * 3)
speed_f->Z *= bounce;
else
speed_f->Z = 0;
result.collides = true;
}
info.new_speed = *speed_f; info.new_speed = *speed_f;
if (info.new_speed.getDistanceFrom(info.old_speed) < 0.1f * BS) result.collisions.push_back(info);
is_collision = false;
if (is_collision) {
info.axis = nearest_collided;
result.collisions.push_back(std::move(info));
}
} }
if (dtime < BS * 1e-10f)
break;
// Speed for finding the next collision
aspeed_f = *speed_f + accel_f * 0.5f * dtime;
// Limit speed for avoiding hangs
aspeed_f = truncate(rangelimv(aspeed_f, -5000.0f, 5000.0f), 10000.0f);
} }
/* /*
@ -573,14 +620,15 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
box.MaxEdge += *pos_f; box.MaxEdge += *pos_f;
} }
if (std::fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.05f) { if (std::fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.05f) {
// This is code is technically only required if `box_info.is_step_up == true`.
// However, players rely on this check/condition to climb stairs faster. See PR #10587.
result.touching_ground = true; result.touching_ground = true;
result.standing_on_object = box_info.isObject();
if (box_info.isObject())
result.standing_on_object = true;
} }
} }
} }
result.collides = !result.collisions.empty();
return result; return result;
} }

View file

@ -140,8 +140,6 @@ void ModConfiguration::addModsFromConfig(
* *
* Alternative candidates for a modname are stored in `candidates`, * Alternative candidates for a modname are stored in `candidates`,
* and used in an error message later. * and used in an error message later.
*
* If not enabled, add `load_mod_modname = false` to world.mt
*/ */
for (const auto &modPath : modPaths) { for (const auto &modPath : modPaths) {
std::vector<ModSpec> addon_mods_in_path = flattenMods(getModsInPath(modPath.second, modPath.first)); std::vector<ModSpec> addon_mods_in_path = flattenMods(getModsInPath(modPath.second, modPath.first));
@ -154,7 +152,7 @@ void ModConfiguration::addModsFromConfig(
candidates[pair->first].emplace_back(mod.virtual_path); candidates[pair->first].emplace_back(mod.virtual_path);
} }
} else { } else {
conf.setBool("load_mod_" + mod.name, false); conf.remove("load_mod_" + mod.name);
} }
} }
} }

View file

@ -30,15 +30,13 @@ void Database_Dummy::loadBlock(const v3s16 &pos, std::string *block)
bool Database_Dummy::deleteBlock(const v3s16 &pos) bool Database_Dummy::deleteBlock(const v3s16 &pos)
{ {
m_database.erase(getBlockAsInteger(pos)); return m_database.erase(getBlockAsInteger(pos)) > 0;
return true;
} }
void Database_Dummy::listAllLoadableBlocks(std::vector<v3s16> &dst) void Database_Dummy::listAllLoadableBlocks(std::vector<v3s16> &dst)
{ {
dst.reserve(m_database.size()); dst.reserve(m_database.size());
for (std::map<s64, std::string>::const_iterator x = m_database.begin(); for (auto x = m_database.begin(); x != m_database.end(); ++x) {
x != m_database.end(); ++x) {
dst.push_back(getIntegerAsBlock(x->first)); dst.push_back(getIntegerAsBlock(x->first));
} }
} }

View file

@ -234,8 +234,7 @@ void PlayerDatabaseFiles::listPlayers(std::vector<std::string> &res)
{ {
std::vector<fs::DirListNode> files = fs::GetDirListing(m_savedir); std::vector<fs::DirListNode> files = fs::GetDirListing(m_savedir);
// list files into players directory // list files into players directory
for (std::vector<fs::DirListNode>::const_iterator it = files.begin(); it != for (auto it = files.begin(); it != files.end(); ++it) {
files.end(); ++it) {
// Ignore directories // Ignore directories
if (it->dir) if (it->dir)
continue; continue;

View file

@ -97,7 +97,7 @@ void Database_PostgreSQL::ping()
bool Database_PostgreSQL::initialized() const bool Database_PostgreSQL::initialized() const
{ {
return (PQstatus(m_conn) == CONNECTION_OK); return m_conn && PQstatus(m_conn) == CONNECTION_OK;
} }
PGresult *Database_PostgreSQL::checkResults(PGresult *result, bool clear) PGresult *Database_PostgreSQL::checkResults(PGresult *result, bool clear)

View file

@ -9,20 +9,20 @@
#include "database.h" #include "database.h"
#include "util/basic_macros.h" #include "util/basic_macros.h"
class Settings; // Template class for PostgreSQL based data storage
class Database_PostgreSQL : public Database
class Database_PostgreSQL: public Database
{ {
public: public:
Database_PostgreSQL(const std::string &connect_string, const char *type); Database_PostgreSQL(const std::string &connect_string, const char *type);
~Database_PostgreSQL(); ~Database_PostgreSQL();
void beginSave(); void beginSave() override;
void endSave(); void endSave() override;
void rollback(); void rollback();
bool initialized() const; bool initialized() const override;
void verifyDatabase() override;
protected: protected:
// Conversion helpers // Conversion helpers
@ -73,7 +73,6 @@ protected:
} }
void createTableIfNotExists(const std::string &table_name, const std::string &definition); void createTableIfNotExists(const std::string &table_name, const std::string &definition);
void verifyDatabase();
// Database initialization // Database initialization
void connectToDatabase(); void connectToDatabase();
@ -99,6 +98,12 @@ private:
int m_pgversion = 0; int m_pgversion = 0;
}; };
// Not sure why why we have to do this. can't C++ figure it out on its own?
#define PARENT_CLASS_FUNCS \
void beginSave() { Database_PostgreSQL::beginSave(); } \
void endSave() { Database_PostgreSQL::endSave(); } \
void verifyDatabase() { Database_PostgreSQL::verifyDatabase(); }
class MapDatabasePostgreSQL : private Database_PostgreSQL, public MapDatabase class MapDatabasePostgreSQL : private Database_PostgreSQL, public MapDatabase
{ {
public: public:
@ -110,8 +115,7 @@ public:
bool deleteBlock(const v3s16 &pos); bool deleteBlock(const v3s16 &pos);
void listAllLoadableBlocks(std::vector<v3s16> &dst); void listAllLoadableBlocks(std::vector<v3s16> &dst);
void beginSave() { Database_PostgreSQL::beginSave(); } PARENT_CLASS_FUNCS
void endSave() { Database_PostgreSQL::endSave(); }
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
@ -129,6 +133,8 @@ public:
bool removePlayer(const std::string &name); bool removePlayer(const std::string &name);
void listPlayers(std::vector<std::string> &res); void listPlayers(std::vector<std::string> &res);
PARENT_CLASS_FUNCS
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
virtual void initStatements(); virtual void initStatements();
@ -143,8 +149,6 @@ public:
AuthDatabasePostgreSQL(const std::string &connect_string); AuthDatabasePostgreSQL(const std::string &connect_string);
virtual ~AuthDatabasePostgreSQL() = default; virtual ~AuthDatabasePostgreSQL() = default;
virtual void verifyDatabase() { Database_PostgreSQL::verifyDatabase(); }
virtual bool getAuth(const std::string &name, AuthEntry &res); virtual bool getAuth(const std::string &name, AuthEntry &res);
virtual bool saveAuth(const AuthEntry &authEntry); virtual bool saveAuth(const AuthEntry &authEntry);
virtual bool createAuth(AuthEntry &authEntry); virtual bool createAuth(AuthEntry &authEntry);
@ -152,6 +156,8 @@ public:
virtual void listNames(std::vector<std::string> &res); virtual void listNames(std::vector<std::string> &res);
virtual void reload(); virtual void reload();
PARENT_CLASS_FUNCS
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
virtual void initStatements(); virtual void initStatements();
@ -176,10 +182,11 @@ public:
bool removeModEntries(const std::string &modname); bool removeModEntries(const std::string &modname);
void listMods(std::vector<std::string> *res); void listMods(std::vector<std::string> *res);
void beginSave() { Database_PostgreSQL::beginSave(); } PARENT_CLASS_FUNCS
void endSave() { Database_PostgreSQL::endSave(); }
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
virtual void initStatements(); virtual void initStatements();
}; };
#undef PARENT_CLASS_FUNCS

View file

@ -2,14 +2,6 @@
// SPDX-License-Identifier: LGPL-2.1-or-later // SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> // Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
/*
SQLite format specification:
blocks:
(PK) INT id
BLOB data
*/
#include "database-sqlite3.h" #include "database-sqlite3.h"
#include "log.h" #include "log.h"
@ -26,23 +18,19 @@ SQLite format specification:
// When to print messages when the database is being held locked by another process // When to print messages when the database is being held locked by another process
// Note: I've seen occasional delays of over 250ms while running minetestmapper. // Note: I've seen occasional delays of over 250ms while running minetestmapper.
#define BUSY_INFO_TRESHOLD 100 // Print first informational message after 100ms. enum {
#define BUSY_WARNING_TRESHOLD 250 // Print warning message after 250ms. Lag is increased. BUSY_INFO_TRESHOLD = 100, // Print first informational message.
#define BUSY_ERROR_TRESHOLD 1000 // Print error message after 1000ms. Significant lag. BUSY_WARNING_TRESHOLD = 250, // Print warning message. Significant lag.
#define BUSY_FATAL_TRESHOLD 3000 // Allow SQLITE_BUSY to be returned, which will cause a minetest crash. BUSY_FATAL_TRESHOLD = 3000, // Allow SQLITE_BUSY to be returned back to the caller.
#define BUSY_ERROR_INTERVAL 10000 // Safety net: report again every 10 seconds BUSY_ERROR_INTERVAL = 10000, // Safety net: report again every 10 seconds
};
#define SQLRES(s, r, m) sqlite3_vrfy(s, m, r);
#define SQLRES(s, r, m) \
if ((s) != (r)) { \
throw DatabaseException(std::string(m) + ": " +\
sqlite3_errmsg(m_database)); \
}
#define SQLOK(s, m) SQLRES(s, SQLITE_OK, m) #define SQLOK(s, m) SQLRES(s, SQLITE_OK, m)
#define PREPARE_STATEMENT(name, query) \ #define PREPARE_STATEMENT(name, query) \
SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL),\ SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL), \
"Failed to prepare query '" query "'") std::string("Failed to prepare query \"").append(query).append("\""))
#define SQLOK_ERRSTREAM(s, m) \ #define SQLOK_ERRSTREAM(s, m) \
if ((s) != SQLITE_OK) { \ if ((s) != SQLITE_OK) { \
@ -50,52 +38,49 @@ SQLite format specification:
<< sqlite3_errmsg(m_database) << std::endl; \ << sqlite3_errmsg(m_database) << std::endl; \
} }
#define FINALIZE_STATEMENT(statement) SQLOK_ERRSTREAM(sqlite3_finalize(statement), \ #define FINALIZE_STATEMENT(name) \
"Failed to finalize " #statement) sqlite3_finalize(m_stmt_##name); /* if this fails who cares */ \
m_stmt_##name = nullptr;
int Database_SQLite3::busyHandler(void *data, int count) int Database_SQLite3::busyHandler(void *data, int count)
{ {
s64 &first_time = reinterpret_cast<s64 *>(data)[0]; u64 &first_time = reinterpret_cast<u64*>(data)[0];
s64 &prev_time = reinterpret_cast<s64 *>(data)[1]; u64 &prev_time = reinterpret_cast<u64*>(data)[1];
s64 cur_time = porting::getTimeMs(); u64 cur_time = porting::getTimeMs();
if (count == 0) { if (count == 0) {
first_time = cur_time; first_time = cur_time;
prev_time = first_time; prev_time = first_time;
} else {
while (cur_time < prev_time)
cur_time += s64(1)<<32;
} }
if (cur_time - first_time < BUSY_INFO_TRESHOLD) { const auto total_diff = cur_time - first_time; // time since first call
; // do nothing const auto this_diff = prev_time - first_time; // time since last call
} else if (cur_time - first_time >= BUSY_INFO_TRESHOLD &&
prev_time - first_time < BUSY_INFO_TRESHOLD) { if (total_diff < BUSY_INFO_TRESHOLD) {
// do nothing
} else if (total_diff >= BUSY_INFO_TRESHOLD &&
this_diff < BUSY_INFO_TRESHOLD) {
infostream << "SQLite3 database has been locked for " infostream << "SQLite3 database has been locked for "
<< cur_time - first_time << " ms." << std::endl; << total_diff << " ms." << std::endl;
} else if (cur_time - first_time >= BUSY_WARNING_TRESHOLD && } else if (total_diff >= BUSY_WARNING_TRESHOLD &&
prev_time - first_time < BUSY_WARNING_TRESHOLD) { this_diff < BUSY_WARNING_TRESHOLD) {
warningstream << "SQLite3 database has been locked for " warningstream << "SQLite3 database has been locked for "
<< cur_time - first_time << " ms." << std::endl; << total_diff << " ms; this causes lag." << std::endl;
} else if (cur_time - first_time >= BUSY_ERROR_TRESHOLD && } else if (total_diff >= BUSY_FATAL_TRESHOLD &&
prev_time - first_time < BUSY_ERROR_TRESHOLD) { this_diff < BUSY_FATAL_TRESHOLD) {
errorstream << "SQLite3 database has been locked for " errorstream << "SQLite3 database has been locked for "
<< cur_time - first_time << " ms; this causes lag." << std::endl; << total_diff << " ms - giving up!" << std::endl;
} else if (cur_time - first_time >= BUSY_FATAL_TRESHOLD && } else if (total_diff / BUSY_ERROR_INTERVAL !=
prev_time - first_time < BUSY_FATAL_TRESHOLD) { this_diff / BUSY_ERROR_INTERVAL) {
errorstream << "SQLite3 database has been locked for "
<< cur_time - first_time << " ms - giving up!" << std::endl;
} else if ((cur_time - first_time) / BUSY_ERROR_INTERVAL !=
(prev_time - first_time) / BUSY_ERROR_INTERVAL) {
// Safety net: keep reporting every BUSY_ERROR_INTERVAL // Safety net: keep reporting every BUSY_ERROR_INTERVAL
errorstream << "SQLite3 database has been locked for " errorstream << "SQLite3 database has been locked for "
<< (cur_time - first_time) / 1000 << " seconds!" << std::endl; << total_diff / 1000 << " seconds!" << std::endl;
} }
prev_time = cur_time; prev_time = cur_time;
// Make sqlite transaction fail if delay exceeds BUSY_FATAL_TRESHOLD // Make sqlite transaction fail if delay exceeds BUSY_FATAL_TRESHOLD
return cur_time - first_time < BUSY_FATAL_TRESHOLD; return total_diff < BUSY_FATAL_TRESHOLD;
} }
@ -130,7 +115,7 @@ void Database_SQLite3::openDatabase()
// Open the database connection // Open the database connection
if (!fs::CreateAllDirs(m_savedir)) { if (!fs::CreateAllDirs(m_savedir)) {
infostream << "Database_SQLite3: Failed to create directory \"" errorstream << "Database_SQLite3: Failed to create directory \""
<< m_savedir << "\"" << std::endl; << m_savedir << "\"" << std::endl;
throw FileNotGoodException("Failed to create database " throw FileNotGoodException("Failed to create database "
"save directory"); "save directory");
@ -138,8 +123,11 @@ void Database_SQLite3::openDatabase()
bool needs_create = !fs::PathExists(dbp); bool needs_create = !fs::PathExists(dbp);
SQLOK(sqlite3_open_v2(dbp.c_str(), &m_database, auto flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL), #ifdef SQLITE_OPEN_EXRESCODE
flags |= SQLITE_OPEN_EXRESCODE;
#endif
SQLOK(sqlite3_open_v2(dbp.c_str(), &m_database, flags, NULL),
std::string("Failed to open SQLite3 database file ") + dbp); std::string("Failed to open SQLite3 database file ") + dbp);
SQLOK(sqlite3_busy_handler(m_database, Database_SQLite3::busyHandler, SQLOK(sqlite3_busy_handler(m_database, Database_SQLite3::busyHandler,
@ -152,9 +140,9 @@ void Database_SQLite3::openDatabase()
std::string query_str = std::string("PRAGMA synchronous = ") std::string query_str = std::string("PRAGMA synchronous = ")
+ itos(g_settings->getU16("sqlite_synchronous")); + itos(g_settings->getU16("sqlite_synchronous"));
SQLOK(sqlite3_exec(m_database, query_str.c_str(), NULL, NULL, NULL), SQLOK(sqlite3_exec(m_database, query_str.c_str(), NULL, NULL, NULL),
"Failed to modify sqlite3 synchronous mode"); "Failed to set SQLite3 synchronous mode");
SQLOK(sqlite3_exec(m_database, "PRAGMA foreign_keys = ON", NULL, NULL, NULL), SQLOK(sqlite3_exec(m_database, "PRAGMA foreign_keys = ON", NULL, NULL, NULL),
"Failed to enable sqlite3 foreign key support"); "Failed to enable SQLite3 foreign key support");
} }
void Database_SQLite3::verifyDatabase() void Database_SQLite3::verifyDatabase()
@ -171,10 +159,47 @@ void Database_SQLite3::verifyDatabase()
m_initialized = true; m_initialized = true;
} }
bool Database_SQLite3::checkTable(const char *table)
{
assert(m_database);
// PRAGMA table_list would be cleaner here but it was only introduced in
// sqlite 3.37.0 (2021-11-27).
// So let's do this: https://stackoverflow.com/a/83195
sqlite3_stmt *m_stmt_tmp = nullptr;
PREPARE_STATEMENT(tmp, "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?;");
str_to_sqlite(m_stmt_tmp, 1, table);
bool ret = (sqlite3_step(m_stmt_tmp) == SQLITE_ROW);
FINALIZE_STATEMENT(tmp)
return ret;
}
bool Database_SQLite3::checkColumn(const char *table, const char *column)
{
assert(m_database);
sqlite3_stmt *m_stmt_tmp = nullptr;
auto query_str = std::string("PRAGMA table_info(").append(table).append(");");
PREPARE_STATEMENT(tmp, query_str.c_str());
bool ret = false;
while (sqlite3_step(m_stmt_tmp) == SQLITE_ROW) {
ret |= sqlite_to_string_view(m_stmt_tmp, 1) == column;
if (ret)
break;
}
FINALIZE_STATEMENT(tmp)
return ret;
}
Database_SQLite3::~Database_SQLite3() Database_SQLite3::~Database_SQLite3()
{ {
FINALIZE_STATEMENT(m_stmt_begin) FINALIZE_STATEMENT(begin)
FINALIZE_STATEMENT(m_stmt_end) FINALIZE_STATEMENT(end)
SQLOK_ERRSTREAM(sqlite3_close(m_database), "Failed to close database"); SQLOK_ERRSTREAM(sqlite3_close(m_database), "Failed to close database");
} }
@ -191,40 +216,68 @@ MapDatabaseSQLite3::MapDatabaseSQLite3(const std::string &savedir):
MapDatabaseSQLite3::~MapDatabaseSQLite3() MapDatabaseSQLite3::~MapDatabaseSQLite3()
{ {
FINALIZE_STATEMENT(m_stmt_read) FINALIZE_STATEMENT(read)
FINALIZE_STATEMENT(m_stmt_write) FINALIZE_STATEMENT(write)
FINALIZE_STATEMENT(m_stmt_list) FINALIZE_STATEMENT(list)
FINALIZE_STATEMENT(m_stmt_delete) FINALIZE_STATEMENT(delete)
} }
void MapDatabaseSQLite3::createDatabase() void MapDatabaseSQLite3::createDatabase()
{ {
assert(m_database); // Pre-condition assert(m_database);
SQLOK(sqlite3_exec(m_database, // Note: before 5.12.0 the format was blocks(pos INT, data BLOB).
// This function only runs for newly created databases.
const char *schema =
"CREATE TABLE IF NOT EXISTS `blocks` (\n" "CREATE TABLE IF NOT EXISTS `blocks` (\n"
" `pos` INT PRIMARY KEY,\n" "`x` INTEGER,"
" `data` BLOB\n" "`y` INTEGER,"
");\n", "`z` INTEGER,"
NULL, NULL, NULL), "`data` BLOB NOT NULL,"
// Declaring a primary key automatically creates an index and the
// order largely dictates which range operations can be sped up.
// see also: <https://www.sqlite.org/optoverview.html#skipscan>
// Putting XZ before Y matches our MapSector abstraction.
"PRIMARY KEY (`x`, `z`, `y`)"
");\n"
;
SQLOK(sqlite3_exec(m_database, schema, NULL, NULL, NULL),
"Failed to create database table"); "Failed to create database table");
} }
void MapDatabaseSQLite3::initStatements() void MapDatabaseSQLite3::initStatements()
{ {
PREPARE_STATEMENT(read, "SELECT `data` FROM `blocks` WHERE `pos` = ? LIMIT 1"); assert(checkTable("blocks"));
PREPARE_STATEMENT(write, "REPLACE INTO `blocks` (`pos`, `data`) VALUES (?, ?)"); m_new_format = checkColumn("blocks", "z");
PREPARE_STATEMENT(delete, "DELETE FROM `blocks` WHERE `pos` = ?"); infostream << "MapDatabaseSQLite3: split column format = "
PREPARE_STATEMENT(list, "SELECT `pos` FROM `blocks`"); << (m_new_format ? "yes" : "no") << std::endl;
verbosestream << "ServerMap: SQLite3 database opened." << std::endl; if (m_new_format) {
PREPARE_STATEMENT(read, "SELECT `data` FROM `blocks` WHERE `x` = ? AND `y` = ? AND `z` = ? LIMIT 1");
PREPARE_STATEMENT(write, "REPLACE INTO `blocks` (`x`, `y`, `z`, `data`) VALUES (?, ?, ?, ?)");
PREPARE_STATEMENT(delete, "DELETE FROM `blocks` WHERE `x` = ? AND `y` = ? AND `z` = ?");
PREPARE_STATEMENT(list, "SELECT `x`, `y`, `z` FROM `blocks`");
} else {
PREPARE_STATEMENT(read, "SELECT `data` FROM `blocks` WHERE `pos` = ? LIMIT 1");
PREPARE_STATEMENT(write, "REPLACE INTO `blocks` (`pos`, `data`) VALUES (?, ?)");
PREPARE_STATEMENT(delete, "DELETE FROM `blocks` WHERE `pos` = ?");
PREPARE_STATEMENT(list, "SELECT `pos` FROM `blocks`");
}
} }
inline void MapDatabaseSQLite3::bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index) inline int MapDatabaseSQLite3::bindPos(sqlite3_stmt *stmt, v3s16 pos, int index)
{ {
SQLOK(sqlite3_bind_int64(stmt, index, getBlockAsInteger(pos)), if (m_new_format) {
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__)); int_to_sqlite(stmt, index, pos.X);
int_to_sqlite(stmt, index + 1, pos.Y);
int_to_sqlite(stmt, index + 2, pos.Z);
return index + 3;
} else {
int64_to_sqlite(stmt, index, getBlockAsInteger(pos));
return index + 1;
}
} }
bool MapDatabaseSQLite3::deleteBlock(const v3s16 &pos) bool MapDatabaseSQLite3::deleteBlock(const v3s16 &pos)
@ -237,7 +290,7 @@ bool MapDatabaseSQLite3::deleteBlock(const v3s16 &pos)
sqlite3_reset(m_stmt_delete); sqlite3_reset(m_stmt_delete);
if (!good) { if (!good) {
warningstream << "deleteBlock: Block failed to delete " warningstream << "deleteBlock: Failed to delete block "
<< pos << ": " << sqlite3_errmsg(m_database) << std::endl; << pos << ": " << sqlite3_errmsg(m_database) << std::endl;
} }
return good; return good;
@ -247,9 +300,8 @@ bool MapDatabaseSQLite3::saveBlock(const v3s16 &pos, std::string_view data)
{ {
verifyDatabase(); verifyDatabase();
bindPos(m_stmt_write, pos); int col = bindPos(m_stmt_write, pos);
SQLOK(sqlite3_bind_blob(m_stmt_write, 2, data.data(), data.size(), NULL), blob_to_sqlite(m_stmt_write, col, data);
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
SQLRES(sqlite3_step(m_stmt_write), SQLITE_DONE, "Failed to save block") SQLRES(sqlite3_step(m_stmt_write), SQLITE_DONE, "Failed to save block")
sqlite3_reset(m_stmt_write); sqlite3_reset(m_stmt_write);
@ -264,6 +316,7 @@ void MapDatabaseSQLite3::loadBlock(const v3s16 &pos, std::string *block)
bindPos(m_stmt_read, pos); bindPos(m_stmt_read, pos);
if (sqlite3_step(m_stmt_read) != SQLITE_ROW) { if (sqlite3_step(m_stmt_read) != SQLITE_ROW) {
block->clear();
sqlite3_reset(m_stmt_read); sqlite3_reset(m_stmt_read);
return; return;
} }
@ -271,7 +324,6 @@ void MapDatabaseSQLite3::loadBlock(const v3s16 &pos, std::string *block)
auto data = sqlite_to_blob(m_stmt_read, 0); auto data = sqlite_to_blob(m_stmt_read, 0);
block->assign(data); block->assign(data);
sqlite3_step(m_stmt_read);
// We should never get more than 1 row, so ok to reset // We should never get more than 1 row, so ok to reset
sqlite3_reset(m_stmt_read); sqlite3_reset(m_stmt_read);
} }
@ -280,8 +332,17 @@ void MapDatabaseSQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
{ {
verifyDatabase(); verifyDatabase();
while (sqlite3_step(m_stmt_list) == SQLITE_ROW) v3s16 p;
dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0))); while (sqlite3_step(m_stmt_list) == SQLITE_ROW) {
if (m_new_format) {
p.X = sqlite_to_int(m_stmt_list, 0);
p.Y = sqlite_to_int(m_stmt_list, 1);
p.Z = sqlite_to_int(m_stmt_list, 2);
} else {
p = getIntegerAsBlock(sqlite_to_int64(m_stmt_list, 0));
}
dst.push_back(p);
}
sqlite3_reset(m_stmt_list); sqlite3_reset(m_stmt_list);
} }
@ -298,35 +359,38 @@ PlayerDatabaseSQLite3::PlayerDatabaseSQLite3(const std::string &savedir):
PlayerDatabaseSQLite3::~PlayerDatabaseSQLite3() PlayerDatabaseSQLite3::~PlayerDatabaseSQLite3()
{ {
FINALIZE_STATEMENT(m_stmt_player_load) FINALIZE_STATEMENT(player_load)
FINALIZE_STATEMENT(m_stmt_player_add) FINALIZE_STATEMENT(player_add)
FINALIZE_STATEMENT(m_stmt_player_update) FINALIZE_STATEMENT(player_update)
FINALIZE_STATEMENT(m_stmt_player_remove) FINALIZE_STATEMENT(player_remove)
FINALIZE_STATEMENT(m_stmt_player_list) FINALIZE_STATEMENT(player_list)
FINALIZE_STATEMENT(m_stmt_player_add_inventory) FINALIZE_STATEMENT(player_add_inventory)
FINALIZE_STATEMENT(m_stmt_player_add_inventory_items) FINALIZE_STATEMENT(player_add_inventory_items)
FINALIZE_STATEMENT(m_stmt_player_remove_inventory) FINALIZE_STATEMENT(player_remove_inventory)
FINALIZE_STATEMENT(m_stmt_player_remove_inventory_items) FINALIZE_STATEMENT(player_remove_inventory_items)
FINALIZE_STATEMENT(m_stmt_player_load_inventory) FINALIZE_STATEMENT(player_load_inventory)
FINALIZE_STATEMENT(m_stmt_player_load_inventory_items) FINALIZE_STATEMENT(player_load_inventory_items)
FINALIZE_STATEMENT(m_stmt_player_metadata_load) FINALIZE_STATEMENT(player_metadata_load)
FINALIZE_STATEMENT(m_stmt_player_metadata_add) FINALIZE_STATEMENT(player_metadata_add)
FINALIZE_STATEMENT(m_stmt_player_metadata_remove) FINALIZE_STATEMENT(player_metadata_remove)
}; };
void PlayerDatabaseSQLite3::createDatabase() void PlayerDatabaseSQLite3::createDatabase()
{ {
assert(m_database); // Pre-condition assert(m_database);
// When designing the schema remember that SQLite only has 5 basic data types
// and ignores length-limited types like "VARCHAR(32)".
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `player` (" "CREATE TABLE IF NOT EXISTS `player` ("
"`name` VARCHAR(50) NOT NULL," "`name` TEXT NOT NULL,"
"`pitch` NUMERIC(11, 4) NOT NULL," "`pitch` NUMERIC NOT NULL,"
"`yaw` NUMERIC(11, 4) NOT NULL," "`yaw` NUMERIC NOT NULL,"
"`posX` NUMERIC(11, 4) NOT NULL," "`posX` NUMERIC NOT NULL,"
"`posY` NUMERIC(11, 4) NOT NULL," "`posY` NUMERIC NOT NULL,"
"`posZ` NUMERIC(11, 4) NOT NULL," "`posZ` NUMERIC NOT NULL,"
"`hp` INT NOT NULL," "`hp` INT NOT NULL,"
"`breath` INT NOT NULL," "`breath` INT NOT NULL,"
"`creation_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," "`creation_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,"
@ -337,9 +401,9 @@ void PlayerDatabaseSQLite3::createDatabase()
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `player_metadata` (" "CREATE TABLE IF NOT EXISTS `player_metadata` ("
" `player` VARCHAR(50) NOT NULL," " `player` TEXT NOT NULL,"
" `metadata` VARCHAR(256) NOT NULL," " `metadata` TEXT NOT NULL,"
" `value` TEXT," " `value` TEXT NOT NULL,"
" PRIMARY KEY(`player`, `metadata`)," " PRIMARY KEY(`player`, `metadata`),"
" FOREIGN KEY (`player`) REFERENCES player (`name`) ON DELETE CASCADE );", " FOREIGN KEY (`player`) REFERENCES player (`name`) ON DELETE CASCADE );",
NULL, NULL, NULL), NULL, NULL, NULL),
@ -347,7 +411,7 @@ void PlayerDatabaseSQLite3::createDatabase()
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `player_inventories` (" "CREATE TABLE IF NOT EXISTS `player_inventories` ("
" `player` VARCHAR(50) NOT NULL," " `player` TEXT NOT NULL,"
" `inv_id` INT NOT NULL," " `inv_id` INT NOT NULL,"
" `inv_width` INT NOT NULL," " `inv_width` INT NOT NULL,"
" `inv_name` TEXT NOT NULL DEFAULT ''," " `inv_name` TEXT NOT NULL DEFAULT '',"
@ -359,7 +423,7 @@ void PlayerDatabaseSQLite3::createDatabase()
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE `player_inventory_items` (" "CREATE TABLE `player_inventory_items` ("
" `player` VARCHAR(50) NOT NULL," " `player` TEXT NOT NULL,"
" `inv_id` INT NOT NULL," " `inv_id` INT NOT NULL,"
" `slot_id` INT NOT NULL," " `slot_id` INT NOT NULL,"
" `item` TEXT NOT NULL DEFAULT ''," " `item` TEXT NOT NULL DEFAULT '',"
@ -401,7 +465,6 @@ void PlayerDatabaseSQLite3::initStatements()
"(`player`, `metadata`, `value`) VALUES (?, ?, ?)") "(`player`, `metadata`, `value`) VALUES (?, ?, ?)")
PREPARE_STATEMENT(player_metadata_remove, "DELETE FROM `player_metadata` " PREPARE_STATEMENT(player_metadata_remove, "DELETE FROM `player_metadata` "
"WHERE `player` = ?") "WHERE `player` = ?")
verbosestream << "ServerEnvironment: SQLite3 database opened (players)." << std::endl;
} }
bool PlayerDatabaseSQLite3::playerDataExists(const std::string &name) bool PlayerDatabaseSQLite3::playerDataExists(const std::string &name)
@ -588,27 +651,27 @@ AuthDatabaseSQLite3::AuthDatabaseSQLite3(const std::string &savedir) :
AuthDatabaseSQLite3::~AuthDatabaseSQLite3() AuthDatabaseSQLite3::~AuthDatabaseSQLite3()
{ {
FINALIZE_STATEMENT(m_stmt_read) FINALIZE_STATEMENT(read)
FINALIZE_STATEMENT(m_stmt_write) FINALIZE_STATEMENT(write)
FINALIZE_STATEMENT(m_stmt_create) FINALIZE_STATEMENT(create)
FINALIZE_STATEMENT(m_stmt_delete) FINALIZE_STATEMENT(delete)
FINALIZE_STATEMENT(m_stmt_list_names) FINALIZE_STATEMENT(list_names)
FINALIZE_STATEMENT(m_stmt_read_privs) FINALIZE_STATEMENT(read_privs)
FINALIZE_STATEMENT(m_stmt_write_privs) FINALIZE_STATEMENT(write_privs)
FINALIZE_STATEMENT(m_stmt_delete_privs) FINALIZE_STATEMENT(delete_privs)
FINALIZE_STATEMENT(m_stmt_last_insert_rowid) FINALIZE_STATEMENT(last_insert_rowid)
} }
void AuthDatabaseSQLite3::createDatabase() void AuthDatabaseSQLite3::createDatabase()
{ {
assert(m_database); // Pre-condition assert(m_database);
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `auth` (" "CREATE TABLE IF NOT EXISTS `auth` ("
"`id` INTEGER PRIMARY KEY AUTOINCREMENT," "`id` INTEGER PRIMARY KEY AUTOINCREMENT,"
"`name` VARCHAR(32) UNIQUE," "`name` TEXT UNIQUE NOT NULL,"
"`password` VARCHAR(512)," "`password` TEXT NOT NULL,"
"`last_login` INTEGER" "`last_login` INTEGER NOT NULL DEFAULT 0"
");", ");",
NULL, NULL, NULL), NULL, NULL, NULL),
"Failed to create auth table"); "Failed to create auth table");
@ -616,7 +679,7 @@ void AuthDatabaseSQLite3::createDatabase()
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `user_privileges` (" "CREATE TABLE IF NOT EXISTS `user_privileges` ("
"`id` INTEGER," "`id` INTEGER,"
"`privilege` VARCHAR(32)," "`privilege` TEXT,"
"PRIMARY KEY (id, privilege)" "PRIMARY KEY (id, privilege)"
"CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES auth (id) ON DELETE CASCADE" "CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES auth (id) ON DELETE CASCADE"
");", ");",
@ -751,18 +814,18 @@ ModStorageDatabaseSQLite3::ModStorageDatabaseSQLite3(const std::string &savedir)
ModStorageDatabaseSQLite3::~ModStorageDatabaseSQLite3() ModStorageDatabaseSQLite3::~ModStorageDatabaseSQLite3()
{ {
FINALIZE_STATEMENT(m_stmt_remove_all) FINALIZE_STATEMENT(remove_all)
FINALIZE_STATEMENT(m_stmt_remove) FINALIZE_STATEMENT(remove)
FINALIZE_STATEMENT(m_stmt_set) FINALIZE_STATEMENT(set)
FINALIZE_STATEMENT(m_stmt_has) FINALIZE_STATEMENT(has)
FINALIZE_STATEMENT(m_stmt_get) FINALIZE_STATEMENT(get)
FINALIZE_STATEMENT(m_stmt_get_keys) FINALIZE_STATEMENT(get_keys)
FINALIZE_STATEMENT(m_stmt_get_all) FINALIZE_STATEMENT(get_all)
} }
void ModStorageDatabaseSQLite3::createDatabase() void ModStorageDatabaseSQLite3::createDatabase()
{ {
assert(m_database); // Pre-condition assert(m_database);
SQLOK(sqlite3_exec(m_database, SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `entries` (\n" "CREATE TABLE IF NOT EXISTS `entries` (\n"
@ -825,8 +888,7 @@ bool ModStorageDatabaseSQLite3::getModEntry(const std::string &modname,
verifyDatabase(); verifyDatabase();
str_to_sqlite(m_stmt_get, 1, modname); str_to_sqlite(m_stmt_get, 1, modname);
SQLOK(sqlite3_bind_blob(m_stmt_get, 2, key.data(), key.size(), NULL), blob_to_sqlite(m_stmt_get, 2, key);
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
bool found = sqlite3_step(m_stmt_get) == SQLITE_ROW; bool found = sqlite3_step(m_stmt_get) == SQLITE_ROW;
if (found) { if (found) {
auto sv = sqlite_to_blob(m_stmt_get, 0); auto sv = sqlite_to_blob(m_stmt_get, 0);
@ -845,8 +907,7 @@ bool ModStorageDatabaseSQLite3::hasModEntry(const std::string &modname,
verifyDatabase(); verifyDatabase();
str_to_sqlite(m_stmt_has, 1, modname); str_to_sqlite(m_stmt_has, 1, modname);
SQLOK(sqlite3_bind_blob(m_stmt_has, 2, key.data(), key.size(), NULL), blob_to_sqlite(m_stmt_has, 2, key);
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
bool found = sqlite3_step(m_stmt_has) == SQLITE_ROW; bool found = sqlite3_step(m_stmt_has) == SQLITE_ROW;
if (found) if (found)
sqlite3_step(m_stmt_has); sqlite3_step(m_stmt_has);
@ -862,10 +923,8 @@ bool ModStorageDatabaseSQLite3::setModEntry(const std::string &modname,
verifyDatabase(); verifyDatabase();
str_to_sqlite(m_stmt_set, 1, modname); str_to_sqlite(m_stmt_set, 1, modname);
SQLOK(sqlite3_bind_blob(m_stmt_set, 2, key.data(), key.size(), NULL), blob_to_sqlite(m_stmt_set, 2, key);
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__)); blob_to_sqlite(m_stmt_set, 3, value);
SQLOK(sqlite3_bind_blob(m_stmt_set, 3, value.data(), value.size(), NULL),
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
SQLRES(sqlite3_step(m_stmt_set), SQLITE_DONE, "Failed to set mod entry") SQLRES(sqlite3_step(m_stmt_set), SQLITE_DONE, "Failed to set mod entry")
sqlite3_reset(m_stmt_set); sqlite3_reset(m_stmt_set);
@ -879,8 +938,7 @@ bool ModStorageDatabaseSQLite3::removeModEntry(const std::string &modname,
verifyDatabase(); verifyDatabase();
str_to_sqlite(m_stmt_remove, 1, modname); str_to_sqlite(m_stmt_remove, 1, modname);
SQLOK(sqlite3_bind_blob(m_stmt_remove, 2, key.data(), key.size(), NULL), blob_to_sqlite(m_stmt_remove, 2, key);
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
sqlite3_vrfy(sqlite3_step(m_stmt_remove), SQLITE_DONE); sqlite3_vrfy(sqlite3_step(m_stmt_remove), SQLITE_DONE);
int changes = sqlite3_changes(m_database); int changes = sqlite3_changes(m_database);
@ -906,6 +964,7 @@ void ModStorageDatabaseSQLite3::listMods(std::vector<std::string> *res)
{ {
verifyDatabase(); verifyDatabase();
// FIXME: please don't do this. this should be sqlite3_step like all others.
char *errmsg; char *errmsg;
int status = sqlite3_exec(m_database, int status = sqlite3_exec(m_database,
"SELECT `modname` FROM `entries` GROUP BY `modname`;", "SELECT `modname` FROM `entries` GROUP BY `modname`;",

View file

@ -13,27 +13,41 @@ extern "C" {
#include "sqlite3.h" #include "sqlite3.h"
} }
// Template class for SQLite3 based data storage
class Database_SQLite3 : public Database class Database_SQLite3 : public Database
{ {
public: public:
virtual ~Database_SQLite3(); virtual ~Database_SQLite3();
void beginSave(); void beginSave() override;
void endSave(); void endSave() override;
bool initialized() const override { return m_initialized; }
/// @note not thread-safe
void verifyDatabase() override;
bool initialized() const { return m_initialized; }
protected: protected:
Database_SQLite3(const std::string &savedir, const std::string &dbname); Database_SQLite3(const std::string &savedir, const std::string &dbname);
// Open and initialize the database if needed // Check if a specific table exists
void verifyDatabase(); bool checkTable(const char *table);
// Check if a table has a specific column
bool checkColumn(const char *table, const char *column);
/* Value conversion helpers */
// Convertors
inline void str_to_sqlite(sqlite3_stmt *s, int iCol, std::string_view str) const inline void str_to_sqlite(sqlite3_stmt *s, int iCol, std::string_view str) const
{ {
sqlite3_vrfy(sqlite3_bind_text(s, iCol, str.data(), str.size(), NULL)); sqlite3_vrfy(sqlite3_bind_text(s, iCol, str.data(), str.size(), NULL));
} }
inline void blob_to_sqlite(sqlite3_stmt *s, int iCol, std::string_view str) const
{
sqlite3_vrfy(sqlite3_bind_blob(s, iCol, str.data(), str.size(), NULL));
}
inline void int_to_sqlite(sqlite3_stmt *s, int iCol, int val) const inline void int_to_sqlite(sqlite3_stmt *s, int iCol, int val) const
{ {
sqlite3_vrfy(sqlite3_bind_int(s, iCol, val)); sqlite3_vrfy(sqlite3_bind_int(s, iCol, val));
@ -104,12 +118,14 @@ protected:
sqlite_to_float(s, iCol + 2)); sqlite_to_float(s, iCol + 2));
} }
// Query verifiers helpers // Helper for verifying result of sqlite3_step() and such
inline void sqlite3_vrfy(int s, std::string_view m = "", int r = SQLITE_OK) const inline void sqlite3_vrfy(int s, std::string_view m = "", int r = SQLITE_OK) const
{ {
if (s != r) { if (s != r) {
std::string msg(m); std::string msg(m);
msg.append(": ").append(sqlite3_errmsg(m_database)); if (!msg.empty())
msg.append(": ");
msg.append(sqlite3_errmsg(m_database));
throw DatabaseException(msg); throw DatabaseException(msg);
} }
} }
@ -119,28 +135,37 @@ protected:
sqlite3_vrfy(s, m, r); sqlite3_vrfy(s, m, r);
} }
// Create the database structure // Called after opening a fresh database file. Should create tables and indices.
virtual void createDatabase() = 0; virtual void createDatabase() = 0;
// Should prepare the necessary statements.
virtual void initStatements() = 0; virtual void initStatements() = 0;
sqlite3 *m_database = nullptr; sqlite3 *m_database = nullptr;
private: private:
// Open the database // Open the database
void openDatabase(); void openDatabase();
bool m_initialized = false; bool m_initialized = false;
std::string m_savedir = ""; const std::string m_savedir;
std::string m_dbname = ""; const std::string m_dbname;
sqlite3_stmt *m_stmt_begin = nullptr; sqlite3_stmt *m_stmt_begin = nullptr;
sqlite3_stmt *m_stmt_end = nullptr; sqlite3_stmt *m_stmt_end = nullptr;
s64 m_busy_handler_data[2]; u64 m_busy_handler_data[2];
static int busyHandler(void *data, int count); static int busyHandler(void *data, int count);
}; };
// Not sure why why we have to do this. can't C++ figure it out on its own?
#define PARENT_CLASS_FUNCS \
void beginSave() { Database_SQLite3::beginSave(); } \
void endSave() { Database_SQLite3::endSave(); } \
void verifyDatabase() { Database_SQLite3::verifyDatabase(); }
class MapDatabaseSQLite3 : private Database_SQLite3, public MapDatabase class MapDatabaseSQLite3 : private Database_SQLite3, public MapDatabase
{ {
public: public:
@ -152,16 +177,19 @@ public:
bool deleteBlock(const v3s16 &pos); bool deleteBlock(const v3s16 &pos);
void listAllLoadableBlocks(std::vector<v3s16> &dst); void listAllLoadableBlocks(std::vector<v3s16> &dst);
void beginSave() { Database_SQLite3::beginSave(); } PARENT_CLASS_FUNCS
void endSave() { Database_SQLite3::endSave(); }
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
virtual void initStatements(); virtual void initStatements();
private: private:
void bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index = 1); /// @brief Bind block position into statement at column index
/// @return index of next column after position
int bindPos(sqlite3_stmt *stmt, v3s16 pos, int index = 1);
bool m_new_format = false;
// Map
sqlite3_stmt *m_stmt_read = nullptr; sqlite3_stmt *m_stmt_read = nullptr;
sqlite3_stmt *m_stmt_write = nullptr; sqlite3_stmt *m_stmt_write = nullptr;
sqlite3_stmt *m_stmt_list = nullptr; sqlite3_stmt *m_stmt_list = nullptr;
@ -179,6 +207,8 @@ public:
bool removePlayer(const std::string &name); bool removePlayer(const std::string &name);
void listPlayers(std::vector<std::string> &res); void listPlayers(std::vector<std::string> &res);
PARENT_CLASS_FUNCS
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
virtual void initStatements(); virtual void initStatements();
@ -216,6 +246,8 @@ public:
virtual void listNames(std::vector<std::string> &res); virtual void listNames(std::vector<std::string> &res);
virtual void reload(); virtual void reload();
PARENT_CLASS_FUNCS
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
virtual void initStatements(); virtual void initStatements();
@ -251,8 +283,7 @@ public:
virtual bool removeModEntries(const std::string &modname); virtual bool removeModEntries(const std::string &modname);
virtual void listMods(std::vector<std::string> *res); virtual void listMods(std::vector<std::string> *res);
virtual void beginSave() { Database_SQLite3::beginSave(); } PARENT_CLASS_FUNCS
virtual void endSave() { Database_SQLite3::endSave(); }
protected: protected:
virtual void createDatabase(); virtual void createDatabase();
@ -267,3 +298,5 @@ private:
sqlite3_stmt *m_stmt_remove = nullptr; sqlite3_stmt *m_stmt_remove = nullptr;
sqlite3_stmt *m_stmt_remove_all = nullptr; sqlite3_stmt *m_stmt_remove_all = nullptr;
}; };
#undef PARENT_CLASS_FUNCS

View file

@ -16,7 +16,12 @@ class Database
public: public:
virtual void beginSave() = 0; virtual void beginSave() = 0;
virtual void endSave() = 0; virtual void endSave() = 0;
/// @return true if database connection is open
virtual bool initialized() const { return true; } virtual bool initialized() const { return true; }
/// Open and initialize the database if needed
virtual void verifyDatabase() {};
}; };
class MapDatabase : public Database class MapDatabase : public Database

View file

@ -112,7 +112,7 @@ void set_default_settings()
settings->setDefault("screenshot_format", "png"); settings->setDefault("screenshot_format", "png");
settings->setDefault("screenshot_quality", "0"); settings->setDefault("screenshot_quality", "0");
settings->setDefault("client_unload_unused_data_timeout", "600"); settings->setDefault("client_unload_unused_data_timeout", "600");
settings->setDefault("client_mapblock_limit", "7500"); settings->setDefault("client_mapblock_limit", "7500"); // about 120 MB
settings->setDefault("enable_build_where_you_stand", "false"); settings->setDefault("enable_build_where_you_stand", "false");
settings->setDefault("curl_timeout", "20000"); settings->setDefault("curl_timeout", "20000");
settings->setDefault("curl_parallel_limit", "8"); settings->setDefault("curl_parallel_limit", "8");
@ -243,7 +243,7 @@ void set_default_settings()
settings->setDefault("tooltip_show_delay", "400"); settings->setDefault("tooltip_show_delay", "400");
settings->setDefault("tooltip_append_itemname", "false"); settings->setDefault("tooltip_append_itemname", "false");
settings->setDefault("fps_max", "60"); settings->setDefault("fps_max", "60");
settings->setDefault("fps_max_unfocused", "20"); settings->setDefault("fps_max_unfocused", "10");
settings->setDefault("viewing_range", "190"); settings->setDefault("viewing_range", "190");
settings->setDefault("client_mesh_chunk", "1"); settings->setDefault("client_mesh_chunk", "1");
settings->setDefault("screen_w", "1024"); settings->setDefault("screen_w", "1024");
@ -270,7 +270,6 @@ void set_default_settings()
settings->setDefault("camera_smoothing", "0.0"); settings->setDefault("camera_smoothing", "0.0");
settings->setDefault("cinematic_camera_smoothing", "0.7"); settings->setDefault("cinematic_camera_smoothing", "0.7");
settings->setDefault("view_bobbing_amount", "1.0"); settings->setDefault("view_bobbing_amount", "1.0");
settings->setDefault("fall_bobbing_amount", "0.03");
settings->setDefault("enable_3d_clouds", "true"); settings->setDefault("enable_3d_clouds", "true");
settings->setDefault("soft_clouds", "false"); settings->setDefault("soft_clouds", "false");
settings->setDefault("cloud_radius", "12"); settings->setDefault("cloud_radius", "12");
@ -422,7 +421,7 @@ void set_default_settings()
// Network // Network
settings->setDefault("enable_ipv6", "true"); settings->setDefault("enable_ipv6", "true");
settings->setDefault("ipv6_server", "false"); settings->setDefault("ipv6_server", "true");
settings->setDefault("max_packets_per_iteration", "1024"); settings->setDefault("max_packets_per_iteration", "1024");
settings->setDefault("port", "30000"); settings->setDefault("port", "30000");
settings->setDefault("strict_protocol_version_checking", "false"); settings->setDefault("strict_protocol_version_checking", "false");
@ -547,6 +546,7 @@ void set_default_settings()
settings->setDefault("virtual_joystick_triggers_aux1", "false"); settings->setDefault("virtual_joystick_triggers_aux1", "false");
settings->setDefault("touch_punch_gesture", "short_tap"); settings->setDefault("touch_punch_gesture", "short_tap");
settings->setDefault("clickable_chat_weblinks", "true"); settings->setDefault("clickable_chat_weblinks", "true");
// Altered settings for Android // Altered settings for Android
#ifdef __ANDROID__ #ifdef __ANDROID__
settings->setDefault("screen_w", "0"); settings->setDefault("screen_w", "0");
@ -558,9 +558,9 @@ void set_default_settings()
settings->setDefault("max_block_generate_distance", "5"); settings->setDefault("max_block_generate_distance", "5");
settings->setDefault("sqlite_synchronous", "1"); settings->setDefault("sqlite_synchronous", "1");
settings->setDefault("server_map_save_interval", "15"); settings->setDefault("server_map_save_interval", "15");
settings->setDefault("client_mapblock_limit", "1000"); settings->setDefault("client_mapblock_limit", "1500");
settings->setDefault("active_block_range", "2"); settings->setDefault("active_block_range", "2");
settings->setDefault("viewing_range", "50"); settings->setDefault("viewing_range", "70");
settings->setDefault("leaves_style", "simple"); settings->setDefault("leaves_style", "simple");
// Note: OpenGL ES 2.0 is not guaranteed to provide depth textures, // Note: OpenGL ES 2.0 is not guaranteed to provide depth textures,
// which we would need for PP. // which we would need for PP.
@ -568,6 +568,7 @@ void set_default_settings()
// still set these two settings in case someone wants to enable it // still set these two settings in case someone wants to enable it
settings->setDefault("debanding", "false"); settings->setDefault("debanding", "false");
settings->setDefault("post_processing_texture_bits", "8"); settings->setDefault("post_processing_texture_bits", "8");
// We don't have working certificate verification...
settings->setDefault("curl_verify_cert", "false"); settings->setDefault("curl_verify_cert", "false");
// Apply settings according to screen size // Apply settings according to screen size

View file

@ -106,9 +106,9 @@ EmergeManager::EmergeManager(Server *server, MetricsBackend *mb)
m_qlimit_generate = nthreads + 1; m_qlimit_generate = nthreads + 1;
// don't trust user input for something very important like this // don't trust user input for something very important like this
m_qlimit_total = rangelim(m_qlimit_total, 1, 1000000); m_qlimit_diskonly = rangelim(m_qlimit_diskonly, 2, 1000000);
m_qlimit_diskonly = rangelim(m_qlimit_diskonly, 1, 1000000);
m_qlimit_generate = rangelim(m_qlimit_generate, 1, 1000000); m_qlimit_generate = rangelim(m_qlimit_generate, 1, 1000000);
m_qlimit_total = std::max(m_qlimit_diskonly, m_qlimit_generate);
for (s16 i = 0; i < nthreads; i++) for (s16 i = 0; i < nthreads; i++)
m_threads.push_back(new EmergeThread(server, i)); m_threads.push_back(new EmergeThread(server, i));
@ -375,8 +375,7 @@ bool EmergeManager::pushBlockEmergeData(
} }
} }
std::pair<std::map<v3s16, BlockEmergeData>::iterator, bool> findres; auto findres = m_blocks_enqueued.insert(std::make_pair(pos, BlockEmergeData()));
findres = m_blocks_enqueued.insert(std::make_pair(pos, BlockEmergeData()));
BlockEmergeData &bedata = findres.first->second; BlockEmergeData &bedata = findres.first->second;
*entry_already_exists = !findres.second; *entry_already_exists = !findres.second;
@ -707,6 +706,8 @@ void *EmergeThread::run()
{ {
ScopeProfiler sp(g_profiler, "EmergeThread: load block - async (sum)"); ScopeProfiler sp(g_profiler, "EmergeThread: load block - async (sum)");
MutexAutoLock dblock(m_db.mutex); MutexAutoLock dblock(m_db.mutex);
// Note: this can throw an exception, but there isn't really
// a good, safe way to handle it.
m_db.loadBlock(pos, databuf); m_db.loadBlock(pos, databuf);
} }
// actually load it, then decide again // actually load it, then decide again

Some files were not shown because too many files have changed in this diff Show more