mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
Compare commits
82 commits
5.11.0-rc1
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
7892541383 | ||
|
358658fa34 | ||
|
68602b2eaf | ||
|
e84ac56e35 | ||
|
47c000a293 | ||
|
304ce4cd54 | ||
|
d54646d342 | ||
|
7abaa8d4cd | ||
|
2796283550 | ||
|
7602308835 | ||
|
bc43019467 | ||
|
8449f5f6db | ||
|
0eb047ca33 | ||
|
98048cb06d | ||
|
6e995972bb | ||
|
08fad862aa | ||
|
c3477a4d08 | ||
|
062207e696 | ||
|
24c1230c7b | ||
|
eb79a76742 | ||
|
c0328e5363 | ||
|
8d822d8231 | ||
|
a11b25f3f5 | ||
|
90121dc66f | ||
|
d74af2f1a7 | ||
|
b6c71b2379 | ||
|
c261c26456 | ||
|
5abf220979 | ||
|
1ceeea34f4 | ||
|
3ae1fd459a | ||
|
0e86366324 | ||
|
58ad604a4b | ||
|
415e96184d | ||
|
8654e16725 | ||
|
eb8b449817 | ||
|
22c81e5292 | ||
|
42a35cec83 | ||
|
fc8c6742c4 | ||
|
ee9258cefd | ||
|
5e89371ecd | ||
|
abcd2e0b81 | ||
|
d12ce68e64 | ||
|
83fd837d75 | ||
|
7d3f0628c4 | ||
|
27bbe3a873 | ||
|
5a8720a484 | ||
|
e51221d247 | ||
|
0890125962 | ||
|
0667cbf5a2 | ||
|
ba62808fe8 | ||
|
50819ace8f | ||
|
ef0219c2ed | ||
|
f4bdf72aa4 | ||
|
cc352f3b66 | ||
|
215b000793 | ||
|
e8728acc5c | ||
|
166e02955e | ||
|
138111a542 | ||
|
191cb117f9 | ||
|
a57677120a | ||
|
75dcd94b90 | ||
|
d027fc9a88 | ||
|
a11d526110 | ||
|
eb797c502a | ||
|
567b9a997a | ||
|
319e270664 | ||
|
d015944f6c | ||
|
b7f01b0cc7 | ||
|
54bf5d62f2 | ||
|
849a583f66 | ||
|
0cb7735125 | ||
|
028949beca | ||
|
6bdeb10c16 | ||
|
44cbae8fad | ||
|
f7b2d4760f | ||
|
1ec19c2ad2 | ||
|
9bfd39f036 | ||
|
cfff6c4fd7 | ||
|
147dd3d372 | ||
|
cda3dc08ca | ||
|
78b4f929ce | ||
|
2c50066c16 |
202 changed files with 3119 additions and 15521 deletions
|
@ -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'
|
||||
CheckOptions:
|
||||
- key: performance-unnecessary-value-param.AllowedTypes
|
||||
|
|
2
.github/workflows/windows.yml
vendored
2
.github/workflows/windows.yml
vendored
|
@ -73,7 +73,7 @@ jobs:
|
|||
env:
|
||||
VCPKG_VERSION: 01f602195983451bc83e72f4214af2cbc495aa94
|
||||
# 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:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
|
@ -11,7 +11,7 @@ set(CLANG_MINIMUM_VERSION "7.0.1")
|
|||
|
||||
# You should not need to edit these manually, use util/bump_version.sh
|
||||
set(VERSION_MAJOR 5)
|
||||
set(VERSION_MINOR 11)
|
||||
set(VERSION_MINOR 12)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||
|
||||
|
|
16
README.md
16
README.md
|
@ -1,13 +1,15 @@
|
|||
Luanti (formerly Minetest)
|
||||
==========================
|
||||
|
||||

|
||||
[](https://hosted.weblate.org/engage/minetest/?utm_source=widget)
|
||||
[](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
<div align="center">
|
||||
<img src="textures/base/pack/logo.png" width="32%">
|
||||
<h1>Luanti (formerly Minetest)</h1>
|
||||
<img src="https://github.com/luanti-org/luanti/workflows/build/badge.svg" alt="Build Status">
|
||||
<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>
|
||||
<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.
|
||||
|
||||
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)
|
||||
|
||||
Table of Contents
|
||||
|
|
|
@ -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
|
||||
index fd5a056e3..83e3cf657 100644
|
||||
--- a/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
|
||||
|
@ -9,7 +8,7 @@ index fd5a056e3..83e3cf657 100644
|
|||
- 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
|
||||
+ */
|
||||
+ (source & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE) {
|
||||
|
|
|
@ -60,8 +60,8 @@ import java.util.Locale;
|
|||
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 2;
|
||||
private static final int SDL_MINOR_VERSION = 30;
|
||||
private static final int SDL_MICRO_VERSION = 8;
|
||||
private static final int SDL_MINOR_VERSION = 32;
|
||||
private static final int SDL_MICRO_VERSION = 0;
|
||||
/*
|
||||
// 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);
|
||||
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 {
|
||||
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 ||
|
||||
/*
|
||||
* CUSTOM ADDITION FOR MINETEST
|
||||
* CUSTOM ADDITION FOR LUANTI
|
||||
* should be upstreamed
|
||||
*/
|
||||
(source & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE) {
|
||||
|
|
11
android/app/src/main/res/values-fr/strings.xml
Normal file
11
android/app/src/main/res/values-fr/strings.xml
Normal 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>
|
11
android/app/src/main/res/values-gl/strings.xml
Normal file
11
android/app/src/main/res/values-gl/strings.xml
Normal 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>
|
|
@ -1,7 +1,7 @@
|
|||
// 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("versionMinor", 11) // Version Minor
|
||||
project.ext.set("versionMinor", 12) // Version Minor
|
||||
project.ext.set("versionPatch", 0) // Version Patch
|
||||
// ^ keep in sync with cmake
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ local facedir_to_dir_map = {
|
|||
1, 4, 3, 2,
|
||||
}
|
||||
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
|
||||
|
||||
function core.dir_to_fourdir(dir)
|
||||
|
@ -110,7 +110,7 @@ function core.dir_to_fourdir(dir)
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
function core.dir_to_wallmounted(dir)
|
||||
|
@ -147,7 +147,7 @@ local wallmounted_to_dir = {
|
|||
vector.new( 0, -1, 0),
|
||||
}
|
||||
function core.wallmounted_to_dir(wallmounted)
|
||||
return wallmounted_to_dir[wallmounted % 8]
|
||||
return vector.copy(wallmounted_to_dir[wallmounted % 8])
|
||||
end
|
||||
|
||||
function core.dir_to_yaw(dir)
|
||||
|
|
|
@ -159,7 +159,6 @@ local function load()
|
|||
{ heading = fgettext_ne("Movement") },
|
||||
"arm_inertia",
|
||||
"view_bobbing_amount",
|
||||
"fall_bobbing_amount",
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -517,7 +516,7 @@ local function get_formspec(dialogdata)
|
|||
|
||||
("button[0,%f;%f,0.8;back;%s]"):format(
|
||||
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(
|
||||
back_w + 0.2, tabsize.height + 0.2, checkbox_w),
|
||||
|
|
|
@ -61,7 +61,7 @@ local function create_minetest_conf_example(settings)
|
|||
end
|
||||
end
|
||||
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")
|
||||
end
|
||||
insert(result, "# type: " .. entry.type)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
local builtin_shared = ...
|
||||
local SCALE = 0.667
|
||||
|
||||
local facedir_to_euler = {
|
||||
{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", {
|
||||
initial_properties = {
|
||||
visual = "item",
|
||||
visual_size = vector.new(SCALE, SCALE, SCALE),
|
||||
textures = {},
|
||||
visual = "node",
|
||||
physical = true,
|
||||
is_visible = false,
|
||||
collide_with_objects = true,
|
||||
|
@ -80,41 +77,15 @@ core.register_entity(":__builtin:falling_node", {
|
|||
-- Save liquidtype for falling water
|
||||
self.liquidtype = def.liquidtype
|
||||
|
||||
-- Set entity visuals
|
||||
if def.drawtype == "torchlike" or def.drawtype == "signlike" then
|
||||
local textures
|
||||
if def.tiles and def.tiles[1] then
|
||||
local tile = def.tiles[1]
|
||||
if type(tile) == "table" 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"
|
||||
-- Set up entity visuals
|
||||
-- For compatibility with older clients we continue to use "item" visual
|
||||
-- for simple situations.
|
||||
local drawtypes = {normal=true, glasslike=true, allfaces=true, nodebox=true}
|
||||
local p2types = {none=true, facedir=true, ["4dir"]=true}
|
||||
if drawtypes[def.drawtype] and p2types[def.paramtype2] and def.use_texture_alpha ~= "blend" then
|
||||
-- Calculate size of falling node
|
||||
local s = {}
|
||||
s.x = (def.visual_scale or 1) * SCALE
|
||||
local s = vector.zero()
|
||||
s.x = (def.visual_scale or 1) * 0.667
|
||||
s.y = s.x
|
||||
s.z = s.x
|
||||
-- Compensate for wield_scale
|
||||
|
@ -125,10 +96,31 @@ core.register_entity(":__builtin:falling_node", {
|
|||
end
|
||||
self.object:set_properties({
|
||||
is_visible = true,
|
||||
wield_item = itemstring,
|
||||
visual = "item",
|
||||
wield_item = node.name,
|
||||
visual_size = s,
|
||||
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
|
||||
|
||||
-- Set collision box (certain nodeboxes only for now)
|
||||
|
@ -148,111 +140,6 @@ core.register_entity(":__builtin:falling_node", {
|
|||
})
|
||||
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,
|
||||
|
||||
get_staticdata = function(self)
|
||||
|
|
|
@ -45,6 +45,7 @@ core.features = {
|
|||
abm_without_neighbors = true,
|
||||
biome_weights = true,
|
||||
particle_blend_clip = true,
|
||||
remove_item_match_meta = true,
|
||||
}
|
||||
|
||||
function core.has_feature(arg)
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"AFCMS",
|
||||
"siliconsniffer",
|
||||
"Wuzzy",
|
||||
"Zemtzov7",
|
||||
"Zemtzov7"
|
||||
],
|
||||
"previous_contributors": [
|
||||
"Ælla Chiana Moskopp (erle) <erle@dieweltistgarnichtso.net> [Logo]",
|
||||
|
|
|
@ -21,7 +21,7 @@ local function clients_list_formspec(dialogdata)
|
|||
"size[6,9.5]",
|
||||
TOUCH_GUI and "padding[0.01,0.01]" or "",
|
||||
"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>") .. "]",
|
||||
"textlist[0.5,1.5;5,6.8;;" .. fmt_formspec_list(clients_list) .. "]",
|
||||
"button[1.5,8.5;3,0.8;quit;OK]"
|
||||
|
|
|
@ -299,7 +299,7 @@ local function handle_buttons(this, fields)
|
|||
worldfile:set("load_mod_" .. mod.name, mod.virtual_path)
|
||||
was_set[mod.name] = true
|
||||
elseif not was_set[mod.name] then
|
||||
worldfile:set("load_mod_" .. mod.name, "false")
|
||||
worldfile:remove("load_mod_" .. mod.name)
|
||||
end
|
||||
elseif mod.enabled then
|
||||
gamedata.errormessage = fgettext_ne("Failed to enable mo" ..
|
||||
|
|
|
@ -190,10 +190,10 @@ local function get_formspec(tabview, name, tabdata)
|
|||
local max_clients = 5
|
||||
if #clients_list > max_clients then
|
||||
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
|
||||
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
|
||||
retval = retval .. "style[btn_view_clients;padding=6]"
|
||||
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
|
||||
end
|
||||
|
||||
local function search_server_list(input)
|
||||
local function search_server_list(input, tabdata)
|
||||
menudata.search_result = nil
|
||||
if #serverlistmgr.servers < 2 then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
tabdata.pre_search_selection = tabdata.pre_search_selection or find_selected_server()
|
||||
|
||||
-- setup the search query
|
||||
local query = parse_search_input(input)
|
||||
if not query then
|
||||
|
@ -419,11 +422,23 @@ local function search_server_list(input)
|
|||
return
|
||||
end
|
||||
|
||||
local current_server = find_selected_server()
|
||||
|
||||
table.sort(search_result, function(a, b)
|
||||
return a.points > b.points
|
||||
end)
|
||||
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)
|
||||
for _, server in ipairs(search_result) do
|
||||
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
|
||||
set_selected_server(nil)
|
||||
end
|
||||
|
||||
local function main_button_handler(tabview, fields, name, tabdata)
|
||||
if fields.te_name then
|
||||
gamedata.playername = fields.te_name
|
||||
|
@ -471,6 +487,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||
end
|
||||
if event.type == "CHG" then
|
||||
set_selected_server(server)
|
||||
tabdata.pre_search_selection = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
@ -484,11 +501,9 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||
if fields.btn_delete_favorite then
|
||||
local idx = core.get_table_index("servers")
|
||||
if not idx then return end
|
||||
local server = tabdata.lookup[idx]
|
||||
if not server then return end
|
||||
|
||||
serverlistmgr.delete_favorite(server)
|
||||
set_selected_server(server)
|
||||
serverlistmgr.delete_favorite(tabdata.lookup[idx])
|
||||
set_selected_server(tabdata.lookup[idx+1])
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -516,13 +531,16 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||
if fields.btn_mp_clear then
|
||||
tabdata.search_for = ""
|
||||
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
|
||||
end
|
||||
|
||||
if fields.btn_mp_search or fields.key_enter_field == "te_search" then
|
||||
tabdata.search_for = fields.te_search
|
||||
search_server_list(fields.te_search)
|
||||
search_server_list(fields.te_search, tabdata)
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
|
@ -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.
|
||||
vsync (VSync) bool false
|
||||
|
||||
# Maximum FPS when the window is not focused, or when the game is paused.
|
||||
fps_max_unfocused (FPS when unfocused or paused) int 20 1 4294967295
|
||||
# Maximum FPS when the window is not focused.
|
||||
fps_max_unfocused (FPS when unfocused) int 10 1 4294967295
|
||||
|
||||
# View distance in nodes.
|
||||
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.
|
||||
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]
|
||||
|
||||
# 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).
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
#
|
||||
# Requires: enable_ipv6
|
||||
ipv6_server (IPv6 server) bool false
|
||||
ipv6_server (IPv6 server) bool true
|
||||
|
||||
[*Server Security]
|
||||
|
||||
|
@ -1797,14 +1791,6 @@ profiler_print_interval (Engine profiling data print interval) int 0 0
|
|||
|
||||
[*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]
|
||||
|
||||
# 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]
|
||||
|
||||
# Enable IPv6 support (for both client and server).
|
||||
# Required for IPv6 connections to work at all.
|
||||
enable_ipv6 (IPv6) bool true
|
||||
|
||||
# Prometheus listener address.
|
||||
# If Luanti is compiled with ENABLE_PROMETHEUS option enabled,
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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]
|
||||
|
||||
# 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.
|
||||
display_density_factor (Display Density Scaling Factor) float 1 0.5 5.0
|
||||
|
||||
|
|
|
@ -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`),
|
||||
|
|
|
@ -22,27 +22,27 @@
|
|||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
It is highly recommended to use vcpkg as package manager.
|
||||
|
||||
After you successfully built vcpkg you can easily install the required libraries:
|
||||
|
||||
```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.
|
||||
|
|
|
@ -1522,7 +1522,7 @@ There are a bunch of different looking node types.
|
|||
* `allfaces`
|
||||
* Often used for partially-transparent nodes.
|
||||
* 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`
|
||||
* Often used for leaves nodes.
|
||||
* This switches between `normal`, `glasslike` and `allfaces` according to
|
||||
|
@ -5689,6 +5689,8 @@ Utilities
|
|||
biome_weights = true,
|
||||
-- Particles can specify a "clip" blend mode (5.11.0)
|
||||
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.
|
||||
* `core.hash_node_position(pos)`: returns a 48-bit integer
|
||||
* `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
|
||||
* Inverse transform of `core.hash_node_position`
|
||||
* `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
|
||||
* `contains_item(listname, stack, [match_meta])`: returns `true` if
|
||||
the stack of items can be fully taken from the list.
|
||||
If `match_meta` is false, only the items' names are compared
|
||||
(default: `false`).
|
||||
* `remove_item(listname, stack)`: take as many items as specified from the
|
||||
list, returns the items that were actually removed (as an `ItemStack`)
|
||||
-- note that any item metadata is ignored, so attempting to remove a specific
|
||||
unique item this way will likely remove the wrong one -- to do that use
|
||||
`set_stack` with an empty `ItemStack`.
|
||||
* If `match_meta` is `true`, item metadata is also considered when comparing
|
||||
items. Otherwise, only the items names are compared. Default: `false`
|
||||
* The method ignores wear.
|
||||
* `remove_item(listname, stack, [match_meta])`: take as many items as specified from the
|
||||
list, returns the items that were actually removed (as an `ItemStack`).
|
||||
* If `match_meta` is `true` (available since feature `remove_item_match_meta`),
|
||||
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
|
||||
`core.get_inventory(location)`.
|
||||
* 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.
|
||||
Defaults to `thirdperson_back` if unspecified.
|
||||
* `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)`:
|
||||
* Sends an already loaded mapblock to the player.
|
||||
* 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`.
|
||||
-- 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.
|
||||
-- "sprite" is a flat texture always facing the player.
|
||||
-- "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
|
||||
-- to be as large as a node, use `0.667` in `visual_size`
|
||||
-- "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},
|
||||
-- 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
|
||||
|
||||
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.
|
||||
-- "sprite" uses 1 texture.
|
||||
-- "upright_sprite" uses 2 textures: {front, back}.
|
||||
|
@ -9262,11 +9277,14 @@ Player properties need to be saved manually.
|
|||
colors = {},
|
||||
-- Currently unused.
|
||||
|
||||
node = {name = "ignore", param1=0, param2=0},
|
||||
-- Node to show when using the "node" visual
|
||||
|
||||
use_texture_alpha = false,
|
||||
-- Use texture's alpha channel.
|
||||
-- Excludes "upright_sprite" and "wielditem".
|
||||
-- Use texture's alpha channel for transparency blending.
|
||||
-- Note: currently causes visual issues when viewed through other
|
||||
-- semi-transparent materials such as water.
|
||||
-- Note: ignored for "item", "wielditem" and "node" visual.
|
||||
|
||||
spritediv = {x = 1, y = 1},
|
||||
-- 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.
|
||||
|
||||
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).
|
||||
|
||||
automatic_rotate = 0,
|
||||
|
@ -9306,6 +9324,7 @@ Player properties need to be saved manually.
|
|||
|
||||
backface_culling = true,
|
||||
-- Set to false to disable backface_culling for model
|
||||
-- Note: only used by "mesh" and "cube" visual
|
||||
|
||||
glow = 0,
|
||||
-- Add this much extra lighting when calculating texture color.
|
||||
|
@ -9341,6 +9360,7 @@ Player properties need to be saved manually.
|
|||
|
||||
shaded = true,
|
||||
-- Setting this to 'false' disables diffuse lighting of entity
|
||||
-- Note: ignored for "item", "wielditem" and "node" visual
|
||||
|
||||
show_on_minimap = false,
|
||||
-- Defaults to true for players, false for other entities.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Luanti Lua Mainmenu API Reference 5.11.0
|
||||
Luanti Lua Mainmenu API Reference 5.12.0
|
||||
========================================
|
||||
|
||||
Introduction
|
||||
|
|
|
@ -281,15 +281,27 @@ storing coordinates separately), but the format has been kept unchanged for
|
|||
that part.
|
||||
|
||||
## `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:
|
||||
|
||||
```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
|
||||
CREATE TABLE `blocks` (`pos` INT NOT NULL PRIMARY KEY, `data` BLOB);
|
||||
```
|
||||
|
||||
## Position Hashing
|
||||
|
||||
Applies to the pre-5.12.0 schema:
|
||||
|
||||
`pos` (a node position hash) is created from the three coordinates of a
|
||||
`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: Zlib data is in such a format that Python's `zlib` at least can
|
||||
> directly decompress.
|
||||
> * NOTE: Since version 29 zstd is used instead of zlib. In addition, the entire
|
||||
> block is first serialized and then compressed (except the version byte).
|
||||
> * NOTE: Since version 29 zstd is used instead of zlib. In addition, the
|
||||
> **entire block** is first serialized and then compressed (except version byte).
|
||||
|
||||
`u8` version
|
||||
* map format version number, see serialization.h for the latest number
|
||||
|
|
|
@ -22,11 +22,15 @@ core.register_node("basenodes:desert_stone", {
|
|||
|
||||
core.register_node("basenodes: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
|
||||
"default_dirt.png^basenodes_dirt_with_grass_bottom.png",
|
||||
{name = "default_dirt.png^default_grass_side.png",
|
||||
tileable_vertical = false}},
|
||||
"basenodes_dirt_with_grass_bottom.png",
|
||||
{name = "default_grass_side.png", tileable_vertical = false},
|
||||
},
|
||||
groups = {crumbly=3, soil=1},
|
||||
})
|
||||
|
||||
|
|
|
@ -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", {
|
||||
initial_properties = {
|
||||
visual = "mesh",
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
local item_with_meta = ItemStack({name = "air", meta = {test = "abc"}})
|
||||
local function get_stack_with_meta(count)
|
||||
return ItemStack({name = "air", count = count, meta = {test = "abc"}})
|
||||
end
|
||||
|
||||
local test_list = {
|
||||
ItemStack("air"),
|
||||
ItemStack(""),
|
||||
ItemStack(item_with_meta),
|
||||
ItemStack(get_stack_with_meta(1)),
|
||||
}
|
||||
|
||||
local function compare_lists(a, b)
|
||||
|
@ -34,12 +35,12 @@ local function test_inventory()
|
|||
assert(not inv:set_width("test", -1))
|
||||
|
||||
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(compare_lists(inv:get_list("test"), test_list))
|
||||
|
||||
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:room_for_item("test", "air 99"))
|
||||
|
@ -48,16 +49,28 @@ local function test_inventory()
|
|||
inv:set_stack("test", 2, "")
|
||||
|
||||
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(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
|
||||
assert(inv:remove_item("test", "air") == item_with_meta)
|
||||
item_with_meta:set_count(2)
|
||||
assert(inv:remove_item("test", "air 2") == item_with_meta)
|
||||
assert(inv:remove_item("test", "air") == get_stack_with_meta(1))
|
||||
assert(inv:remove_item("test", "air 2") == get_stack_with_meta(2))
|
||||
assert(inv:remove_item("test", "air") == ItemStack("air"))
|
||||
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
|
||||
local before = inv:get_list("test")
|
||||
pcall(inv.set_lists, inv, {test = true})
|
||||
|
|
|
@ -189,6 +189,29 @@ local function test_write_json()
|
|||
end
|
||||
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 info = core.get_game_info()
|
||||
local game_conf = Settings(info.path .. "/game.conf")
|
||||
|
|
|
@ -21,7 +21,7 @@ Aside from standard search options (`ZLIB_INCLUDE_DIR`, `ZLIB_LIBRARY`, ...) the
|
|||
* `ENABLE_OPENGL` - Enable OpenGL driver
|
||||
* `ENABLE_OPENGL3` (default: `OFF`) - Enable OpenGL 3+ 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.
|
||||
|
||||
|
|
|
@ -34,16 +34,16 @@ public:
|
|||
/** \return Pointer to mesh which is displayed by this node. */
|
||||
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
|
||||
causing all mesh scene nodes referencing this mesh to change, too.
|
||||
\param readonly Flag if the materials shall be read-only. */
|
||||
virtual void setReadOnlyMaterials(bool readonly) = 0;
|
||||
\param shared Flag if the materials shall be shared. */
|
||||
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
|
||||
/** This flag can be set by setReadOnlyMaterials().
|
||||
\return Whether the materials are read-only. */
|
||||
virtual bool isReadOnlyMaterials() const = 0;
|
||||
//! Check if the scene node does not copy the materials of the mesh but uses them directly.
|
||||
/** This flag can be set by setSharedMaterials().
|
||||
\return Whether the materials are shared. */
|
||||
virtual bool isSharedMaterials() const = 0;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
|
|
@ -310,7 +310,11 @@ public:
|
|||
\return The material at that index. */
|
||||
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.
|
||||
|
|
|
@ -198,9 +198,6 @@ public:
|
|||
or similar. */
|
||||
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
|
||||
/** \return Color format of the window. */
|
||||
virtual video::ECOLOR_FORMAT getColorFormat() const = 0;
|
||||
|
|
|
@ -472,7 +472,7 @@ public:
|
|||
};
|
||||
|
||||
//! global const identity Material
|
||||
IRRLICHT_API extern SMaterial IdentityMaterial;
|
||||
IRRLICHT_API extern const SMaterial IdentityMaterial;
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
|
|
@ -18,47 +18,38 @@ namespace core
|
|||
|
||||
//! Rounding error constant often used when comparing f32 values.
|
||||
|
||||
const f32 ROUNDING_ERROR_f32 = 0.000001f;
|
||||
const f64 ROUNDING_ERROR_f64 = 0.00000001;
|
||||
constexpr f32 ROUNDING_ERROR_f32 = 0.000001f;
|
||||
constexpr f64 ROUNDING_ERROR_f64 = 0.00000001;
|
||||
|
||||
#ifdef PI // make sure we don't collide with a define
|
||||
#undef PI
|
||||
#endif
|
||||
//! Constant for PI.
|
||||
const f32 PI = 3.14159265359f;
|
||||
|
||||
//! Constant for reciprocal of PI.
|
||||
const f32 RECIPROCAL_PI = 1.0f / PI;
|
||||
|
||||
//! Constant for half of PI.
|
||||
const f32 HALF_PI = PI / 2.0f;
|
||||
constexpr f32 PI = M_PI;
|
||||
|
||||
#ifdef PI64 // make sure we don't collide with a define
|
||||
#undef PI64
|
||||
#endif
|
||||
//! Constant for 64bit PI.
|
||||
const f64 PI64 = 3.1415926535897932384626433832795028841971693993751;
|
||||
|
||||
//! Constant for 64bit reciprocal of PI.
|
||||
const f64 RECIPROCAL_PI64 = 1.0 / PI64;
|
||||
constexpr f64 PI64 = M_PI;
|
||||
|
||||
//! 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)
|
||||
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)
|
||||
const f64 DEGTORAD64 = PI64 / 180.0;
|
||||
constexpr f64 DEGTORAD64 = PI64 / 180.0;
|
||||
|
||||
//! 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
|
||||
/** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
|
||||
\param radians The radians value to convert to degrees.
|
||||
*/
|
||||
inline f32 radToDeg(f32 radians)
|
||||
inline constexpr f32 radToDeg(f32 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
|
||||
\param radians The radians value to convert to degrees.
|
||||
*/
|
||||
inline f64 radToDeg(f64 radians)
|
||||
inline constexpr f64 radToDeg(f64 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
|
||||
\param degrees The degrees value to convert to radians.
|
||||
*/
|
||||
inline f32 degToRad(f32 degrees)
|
||||
inline constexpr f32 degToRad(f32 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
|
||||
\param degrees The degrees value to convert to radians.
|
||||
*/
|
||||
inline f64 degToRad(f64 degrees)
|
||||
inline constexpr f64 degToRad(f64 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>
|
||||
inline const T &min_(const T &a, const T &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>
|
||||
inline const T &min_(const T &a, const T &b, const T &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>
|
||||
inline const T &max_(const T &a, const T &b)
|
||||
{
|
||||
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>
|
||||
inline const T &max_(const T &a, const T &b, const T &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>
|
||||
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
|
||||
|
@ -140,19 +131,6 @@ inline const T clamp(const T &value, const T &low, const T &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>
|
||||
inline T roundingError();
|
||||
|
||||
|
|
|
@ -162,21 +162,12 @@ public:
|
|||
//! Returns true if the matrix is the identity matrix
|
||||
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.
|
||||
CMatrix4<T> &setTranslation(const vector3d<T> &translation);
|
||||
|
||||
//! Gets the current translation
|
||||
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.
|
||||
//! NOTE: Rotation order is ZYX. This means that vectors are
|
||||
//! 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);
|
||||
|
||||
//! 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: 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.
|
||||
|
@ -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.
|
||||
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().
|
||||
/** 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
|
||||
setting rotation (so no scale/shear). Thought it (probably) works as long as scale doesn't flip handedness.
|
||||
NOTE: This only works correctly for TRS matrix products where S is a positive, component-wise scaling (see setScale).
|
||||
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.
|
||||
/** The 4th row and column are unmodified. */
|
||||
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);
|
||||
//! Same as getRotationRadians, but returns degrees.
|
||||
vector3d<T> getRotationDegrees() const;
|
||||
|
||||
//! Make a rotation matrix from angle and axis, assuming left handed rotation.
|
||||
/** The 4th row and column are unmodified. */
|
||||
|
@ -225,10 +208,10 @@ public:
|
|||
CMatrix4<T> &setScale(const vector3d<T> &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
|
||||
core::vector3d<T> getScale() const;
|
||||
vector3d<T> getScale() const;
|
||||
|
||||
//! Translate a vector by the inverse of the translation part of this matrix.
|
||||
void inverseTranslateVect(vector3df &vect) const;
|
||||
|
@ -259,7 +242,7 @@ public:
|
|||
//! 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.
|
||||
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
|
||||
/** 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;
|
||||
|
||||
//! 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
|
||||
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
|
||||
void transformBoxEx(core::aabbox3d<f32> &box) const;
|
||||
void transformBoxEx(aabbox3d<f32> &box) const;
|
||||
|
||||
//! Multiplies this matrix by a 1x4 matrix
|
||||
void multiplyWith1x4Matrix(T *matrix) const;
|
||||
|
@ -338,16 +321,16 @@ public:
|
|||
\param plane: plane into which the geometry if flattened into
|
||||
\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. */
|
||||
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.
|
||||
/** 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.
|
||||
/** \param b: other matrix to interpolate with
|
||||
\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
|
||||
CMatrix4<T> getTransposed() const;
|
||||
|
@ -359,13 +342,13 @@ public:
|
|||
/** \param from: vector to rotate from
|
||||
\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
|
||||
/** \param center Position to rotate around
|
||||
\param translate Translation applied after the rotation
|
||||
*/
|
||||
void setRotationCenter(const core::vector3df ¢er, const core::vector3df &translate);
|
||||
void setRotationCenter(const vector3df ¢er, const vector3df &translate);
|
||||
|
||||
//! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis
|
||||
/** \param camPos: viewer position in world coo
|
||||
|
@ -374,11 +357,11 @@ public:
|
|||
\param axis: axis to rotate about
|
||||
\param from: source vector to rotate from
|
||||
*/
|
||||
void buildAxisAlignedBillboard(const core::vector3df &camPos,
|
||||
const core::vector3df ¢er,
|
||||
const core::vector3df &translation,
|
||||
const core::vector3df &axis,
|
||||
const core::vector3df &from);
|
||||
void buildAxisAlignedBillboard(const vector3df &camPos,
|
||||
const vector3df ¢er,
|
||||
const vector3df &translation,
|
||||
const vector3df &axis,
|
||||
const vector3df &from);
|
||||
|
||||
/*
|
||||
construct 2D Texture transformations
|
||||
|
@ -386,9 +369,9 @@ public:
|
|||
*/
|
||||
//! Set to a texture transformation matrix with the given parameters.
|
||||
CMatrix4<T> &buildTextureTransform(f32 rotateRad,
|
||||
const core::vector2df &rotatecenter,
|
||||
const core::vector2df &translate,
|
||||
const core::vector2df &scale);
|
||||
const vector2df &rotatecenter,
|
||||
const vector2df &translate,
|
||||
const vector2df &scale);
|
||||
|
||||
//! Set texture transformation rotation
|
||||
/** Rotate about z axis, recenter at (0.5,0.5).
|
||||
|
@ -439,9 +422,12 @@ public:
|
|||
CMatrix4<T> &setM(const T *data);
|
||||
|
||||
//! 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:
|
||||
template <bool degrees>
|
||||
vector3d<T> getRotation(const vector3d<T> &scale) const;
|
||||
|
||||
//! Matrix data, stored in row-major order
|
||||
T M[16];
|
||||
};
|
||||
|
@ -645,21 +631,8 @@ inline CMatrix4<T> &CMatrix4<T>::operator*=(const T &scalar)
|
|||
template <class T>
|
||||
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);
|
||||
return setbyproduct_nocheck(temp, other);
|
||||
#endif
|
||||
}
|
||||
|
||||
//! multiply by another matrix
|
||||
|
@ -699,30 +672,13 @@ inline CMatrix4<T> &CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T> &other_a
|
|||
template <class T>
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
//! multiply by another matrix
|
||||
template <class T>
|
||||
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);
|
||||
|
||||
const T *m1 = M;
|
||||
|
@ -764,15 +720,6 @@ inline CMatrix4<T> &CMatrix4<T>::setTranslation(const vector3d<T> &translation)
|
|||
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>
|
||||
inline CMatrix4<T> &CMatrix4<T>::setScale(const vector3d<T> &scale)
|
||||
{
|
||||
|
@ -805,13 +752,7 @@ inline vector3d<T> CMatrix4<T>::getScale() const
|
|||
template <class T>
|
||||
inline CMatrix4<T> &CMatrix4<T>::setRotationDegrees(const vector3d<T> &rotation)
|
||||
{
|
||||
return setRotationRadians(rotation * core::DEGTORAD);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline CMatrix4<T> &CMatrix4<T>::setInverseRotationDegrees(const vector3d<T> &rotation)
|
||||
{
|
||||
return setInverseRotationRadians(rotation * core::DEGTORAD);
|
||||
return setRotationRadians(rotation * DEGTORAD);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
@ -841,91 +782,60 @@ inline CMatrix4<T> &CMatrix4<T>::setRotationRadians(const vector3d<T> &rotation)
|
|||
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>
|
||||
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 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 core::vector3d<f64> invScale(core::reciprocal(scale.X), core::reciprocal(scale.Y), core::reciprocal(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 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));
|
||||
const f64 C = cos(Y);
|
||||
Y *= RADTODEG64;
|
||||
f64 a = clamp(mat[2] * invScale.X, -1.0, 1.0);
|
||||
f64 Y = -asin(a);
|
||||
|
||||
f64 rotx, roty, X, Z;
|
||||
|
||||
if (!core::iszero((T)C)) {
|
||||
const f64 invC = core::reciprocal(C);
|
||||
rotx = mat[10] * invC * invScale.Z;
|
||||
roty = mat[6] * invC * invScale.Y;
|
||||
X = atan2(roty, rotx) * RADTODEG64;
|
||||
rotx = mat[0] * invC * invScale.X;
|
||||
roty = mat[1] * invC * invScale.X;
|
||||
Z = atan2(roty, rotx) * RADTODEG64;
|
||||
if (!core::equals(std::abs(a), 1.0)) {
|
||||
// abs(a) = abs(sin(Y)) = 1 <=> cos(Y) = 0
|
||||
rotx = mat[10] * invScale.Z;
|
||||
roty = mat[6] * invScale.Y;
|
||||
X = atan2(roty, rotx);
|
||||
rotx = mat[0] * invScale.X;
|
||||
roty = mat[1] * invScale.X;
|
||||
Z = atan2(roty, rotx);
|
||||
} else {
|
||||
X = 0.0;
|
||||
rotx = mat[5] * invScale.Y;
|
||||
roty = -mat[4] * invScale.Y;
|
||||
Z = atan2(roty, rotx) * RADTODEG64;
|
||||
rotx = mat[5];
|
||||
roty = -mat[4];
|
||||
Z = atan2(roty, rotx);
|
||||
}
|
||||
|
||||
// fix values that get below zero
|
||||
if (X < 0.0)
|
||||
X += 360.0;
|
||||
if (Y < 0.0)
|
||||
Y += 360.0;
|
||||
if (Z < 0.0)
|
||||
Z += 360.0;
|
||||
if (degrees) {
|
||||
X *= core::RADTODEG64;
|
||||
Y *= core::RADTODEG64;
|
||||
Z *= core::RADTODEG64;
|
||||
}
|
||||
|
||||
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>
|
||||
inline vector3d<T> CMatrix4<T>::getRotationDegrees() const
|
||||
{
|
||||
// Note: Using getScale() here make it look like it could do matrix decomposition.
|
||||
// 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;
|
||||
return getRotation<true>(getScale());
|
||||
}
|
||||
|
||||
//! 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;
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
template <class T>
|
||||
inline CMatrix4<T> &CMatrix4<T>::makeIdentity()
|
||||
{
|
||||
|
@ -1002,77 +910,6 @@ inline bool CMatrix4<T>::isIdentity() const
|
|||
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>
|
||||
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>
|
||||
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[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
|
||||
template <class T>
|
||||
inline void CMatrix4<T>::transformPlane(core::plane3d<f32> &plane) const
|
||||
inline void CMatrix4<T>::transformPlane(plane3d<f32> &plane) const
|
||||
{
|
||||
vector3df member;
|
||||
// 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
|
||||
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;
|
||||
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()
|
||||
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 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.
|
||||
/// 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;
|
||||
|
||||
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[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;
|
||||
|
||||
d = core::reciprocal(d);
|
||||
d = reciprocal(d);
|
||||
|
||||
out[0] = d * (m[5] * (m[10] * m[15] - m[11] * m[14]) +
|
||||
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.
|
||||
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();
|
||||
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.
|
||||
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);
|
||||
|
||||
|
@ -1797,7 +1623,7 @@ inline void CMatrix4<T>::getTransposed(CMatrix4<T> &o) const
|
|||
|
||||
// used to scale <-1,-1><1,1> to viewport
|
||||
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 scaleY = -(viewport.getHeight() - 0.75f) * 0.5f;
|
||||
|
@ -1808,7 +1634,7 @@ inline CMatrix4<T> &CMatrix4<T>::buildNDCToDCMatrix(const core::rect<s32> &viewp
|
|||
makeIdentity();
|
||||
M[12] = (T)dx;
|
||||
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
|
||||
|
@ -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
|
||||
*/
|
||||
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
|
||||
core::vector3df f(from);
|
||||
core::vector3df t(to);
|
||||
vector3df f(from);
|
||||
vector3df t(to);
|
||||
f.normalize();
|
||||
t.normalize();
|
||||
|
||||
// axis multiplication by sin
|
||||
core::vector3df vs(t.crossProduct(f));
|
||||
vector3df vs(t.crossProduct(f));
|
||||
|
||||
// axis of rotation
|
||||
core::vector3df v(vs);
|
||||
vector3df v(vs);
|
||||
v.normalize();
|
||||
|
||||
// cosine angle
|
||||
T ca = f.dotProduct(t);
|
||||
|
||||
core::vector3df vt(v * (1 - ca));
|
||||
vector3df vt(v * (1 - ca));
|
||||
|
||||
M[0] = vt.X * v.X + 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>
|
||||
inline void CMatrix4<T>::buildAxisAlignedBillboard(
|
||||
const core::vector3df &camPos,
|
||||
const core::vector3df ¢er,
|
||||
const core::vector3df &translation,
|
||||
const core::vector3df &axis,
|
||||
const core::vector3df &from)
|
||||
const vector3df &camPos,
|
||||
const vector3df ¢er,
|
||||
const vector3df &translation,
|
||||
const vector3df &axis,
|
||||
const vector3df &from)
|
||||
{
|
||||
// axis of rotation
|
||||
core::vector3df up = axis;
|
||||
vector3df up = axis;
|
||||
up.normalize();
|
||||
const core::vector3df forward = (camPos - center).normalize();
|
||||
const core::vector3df right = up.crossProduct(forward).normalize();
|
||||
const vector3df forward = (camPos - center).normalize();
|
||||
const vector3df right = up.crossProduct(forward).normalize();
|
||||
|
||||
// correct look vector
|
||||
const core::vector3df look = right.crossProduct(up);
|
||||
const vector3df look = right.crossProduct(up);
|
||||
|
||||
// rotate from to
|
||||
// axis multiplication by sin
|
||||
const core::vector3df vs = look.crossProduct(from);
|
||||
const vector3df vs = look.crossProduct(from);
|
||||
|
||||
// cosine angle
|
||||
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[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
|
||||
template <class T>
|
||||
inline void CMatrix4<T>::setRotationCenter(const core::vector3df ¢er, const core::vector3df &translation)
|
||||
inline void CMatrix4<T>::setRotationCenter(const vector3df ¢er, const vector3df &translation)
|
||||
{
|
||||
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);
|
||||
|
@ -1945,9 +1771,9 @@ inline void CMatrix4<T>::setRotationCenter(const core::vector3df ¢er, const
|
|||
|
||||
template <class T>
|
||||
inline CMatrix4<T> &CMatrix4<T>::buildTextureTransform(f32 rotateRad,
|
||||
const core::vector2df &rotatecenter,
|
||||
const core::vector2df &translate,
|
||||
const core::vector2df &scale)
|
||||
const vector2df &rotatecenter,
|
||||
const vector2df &translate,
|
||||
const vector2df &scale)
|
||||
{
|
||||
const f32 c = cosf(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
|
||||
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)
|
||||
if (!core::equals(M[i], other.M[i], tolerance))
|
||||
|
|
|
@ -33,6 +33,12 @@ public:
|
|||
explicit constexpr vector3d(T 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
|
||||
|
||||
vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); }
|
||||
|
|
|
@ -619,7 +619,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
|||
|
||||
// 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);
|
||||
|
||||
core::quaternion QRotation;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
// 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();
|
||||
joint->Animatedscale = scale;
|
||||
core::matrix4 inverseScale;
|
||||
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();
|
||||
joint->Animatedrotation = mat.getRotationRadians(scale);
|
||||
// Invert the rotation because it is applied using `getMatrix_transposed`,
|
||||
// which again inverts.
|
||||
joint->Animatedrotation.makeInverse();
|
||||
|
|
|
@ -308,8 +308,6 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters ¶m) :
|
|||
if (SDL_Init(flags) < 0) {
|
||||
os::Printer::log("Unable to initialize SDL", SDL_GetError(), ELL_ERROR);
|
||||
Close = true;
|
||||
} else {
|
||||
os::Printer::log("SDL initialized", ELL_INFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,21 +322,27 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters ¶m) :
|
|||
}
|
||||
}
|
||||
|
||||
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_
|
||||
SDL_GetWindowWMInfo(Window, &Info);
|
||||
#endif //_IRR_EMSCRIPTEN_PLATFORM_
|
||||
core::stringc sdlversion = "SDL Version ";
|
||||
sdlversion += Info.version.major;
|
||||
sdlversion += ".";
|
||||
sdlversion += Info.version.minor;
|
||||
sdlversion += ".";
|
||||
sdlversion += Info.version.patch;
|
||||
sdlver += " on ";
|
||||
sdlver += SDL_GetPlatform();
|
||||
}
|
||||
|
||||
Operator = new COSOperator(sdlversion);
|
||||
Operator = new COSOperator(sdlver);
|
||||
if (SDLDeviceInstances == 1) {
|
||||
os::Printer::log(sdlversion.c_str(), ELL_INFORMATION);
|
||||
os::Printer::log(sdlver.c_str(), ELL_INFORMATION);
|
||||
}
|
||||
|
||||
// create cursor control
|
||||
|
@ -706,6 +710,10 @@ bool CIrrDeviceSDL::run()
|
|||
irrevent.MouseInput.X = MouseX;
|
||||
irrevent.MouseInput.Y = MouseY;
|
||||
|
||||
// wheel y can be 0 if scrolling sideways
|
||||
if (irrevent.MouseInput.Wheel == 0.0f)
|
||||
break;
|
||||
|
||||
postEventFromUser(irrevent);
|
||||
break;
|
||||
}
|
||||
|
@ -1248,15 +1256,6 @@ bool CIrrDeviceSDL::supportsTouchEvents() const
|
|||
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
|
||||
bool CIrrDeviceSDL::isWindowActive() const
|
||||
{
|
||||
|
|
|
@ -96,9 +96,6 @@ public:
|
|||
//! Checks if the Irrlicht device supports touch events.
|
||||
bool supportsTouchEvents() const override;
|
||||
|
||||
//! Checks whether windowing uses the Wayland protocol.
|
||||
bool isUsingWayland() const override;
|
||||
|
||||
//! Get the position of this window on screen
|
||||
core::position2di getWindowPosition() override;
|
||||
|
||||
|
@ -340,7 +337,6 @@ private:
|
|||
};
|
||||
|
||||
core::array<SKeyMap> KeyMap;
|
||||
SDL_SysWMinfo Info;
|
||||
|
||||
s32 CurrentTouchCount;
|
||||
bool IsInBackground;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# When enabling SDL2 by default on macOS, don't forget to change
|
||||
# "NSHighResolutionCapable" to true in "Info.plist".
|
||||
if(ANDROID)
|
||||
if(NOT APPLE)
|
||||
set(DEFAULT_SDL2 ON)
|
||||
endif()
|
||||
|
||||
|
@ -33,6 +33,15 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
|
|||
elseif(MSVC)
|
||||
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)
|
||||
|
||||
# Enable SSE for floating point math on 32-bit x86 by default
|
||||
|
|
|
@ -21,7 +21,7 @@ CMeshSceneNode::CMeshSceneNode(IMesh *mesh, ISceneNode *parent, ISceneManager *m
|
|||
const core::vector3df &scale) :
|
||||
IMeshSceneNode(parent, mgr, id, position, rotation, scale),
|
||||
Mesh(0),
|
||||
PassCount(0), ReadOnlyMaterials(false)
|
||||
PassCount(0), SharedMaterials(false)
|
||||
{
|
||||
setMesh(mesh);
|
||||
}
|
||||
|
@ -49,9 +49,9 @@ void CMeshSceneNode::OnRegisterSceneNode()
|
|||
int solidCount = 0;
|
||||
|
||||
// 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) {
|
||||
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))
|
||||
++transparentCount;
|
||||
|
@ -93,7 +93,7 @@ void CMeshSceneNode::render()
|
|||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) {
|
||||
scene::IMeshBuffer *mb = Mesh->getMeshBuffer(i);
|
||||
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);
|
||||
|
||||
|
@ -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
|
||||
//! 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)
|
||||
{
|
||||
if (Mesh && ReadOnlyMaterials && i < Mesh->getMeshBufferCount()) {
|
||||
ReadOnlyMaterial = Mesh->getMeshBuffer(i)->getMaterial();
|
||||
return ReadOnlyMaterial;
|
||||
if (Mesh && SharedMaterials && i < Mesh->getMeshBufferCount()) {
|
||||
return Mesh->getMeshBuffer(i)->getMaterial();
|
||||
}
|
||||
|
||||
if (i >= Materials.size())
|
||||
|
@ -183,7 +179,7 @@ video::SMaterial &CMeshSceneNode::getMaterial(u32 i)
|
|||
//! returns amount of materials used by this scene node.
|
||||
u32 CMeshSceneNode::getMaterialCount() const
|
||||
{
|
||||
if (Mesh && ReadOnlyMaterials)
|
||||
if (Mesh && SharedMaterials)
|
||||
return Mesh->getMeshBufferCount();
|
||||
|
||||
return Materials.size();
|
||||
|
@ -206,9 +202,10 @@ void CMeshSceneNode::copyMaterials()
|
|||
{
|
||||
Materials.clear();
|
||||
|
||||
if (Mesh) {
|
||||
if (Mesh && !SharedMaterials) {
|
||||
video::SMaterial mat;
|
||||
|
||||
Materials.reserve(Mesh->getMeshBufferCount());
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) {
|
||||
IMeshBuffer *mb = Mesh->getMeshBuffer(i);
|
||||
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.
|
||||
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
|
||||
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
|
||||
bool CMeshSceneNode::isReadOnlyMaterials() const
|
||||
bool CMeshSceneNode::isSharedMaterials() const
|
||||
{
|
||||
return ReadOnlyMaterials;
|
||||
return SharedMaterials;
|
||||
}
|
||||
|
||||
//! 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);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->ReadOnlyMaterials = ReadOnlyMaterials;
|
||||
nb->SharedMaterials = SharedMaterials;
|
||||
nb->Materials = Materials;
|
||||
|
||||
if (newParent)
|
||||
|
|
|
@ -52,13 +52,16 @@ public:
|
|||
//! Returns the current 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.
|
||||
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
|
||||
referencing this mesh to change too. */
|
||||
void setReadOnlyMaterials(bool readonly) override;
|
||||
//! 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
|
||||
causing all mesh scene nodes referencing this mesh to change, too.
|
||||
\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
|
||||
bool isReadOnlyMaterials() const override;
|
||||
//! Check if the scene node does not copy the materials of the mesh but uses them directly.
|
||||
/** 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.
|
||||
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
|
||||
|
@ -71,14 +74,13 @@ public:
|
|||
protected:
|
||||
void copyMaterials();
|
||||
|
||||
core::array<video::SMaterial> Materials;
|
||||
std::vector<video::SMaterial> Materials;
|
||||
core::aabbox3d<f32> Box{{0, 0, 0}};
|
||||
video::SMaterial ReadOnlyMaterial;
|
||||
|
||||
IMesh *Mesh;
|
||||
|
||||
s32 PassCount;
|
||||
bool ReadOnlyMaterials;
|
||||
bool SharedMaterials;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
|
|
@ -1455,9 +1455,9 @@ void CNullDriver::setMaterialRendererName(u32 idx, const char *name)
|
|||
void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames)
|
||||
{
|
||||
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)
|
||||
irr::core::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
|
||||
std::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1526,8 +1526,6 @@ bool CXMeshFileLoader::parseDataObjectAnimationKey(SkinnedMesh::SJoint *joint)
|
|||
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->addPositionKey(joint, time, mat.getTranslation());
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ const matrix4 IdentityMatrix(matrix4::EM4CONST_IDENTITY);
|
|||
|
||||
namespace video
|
||||
{
|
||||
SMaterial IdentityMaterial;
|
||||
const SMaterial IdentityMaterial;
|
||||
|
||||
extern "C" IRRLICHT_API bool IRRCALLCONV isDriverSupported(E_DRIVER_TYPE driver)
|
||||
{
|
||||
|
|
|
@ -149,6 +149,6 @@
|
|||
<update_contact>celeron55@gmail.com</update_contact>
|
||||
|
||||
<releases>
|
||||
<release date="2024-11-10" version="5.10.0"/>
|
||||
<release date="2025-02-14" version="5.11.0"/>
|
||||
</releases>
|
||||
</component>
|
||||
|
|
|
@ -3,9 +3,9 @@ msgstr ""
|
|||
"Project-Id-Version: minetest\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-02-09 13:23+0100\n"
|
||||
"PO-Revision-Date: 2025-01-27 06:02+0000\n"
|
||||
"Last-Translator: 109247019824 "
|
||||
"<109247019824@users.noreply.hosted.weblate.org>\n"
|
||||
"PO-Revision-Date: 2025-02-11 02:02+0000\n"
|
||||
"Last-Translator: 109247019824 <109247019824@users.noreply.hosted.weblate.org>"
|
||||
"\n"
|
||||
"Language-Team: Bulgarian <https://hosted.weblate.org/projects/minetest/"
|
||||
"minetest/bg/>\n"
|
||||
"Language: bg\n"
|
||||
|
@ -264,13 +264,12 @@ msgid "Show technical names"
|
|||
msgstr "Технически наименования"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Сензорен екран"
|
||||
msgstr "Подредба на сензорния екран"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
msgid "pause_menu"
|
||||
msgstr ""
|
||||
msgstr "pause_menu"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -612,6 +611,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Това е списък на клиентите свързани с\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
|
180
po/de/luanti.po
180
po/de/luanti.po
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: German (Minetest)\n"
|
||||
"Report-Msgid-Bugs-To: \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"
|
||||
"Language-Team: German <https://hosted.weblate.org/projects/minetest/minetest/"
|
||||
"de/>\n"
|
||||
|
@ -263,14 +263,12 @@ msgid "Show technical names"
|
|||
msgstr "Technische Namen zeigen"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Touchscreen"
|
||||
msgstr "Touchscreen-Layout"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "pause_menu"
|
||||
msgstr "Bildwiederholrate im Pausenmenü"
|
||||
msgstr "pause_menu"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -436,7 +434,7 @@ msgstr "Mods"
|
|||
#: builtin/mainmenu/content/dlg_contentdb.lua
|
||||
#: builtin/mainmenu/content/dlg_package.lua
|
||||
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
|
||||
msgid "No updates"
|
||||
|
@ -610,6 +608,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Dies ist die Liste der Clients, die zu\n"
|
||||
"$1 verbunden sind"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
@ -975,25 +975,24 @@ msgstr ""
|
|||
"der jede Umbennenung hier überschreiben wird."
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
#, fuzzy
|
||||
msgid "Expand all"
|
||||
msgstr "Alle aktivieren"
|
||||
msgstr "Alle ausklappen"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "Group by prefix"
|
||||
msgstr ""
|
||||
msgstr "Nach Präfix gruppieren"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
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
|
||||
msgid "The $1 server uses the following mods:"
|
||||
msgstr ""
|
||||
msgstr "Der Server $1 nutzt folgende Mods:"
|
||||
|
||||
#: builtin/mainmenu/dlg_version_info.lua
|
||||
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
|
||||
msgid ""
|
||||
|
@ -1203,20 +1202,20 @@ msgstr ""
|
|||
"Sie müssen ein Spiel installieren, bevor Sie eine Welt erstellen können."
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Add favorite"
|
||||
msgstr "Favorit entfernen"
|
||||
msgstr "Favorit hinzufügen"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
msgstr "Client"
|
||||
msgstr ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Creative mode"
|
||||
|
@ -1232,9 +1231,8 @@ msgid "Favorites"
|
|||
msgstr "Favoriten"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Game: $1"
|
||||
msgstr "Spiel"
|
||||
msgstr "Spiel: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Incompatible Servers"
|
||||
|
@ -1249,14 +1247,12 @@ msgid "Login"
|
|||
msgstr "Einloggen"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Number of mods: $1"
|
||||
msgstr "Anzahl der Erzeugerthreads"
|
||||
msgstr "Anzahl der Mods: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Open server website"
|
||||
msgstr "Taktung dedizierter Server"
|
||||
msgstr "Server-Webseite besuchen"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Ping"
|
||||
|
@ -1269,6 +1265,10 @@ msgid ""
|
|||
"mod:<name>\n"
|
||||
"player:<name>"
|
||||
msgstr ""
|
||||
"Mögliche Filter\n"
|
||||
"game:<Name>\n"
|
||||
"mod:<Name>\n"
|
||||
"player:<Name>"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Public Servers"
|
||||
|
@ -1364,9 +1364,8 @@ msgid "Access denied. Reason: %s"
|
|||
msgstr "Zugriff verweigert. Grund: %s"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "All debug info hidden"
|
||||
msgstr "Debug-Infos angezeigt"
|
||||
msgstr "Alle Debug-Infos verborgen"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Automatic forward disabled"
|
||||
|
@ -1390,7 +1389,7 @@ msgstr "Blockgrenzen für Blöcke in Nähe angezeigt"
|
|||
|
||||
#: src/client/game.cpp
|
||||
msgid "Bounding boxes shown"
|
||||
msgstr ""
|
||||
msgstr "Grenzboxen angezeigt"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Camera update disabled"
|
||||
|
@ -1632,9 +1631,8 @@ msgid "Volume changed to %d%%"
|
|||
msgstr "Lautstärke auf %d%% gesetzt"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Wireframe shown"
|
||||
|
@ -2067,9 +2065,8 @@ msgid "Failed to compile the \"%s\" shader."
|
|||
msgstr "Fehler beim Kompilieren des „%s“-Shaders."
|
||||
|
||||
#: src/client/shader.cpp
|
||||
#, fuzzy
|
||||
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"
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2306,35 +2303,32 @@ msgid "Sound Volume: %d%%"
|
|||
msgstr "Tonlautstärke: %d%%"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Add button"
|
||||
msgstr "Mittlere Taste"
|
||||
msgstr "Button hinzufügen"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Done"
|
||||
msgstr "Fertig!"
|
||||
msgstr "Fertig"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Remove"
|
||||
msgstr "Entfernter Server"
|
||||
msgstr "Entfernen"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
msgstr "Zurücksetzen"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
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
|
||||
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
|
||||
msgid "Tap outside to deselect."
|
||||
msgstr ""
|
||||
msgstr "Außerhalb antippen zum Abwählen."
|
||||
|
||||
#: src/gui/touchscreenlayout.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"3D support.\n"
|
||||
"Currently supported:\n"
|
||||
|
@ -2595,9 +2588,7 @@ msgstr ""
|
|||
"zeilenbasierte Polarisation.\n"
|
||||
"- topbottom: Bildschirm horizontal teilen.\n"
|
||||
"- sidebyside: Bildschirm vertikal teilen.\n"
|
||||
"- crossview: Schieläugiges 3-D\n"
|
||||
"Beachten Sie, dass der „interlaced“-Modus erfordert, dass Shader aktiviert "
|
||||
"sind."
|
||||
"- crossview: Schieläugiges 3-D"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -2692,11 +2683,13 @@ msgid ""
|
|||
"All mesh buffers with less than this number of vertices will be merged\n"
|
||||
"during map rendering. This improves rendering performance."
|
||||
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
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Allows liquids to be translucent."
|
||||
|
@ -3107,7 +3100,7 @@ msgstr "Wolken im Menü"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Color depth for post-processing texture"
|
||||
msgstr ""
|
||||
msgstr "Farbtiefe für Nachbearbeitungstextur"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Colored fog"
|
||||
|
@ -3127,7 +3120,6 @@ msgstr ""
|
|||
"für Details."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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 "
|
||||
|
@ -3145,7 +3137,7 @@ msgstr ""
|
|||
"Sie können auch Inhaltseinstufungen festlegen.\n"
|
||||
"Diese Flags sind von Luanti-Versionen unabhängig,\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
|
||||
msgid ""
|
||||
|
@ -3316,6 +3308,11 @@ msgid ""
|
|||
"Reducing this can improve performance, but some effects (e.g. debanding)\n"
|
||||
"require more than 8 bits to work."
|
||||
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
|
||||
msgid "Dedicated server step"
|
||||
|
@ -3544,6 +3541,10 @@ msgid ""
|
|||
"situations\n"
|
||||
"where transparency sorting would be very slow otherwise."
|
||||
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
|
||||
msgid "Dump the mapgen debug information."
|
||||
|
@ -3628,14 +3629,12 @@ msgstr ""
|
|||
"Verhalten des menschlichen Auges simuliert."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable colored shadows for transculent nodes.\n"
|
||||
"This is expensive."
|
||||
msgstr ""
|
||||
"Aktiviert gefärbte Schatten. \n"
|
||||
"Falls aktiv, werden transluzente Blöcke gefärbte Schatten werfen. Dies ist "
|
||||
"rechenintensiv."
|
||||
"Aktiviert gefärbte Schatten für transluzente Blöcke.\n"
|
||||
"Dies ist rechenintensiv."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Enable console window"
|
||||
|
@ -3721,14 +3720,12 @@ msgstr ""
|
|||
"1.0 für den Standardwert, 2.0 für doppelte Geschwindigkeit."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable/disable running an IPv6 server.\n"
|
||||
"Ignored if bind_address is set."
|
||||
msgstr ""
|
||||
"Server als IPv6 laufen lassen (oder nicht).\n"
|
||||
"Wird ignoriert, falls bind_address gesetzt ist.\n"
|
||||
"Dafür muss außerdem enable_ipv6 aktiviert sein."
|
||||
"Wird ignoriert, falls bind_address gesetzt ist."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -4399,15 +4396,15 @@ msgstr ""
|
|||
"ihr Passwort zu ein leeres Passwort ändern."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"If enabled, server account registration is separate from login in the UI.\n"
|
||||
"If disabled, connecting to a server will automatically register a new "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Falls aktiviert, wird die Kontoregistrierung vom Einloggen in der "
|
||||
"Benutzeroberfläche getrennt behandelt.\n"
|
||||
"Falls deaktiviert, werden neue Konten beim Einloggen automatisch registriert."
|
||||
"Falls aktiviert, wird die Serverkontoregistrierung in der Benutzeroberfläche "
|
||||
"getrennt vom Einloggen behandelt.\n"
|
||||
"Falls deaktiviert, werden neue Konten beim Verbindungsaufbau zu einem Server "
|
||||
"automatisch registriert."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -5313,7 +5310,7 @@ msgstr "Untergrenze der zufälligen Anzahl kleiner Höhlen je Mapchunk."
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Minimum vertex count for mesh buffers"
|
||||
msgstr ""
|
||||
msgstr "Minimale Punktanzahl für Meshpuffer"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Mipmapping"
|
||||
|
@ -5409,16 +5406,15 @@ msgstr ""
|
|||
"- Die optionalen Schwebeländer von v7 (standardmäßig deaktiviert)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Name of the player.\n"
|
||||
"When running a server, a client connecting with this name is admin.\n"
|
||||
"When starting from the main menu, this is overridden."
|
||||
msgstr ""
|
||||
"Name des Spielers.\n"
|
||||
"Wenn ein Server gestartet wird, werden Clients mit diesem Namen zu "
|
||||
"Administratoren.\n"
|
||||
"Wird vom Hauptmenü aus gestartet, wird diese Einstellung überschrieben."
|
||||
"Wenn ein Server gestartet wird, wird ein Client mit diesem Namen zum "
|
||||
"Administrator.\n"
|
||||
"Wenn vom Hauptmenü aus gestartet, wird diese Einstellung überschrieben."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
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"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Select the antialiasing method to apply.\n"
|
||||
"\n"
|
||||
|
@ -5965,20 +5960,22 @@ msgstr ""
|
|||
"\n"
|
||||
"* None – Keine Kantenglättung (Standard)\n"
|
||||
"\n"
|
||||
"* FSAA – Von der Hardware bereitgestellte Vollbildkantenglättung (nicht\n"
|
||||
"kompatibel mit Nachbearbeitung und Unterabtastung), auch bekannt\n"
|
||||
"als Multi-Sample Antialiasing (MSAA). Glättet Blockkanten aus, "
|
||||
"beeinträchtigt\n"
|
||||
"aber nicht die Innenseiten der Texturen.\n"
|
||||
"Um diese Option zu ändern, ist ein Neustart erforderlich.\n"
|
||||
"* FSAA – Von der Hardware bereitgestellte Vollbildkantenglättung\n"
|
||||
"Auch bekannt als „Multi-Sample Antialiasing“ (MSAA)\n"
|
||||
"Glättet Blockkanten, aber hat keine Auswirkung auf das Innere von Texturen.\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 "
|
||||
"erkennen\n"
|
||||
"und zu glätten. Bietet eine Balance zwischen Geschwindigkeit und "
|
||||
"Bildqualität.\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"
|
||||
"die Aliasing-Effekte zu reduzieren. Dies ist die langsamste und genaueste "
|
||||
"Methode."
|
||||
|
@ -6419,7 +6416,6 @@ msgstr ""
|
|||
"(oder alle) Gegenstände setzen kann."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Spread a complete update of the shadow map over a given number of frames.\n"
|
||||
"Higher values might make shadows laggy, lower values\n"
|
||||
|
@ -6427,8 +6423,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Eine vollständige Aktualisierung der Schattenkarte über die angegebene\n"
|
||||
"Anzahl Frames verteilen. Höhere Werte können dazu führen, dass\n"
|
||||
"Schatten langsamer reagieren, niedrigere Werte sind rechenintensiver.\n"
|
||||
"Minimalwert: 1; Maximalwert: 16"
|
||||
"Schatten langsamer reagieren, niedrigere Werte sind rechenintensiver."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6876,9 +6871,8 @@ msgid "Transparency Sorting Distance"
|
|||
msgstr "Transparenzsortierungsdistanz"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid "Transparency Sorting Group by Buffers"
|
||||
msgstr "Transparenzsortierungsdistanz"
|
||||
msgstr "Transparenzsortierung nach Puffer gruppieren"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Trees noise"
|
||||
|
@ -6942,7 +6936,6 @@ msgid "Undersampling"
|
|||
msgstr "Unterabtastung"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Undersampling is similar to using a lower screen resolution, but it applies\n"
|
||||
"to the game world only, keeping the GUI intact.\n"
|
||||
|
@ -6954,11 +6947,14 @@ msgid ""
|
|||
"to a non-default value."
|
||||
msgstr ""
|
||||
"Unterabtastung ist ähnlich der Verwendung einer niedrigeren "
|
||||
"Bildschirmauflösung, aber sie wird nur auf die Spielwelt angewandt, während "
|
||||
"die GUI intakt bleibt.\n"
|
||||
"Bildschirmauflösung,\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 "
|
||||
"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
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Use anisotropic filtering when looking at textures from an angle.\n"
|
||||
"This provides a significant improvement when used together with mipmapping."
|
||||
msgstr ""
|
||||
"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
|
||||
msgid "Use bilinear filtering when scaling textures."
|
||||
|
@ -7268,7 +7265,6 @@ msgstr ""
|
|||
"die Inventarbilder von Blöcken)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"When using bilinear/trilinear filtering, low-resolution textures\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"
|
||||
"texture autoscaling."
|
||||
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"
|
||||
"mit Pixelwiederholung vergrößert, um scharfe Pixel zu behalten. Dies setzt "
|
||||
"die\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"
|
||||
"werden empfohlen. Diese Einstellung trifft NUR dann in Kraft, falls\n"
|
||||
"der bilineare/trilineare/anisotrope Filter aktiviert ist.\n"
|
||||
"zu einem schärferen Aussehen, aber erfordern mehr Speicher.\n"
|
||||
"Diese Einstellung trifft NUR dann in Kraft, falls\n"
|
||||
"einer der genannten Filter aktiviert ist.\n"
|
||||
"Dies wird außerdem verwendet als die Basisblocktexturengröße für\n"
|
||||
"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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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"
|
||||
"pause menu."
|
||||
msgstr ""
|
||||
"Ob die Töne stummgeschaltet werden. Man kann die Töne jederzeit "
|
||||
"stummschalten,\n"
|
||||
"außer, wenn das Tonsystem ausgeschaltet wurde (enable_sound=false).\n"
|
||||
"stummschalten.\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
|
||||
msgid ""
|
||||
|
|
192
po/es/luanti.po
192
po/es/luanti.po
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: Spanish (Minetest)\n"
|
||||
"Report-Msgid-Bugs-To: \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"
|
||||
"Language-Team: Spanish <https://hosted.weblate.org/projects/minetest/"
|
||||
"minetest/es/>\n"
|
||||
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\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
|
||||
msgid "Clear the out chat queue"
|
||||
|
@ -263,14 +263,12 @@ msgid "Show technical names"
|
|||
msgstr "Mostrar los nombres técnicos"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Pantalla táctil"
|
||||
msgstr "Diseño de pantalla táctil"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "pause_menu"
|
||||
msgstr "FPS (cuadros/s) en el menú de pausa"
|
||||
msgstr "pause_menu"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -610,6 +608,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Esta es la lista de clientes conectados a\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
@ -974,21 +974,20 @@ msgstr ""
|
|||
"cual sobreescribirá cualquier renombrado desde aquí."
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
#, fuzzy
|
||||
msgid "Expand all"
|
||||
msgstr "Activar todos"
|
||||
msgstr "Expandir todo"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "Group by prefix"
|
||||
msgstr ""
|
||||
msgstr "Grupo por prefijo"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
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
|
||||
msgid "The $1 server uses the following mods:"
|
||||
msgstr ""
|
||||
msgstr "El servidor $1 usa los siguientes mods:"
|
||||
|
||||
#: builtin/mainmenu/dlg_version_info.lua
|
||||
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."
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Add favorite"
|
||||
msgstr "Eliminar el favorito"
|
||||
msgstr "Añadir a favorito"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Address"
|
||||
msgstr "Dirección"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
msgstr "Cliente"
|
||||
msgstr ""
|
||||
"Clientes:\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Creative mode"
|
||||
|
@ -1230,9 +1229,8 @@ msgid "Favorites"
|
|||
msgstr "Favoritos"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Game: $1"
|
||||
msgstr "Juego"
|
||||
msgstr "Juego: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Incompatible Servers"
|
||||
|
@ -1247,26 +1245,29 @@ msgid "Login"
|
|||
msgstr "Iniciar sesión"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Number of mods: $1"
|
||||
msgstr "Número de hilos emergentes"
|
||||
msgstr "Número de mods: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Open server website"
|
||||
msgstr "Intervalo de servidor dedicado"
|
||||
msgstr "Abrir sitio web del servidor"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Ping"
|
||||
msgstr "Ping"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Possible filters\n"
|
||||
"game:<name>\n"
|
||||
"mod:<name>\n"
|
||||
"player:<name>"
|
||||
msgstr ""
|
||||
"Posibles filtros\n"
|
||||
"game:<nombre>\n"
|
||||
"mod:<nombre>\n"
|
||||
"player:<nombre>"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Public Servers"
|
||||
|
@ -1274,7 +1275,7 @@ msgstr "Servidores Públicos"
|
|||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Refresh"
|
||||
msgstr "Actualizar"
|
||||
msgstr "Refrescar"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Remove favorite"
|
||||
|
@ -1364,9 +1365,8 @@ msgid "Access denied. Reason: %s"
|
|||
msgstr "Acceso denegado. Razón: %s"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "All debug info hidden"
|
||||
msgstr "Info de depuración mostrada"
|
||||
msgstr "Toda la información de depuración oculta"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Automatic forward disabled"
|
||||
|
@ -1390,7 +1390,7 @@ msgstr "Límites de bloque mostrados para bloques cercanos"
|
|||
|
||||
#: src/client/game.cpp
|
||||
msgid "Bounding boxes shown"
|
||||
msgstr ""
|
||||
msgstr "Cajas delimitadoras mostradas"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Camera update disabled"
|
||||
|
@ -1633,9 +1633,8 @@ msgid "Volume changed to %d%%"
|
|||
msgstr "Volumen cambiado a %d%%"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Wireframe shown"
|
||||
|
@ -2068,9 +2067,8 @@ msgid "Failed to compile the \"%s\" shader."
|
|||
msgstr "Fallo al compilar el shader \"%s\"."
|
||||
|
||||
#: src/client/shader.cpp
|
||||
#, fuzzy
|
||||
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"
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2235,11 +2233,11 @@ msgstr "Alternar el registro del chat"
|
|||
|
||||
#: src/gui/guiKeyChangeMenu.cpp src/gui/touchscreenlayout.cpp
|
||||
msgid "Toggle fast"
|
||||
msgstr "Activar rápido"
|
||||
msgstr "Alternar rápido"
|
||||
|
||||
#: src/gui/guiKeyChangeMenu.cpp src/gui/touchscreenlayout.cpp
|
||||
msgid "Toggle fly"
|
||||
msgstr "Activar volar"
|
||||
msgstr "Alternar volar"
|
||||
|
||||
#: src/gui/guiKeyChangeMenu.cpp
|
||||
msgid "Toggle fog"
|
||||
|
@ -2307,35 +2305,33 @@ msgid "Sound Volume: %d%%"
|
|||
msgstr "Volumen del sonido: %d%%"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Add button"
|
||||
msgstr "Botón central"
|
||||
msgstr "Agregar botón"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Done"
|
||||
msgstr "¡Completado!"
|
||||
msgstr "Hecho"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Remove"
|
||||
msgstr "Servidor remoto"
|
||||
msgstr "Eliminar"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
msgstr "Reiniciar"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Start dragging a button to add. Tap outside to cancel."
|
||||
msgstr ""
|
||||
"Comienza arrastrando un botón para agregarlo. Toca afuera para cancelar."
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
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
|
||||
msgid "Tap outside to deselect."
|
||||
msgstr ""
|
||||
msgstr "Toca afuera para anular la selección."
|
||||
|
||||
#: src/gui/touchscreenlayout.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"3D support.\n"
|
||||
"Currently supported:\n"
|
||||
|
@ -2588,14 +2583,13 @@ msgid ""
|
|||
msgstr ""
|
||||
"Soporte 3D.\n"
|
||||
"Soportado actualmente:\n"
|
||||
"- Ninguno (none): sin salida 3D.\n"
|
||||
"- Anaglifo (anaglyph): 3D en colores cían y magenta.\n"
|
||||
"- Entrelazado (interlaced): soporte para pantallas con polarización "
|
||||
"basada en filas impar/par.\n"
|
||||
"- Arriba-abajo (topbottom): dividir pantalla arriba y abajo.\n"
|
||||
"- Lado a lado (sidebyside): dividir pantalla lado a lado.\n"
|
||||
"- Vista cruzada (crossview): visión 3D cruzada.\n"
|
||||
"Nota: el modo entrelazado requiere que los sombreadores estén activados."
|
||||
"- Ninguno: sin salida 3D.\n"
|
||||
"- Anaglifo: 3D en colores cían y magenta.\n"
|
||||
"- Entrelazado: soporte para pantallas con polarización basada en filas "
|
||||
"impar/par.\n"
|
||||
"- Arriba-abajo: dividir pantalla arriba y abajo.\n"
|
||||
"- Lado a lado: dividir pantalla lado a lado.\n"
|
||||
"- Vista cruzada: visión 3D cruzada"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -2687,11 +2681,14 @@ msgid ""
|
|||
"All mesh buffers with less than this number of vertices will be merged\n"
|
||||
"during map rendering. This improves rendering performance."
|
||||
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
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Allows liquids to be translucent."
|
||||
|
@ -3105,7 +3102,7 @@ msgstr "Nubes en el menú"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Color depth for post-processing texture"
|
||||
msgstr ""
|
||||
msgstr "Profundidad de color para la textura post-procesamiento"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Colored fog"
|
||||
|
@ -3125,7 +3122,6 @@ msgstr ""
|
|||
"Útil para pruebas. Ver al_extensions.[h,cpp] para más detalles."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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 "
|
||||
|
@ -3142,7 +3138,7 @@ msgstr ""
|
|||
"según lo definido por la Free Software Foundation.\n"
|
||||
"También puedes especificar clasificaciones de contenido.\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/"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -3313,6 +3309,11 @@ msgid ""
|
|||
"Reducing this can improve performance, but some effects (e.g. debanding)\n"
|
||||
"require more than 8 bits to work."
|
||||
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
|
||||
msgid "Dedicated server step"
|
||||
|
@ -3537,6 +3538,11 @@ msgid ""
|
|||
"situations\n"
|
||||
"where transparency sorting would be very slow otherwise."
|
||||
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
|
||||
msgid "Dump the mapgen debug information."
|
||||
|
@ -3621,14 +3627,12 @@ msgstr ""
|
|||
"el comportamiento del ojo humano."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable colored shadows for transculent nodes.\n"
|
||||
"This is expensive."
|
||||
msgstr ""
|
||||
"Habilitar las sombras coloreadas.\n"
|
||||
"Si el valor es verdadero los nodos traslúcidos proyectarán sombras "
|
||||
"coloreadas. Esta opción usa muchos recursos."
|
||||
"Habilita las sombras de colores para nodos translúcidos.\n"
|
||||
"Esto es costoso."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Enable console window"
|
||||
|
@ -3712,14 +3716,12 @@ msgstr ""
|
|||
"Por ejemplo: 0 para balanceo sin vista; 1.0 para normal; 2.0 para doble."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable/disable running an IPv6 server.\n"
|
||||
"Ignored if bind_address is set."
|
||||
msgstr ""
|
||||
"Habilita/deshabilita la ejecución de un servidor IPv6.\n"
|
||||
"Ignorado si se establece bind_address.\n"
|
||||
"Necesita habilitar enable_ipv6 para ser activado."
|
||||
"Activa/desactiva la ejecución de un servidor IPv6.\n"
|
||||
"Se ignora si bind_address está establecido."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -3749,7 +3751,7 @@ msgstr "Activar el desplazamiento suave."
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
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
|
||||
msgid ""
|
||||
|
@ -4384,7 +4386,6 @@ msgstr ""
|
|||
"la suya por una contraseña vacía."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"If enabled, server account registration is separate from login in the UI.\n"
|
||||
"If disabled, connecting to a server will automatically register a new "
|
||||
|
@ -4392,8 +4393,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Si está activado, el registro de la cuenta es independiente del inicio de "
|
||||
"sesión en la interfaz de usuario.\n"
|
||||
"Si está deshabilitado, las cuentas nuevas se registrarán automáticamente al "
|
||||
"iniciar sesión."
|
||||
"Si está desactivado, la conexión a un servidor registrará automáticamente "
|
||||
"una nueva cuenta."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -5298,7 +5299,7 @@ msgstr ""
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Minimum vertex count for mesh buffers"
|
||||
msgstr ""
|
||||
msgstr "Recuento mínimo de vértices para buffers de malla"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Mipmapping"
|
||||
|
@ -5393,15 +5394,14 @@ msgstr ""
|
|||
"- Las islas flotantes opcionales de v7 (desactivadas por defecto)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Name of the player.\n"
|
||||
"When running a server, a client connecting with this name is admin.\n"
|
||||
"When starting from the main menu, this is overridden."
|
||||
msgstr ""
|
||||
"Nombre del jugador.\n"
|
||||
"Cuando se ejecuta un servidor, los clientes que se conecten con este nombre "
|
||||
"son administradores.\n"
|
||||
"Al ejecutar un servidor, el cliente que se conecta con este nombre es "
|
||||
"administrador.\n"
|
||||
"Al comenzar desde el menú principal, esto se anula."
|
||||
|
||||
#: 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"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Select the antialiasing method to apply.\n"
|
||||
"\n"
|
||||
|
@ -5950,26 +5949,28 @@ msgid ""
|
|||
"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."
|
||||
msgstr ""
|
||||
"Seleccione el método de antialiasing a aplicar.\n"
|
||||
"Seleccione el método de suavizado a aplicar.\n"
|
||||
"\n"
|
||||
"* Ninguno - Sin antialiasing (por defecto)\n"
|
||||
"* Ninguno - Sin suavizado (por defecto)\n"
|
||||
"\n"
|
||||
"* FSAA - Antialiasing de pantalla completa por hardware\n"
|
||||
"(incompatible con Postprocesado y Submuestreo)\n"
|
||||
"También conocido como antialiasing multimuestra (MSAA)\n"
|
||||
"Suaviza los bordes de los bloques pero no afecta al interior de las "
|
||||
"texturas.\n"
|
||||
"Es necesario reiniciar para cambiar esta opción.\n"
|
||||
"* FSAA - Suavizado de pantalla completa por hardware\n"
|
||||
"También conocido como suavizado multimuestra (MSAA)\n"
|
||||
"Suaviza los bordes de los bloques pero no afecta al interior de las texturas."
|
||||
"\n"
|
||||
"* FXAA - Antialiasing rápido aproximado (requiere shaders)\n"
|
||||
"Aplica un filtro de postprocesado para detectar y suavizar los bordes de "
|
||||
"\n"
|
||||
"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"
|
||||
"Proporciona un equilibrio entre velocidad y calidad de imagen.\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, "
|
||||
"reduce la escala para reducir los efectos de aliasing.\n"
|
||||
"los efectos del aliasing. Es el método más lento y preciso."
|
||||
"reduce la escala para reducir\n"
|
||||
"los efectos de distorsión. Es el método más lento y preciso."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Selection box border color (R,G,B)."
|
||||
|
@ -6410,7 +6411,6 @@ msgstr ""
|
|||
"pila para ciertos ítems (o para todos)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Spread a complete update of the shadow map over a given number of frames.\n"
|
||||
"Higher values might make shadows laggy, lower values\n"
|
||||
|
@ -6420,8 +6420,7 @@ msgstr ""
|
|||
"determinado de fotogramas.\n"
|
||||
"Los valores más altos pueden hacer que las sombras se retrasen, los valores "
|
||||
"más bajos\n"
|
||||
"consumirán más recursos.\n"
|
||||
"Valor mínimo: 1; valor máximo: 16"
|
||||
"consumirán más recursos."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6872,9 +6871,8 @@ msgid "Transparency Sorting Distance"
|
|||
msgstr "Distancia de Clasificación de Transparencia"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Use anisotropic filtering when looking at textures from an angle.\n"
|
||||
"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
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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"
|
||||
"pause menu."
|
||||
msgstr ""
|
||||
"Si deseas silenciar los sonidos. Puedes activar el sonido en cualquier "
|
||||
"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 silencio "
|
||||
"o\n"
|
||||
"usando el menú de pausa."
|
||||
"momento.\n"
|
||||
"En el juego, puedes alternar el estado de silencio con la tecla de silenciar "
|
||||
"o usando el\n"
|
||||
"menú de pausa."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
|
255
po/fr/luanti.po
255
po/fr/luanti.po
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: French (Minetest)\n"
|
||||
"Report-Msgid-Bugs-To: \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"
|
||||
"Language-Team: French <https://hosted.weblate.org/projects/minetest/minetest/"
|
||||
"fr/>\n"
|
||||
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\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
|
||||
msgid "Clear the out chat queue"
|
||||
|
@ -263,14 +263,12 @@ msgid "Show technical names"
|
|||
msgstr "Montrer les noms techniques"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Écran tactile"
|
||||
msgstr "Disposition de l'écran tactile"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "pause_menu"
|
||||
msgstr "FPS maximum sur le menu pause"
|
||||
msgstr "pause_menu"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -319,7 +317,7 @@ msgstr "Très basses"
|
|||
|
||||
#: builtin/fstk/ui.lua
|
||||
msgid "<none available>"
|
||||
msgstr "< aucun disponible >"
|
||||
msgstr "<non disponible>"
|
||||
|
||||
#: builtin/fstk/ui.lua
|
||||
msgid "An error occurred in a Lua script:"
|
||||
|
@ -610,6 +608,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Voici la liste des clients connectés à\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
@ -977,21 +977,20 @@ msgstr ""
|
|||
"remplace tout renommage effectué ici."
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
#, fuzzy
|
||||
msgid "Expand all"
|
||||
msgstr "Tout activer"
|
||||
msgstr "Tout développer"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "Group by prefix"
|
||||
msgstr ""
|
||||
msgstr "Grouper par préfixe"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
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
|
||||
msgid "The $1 server uses the following mods:"
|
||||
msgstr ""
|
||||
msgstr "Le serveur $1 utilise les mods suivants :"
|
||||
|
||||
#: builtin/mainmenu/dlg_version_info.lua
|
||||
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."
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Add favorite"
|
||||
msgstr "Supprimer le favori"
|
||||
msgstr "Ajouter aux favoris"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
msgstr "Client"
|
||||
msgstr ""
|
||||
"Clients : \n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Creative mode"
|
||||
|
@ -1234,9 +1233,8 @@ msgid "Favorites"
|
|||
msgstr "Favoris"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Game: $1"
|
||||
msgstr "Jeu"
|
||||
msgstr "Jeu : $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Incompatible Servers"
|
||||
|
@ -1251,14 +1249,12 @@ msgid "Login"
|
|||
msgstr "Connexion"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Number of mods: $1"
|
||||
msgstr "Nombre de fils émergents"
|
||||
msgstr "Nombre de mods : $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Ping"
|
||||
|
@ -1271,6 +1267,10 @@ msgid ""
|
|||
"mod:<name>\n"
|
||||
"player:<name>"
|
||||
msgstr ""
|
||||
"Filtres possibles :\n"
|
||||
"game:<nom>\n"
|
||||
"mod:<nom>\n"
|
||||
"player:<nom>"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Public Servers"
|
||||
|
@ -1366,9 +1366,8 @@ msgid "Access denied. Reason: %s"
|
|||
msgstr "Accès refusé. Raison : %s"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "All debug info hidden"
|
||||
msgstr "Informations de débogage affichées"
|
||||
msgstr "Informations de débogage cachées"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Automatic forward disabled"
|
||||
|
@ -1392,7 +1391,7 @@ msgstr "Limites des blocs affichées pour les blocs voisins"
|
|||
|
||||
#: src/client/game.cpp
|
||||
msgid "Bounding boxes shown"
|
||||
msgstr ""
|
||||
msgstr "Limites des boîtes affichées"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Camera update disabled"
|
||||
|
@ -1635,10 +1634,8 @@ msgid "Volume changed to %d%%"
|
|||
msgstr "Volume réglé sur %d %%"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "Wireframe not supported by video driver"
|
||||
msgstr ""
|
||||
"Les nuanceurs sont activés mais GLSL n'est pas pris en charge par le pilote."
|
||||
msgstr "Fils de fer non pris en charge par le pilote vidéo"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Wireframe shown"
|
||||
|
@ -2068,10 +2065,8 @@ msgid "Failed to compile the \"%s\" shader."
|
|||
msgstr "Échec de la compilation du nuanceur « %s »."
|
||||
|
||||
#: src/client/shader.cpp
|
||||
#, fuzzy
|
||||
msgid "GLSL is not supported by the driver"
|
||||
msgstr ""
|
||||
"Les nuanceurs sont activés mais GLSL n'est pas pris en charge par le pilote."
|
||||
msgstr "GLSL n'est pas pris en charge par le pilote vidéo"
|
||||
|
||||
#. ~ Error when a mod is missing dependencies. Ex: "Mod Title is missing: mod1, mod2, mod3"
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2091,7 +2086,7 @@ msgid ""
|
|||
"Note: this may be caused by a dependency cycle, in which case try updating "
|
||||
"the mods."
|
||||
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."
|
||||
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2308,35 +2303,35 @@ msgid "Sound Volume: %d%%"
|
|||
msgstr "Volume du son : %d %%"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Add button"
|
||||
msgstr "Clic central"
|
||||
msgstr "Ajouter un bouton"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Done"
|
||||
msgstr "Terminé !"
|
||||
msgstr "Terminé"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Remove"
|
||||
msgstr "Serveur distant"
|
||||
msgstr "Supprimer"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
msgstr "Réinitialiser"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Start dragging a button to add. Tap outside to cancel."
|
||||
msgstr ""
|
||||
"Faire glisser un bouton pour ajouter. Appuyer à l'extérieur pour annuler."
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Tap a button to select it. Drag a button to move it."
|
||||
msgstr ""
|
||||
"Appuyer sur un bouton pour le sélectionner. Faire glisser un bouton pour le "
|
||||
"déplacer."
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Tap outside to deselect."
|
||||
msgstr ""
|
||||
msgstr "Appuyer à l'extérieur pour désélectionner."
|
||||
|
||||
#: src/gui/touchscreenlayout.cpp
|
||||
msgid "Joystick"
|
||||
|
@ -2524,7 +2519,7 @@ msgstr "Nuages 3D"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "3D mode"
|
||||
msgstr "Mode écran 3D"
|
||||
msgstr "Mode 3D"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"3D support.\n"
|
||||
"Currently supported:\n"
|
||||
|
@ -2592,8 +2586,7 @@ msgstr ""
|
|||
"lignes paires/impaires.\n"
|
||||
"– haut-bas : partage haut et bas 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"
|
||||
"Noter que le mode entrelacé nécessite que les nuanceurs soient activés."
|
||||
"– vision croisée : vision croisée 3D."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -2683,11 +2676,13 @@ msgid ""
|
|||
"All mesh buffers with less than this number of vertices will be merged\n"
|
||||
"during map rendering. This improves rendering performance."
|
||||
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
|
||||
#, fuzzy
|
||||
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
|
||||
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 "
|
||||
"plus lumineux.\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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -2777,7 +2772,7 @@ msgstr ""
|
|||
"effectue un tramage supplémentaire ou si les canaux de couleur ne sont pas "
|
||||
"quantifiés à 8 bits.\n"
|
||||
"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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -2836,8 +2831,8 @@ msgstr ""
|
|||
"Des valeurs plus faibles peuvent augmenter la performance du serveur, mais "
|
||||
"peut provoquer l'apparition de problèmes de rendu (certains blocs ne sont "
|
||||
"pas visibles).\n"
|
||||
"Ceci est particulièrement utile pour les très grandes distances de vue (plus "
|
||||
"de 500).\n"
|
||||
"C'est particulièrement utile pour les très grandes distances de vue (plus de "
|
||||
"500).\n"
|
||||
"Établie en blocs de carte (16 nœuds)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -3099,7 +3094,7 @@ msgstr "Nuages dans le menu"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Color depth for post-processing texture"
|
||||
msgstr ""
|
||||
msgstr "Profondeur de couleur pour la texture de post-traitement"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Colored fog"
|
||||
|
@ -3119,7 +3114,6 @@ msgstr ""
|
|||
"Utile pour les tests. Voir « al_extensions.[h, cpp] » pour plus de détails."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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 "
|
||||
|
@ -3272,7 +3266,7 @@ msgid ""
|
|||
"This also applies to the object crosshair."
|
||||
msgstr ""
|
||||
"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
|
||||
msgid "Crosshair color"
|
||||
|
@ -3284,7 +3278,7 @@ msgid ""
|
|||
"Also controls the object crosshair color"
|
||||
msgstr ""
|
||||
"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
|
||||
msgid "Debug log file size threshold"
|
||||
|
@ -3305,6 +3299,10 @@ msgid ""
|
|||
"Reducing this can improve performance, but some effects (e.g. debanding)\n"
|
||||
"require more than 8 bits to work."
|
||||
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
|
||||
msgid "Dedicated server step"
|
||||
|
@ -3345,8 +3343,8 @@ msgid ""
|
|||
"but also uses more resources."
|
||||
msgstr ""
|
||||
"Définir la qualité du filtrage des ombres.\n"
|
||||
"Ceci simule l'effet d'ombres douces en appliquant un disque PCF ou Poisson "
|
||||
"mais utilise également plus de ressources."
|
||||
"Cela simule l'effet d'ombres douces en appliquant le PCF ou le disque de "
|
||||
"Poisson mais utilise également plus de ressources."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -3364,10 +3362,10 @@ msgstr ""
|
|||
"Les anciens clients sont compatibles dans le sens où ils ne plantent pas "
|
||||
"lors de la connexion aux serveurs récents,\n"
|
||||
"mais ils peuvent ne pas prendre en charge certaines fonctionnalités.\n"
|
||||
"Ceci permet un contrôle plus précis que "
|
||||
"« strict_protocol_version_checking ».\n"
|
||||
"Luanti applique toujours son propre minimum interne, activer "
|
||||
"« strict_protocol_version_checking » le remplace."
|
||||
"Cela permet un contrôle plus précis que « strict_protocol_version_checking »."
|
||||
"\n"
|
||||
"Luanti applique toujours son propre minimum interne, activer « "
|
||||
"strict_protocol_version_checking » le remplace."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Defines areas where trees have apples."
|
||||
|
@ -3441,7 +3439,7 @@ msgid ""
|
|||
"down the rate of mesh updates, thus reducing jitter on slower clients."
|
||||
msgstr ""
|
||||
"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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -3528,6 +3526,10 @@ msgid ""
|
|||
"situations\n"
|
||||
"where transparency sorting would be very slow otherwise."
|
||||
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
|
||||
msgid "Dump the mapgen debug information."
|
||||
|
@ -3589,7 +3591,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Activer le filtrage par disque de Poisson.\n"
|
||||
"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
|
||||
msgid "Enable Post Processing"
|
||||
|
@ -3597,7 +3599,7 @@ msgstr "Activer le post-traitement"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
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
|
||||
msgid ""
|
||||
|
@ -3613,14 +3615,12 @@ msgstr ""
|
|||
"simulant le comportement de l’œil humain."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable colored shadows for transculent nodes.\n"
|
||||
"This is expensive."
|
||||
msgstr ""
|
||||
"Activer les ombres colorées.\n"
|
||||
"Sur les nœuds vraiment transparents, projette des ombres colorées. Ceci est "
|
||||
"coûteux."
|
||||
"Activer les ombres colorées pour les nœuds translucides.\n"
|
||||
"Cela utilise beaucoup de ressources."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Enable console window"
|
||||
|
@ -3707,14 +3707,12 @@ msgstr ""
|
|||
"double."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable/disable running an IPv6 server.\n"
|
||||
"Ignored if bind_address is set."
|
||||
msgstr ""
|
||||
"Activer/désactiver l'usage d'un serveur IPv6.\n"
|
||||
"Ignoré si « bind_address » est activé.\n"
|
||||
"A besoin de « enable_ipv6 » pour être activé."
|
||||
"Ignoré si « bind_address » est activé."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -3978,7 +3976,7 @@ msgid ""
|
|||
"be\n"
|
||||
"sized 16, 32, 48, etc., so a mod requesting a size of 25 will get 32."
|
||||
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 "
|
||||
"divisibles par cette valeur, en pixels.\n"
|
||||
"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, "
|
||||
"établie en blocs de carte (16 nœuds).\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 "
|
||||
"joueur regarde (cela peut éviter que des mobs disparaissent soudainement de "
|
||||
"la vue)."
|
||||
|
@ -4288,7 +4286,7 @@ msgid ""
|
|||
"Decrease this to increase liquid resistance to movement."
|
||||
msgstr ""
|
||||
"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
|
||||
msgid "How wide to make rivers."
|
||||
|
@ -4376,16 +4374,15 @@ msgstr ""
|
|||
"de le remplacer par un mot de passe vide."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"If enabled, server account registration is separate from login in the UI.\n"
|
||||
"If disabled, connecting to a server will automatically register a new "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Si activé, l'enregistrement du compte est séparé de la connexion dans "
|
||||
"l'interface utilisateur.\n"
|
||||
"Si désactivé, les nouveaux comptes sont enregistrés automatiquement lors de "
|
||||
"la connexion."
|
||||
"Si activé, l'enregistrement du compte sur le serveur est séparé de la "
|
||||
"connexion dans l'interface utilisateur.\n"
|
||||
"Si désactivé, la connexion à un serveur entraîne automatiquement "
|
||||
"l'enregistrement d'un nouveau compte."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -4396,7 +4393,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Si activé, le serveur effectue la détermination des blocs de carte "
|
||||
"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 "
|
||||
"l'utilité du mode sans collisions est réduite."
|
||||
|
||||
|
@ -4473,7 +4470,7 @@ msgid ""
|
|||
"This is usually only needed by core/builtin contributors"
|
||||
msgstr ""
|
||||
"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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -4752,7 +4749,7 @@ msgid ""
|
|||
"- trace"
|
||||
msgstr ""
|
||||
"Niveau de journalisation à écrire dans « debug.txt » :\n"
|
||||
"– < rien > (pas de journalisation)\n"
|
||||
"– <vide> (pas de journalisation)\n"
|
||||
"– aucun (messages sans niveau)\n"
|
||||
"– erreur\n"
|
||||
"– avertissement\n"
|
||||
|
@ -5282,7 +5279,7 @@ msgstr ""
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Minimum vertex count for mesh buffers"
|
||||
msgstr ""
|
||||
msgstr "Nombre minimal de sommets pour les tampons de maillage"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Mipmapping"
|
||||
|
@ -5378,15 +5375,14 @@ msgstr ""
|
|||
"– les terrains flottants optionnels du générateur v7 (désactivé par défaut)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Name of the player.\n"
|
||||
"When running a server, a client connecting with this name is admin.\n"
|
||||
"When starting from the main menu, this is overridden."
|
||||
msgstr ""
|
||||
"Nom du joueur.\n"
|
||||
"Lorsqu'un serveur est lancé, les clients se connectant avec ce nom sont "
|
||||
"administrateurs.\n"
|
||||
"Lorsqu'un serveur est lancé, le client se connectant avec ce nom est "
|
||||
"administrateur.\n"
|
||||
"Lors du démarrage à partir du menu principal, celui-ci est remplacé."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -5614,7 +5610,7 @@ msgstr ""
|
|||
"des boutons de la souris.\n"
|
||||
"Activer cette option lorsque vous creusez ou placez trop souvent par "
|
||||
"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
|
||||
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."
|
||||
msgstr ""
|
||||
"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 "
|
||||
"anticrénelage.\n"
|
||||
"Ceci lisse certains bords grossiers, et mélange les pixels en réduisant "
|
||||
"l'utilisateur, à l'aide d'un filtre au plus proche voisin avec anticrénelage."
|
||||
"\n"
|
||||
"Cela lisse certains bords grossiers, et mélange les pixels en réduisant "
|
||||
"l'échelle.\n"
|
||||
"Au détriment d'un effet de flou sur des pixels en bordure quand les images "
|
||||
"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"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Select the antialiasing method to apply.\n"
|
||||
"\n"
|
||||
|
@ -5938,17 +5933,22 @@ msgstr ""
|
|||
"\n"
|
||||
"* Aucun – Pas d'anticrénelage (par défaut)\n"
|
||||
"\n"
|
||||
"* FSAA – Anticrénelage de la scène complète (incompatible avec « Post-"
|
||||
"traitement » et « Sous-échantillonnage »)\n"
|
||||
"* FSAA – Anticrénelage matériel de la scène complète\n"
|
||||
"Alias anticrénelage multi-échantillon (MSAA), lisse les bords des blocs mais "
|
||||
"n'affecte pas l'intérieur des textures.\n"
|
||||
"Un redémarrage est nécessaire pour modifier cette option.\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 à "
|
||||
"contraste élevé, fournit un équilibre entre vitesse et qualité d'image.\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 "
|
||||
"diminuer le crénelage. C'est la méthode la plus lente et la plus précise."
|
||||
|
||||
|
@ -6187,7 +6187,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"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"
|
||||
"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
|
||||
msgid "Shader path"
|
||||
|
@ -6389,7 +6389,6 @@ msgstr ""
|
|||
"certains (ou tous) objets."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Spread a complete update of the shadow map over a given number of frames.\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é "
|
||||
"d'images.\n"
|
||||
"Des valeurs plus élevées peuvent rendre les ombres plus lentes, des valeurs "
|
||||
"plus faibles consomment plus de ressources.\n"
|
||||
"Valeur minimale : 1 ; valeur maximale : 16"
|
||||
"plus faibles consomment plus de ressources."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6666,11 +6664,11 @@ msgid ""
|
|||
msgstr ""
|
||||
"Le rayon du volume de blocs autour de chaque joueur soumis au bloc actif, "
|
||||
"établi en blocs de carte (16 nœuds).\n"
|
||||
"Dans les blocs actifs, les objets sont chargés et les « ABMs » sont "
|
||||
"exécutés.\n"
|
||||
"Dans les blocs actifs, les objets sont chargés et les « ABMs » sont exécutés."
|
||||
"\n"
|
||||
"C'est également la distance minimale dans laquelle les objets actifs (mobs) "
|
||||
"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
|
||||
msgid ""
|
||||
|
@ -6701,7 +6699,7 @@ msgstr ""
|
|||
"Intensité (obscurité) de l'ombrage des blocs avec l'occlusion ambiante.\n"
|
||||
"Les valeurs plus faibles sont plus sombres, les valeurs plus hautes sont "
|
||||
"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 "
|
||||
"proche des valeurs valides."
|
||||
|
||||
|
@ -6798,7 +6796,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Pour réduire le décalage, le transfert des blocs est ralenti quand un joueur "
|
||||
"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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -6843,12 +6841,11 @@ msgstr "Liquides translucides"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Transparency Sorting Distance"
|
||||
msgstr "Distance de tri de la transparence"
|
||||
msgstr "Tri de la transparence par distance"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Trees noise"
|
||||
|
@ -6912,7 +6909,6 @@ msgid "Undersampling"
|
|||
msgstr "Sous-échantillonnage"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Undersampling is similar to using a lower screen resolution, but it applies\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 "
|
||||
"inférieure.\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"
|
||||
"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
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Use anisotropic filtering when looking at textures from an angle.\n"
|
||||
"This provides a significant improvement when used together with mipmapping."
|
||||
msgstr ""
|
||||
"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
|
||||
msgid "Use bilinear filtering when scaling textures."
|
||||
|
@ -6998,10 +6998,10 @@ msgid ""
|
|||
"This flag enables use of raytraced occlusion culling test for\n"
|
||||
"client mesh sizes smaller than 4x4x4 map blocks."
|
||||
msgstr ""
|
||||
"Utiliser l'élimination des blocs invisibles par Ray Tracing avec le nouvel "
|
||||
"algorithme.\n"
|
||||
"Utiliser l'élimination des blocs invisibles par lancer de rayons avec le "
|
||||
"nouvel algorithme.\n"
|
||||
"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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -7237,7 +7237,6 @@ msgstr ""
|
|||
"directement par le matériel (ex. : textures des blocs dans l'inventaire)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"When using bilinear/trilinear filtering, low-resolution textures\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"
|
||||
"texture autoscaling."
|
||||
msgstr ""
|
||||
"En utilisant le filtrage bilinéaire/trilinéaire/anisotrope, les textures de "
|
||||
"basse résolution peuvent être floues.\n"
|
||||
"Elles sont donc agrandies avec l'interpolation au plus proche voisin pour "
|
||||
"préserver des pixels nets.\n"
|
||||
"Ceci détermine la taille minimale pour les textures agrandies ;\n"
|
||||
"En utilisant le filtrage bilinéaire/trilinéaire, les textures de basse "
|
||||
"résolution peuvent être floues.\n"
|
||||
"Cette option les agrandies automatiquement afin de préserver des pixels nets."
|
||||
"\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 "
|
||||
"mémoire. Les puissances de 2 sont recommandées.\n"
|
||||
"Ce paramètre est appliqué seulement si le filtrage bilinéaire/trilinéaire/"
|
||||
"anisotrope est activé.\n"
|
||||
"Ceci est également utilisé comme taille de texture de nœud de base pour "
|
||||
"mémoire.\n"
|
||||
"Ce paramètre est appliqué UNIQUEMENT si l'un des filtres mentionnés est "
|
||||
"activé.\n"
|
||||
"Cela est également utilisé comme taille de texture de nœud de base pour "
|
||||
"l'agrandissement automatique des textures alignées sur le monde."
|
||||
|
||||
#: 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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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"
|
||||
"pause menu."
|
||||
msgstr ""
|
||||
"S'il faut couper le son. Vous pouvez réactiver le son à tout moment, sauf si "
|
||||
"le système audio est désactivé (« enable_sound=false »).\n"
|
||||
"S'il faut couper le son. Vous pouvez réactiver le son à tout moment.\n"
|
||||
"Dans le jeu, vous pouvez basculer l'état du son avec la touche « Muet » ou "
|
||||
"en utilisant le menu pause."
|
||||
|
||||
|
@ -7399,7 +7396,7 @@ msgstr ""
|
|||
"Distance Y sur laquelle les terrains flottants passent d'une densité "
|
||||
"maximale à une densité nulle.\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"
|
||||
"Doit être inférieure ou égale à la moitié de la distance entre les limites Y."
|
||||
|
||||
|
|
196
po/gl/luanti.po
196
po/gl/luanti.po
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: minetest\n"
|
||||
"Report-Msgid-Bugs-To: \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"
|
||||
"Language-Team: Galician <https://hosted.weblate.org/projects/minetest/"
|
||||
"minetest/gl/>\n"
|
||||
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\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
|
||||
msgid "Clear the out chat queue"
|
||||
|
@ -263,13 +263,12 @@ msgid "Show technical names"
|
|||
msgstr "Mostrar nomes técnicos"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Pantalla táctil"
|
||||
msgstr "Disposición da pantalla táctil"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
msgid "pause_menu"
|
||||
msgstr ""
|
||||
msgstr "_menú de pausa"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -609,6 +608,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Esta é a lista de clientes conectados a\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
@ -882,7 +883,7 @@ msgstr "Desexa eliminar \"$1\"?"
|
|||
#: builtin/mainmenu/dlg_delete_content.lua
|
||||
#: builtin/mainmenu/dlg_delete_world.lua builtin/mainmenu/tab_local.lua
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
msgstr "Borrar"
|
||||
|
||||
#: builtin/mainmenu/dlg_delete_content.lua
|
||||
msgid "pkgmgr: failed to delete \"$1\""
|
||||
|
@ -971,21 +972,20 @@ msgstr ""
|
|||
"non permitirá cambios de nome aquí."
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
#, fuzzy
|
||||
msgid "Expand all"
|
||||
msgstr "Activar todo"
|
||||
msgstr "Expandir todo"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "Group by prefix"
|
||||
msgstr ""
|
||||
msgstr "Agrupar por prefixo"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
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
|
||||
msgid "The $1 server uses the following mods:"
|
||||
msgstr ""
|
||||
msgstr "O servidor $1 usa as seguintes modificacións:"
|
||||
|
||||
#: builtin/mainmenu/dlg_version_info.lua
|
||||
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."
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Add favorite"
|
||||
msgstr "Favorito remoto"
|
||||
msgstr "Engadir aos favoritos"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Address"
|
||||
msgstr "Enderezo"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
msgstr "Cliente"
|
||||
msgstr ""
|
||||
"Clientes:\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Creative mode"
|
||||
|
@ -1228,9 +1228,8 @@ msgid "Favorites"
|
|||
msgstr "Favoritos"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Game: $1"
|
||||
msgstr "Xogo"
|
||||
msgstr "Xogo: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Incompatible Servers"
|
||||
|
@ -1245,14 +1244,12 @@ msgid "Login"
|
|||
msgstr "Identificarse"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Number of mods: $1"
|
||||
msgstr "Número de fíos emerxentes"
|
||||
msgstr "Número de modificacións: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Open server website"
|
||||
msgstr "Intervalo de servidor dedicado"
|
||||
msgstr "Abrir o sitio web do servidor"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Ping"
|
||||
|
@ -1265,6 +1262,10 @@ msgid ""
|
|||
"mod:<name>\n"
|
||||
"player:<name>"
|
||||
msgstr ""
|
||||
"Filtros posibles\n"
|
||||
"xogo:<nome>\n"
|
||||
"mod:<nome>\"\n"
|
||||
"xogador:<nome"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Public Servers"
|
||||
|
@ -1360,9 +1361,8 @@ msgid "Access denied. Reason: %s"
|
|||
msgstr "Acceso negado. Motivo: %s"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "All debug info hidden"
|
||||
msgstr "Info de depuración mostrada"
|
||||
msgstr "Toda a información de depuración oculta"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Automatic forward disabled"
|
||||
|
@ -1386,7 +1386,7 @@ msgstr "Límites de bloques mostrados para bloques pretos"
|
|||
|
||||
#: src/client/game.cpp
|
||||
msgid "Bounding boxes shown"
|
||||
msgstr ""
|
||||
msgstr "Caixas delimitadoras amosadas"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Camera update disabled"
|
||||
|
@ -1627,9 +1627,8 @@ msgid "Volume changed to %d%%"
|
|||
msgstr "Volume cambiado a %d%%"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Wireframe shown"
|
||||
|
@ -2062,9 +2061,8 @@ msgid "Failed to compile the \"%s\" shader."
|
|||
msgstr "Produciuse un erro ao compilar o sombreador \"%s\"."
|
||||
|
||||
#: src/client/shader.cpp
|
||||
#, fuzzy
|
||||
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"
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2301,35 +2299,32 @@ msgid "Sound Volume: %d%%"
|
|||
msgstr "Son: %d%%"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Add button"
|
||||
msgstr "Botón central"
|
||||
msgstr "Engadir botón"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Done"
|
||||
msgstr "Feito!"
|
||||
msgstr "Feito"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Remove"
|
||||
msgstr "Servidor remoto"
|
||||
msgstr "Eliminar"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
msgstr "Restablecer"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
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
|
||||
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
|
||||
msgid "Tap outside to deselect."
|
||||
msgstr ""
|
||||
msgstr "Toca fóra para deseleccionar."
|
||||
|
||||
#: src/gui/touchscreenlayout.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"3D support.\n"
|
||||
"Currently supported:\n"
|
||||
|
@ -2578,14 +2572,13 @@ msgid ""
|
|||
msgstr ""
|
||||
"Soporte 3D.\n"
|
||||
"Soportado actualmente:\n"
|
||||
"- none: sen saída 3D.\n"
|
||||
"- anaglyph: 3D en cor ciano/maxenta.\n"
|
||||
"- interlaced: soporte de pantalla polarizada baseada en liñas par/ímpar.\n"
|
||||
"- topbottom: pantalla dividida superior/inferior.\n"
|
||||
"- sidebyside: pantalla dividida lado a lado.\n"
|
||||
" - crossview: 3D para ver cruzado\n"
|
||||
"Teña en conta que o modo entrelazado require cos sombreadores estean "
|
||||
"activados."
|
||||
"- ningún: sen saída 3D.\n"
|
||||
"- anáglifo: 3D en cor ciano/maxenta.\n"
|
||||
"- entrelazado: soporte de pantalla polarizada baseada en liñas par/ímpar."
|
||||
"\n"
|
||||
"- arriba-abaixo: pantalla dividida superior/inferior.\n"
|
||||
"- lado a lado: pantalla dividida lado a lado.\n"
|
||||
"- vista cruzada: 3D para ver cruzado"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -2674,11 +2667,13 @@ msgid ""
|
|||
"All mesh buffers with less than this number of vertices will be merged\n"
|
||||
"during map rendering. This improves rendering performance."
|
||||
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
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Allows liquids to be translucent."
|
||||
|
@ -3089,7 +3084,7 @@ msgstr "Nubes no menú"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Color depth for post-processing texture"
|
||||
msgstr ""
|
||||
msgstr "Profundidade de cor para a textura de post-procesamento"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Colored fog"
|
||||
|
@ -3108,7 +3103,6 @@ msgstr ""
|
|||
"Útil para probas. Vexa al_extensions.[h,cpp] para máis detalles."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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 "
|
||||
|
@ -3294,6 +3288,11 @@ msgid ""
|
|||
"Reducing this can improve performance, but some effects (e.g. debanding)\n"
|
||||
"require more than 8 bits to work."
|
||||
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
|
||||
msgid "Dedicated server step"
|
||||
|
@ -3518,6 +3517,11 @@ msgid ""
|
|||
"situations\n"
|
||||
"where transparency sorting would be very slow otherwise."
|
||||
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
|
||||
msgid "Dump the mapgen debug information."
|
||||
|
@ -3602,14 +3606,12 @@ msgstr ""
|
|||
"simulando o comportamento do ollo humano."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable colored shadows for transculent nodes.\n"
|
||||
"This is expensive."
|
||||
msgstr ""
|
||||
"Activar sombras coloridas.\n"
|
||||
"Se o valor é verdadeiro, os bloques traslúcidos proxectarán sombras "
|
||||
"coloridas. Esta opción precisa de moitos recursos."
|
||||
"Activar sombras coloreadas para nós translúcidos.\n"
|
||||
"Isto é custoso."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable/disable running an IPv6 server.\n"
|
||||
"Ignored if bind_address is set."
|
||||
msgstr ""
|
||||
"Activa/desactiva a execución dun servidor IPv6.\n"
|
||||
"Ignorado se establécese bind_address.\n"
|
||||
"É preciso enable_ipv6 para activalo."
|
||||
"Activar/desactivar a execución dun servidor IPv6.\n"
|
||||
"Ignorado se está configurada a bind_address."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -4364,14 +4364,15 @@ msgstr ""
|
|||
"cambiar o seu contrasinal a un contrasinal baleiro."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"If enabled, server account registration is separate from login in the UI.\n"
|
||||
"If disabled, connecting to a server will automatically register a new "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Activar confirmación de rexistro ao se conectar ao servidor\n"
|
||||
"Se está desactivado, rexistrarase unha nova conta automáticamente."
|
||||
"Se está activado, o rexistro da conta do servidor é separado do inicio de "
|
||||
"sesión na interface de usuario.\n"
|
||||
"Se está desactivado, conectar a un servidor rexistrará automaticamente unha "
|
||||
"nova conta."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -5262,7 +5263,7 @@ msgstr "Límite mínimo do número aleatorio de covas pequenas por chunk."
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
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
|
||||
msgid "Mipmapping"
|
||||
|
@ -5357,16 +5358,15 @@ msgstr ""
|
|||
"- Os terreos flotantes opcionais de v7 (desactivados por defecto)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Name of the player.\n"
|
||||
"When running a server, a client connecting with this name is admin.\n"
|
||||
"When starting from the main menu, this is overridden."
|
||||
msgstr ""
|
||||
"Nome do xogador.\n"
|
||||
"Cando se executa un servidor, os clientes que se conectan con este nome son "
|
||||
"administradores.\n"
|
||||
"Ao comezar desde o menú principal, isto substitúese."
|
||||
"Cando se executa un servidor, un cliente que se conecte con este nome será "
|
||||
"administrador.\n"
|
||||
"Cando se inicie desde o menú principal, isto será substituído."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6356,18 +6356,16 @@ msgstr ""
|
|||
"cantidade na que agrupar algúns (ou todos) os obxectos."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Spread a complete update of the shadow map over a given number of frames.\n"
|
||||
"Higher values might make shadows laggy, lower values\n"
|
||||
"will consume more resources."
|
||||
msgstr ""
|
||||
"Distribuír unha actualización completa do mapa de sombras sobre unha "
|
||||
"determinada cantidade de fotogramas.\n"
|
||||
"Os valores máis altos poden facer cas sombras sexan lentas e os valores máis "
|
||||
"baixos\n"
|
||||
"consumirán máis recursos.\n"
|
||||
"Valor mínimo: 1; Valor máximo 16"
|
||||
"Espallar unha actualización completa do mapa de sombras ao longo dun número "
|
||||
"determinado de fotogramas.\n"
|
||||
"Valores máis altos poden facer que as sombras vaian con retardo, mentres que "
|
||||
"valores máis baixos\n"
|
||||
"consumirán máis recursos."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6650,7 +6648,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"O backend de renderizado.\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
|
||||
msgid ""
|
||||
|
@ -6814,9 +6812,8 @@ msgid "Transparency Sorting Distance"
|
|||
msgstr "Distancia de ordenación de transparencias"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Trees noise"
|
||||
|
@ -6876,7 +6873,6 @@ msgid "Undersampling"
|
|||
msgstr "Submostraxe"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Undersampling is similar to using a lower screen resolution, but it applies\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"
|
||||
"Debería dar un aumento máis significativo do rendemento a costa dunha imaxe "
|
||||
"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
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Use anisotropic filtering when looking at textures from an angle.\n"
|
||||
"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
|
||||
msgid "Use bilinear filtering when scaling textures."
|
||||
|
@ -7195,7 +7196,6 @@ msgstr ""
|
|||
"ao hardware (por exemplo, renderizado en textura para nós do inventario)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"When using bilinear/trilinear filtering, low-resolution textures\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"
|
||||
"texture autoscaling."
|
||||
msgstr ""
|
||||
"Cando se usan filtros bilineais/trilineais/anisótropos, texturas de baixa "
|
||||
"resolución\n"
|
||||
"poden ser borrosas, polo que amplíaos automaticamente co veciño máis "
|
||||
"próximo\n"
|
||||
"interpolación para preservar píxeles nítidos. Isto establece o tamaño mínimo "
|
||||
"de textura\n"
|
||||
"para as texturas mejoradas; valores máis altos parecen máis nítidos, pero "
|
||||
"requiren máis\n"
|
||||
"memoria. Recoméndase potencias de 2. Esta configuración só se aplica se\n"
|
||||
"O filtrado bilineal/trilineal/anisótropo está activado.\n"
|
||||
"Tamén se usa como tamaño de textura do nodo base para aliñados ao mundo\n"
|
||||
"Cando se usa filtrado bilineal/trilineal, as texturas de baixa resolución\n"
|
||||
"poden quedar borrosas, polo que esta opción amplía automaticamente as "
|
||||
"texturas para preservar\n"
|
||||
"píxeles nítidos. Isto define o tamaño mínimo da textura para as texturas "
|
||||
"ampliadas;\n"
|
||||
"valores máis altos son máis nítidos, pero requiren máis memoria.\n"
|
||||
"Esta configuración APLÍCASE SÓ se algún dos filtros mencionados está "
|
||||
"habilitado.\n"
|
||||
"Este tamén se usa como tamaño de textura do nodo base para aliñados ao "
|
||||
"mundo\n"
|
||||
"autoescalado de texturas."
|
||||
|
||||
#: 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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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"
|
||||
"pause menu."
|
||||
msgstr ""
|
||||
"Indica se hai que silenciar os sons. Podes activar o son en calquera "
|
||||
"momento, a non ser que\n"
|
||||
"esté desactivado (enable_sound=false).\n"
|
||||
"No xogo podes cambiar o estado de silencio coa tecla de silencio ou no\n"
|
||||
"menú de pausa."
|
||||
"Se activar ou desactivar os sons. Pódese reactivar o son en calquera momento."
|
||||
"\n"
|
||||
"No xogo, podes alternar o estado de silencio coa tecla de silencio ou "
|
||||
"utilizando\n"
|
||||
"o menú de pausa."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
|
6450
po/ia/luanti.po
6450
po/ia/luanti.po
File diff suppressed because it is too large
Load diff
229
po/id/luanti.po
229
po/id/luanti.po
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: Indonesian (Minetest)\n"
|
||||
"Report-Msgid-Bugs-To: \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"
|
||||
"Language-Team: Indonesian <https://hosted.weblate.org/projects/minetest/"
|
||||
"minetest/id/>\n"
|
||||
|
@ -263,14 +263,12 @@ msgid "Show technical names"
|
|||
msgstr "Tampilkan nama teknis"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Layar Sentuh"
|
||||
msgstr "Tata letak layar sentuh"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "pause_menu"
|
||||
msgstr "FPS (bingkai per detik) pada menu jeda"
|
||||
msgstr "pause_menu"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -608,6 +606,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Ini daftar klien yang terhubung ke\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
@ -967,21 +967,20 @@ msgstr ""
|
|||
"akan menimpa penggantian nama yang ada."
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
#, fuzzy
|
||||
msgid "Expand all"
|
||||
msgstr "Nyalakan semua"
|
||||
msgstr "Buka semua"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "Group by prefix"
|
||||
msgstr ""
|
||||
msgstr "Kelompokkan berdasarkan awalan"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
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
|
||||
msgid "The $1 server uses the following mods:"
|
||||
msgstr ""
|
||||
msgstr "Server $1 menggunakan mod berikut:"
|
||||
|
||||
#: builtin/mainmenu/dlg_version_info.lua
|
||||
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."
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Add favorite"
|
||||
msgstr "Hapus favorit"
|
||||
msgstr "Tambahkan favorit"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Address"
|
||||
msgstr "Alamat"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
msgstr "Klien"
|
||||
msgstr ""
|
||||
"Klien:\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Creative mode"
|
||||
|
@ -1222,9 +1221,8 @@ msgid "Favorites"
|
|||
msgstr "Favorit"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Game: $1"
|
||||
msgstr "Permainan"
|
||||
msgstr "Permainan: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Incompatible Servers"
|
||||
|
@ -1239,14 +1237,12 @@ msgid "Login"
|
|||
msgstr "Masuk"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Number of mods: $1"
|
||||
msgstr "Jumlah utas kemunculan"
|
||||
msgstr "Jumlah mod: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Open server website"
|
||||
msgstr "Langkah server khusus"
|
||||
msgstr "Buka situs web server"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Ping"
|
||||
|
@ -1259,6 +1255,10 @@ msgid ""
|
|||
"mod:<name>\n"
|
||||
"player:<name>"
|
||||
msgstr ""
|
||||
"Filter yang memungkinkan\n"
|
||||
"game:<nama>\n"
|
||||
"mod:<nama>\n"
|
||||
"player:<name>"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Public Servers"
|
||||
|
@ -1354,9 +1354,8 @@ msgid "Access denied. Reason: %s"
|
|||
msgstr "Akses ditolak. Alasan: %s"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "All debug info hidden"
|
||||
msgstr "Info awakutu ditampilkan"
|
||||
msgstr "Semua info awakutu disembunyikan"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Automatic forward disabled"
|
||||
|
@ -1380,7 +1379,7 @@ msgstr "Batasan blok ditampilkan untuk blok sekitar"
|
|||
|
||||
#: src/client/game.cpp
|
||||
msgid "Bounding boxes shown"
|
||||
msgstr ""
|
||||
msgstr "Kotak ikatan ditampilkan"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Camera update disabled"
|
||||
|
@ -1623,9 +1622,8 @@ msgid "Volume changed to %d%%"
|
|||
msgstr "Volume diubah ke %d%%"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Wireframe shown"
|
||||
|
@ -2058,9 +2056,8 @@ msgid "Failed to compile the \"%s\" shader."
|
|||
msgstr "Gagal mengompilasi shader \"%s\"."
|
||||
|
||||
#: src/client/shader.cpp
|
||||
#, fuzzy
|
||||
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"
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2297,35 +2294,33 @@ msgid "Sound Volume: %d%%"
|
|||
msgstr "Volume Suara: %d%%"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Add button"
|
||||
msgstr "Klik Tengah"
|
||||
msgstr "Tambahkan tombol"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Done"
|
||||
msgstr "Selesai!"
|
||||
msgstr "Selesai"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Remove"
|
||||
msgstr "Server jarak jauh"
|
||||
msgstr "Hapus"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
msgstr "Atur ulang"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Start dragging a button to add. Tap outside to cancel."
|
||||
msgstr ""
|
||||
"Mulai menarik tombol untuk menambahkan. Ketuk di luar untuk membatalkan."
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
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
|
||||
msgid "Tap outside to deselect."
|
||||
msgstr ""
|
||||
msgstr "Ketuk di luar untuk membatalkan pilihan."
|
||||
|
||||
#: src/gui/touchscreenlayout.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"3D support.\n"
|
||||
"Currently supported:\n"
|
||||
|
@ -2571,8 +2565,7 @@ msgstr ""
|
|||
"- interlaced: garis ganjil/genap berdasarkan polarisasi layar.\n"
|
||||
"- topbottom: pisahkan layar atas/bawah.\n"
|
||||
"- sidebyside: pisahkan layar kiri/kanan.\n"
|
||||
"- crossview: 3d dengan pandang silang\n"
|
||||
"Catat bahwa mode interlaced memerlukan penggunaan shader."
|
||||
"- crossview: 3d dengan pandang silang"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -2661,11 +2654,12 @@ msgid ""
|
|||
"All mesh buffers with less than this number of vertices will be merged\n"
|
||||
"during map rendering. This improves rendering performance."
|
||||
msgstr ""
|
||||
"Semua penyangga jaring kurang dari jumlah verteks ini akan digabungkan\n"
|
||||
"saat perenderan peta. Ini meningkatkan performa perenderan."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
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
|
||||
msgid "Allows liquids to be translucent."
|
||||
|
@ -3075,7 +3069,7 @@ msgstr "Awan dalam menu"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Color depth for post-processing texture"
|
||||
msgstr ""
|
||||
msgstr "Kedalaman warna untuk tekstur pasca-pemrosesan"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Colored fog"
|
||||
|
@ -3095,7 +3089,6 @@ msgstr ""
|
|||
"Berguna untuk pengujian. Lihat al_extensions.[h,cpp] untuk detailnya."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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 "
|
||||
|
@ -3281,6 +3274,11 @@ msgid ""
|
|||
"Reducing this can improve performance, but some effects (e.g. debanding)\n"
|
||||
"require more than 8 bits to work."
|
||||
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
|
||||
msgid "Dedicated server step"
|
||||
|
@ -3500,6 +3498,11 @@ msgid ""
|
|||
"situations\n"
|
||||
"where transparency sorting would be very slow otherwise."
|
||||
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
|
||||
msgid "Dump the mapgen debug information."
|
||||
|
@ -3584,14 +3587,12 @@ msgstr ""
|
|||
"menyimulasikan perilaku mata manusia."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable colored shadows for transculent nodes.\n"
|
||||
"This is expensive."
|
||||
msgstr ""
|
||||
"Menyalakan bayangan berwarna.\n"
|
||||
"Nilai true berarti nodus agak tembus pandang memiliki bayangan berwarna. Ini "
|
||||
"memerlukan sumber daya besar."
|
||||
"Aktif kan bayangan berwarna untuk nodus translusen.\n"
|
||||
"Ini komputasi mahal."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Enable console window"
|
||||
|
@ -3670,14 +3671,12 @@ msgstr ""
|
|||
"Contoh: 0 untuk tanpa view bobbing; 1.0 untuk normal; 2.0 untuk 2x lipat."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable/disable running an IPv6 server.\n"
|
||||
"Ignored if bind_address is set."
|
||||
msgstr ""
|
||||
"Nyalakan/matikan server IPv6.\n"
|
||||
"Diabaikan jika bind_address telah diatur.\n"
|
||||
"Perlu menyalakan enable_ipv6."
|
||||
"Aktif kan/nonaktifkan menjalankan server IPv6.\n"
|
||||
"Diabaikan jika bind_address telah diatur."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -4323,14 +4322,14 @@ msgstr ""
|
|||
"menggantinya dengan kata sandi kosong."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"If enabled, server account registration is separate from login in the UI.\n"
|
||||
"If disabled, connecting to a server will automatically register a new "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Jika dinyalakan, tampilan pendaftaran akun dan masuk akan dipisah.\n"
|
||||
"Jika dimatikan, akun baru akan didaftarkan secara otomatis saat masuk."
|
||||
"Jika diaktifkan, pendaftaran akun server terpisah dari log masuk dalam UI.\n"
|
||||
"Jika dinonaktifkan, menghubungkan ke server akan mendaftarkan akun secara "
|
||||
"otomatis."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -5204,7 +5203,7 @@ msgstr "Batas minimal nilai acak untuk gua kecil per potongan peta."
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Minimum vertex count for mesh buffers"
|
||||
msgstr ""
|
||||
msgstr "Jumlah verteks minimum untuk penyangga jaring"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Mipmapping"
|
||||
|
@ -5299,16 +5298,15 @@ msgstr ""
|
|||
"- \"floatlands\" pada pembuat peta v7 (dimatikan secara bawaan)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Name of the player.\n"
|
||||
"When running a server, a client connecting with this name is admin.\n"
|
||||
"When starting from the main menu, this is overridden."
|
||||
msgstr ""
|
||||
"Nama si pemain.\n"
|
||||
"Saat menjalankan server, klien yang tersambung dengan nama ini adalah "
|
||||
"pengurus.\n"
|
||||
"Saat menjalankan dari menu utama, nilai ini ditimpa."
|
||||
"Nama pemain.\n"
|
||||
"Saat menjalankan server, klien yang tersambung dengan nama ini adalah admin."
|
||||
"\n"
|
||||
"Saat memulai dari menu utama, ini ditimpa."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
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"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Select the antialiasing method to apply.\n"
|
||||
"\n"
|
||||
|
@ -5837,26 +5834,46 @@ msgid ""
|
|||
"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."
|
||||
msgstr ""
|
||||
"Pilih metode antialiasing yang akan diterapkan.\n"
|
||||
"Pilih metode antialiasing untuk diterapkan.\n"
|
||||
"\n"
|
||||
"* Tidak ada - Tidak ada antialiasing (bawaan)\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"
|
||||
"* FXAA - Antialiasing perkiraan cepat (memerlukan shader)\n"
|
||||
"Menerapkan filter pasca-pemrosesan untuk mendeteksi dan memperhalus tepi "
|
||||
"yang sangat kontras.\n"
|
||||
"* Tidak ada - tidak ada antialiasing (default)\n"
|
||||
"\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"
|
||||
"\n"
|
||||
"* SSAA - Antialiasing super-sampling (memerlukan shader)\n"
|
||||
"Merender gambar pemandangan dengan resolusi lebih tinggi, kemudian "
|
||||
"memperkecil skala untuk mengurangi\n"
|
||||
"mengurangi efek aliasing. Ini adalah metode yang paling lambat dan paling "
|
||||
"akurat."
|
||||
"\n"
|
||||
"\n"
|
||||
"* SSAA - Antialiasing Super -Sampling\n"
|
||||
"\n"
|
||||
"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
|
||||
msgid "Selection box border color (R,G,B)."
|
||||
|
@ -6283,16 +6300,15 @@ msgstr ""
|
|||
"semua) barang."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Spread a complete update of the shadow map over a given number of frames.\n"
|
||||
"Higher values might make shadows laggy, lower values\n"
|
||||
"will consume more resources."
|
||||
msgstr ""
|
||||
"Menyebarkan pembaruan peta bayangan dalam jumlah bingkai yang diberikan.\n"
|
||||
"Nilai tinggi bisa membuat bayangan patah-patah, nilai rendah akan perlu\n"
|
||||
"sumber daya lebih banyak.\n"
|
||||
"Nilai minimum: 1; nilai maksimum: 16"
|
||||
"Sebarkan pembaruan lengkap peta bayangan pada sejumlah bingkai tertentu.\n"
|
||||
"Nilai yang lebih tinggi mungkin membuat bayangan lambat, nilai yang lebih "
|
||||
"rendah\n"
|
||||
"akan mengkonsumsi lebih banyak sumber daya."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6721,9 +6737,8 @@ msgid "Transparency Sorting Distance"
|
|||
msgstr "Jarak Pengurutan Transparansi"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid "Transparency Sorting Group by Buffers"
|
||||
msgstr "Jarak Pengurutan Transparansi"
|
||||
msgstr "Jarak Pengurutan Transparansi berdasarkan Penyangga"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Trees noise"
|
||||
|
@ -6783,7 +6798,6 @@ msgid "Undersampling"
|
|||
msgstr "Undersampling(Pengambilan sampel yang terlalu rendah)"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Undersampling is similar to using a lower screen resolution, but it applies\n"
|
||||
"to the game world only, keeping the GUI intact.\n"
|
||||
|
@ -6794,10 +6808,13 @@ msgid ""
|
|||
"set\n"
|
||||
"to a non-default value."
|
||||
msgstr ""
|
||||
"Undersampling seperti menggunakan resolusi layar yang lebih rendah, tetapi\n"
|
||||
"hanya berlaku untuk dunia permainan saja, antarmuka grafis tetap.\n"
|
||||
"Seharusnya memberikan dorongan kinerja dengan gambar yang kurang detail.\n"
|
||||
"Nilai yang lebih tinggi menghasilkan gambar yang kurang detail."
|
||||
"Undersampling hampir mirip seperti menggunakan resolusi layer yang lebih "
|
||||
"rendah, tetapi hanya diterapkan ke dunia permainan saja sambil menjaga GUI.\n"
|
||||
"Ini seharusnya memberikan peningkatan performa dengan mengurangi 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
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Use anisotropic filtering when looking at textures from an angle.\n"
|
||||
"This provides a significant improvement when used together with mipmapping."
|
||||
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
|
||||
msgid "Use bilinear filtering when scaling textures."
|
||||
|
@ -7102,7 +7120,6 @@ msgstr ""
|
|||
"perangkat keras (misal gambar ke tekstur untuk nodus dalam inventaris)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"When using bilinear/trilinear filtering, low-resolution textures\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"
|
||||
"texture autoscaling."
|
||||
msgstr ""
|
||||
"Saat menggunakan filter bilinear/trilinear/anisotropik, tekstur resolusi\n"
|
||||
"rendah dapat dikaburkan sehingga diperbesar otomatis dengan interpolasi\n"
|
||||
"nearest-neighbor untuk menjaga ketajaman piksel. Ini mengatur ukuran\n"
|
||||
"tekstur minimum untuk tekstur yang diperbesar; semakin tinggi semakin\n"
|
||||
"tajam, tetapi butuh memori lebih. Perpangkatan dua disarankan. Pengaturan\n"
|
||||
"ini HANYA diterapkan jika menggunakan filter bilinear/trilinear/"
|
||||
"anisotropik.\n"
|
||||
"Ini juga digunakan sebagai ukuran dasar tekstur nodus untuk penyekalaan\n"
|
||||
"otomatis tekstur yang sejajar dengan dunia."
|
||||
"Saat menggunakan pemfilteran bilinear/trilinear, tekstur resolusi rendah\n"
|
||||
"bisa dikaburkan, jadi opsi ini secara otomatis meningkatkannya untuk "
|
||||
"menjaga\n"
|
||||
"piksel tajam. Ini mendefinisikan ukuran tekstur minimum untuk tekstur yang "
|
||||
"ditingkatkan;\n"
|
||||
"Nilai yang lebih tinggi terlihat lebih tajam, tetapi membutuhkan lebih "
|
||||
"banyak memori.\n"
|
||||
"Pengaturan ini hanya diterapkan jika salah satu filter yang disebutkan "
|
||||
"diaktifkan.\n"
|
||||
"Ini juga digunakan sebagai ukuran tekstur simpul dasar untuk dunia yang "
|
||||
"selaras\n"
|
||||
"Tekstur Autoscaling."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
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."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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"
|
||||
"pause menu."
|
||||
msgstr ""
|
||||
"Apakah akan membisukan suara atau tidak. Anda dapat membunyikan\n"
|
||||
"suara kapan pun, kecuali sistem suara dimatikan (enable_sound = false).\n"
|
||||
"Dalam permainan, Anda dapat beralih mode bisu dengan tombol bisu\n"
|
||||
"atau melalui menu jeda."
|
||||
"Apakah suara dibisukan atau tidak. Kamu bisa membunyikan suara kapan pun.\n"
|
||||
"Dalam permainan, kamu bisa sakelar keadaan bisu dengan tombol bisikan atau "
|
||||
"menggunakan\n"
|
||||
"menu jeda."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
|
227
po/ru/luanti.po
227
po/ru/luanti.po
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: Russian (Minetest)\n"
|
||||
"Report-Msgid-Bugs-To: \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"
|
||||
"Language-Team: Russian <https://hosted.weblate.org/projects/minetest/"
|
||||
"minetest/ru/>\n"
|
||||
|
@ -264,14 +264,12 @@ msgid "Show technical names"
|
|||
msgstr "Показывать технические названия"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "Touchscreen layout"
|
||||
msgstr "Сенсорный экран"
|
||||
msgstr "Pазложение сенсорного экрана"
|
||||
|
||||
#: builtin/common/settings/dlg_settings.lua
|
||||
#, fuzzy
|
||||
msgid "pause_menu"
|
||||
msgstr "Кадровая частота во время паузы"
|
||||
msgstr "меню_паузы"
|
||||
|
||||
#: builtin/common/settings/settingtypes.lua
|
||||
msgid "Client Mods"
|
||||
|
@ -609,6 +607,8 @@ msgid ""
|
|||
"This is the list of clients connected to\n"
|
||||
"$1"
|
||||
msgstr ""
|
||||
"Это список подключённых клиентов к\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/dlg_config_world.lua
|
||||
msgid "(Enabled, has error)"
|
||||
|
@ -972,21 +972,21 @@ msgstr ""
|
|||
"перезапишет указанное здесь значение."
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
#, fuzzy
|
||||
msgid "Expand all"
|
||||
msgstr "Включить всё"
|
||||
msgstr "Расширить всё"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "Group by prefix"
|
||||
msgstr ""
|
||||
msgstr "Сгруппировать по префиксу"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "The $1 server uses a game called $2 and the following mods:"
|
||||
msgstr ""
|
||||
"На сервере $1 используется игра под названием $2 со следующими дополнениями:"
|
||||
|
||||
#: builtin/mainmenu/dlg_server_list_mods.lua
|
||||
msgid "The $1 server uses the following mods:"
|
||||
msgstr ""
|
||||
msgstr "Сервер $1 использует следующие дополнения:"
|
||||
|
||||
#: builtin/mainmenu/dlg_version_info.lua
|
||||
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 "Вам требуется установить игру, прежде чем вы сможете создать мир."
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Add favorite"
|
||||
msgstr "Удалить избранное"
|
||||
msgstr "Добавить избранное"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Address"
|
||||
msgstr "Адрес"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Clients:\n"
|
||||
"$1"
|
||||
msgstr "Клиент"
|
||||
msgstr ""
|
||||
"Клиенты:\n"
|
||||
"$1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Creative mode"
|
||||
|
@ -1227,9 +1227,8 @@ msgid "Favorites"
|
|||
msgstr "Избранное"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Game: $1"
|
||||
msgstr "Игра"
|
||||
msgstr "Игра: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Incompatible Servers"
|
||||
|
@ -1244,14 +1243,12 @@ msgid "Login"
|
|||
msgstr "Войти"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Number of mods: $1"
|
||||
msgstr "Количество потоков подгрузки"
|
||||
msgstr "Количество модов: $1"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
#, fuzzy
|
||||
msgid "Open server website"
|
||||
msgstr "Шаг выделенного сервера"
|
||||
msgstr "Открыть веб-сайт сервера"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Ping"
|
||||
|
@ -1264,6 +1261,10 @@ msgid ""
|
|||
"mod:<name>\n"
|
||||
"player:<name>"
|
||||
msgstr ""
|
||||
"Возможные фильтры\n"
|
||||
"игра:<имя>\n"
|
||||
"дополнение:<имя>\n"
|
||||
"игрок:<имя>"
|
||||
|
||||
#: builtin/mainmenu/tab_online.lua
|
||||
msgid "Public Servers"
|
||||
|
@ -1359,9 +1360,8 @@ msgid "Access denied. Reason: %s"
|
|||
msgstr "Доступ запрещён. Причина: %s"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "All debug info hidden"
|
||||
msgstr "Отладочные сведения отображены"
|
||||
msgstr "Все отладочные сведения скрыты"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Automatic forward disabled"
|
||||
|
@ -1385,7 +1385,7 @@ msgstr "Границы показаны для ближайших мапблок
|
|||
|
||||
#: src/client/game.cpp
|
||||
msgid "Bounding boxes shown"
|
||||
msgstr ""
|
||||
msgstr "Показаны ограничивающие рамки"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Camera update disabled"
|
||||
|
@ -1623,9 +1623,8 @@ msgid "Volume changed to %d%%"
|
|||
msgstr "Громкость установлена на %d%%"
|
||||
|
||||
#: src/client/game.cpp
|
||||
#, fuzzy
|
||||
msgid "Wireframe not supported by video driver"
|
||||
msgstr "Шейдеры включены, но GLSL не поддерживается драйвером."
|
||||
msgstr "Полигоны не доступны этим видео драйвером"
|
||||
|
||||
#: src/client/game.cpp
|
||||
msgid "Wireframe shown"
|
||||
|
@ -2058,9 +2057,8 @@ msgid "Failed to compile the \"%s\" shader."
|
|||
msgstr "Не удалось скомпилировать шейдер «%s»."
|
||||
|
||||
#: src/client/shader.cpp
|
||||
#, fuzzy
|
||||
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"
|
||||
#: src/content/mod_configuration.cpp
|
||||
|
@ -2296,35 +2294,35 @@ msgid "Sound Volume: %d%%"
|
|||
msgstr "Громкость звука: %d%%"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Add button"
|
||||
msgstr "Средняя кнопка"
|
||||
msgstr "Добавить кнопку"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Done"
|
||||
msgstr "Готово!"
|
||||
msgstr "Готово"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
#, fuzzy
|
||||
msgid "Remove"
|
||||
msgstr "Удалённый сервер"
|
||||
msgstr "Убрать"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
msgstr "Сбросить"
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Start dragging a button to add. Tap outside to cancel."
|
||||
msgstr ""
|
||||
"Начните перетаскивать кнопку, чтобы добавить. Нажмите \"За пределами\", "
|
||||
"чтобы отменить."
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Tap a button to select it. Drag a button to move it."
|
||||
msgstr ""
|
||||
"Нажмите на кнопку, чтобы выбрать её. Перетащите кнопку, чтобы перемещать её."
|
||||
|
||||
#: src/gui/touchscreeneditor.cpp
|
||||
msgid "Tap outside to deselect."
|
||||
msgstr ""
|
||||
msgstr "Нажмите \"Снаружи\", чтобы отменить выбор."
|
||||
|
||||
#: src/gui/touchscreenlayout.cpp
|
||||
msgid "Joystick"
|
||||
|
@ -2555,7 +2553,6 @@ msgid "3D noise that determines number of dungeons per mapchunk."
|
|||
msgstr "3D-шум, определяющий количество подземелий на мапчанк карты."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"3D support.\n"
|
||||
"Currently supported:\n"
|
||||
|
@ -2566,15 +2563,14 @@ msgid ""
|
|||
"- sidebyside: split screen side by side.\n"
|
||||
"- crossview: Cross-eyed 3d"
|
||||
msgstr ""
|
||||
"3D-анаглиф.\n"
|
||||
"Поддержка 3D.\n"
|
||||
"Сейчас поддерживаются:\n"
|
||||
"- none: без 3D.\n"
|
||||
"- none: без 3d выхода.\n"
|
||||
"- anaglyph: для красно/синих очков.\n"
|
||||
"- interlaced: поляризация с чётными/нечётными линиями.\n"
|
||||
"- topbottom: горизонтальное разделение экрана.\n"
|
||||
"- sidebyside: вертикальное разделение экрана.\n"
|
||||
"- crossview: перекрёстная стереопара.\n"
|
||||
"Примечание: для режима «interlaced» должны быть включены шейдеры."
|
||||
"- crossview: перекрёстная стереопара 3d"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -2663,11 +2659,12 @@ msgid ""
|
|||
"All mesh buffers with less than this number of vertices will be merged\n"
|
||||
"during map rendering. This improves rendering performance."
|
||||
msgstr ""
|
||||
"Все буферы мешей с меньшим количеством вершин будут объединены\n"
|
||||
"во время рендера карты. Это повышает производительность рендеринга."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid "Allow clouds to look 3D instead of flat."
|
||||
msgstr "Объёмные облака вместо плоских."
|
||||
msgstr "Позволяет облакам выглядеть больше 3D, чем плоскими."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Allows liquids to be translucent."
|
||||
|
@ -3080,7 +3077,7 @@ msgstr "Облака в меню"
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Color depth for post-processing texture"
|
||||
msgstr ""
|
||||
msgstr "Глубина цвета для постобработки текстуры"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Colored fog"
|
||||
|
@ -3101,7 +3098,6 @@ msgstr ""
|
|||
"[h,cpp]."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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 "
|
||||
|
@ -3112,12 +3108,12 @@ msgid ""
|
|||
"so see a full list at https://content.luanti.org/help/content_flags/"
|
||||
msgstr ""
|
||||
"Список разделенных запятыми флажков для скрытия в хранилище контента.\n"
|
||||
"\"nonfree\" может использоваться для скрытия пакетов,\n"
|
||||
"которые не подпадают под категорию Free Software Foundation,\n"
|
||||
"как это определено Фондом свободного программного обеспечения.\n"
|
||||
"Вы также можете указать рейтинг контента. Эти флаги не зависят от версий "
|
||||
"Luanti,\n"
|
||||
"поэтому смотрите полный список по адресу https://content.minetest.net/help/"
|
||||
"«несвободный» может использоваться для скрытия пакетов, которые не подпадают "
|
||||
"под категорию «свободного программного обеспечения»,\n"
|
||||
"как это определено Фондом Свободного Программного Обеспечения.\n"
|
||||
"Вы также можете указать рейтинг контента.\n"
|
||||
"Эти флаги не зависят от версий Luanti,\n"
|
||||
"поэтому смотрите полный список по адресу https://content.luanti.org/help/"
|
||||
"content_flags/"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
|
@ -3287,6 +3283,11 @@ msgid ""
|
|||
"Reducing this can improve performance, but some effects (e.g. debanding)\n"
|
||||
"require more than 8 bits to work."
|
||||
msgstr ""
|
||||
"Определить глубину цвета текстуры, используемой для конвейера постобработки."
|
||||
"\n"
|
||||
"Уменьшение этого параметра может повысить производительность, но для работы "
|
||||
"некоторых эффектов (например, для удаления пятен)\n"
|
||||
"требуется более 8 бит."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Dedicated server step"
|
||||
|
@ -3507,6 +3508,11 @@ msgid ""
|
|||
"situations\n"
|
||||
"where transparency sorting would be very slow otherwise."
|
||||
msgstr ""
|
||||
"Рисовать треугольники, отсортированные по прозрачности, сгруппированные по "
|
||||
"их меш буферам.\n"
|
||||
"Это нарушает сортировку по прозрачности между меш буферами, но позволяет "
|
||||
"избежать ситуаций,\n"
|
||||
"когда в противном случае сортировка по прозрачности была бы очень медленной."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Dump the mapgen debug information."
|
||||
|
@ -3591,14 +3597,12 @@ msgstr ""
|
|||
"имитируя поведение человеческого глаза."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable colored shadows for transculent nodes.\n"
|
||||
"This is expensive."
|
||||
msgstr ""
|
||||
"Включить цветные тени.\n"
|
||||
"Когда включено, прозрачные ноды отбрасывают цветные тени. Это "
|
||||
"ресурсозатратно."
|
||||
"Включите цветные тени для трансгенных блоков.\n"
|
||||
"Это дорого."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Enable console window"
|
||||
|
@ -3681,14 +3685,12 @@ msgstr ""
|
|||
"Например: 0 отключает покачивание, 1.0 для обычного, 2.0 для двойного."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Enable/disable running an IPv6 server.\n"
|
||||
"Ignored if bind_address is set."
|
||||
msgstr ""
|
||||
"Включить/отключить запуск IPv6-сервера.\n"
|
||||
"Игнорируется, если задан «bind_address».\n"
|
||||
"Для включения необходим «enable_ipv6»."
|
||||
"Включить/отключить запуск сервера IPv6.\n"
|
||||
"Игнорируется, если задан параметр bind_address."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -4333,16 +4335,15 @@ msgstr ""
|
|||
"Если включено, то новые игроки не смогут подключаться с пустым паролем."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"If enabled, server account registration is separate from login in the UI.\n"
|
||||
"If disabled, connecting to a server will automatically register a new "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Если включено, регистрация аккаунта выполняется в интерфейсе отдельно от "
|
||||
"входа.\n"
|
||||
"Если отключено, новые учётные записи будут регистрироваться автоматически "
|
||||
"при входе."
|
||||
"Если этот параметр включен, регистрация учетной записи сервера выполняется "
|
||||
"отдельно от входа в пользовательский интерфейс.\n"
|
||||
"Если он отключен, при подключении к серверу автоматически регистрируется "
|
||||
"новая учетная запись."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -5212,7 +5213,7 @@ msgstr "Минимум малых пещер на мапчанк."
|
|||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Minimum vertex count for mesh buffers"
|
||||
msgstr ""
|
||||
msgstr "Минимальное количество вершин для меш буферов"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Mipmapping"
|
||||
|
@ -5307,15 +5308,15 @@ msgstr ""
|
|||
"- Дополнительные парящие острова из v7 (выключено по умолчанию)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Name of the player.\n"
|
||||
"When running a server, a client connecting with this name is admin.\n"
|
||||
"When starting from the main menu, this is overridden."
|
||||
msgstr ""
|
||||
"Имя игрока.\n"
|
||||
"При запуске сервера клиенты с этим именем будут администраторами.\n"
|
||||
"Будет переопределено при запуске из главного меню."
|
||||
"При запуске сервера клиент, подключающийся под этим именем, является "
|
||||
"администратором.\n"
|
||||
"При запуске из главного меню это значение переопределяется."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -5824,7 +5825,6 @@ msgid "See https://www.sqlite.org/pragma.html#pragma_synchronous"
|
|||
msgstr "См. http://www.sqlite.org/pragma.html#pragma_synchronous"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Select the antialiasing method to apply.\n"
|
||||
"\n"
|
||||
|
@ -5849,25 +5849,27 @@ msgid ""
|
|||
msgstr ""
|
||||
"Выберите метод сглаживания, который необходимо применить.\n"
|
||||
"\n"
|
||||
"* * Нет - сглаживание отсутствует (по умолчанию).\n"
|
||||
"* None - Нет сглаживания (по умолчанию)\n"
|
||||
"\n"
|
||||
"* FSAA - Аппаратное полноэкранное сглаживание\n"
|
||||
"(несовместимое с постобработкой и недостаточной дискретизацией)\n"
|
||||
", аналогичное сглаживанию с несколькими выборками (MSAA)\n"
|
||||
"* FSAA - Аппаратное полноэкранное сглаживание,\n"
|
||||
"аналогичное сглаживанию с несколькими выборками (MSAA).\n"
|
||||
"Сглаживает края блоков, но не влияет на внутреннюю часть текстур.\n"
|
||||
"Для изменения этого параметра требуется перезагрузка.\n"
|
||||
"\n"
|
||||
"* FXAA - Быстрое приблизительное сглаживание (требуется использование "
|
||||
"шейдеров)\n"
|
||||
"Применяется фильтр последующей обработки для обнаружения и сглаживания "
|
||||
"Если постобработка отключена, для изменения FSAA требуется перезапуск.\n"
|
||||
"Кроме того, если постобработка отключена, FSAA не будет работать в сочетании "
|
||||
"с\n"
|
||||
"недостаточной дискретизацией или настройкой \"3d_mode\", не используемой по "
|
||||
"умолчанию.\n"
|
||||
"\n"
|
||||
"* FXAA - Быстрое приблизительное сглаживание\n"
|
||||
"Применяет фильтр последующей обработки для обнаружения и сглаживания "
|
||||
"высококонтрастных краев.\n"
|
||||
"Обеспечивает баланс между скоростью и качеством изображения.\n"
|
||||
"\n"
|
||||
"* SSAA - сглаживание с использованием суперсэмплирования (требуются "
|
||||
"шейдеры)\n"
|
||||
"Визуализирует изображение сцены с более высоким разрешением, затем уменьшает "
|
||||
"масштаб, чтобы уменьшить\n"
|
||||
"эффекты наложения. Это самый медленный и точный метод."
|
||||
"* SSAA - Сглаживание с использованием суперсэмплирования\n"
|
||||
"Позволяет получить изображение сцены с более высоким разрешением, а затем "
|
||||
"уменьшить масштаб, чтобы уменьшить\n"
|
||||
"эффекты сглаживания. Это самый медленный и точный метод."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Selection box border color (R,G,B)."
|
||||
|
@ -6300,17 +6302,14 @@ msgstr ""
|
|||
"(или всех) предметов."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Spread a complete update of the shadow map over a given number of frames.\n"
|
||||
"Higher values might make shadows laggy, lower values\n"
|
||||
"will consume more resources."
|
||||
msgstr ""
|
||||
"Распространяет полное обновление карты теней на заданное количество кадров.\n"
|
||||
"Более высокие значения могут сделать тени нестабильными, более низкие "
|
||||
"значения\n"
|
||||
"будут потреблять больше ресурсов.\n"
|
||||
"Минимум: 1; максимум: 16"
|
||||
"Распространить полное обновление карты теней на заданное количество кадров.\n"
|
||||
"Более высокие значения могут привести к запаздыванию теней,\n"
|
||||
"более низкие значения потребляют больше ресурсов."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -6753,9 +6752,8 @@ msgid "Transparency Sorting Distance"
|
|||
msgstr "Дальность сортировки по прозрачности"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid "Transparency Sorting Group by Buffers"
|
||||
msgstr "Дальность сортировки по прозрачности"
|
||||
msgstr "Прозрачность Сортировки Групп по Буферам"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Trees noise"
|
||||
|
@ -6816,7 +6814,6 @@ msgid "Undersampling"
|
|||
msgstr "Субдискретизация"
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Undersampling is similar to using a lower screen resolution, but it applies\n"
|
||||
"to the game world only, keeping the GUI intact.\n"
|
||||
|
@ -6827,12 +6824,15 @@ msgid ""
|
|||
"set\n"
|
||||
"to a non-default value."
|
||||
msgstr ""
|
||||
"Субдискретизация аналогична использованию низкого разрешения экрана,\n"
|
||||
"но она применяется только к игровому миру, графический интерфейс не "
|
||||
"затрагивается.\n"
|
||||
"Значительно увеличивает производительность за счёт вывода менее подробного "
|
||||
"изображения.\n"
|
||||
"Высокие значения приводят к менее проработанному изображению."
|
||||
"Недостаточная дискретизация аналогична использованию более низкого "
|
||||
"разрешения экрана, но применяется\n"
|
||||
"только к игровому миру, сохраняя графический интерфейс без изменений.\n"
|
||||
"Это должно значительно повысить производительность за счет снижения "
|
||||
"детализации изображения.\n"
|
||||
"Более высокие значения приводят к снижению детализации изображения.\n"
|
||||
"Примечание: В настоящее время недостаточная дискретизация не поддерживается, "
|
||||
"если для параметра \"3d_mode\" установлено\n"
|
||||
"значение, отличное от значения по умолчанию."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Unlimited player transfer distance"
|
||||
|
@ -6859,12 +6859,13 @@ msgid "Use a cloud animation for the main menu background."
|
|||
msgstr "Анимированные облака в главном меню."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Use anisotropic filtering when looking at textures from an angle.\n"
|
||||
"This provides a significant improvement when used together with mipmapping."
|
||||
msgstr ""
|
||||
"Использовать анизотропную фильтрацию при взгляде на текстуры под углом."
|
||||
"Использовать анизотропную фильтрацию при просмотре текстур под углом.\n"
|
||||
"Это обеспечивает значительное улучшение при использовании в сочетании с "
|
||||
"мип-картированием."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid "Use bilinear filtering when scaling textures."
|
||||
|
@ -7138,7 +7139,6 @@ msgstr ""
|
|||
"аппаратно (прим. render-to-texture для нод в инвентаре)."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"When using bilinear/trilinear filtering, low-resolution textures\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"
|
||||
"texture autoscaling."
|
||||
msgstr ""
|
||||
"Когда используются билинейный/трилинейный/анизотропный фильтры, то текстуры "
|
||||
"низкого разрешения\n"
|
||||
"могут быть размытыми, поэтому они автоматически увеличиваются ближайшей\n"
|
||||
"интерполяцией для сохранения четкости пикселей. Это устанавливает "
|
||||
"минимальный размер текстуры\n"
|
||||
"для увеличенных текстур; большие значения выглядят чётче, но требуют больше\n"
|
||||
"памяти. Рекомендуются степени числа 2. Эта настройки применяется ТОЛЬКО "
|
||||
"если\n"
|
||||
"билинейный/трилинейный/анизотропный фильтр включен.\n"
|
||||
"Это также используется для автомасштабирования как основной размер для\n"
|
||||
"повёрнутых по сторонам света текстур блока."
|
||||
"При использовании билинейной/трилинейной фильтрации текстуры с низким "
|
||||
"разрешением\n"
|
||||
"могут быть размыты, поэтому этот параметр автоматически увеличивает их "
|
||||
"масштаб, чтобы сохранить\n"
|
||||
"четкие пиксели. Это определяет минимальный размер текстуры для текстур в "
|
||||
"увеличенном масштабе;\n"
|
||||
"более высокие значения выглядят четче, но требуют больше памяти.\n"
|
||||
"Этот параметр применяется ТОЛЬКО в том случае, если включен любой из "
|
||||
"упомянутых фильтров.\n"
|
||||
"Он также используется в качестве базового размера текстуры узла для\n"
|
||||
"автоматического масштабирования текстуры, выровненной по окружности."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
@ -7194,16 +7194,15 @@ msgid "Whether to fog out the end of the visible area."
|
|||
msgstr "Затуманивает конец видимой области."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"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"
|
||||
"pause menu."
|
||||
msgstr ""
|
||||
"Заглушает звуки. Вы можете включить звуки в любое время, если\n"
|
||||
"звуковая система не отключена (enable_sound=false).\n"
|
||||
"Внутри игры, вы можете включить переключать звуки, нажав на клавишу\n"
|
||||
"заглушения звука или используя меню паузы."
|
||||
"Следует ли отключать звук. Вы можете включить звук в любое время.\n"
|
||||
"В игре вы можете переключать режим отключения звука с помощью клавиши "
|
||||
"отключения звука\n"
|
||||
"или с помощью меню паузы."
|
||||
|
||||
#: src/settings_translation_file.cpp
|
||||
msgid ""
|
||||
|
|
6445
po/yue/luanti.po
6445
po/yue/luanti.po
File diff suppressed because it is too large
Load diff
|
@ -34,7 +34,7 @@ static constexpr f32 CAMERA_OFFSET_STEP = 200;
|
|||
#define WIELDMESH_AMPLITUDE_Y 10.0f
|
||||
|
||||
static const char *setting_names[] = {
|
||||
"fall_bobbing_amount", "view_bobbing_amount", "fov", "arm_inertia",
|
||||
"view_bobbing_amount", "fov", "arm_inertia",
|
||||
"show_nametag_backgrounds",
|
||||
};
|
||||
|
||||
|
@ -78,7 +78,6 @@ void Camera::readSettings()
|
|||
* (as opposed to the this local caching). This can be addressed in
|
||||
* 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);
|
||||
// 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.
|
||||
|
@ -130,13 +129,6 @@ inline f32 my_modf(f32 x)
|
|||
|
||||
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;
|
||||
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)
|
||||
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
|
||||
{
|
||||
v3f eye_offset = player->getEyeOffset();
|
||||
switch(m_camera_mode) {
|
||||
case CAMERA_MODE_ANY:
|
||||
assert(false);
|
||||
break;
|
||||
case CAMERA_MODE_FIRST:
|
||||
eye_offset += player->eye_offset_first;
|
||||
break;
|
||||
|
@ -389,7 +364,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
|||
}
|
||||
|
||||
// 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->setRotation(v3f(pitch, 0,
|
||||
cameratilt * player->hurt_tilt_strength));
|
||||
|
|
|
@ -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
|
||||
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);
|
||||
|
||||
// Toggle the current camera mode
|
||||
void toggleCameraMode() {
|
||||
void toggleCameraMode()
|
||||
{
|
||||
if (m_camera_mode == CAMERA_MODE_FIRST)
|
||||
m_camera_mode = CAMERA_MODE_THIRD;
|
||||
else if (m_camera_mode == CAMERA_MODE_THIRD)
|
||||
|
@ -185,7 +184,7 @@ public:
|
|||
}
|
||||
|
||||
//read the current camera mode
|
||||
inline CameraMode getCameraMode()
|
||||
inline CameraMode getCameraMode() const
|
||||
{
|
||||
return m_camera_mode;
|
||||
}
|
||||
|
@ -257,8 +256,6 @@ private:
|
|||
s32 m_view_bobbing_state = 0;
|
||||
// Speed of view bobbing animation
|
||||
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)
|
||||
f32 m_digging_anim = 0.0f;
|
||||
|
@ -273,7 +270,6 @@ private:
|
|||
|
||||
CameraMode m_camera_mode = CAMERA_MODE_FIRST;
|
||||
|
||||
f32 m_cache_fall_bobbing_amount;
|
||||
f32 m_cache_view_bobbing_amount;
|
||||
bool m_arm_inertia;
|
||||
|
||||
|
|
|
@ -398,11 +398,7 @@ void Client::step(float dtime)
|
|||
if (dtime > DTIME_LIMIT)
|
||||
dtime = DTIME_LIMIT;
|
||||
|
||||
m_animation_time += dtime;
|
||||
if(m_animation_time > 60.0)
|
||||
m_animation_time -= 60.0;
|
||||
|
||||
m_time_of_day_update_timer += dtime;
|
||||
m_animation_time = fmodf(m_animation_time + dtime, 60.0f);
|
||||
|
||||
ReceiveAll();
|
||||
|
||||
|
@ -450,20 +446,43 @@ void Client::step(float dtime)
|
|||
/*
|
||||
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)) {
|
||||
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,
|
||||
std::max(g_settings->getFloat("client_unload_unused_data_timeout"), 0.0f),
|
||||
g_settings->getS32("client_mapblock_limit"),
|
||||
&deleted_blocks);
|
||||
mapblock_limit, &deleted_blocks);
|
||||
|
||||
/*
|
||||
Send info to server
|
||||
NOTE: This loop is intentionally iterated the way it is.
|
||||
*/
|
||||
// Send info to server
|
||||
|
||||
std::vector<v3s16>::iterator i = deleted_blocks.begin();
|
||||
auto i = deleted_blocks.begin();
|
||||
std::vector<v3s16> sendlist;
|
||||
for(;;) {
|
||||
if(sendlist.size() == 255 || i == deleted_blocks.end()) {
|
||||
|
@ -644,9 +663,11 @@ void Client::step(float dtime)
|
|||
if (num_processed_meshes > 0)
|
||||
g_profiler->graphAdd("num_processed_meshes", num_processed_meshes);
|
||||
|
||||
auto shadow_renderer = RenderingEngine::get_shadow_renderer();
|
||||
if (shadow_renderer && force_update_shadows)
|
||||
shadow_renderer->setForceUpdateShadowMap();
|
||||
if (force_update_shadows && !g_settings->getFlag("performance_tradeoffs")) {
|
||||
auto shadow = RenderingEngine::get_shadow_renderer();
|
||||
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?).");
|
||||
}
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
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
|
||||
void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt, bool camera_inverted)
|
||||
{
|
||||
v3f pf = myplayer->getPosition() * 100;
|
||||
v3f sf = myplayer->getSpeed() * 100;
|
||||
v3s32 position = v3s32::from(myplayer->getPosition() * 100);
|
||||
v3s32 speed = v3s32::from(myplayer->getSpeed() * 100);
|
||||
s32 pitch = myplayer->getPitch() * 100;
|
||||
s32 yaw = myplayer->getYaw() * 100;
|
||||
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_dir = myplayer->control.movement_direction;
|
||||
|
||||
v3s32 position(pf.X, pf.Y, pf.Z);
|
||||
v3s32 speed(sf.X, sf.Y, sf.Z);
|
||||
|
||||
/*
|
||||
Format:
|
||||
[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)
|
||||
{
|
||||
{
|
||||
v3s16 p = nodepos;
|
||||
infostream<<"Client::addUpdateMeshTaskForNode(): "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;
|
||||
}
|
||||
infostream << "Client::addUpdateMeshTaskForNode(): " << nodepos << std::endl;
|
||||
|
||||
v3s16 blockpos = getNodeBlockPos(nodepos);
|
||||
v3s16 blockpos_relative = blockpos * MAP_BLOCKSIZE;
|
||||
|
|
|
@ -217,6 +217,7 @@ public:
|
|||
void handleCommand_MediaPush(NetworkPacket *pkt);
|
||||
void handleCommand_MinimapModes(NetworkPacket *pkt);
|
||||
void handleCommand_SetLighting(NetworkPacket *pkt);
|
||||
void handleCommand_Camera(NetworkPacket* pkt);
|
||||
|
||||
void ProcessData(NetworkPacket *pkt);
|
||||
|
||||
|
@ -485,23 +486,18 @@ private:
|
|||
u8 m_server_ser_ver;
|
||||
|
||||
// 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.
|
||||
u16 m_proto_ver = 0;
|
||||
|
||||
bool m_update_wielded_item = false;
|
||||
Inventory *m_inventory_from_server = nullptr;
|
||||
float m_inventory_from_server_age = 0.0f;
|
||||
s32 m_mapblock_limit_logged = 0;
|
||||
PacketCounter m_packetcounter;
|
||||
// Block mesh animation parameters
|
||||
float m_animation_time = 0.0f;
|
||||
int m_crack_level = -1;
|
||||
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;
|
||||
u32 m_last_chat_message_sent;
|
||||
float m_chat_message_allowance = 5.0f;
|
||||
|
@ -537,11 +533,6 @@ private:
|
|||
// Pending downloads of dynamic media (key: token)
|
||||
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
|
||||
float m_recommended_send_interval = 0.1f;
|
||||
|
||||
|
|
|
@ -441,8 +441,8 @@ void ClientEnvironment::getSelectedActiveObjects(
|
|||
GenericCAO* gcao = dynamic_cast<GenericCAO*>(obj);
|
||||
if (gcao != nullptr && gcao->getProperties().rotate_selectionbox) {
|
||||
gcao->getSceneNode()->updateAbsolutePosition();
|
||||
const v3f deg = obj->getSceneNode()->getAbsoluteTransformation().getRotationDegrees();
|
||||
collision = boxLineCollision(selection_box, deg,
|
||||
const v3f rad = obj->getSceneNode()->getAbsoluteTransformation().getRotationRadians();
|
||||
collision = boxLineCollision(selection_box, rad,
|
||||
rel_pos, line_vector, ¤t_intersection, ¤t_normal, ¤t_raw_normal);
|
||||
} else {
|
||||
collision = boxLineCollision(selection_box, rel_pos, line_vector,
|
||||
|
|
|
@ -36,6 +36,7 @@ enum ClientEventType : u8
|
|||
CE_SET_STARS,
|
||||
CE_OVERRIDE_DAY_NIGHT_RATIO,
|
||||
CE_CLOUD_PARAMS,
|
||||
CE_UPDATE_CAMERA,
|
||||
CLIENTEVENT_MAX,
|
||||
};
|
||||
|
||||
|
@ -66,11 +67,14 @@ struct ClientEventHudChange
|
|||
|
||||
struct ClientEvent
|
||||
{
|
||||
// TODO: should get rid of this ctor
|
||||
ClientEvent() : type(CE_NONE) {}
|
||||
|
||||
ClientEvent(ClientEventType type) : type(type) {}
|
||||
|
||||
ClientEventType type;
|
||||
union
|
||||
{
|
||||
// struct{
|
||||
//} none;
|
||||
struct
|
||||
{
|
||||
u16 amount;
|
||||
|
@ -86,8 +90,6 @@ struct ClientEvent
|
|||
std::string *formspec;
|
||||
std::string *formname;
|
||||
} show_formspec;
|
||||
// struct{
|
||||
//} textures_updated;
|
||||
ParticleParameters *spawn_particle;
|
||||
struct
|
||||
{
|
||||
|
|
|
@ -52,6 +52,13 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc,
|
|||
|
||||
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->setHardwareMappingHint(scene::EHM_DYNAMIC);
|
||||
}
|
||||
|
@ -366,6 +373,19 @@ void Clouds::render()
|
|||
if (SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
|
||||
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();
|
||||
|
||||
// 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?
|
||||
m_camera_pos = camera_p;
|
||||
m_camera_inside_cloud = false; // default
|
||||
m_camera_inside_cloud = false;
|
||||
if (is3D()) {
|
||||
float camera_height = camera_p.Y - BS * m_camera_offset.Y;
|
||||
if (camera_height >= m_box.MinEdge.Y &&
|
||||
camera_height <= m_box.MaxEdge.Y) {
|
||||
v2f camera_in_noise;
|
||||
camera_in_noise.X = floor((camera_p.X - m_origin.X) / cloud_size + 0.5);
|
||||
camera_in_noise.Y = floor((camera_p.Z - m_origin.Y) / cloud_size + 0.5);
|
||||
camera_in_noise.X = floorf((camera_p.X - m_origin.X) / cloud_size + 0.5f);
|
||||
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);
|
||||
m_camera_inside_cloud = filled;
|
||||
}
|
||||
|
|
|
@ -134,8 +134,11 @@ private:
|
|||
{
|
||||
float height_bs = m_params.height * BS;
|
||||
float thickness_bs = m_params.thickness * BS;
|
||||
m_box = aabb3f(-BS * 1000000.0f, height_bs, -BS * 1000000.0f,
|
||||
BS * 1000000.0f, height_bs + thickness_bs, BS * 1000000.0f);
|
||||
float far_bs = 1000000.0f * BS;
|
||||
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();
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "client/sound.h"
|
||||
#include "client/texturesource.h"
|
||||
#include "client/mapblock_mesh.h"
|
||||
#include "client/content_mapblock.h"
|
||||
#include "client/meshgen/collector.h"
|
||||
#include "util/basic_macros.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/serialize.h"
|
||||
|
@ -180,6 +182,55 @@ static void setColorParam(scene::ISceneNode *node, video::SColor 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
|
||||
*/
|
||||
|
@ -572,6 +623,8 @@ void GenericCAO::removeFromScene(bool permanent)
|
|||
m_spritenode = nullptr;
|
||||
}
|
||||
|
||||
m_meshnode_animation.clear();
|
||||
|
||||
if (m_matrixnode) {
|
||||
m_matrixnode->remove();
|
||||
m_matrixnode->drop();
|
||||
|
@ -602,8 +655,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
|||
|
||||
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();
|
||||
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);
|
||||
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->grab();
|
||||
};
|
||||
m_matrixnode = m_smgr->addDummyTransformationSceneNode();
|
||||
m_matrixnode->grab();
|
||||
|
||||
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.forEachTexture([] (auto &tex) {
|
||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
||||
|
@ -637,28 +691,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
|||
node->forEachMaterial(setMaterial);
|
||||
};
|
||||
|
||||
if (m_prop.visual == "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();
|
||||
if (m_prop.visual == "upright_sprite") {
|
||||
auto mesh = make_irr<scene::SMesh>();
|
||||
f32 dx = BS * m_prop.visual_size.X / 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->grab();
|
||||
} else if (m_prop.visual == "cube") {
|
||||
grabMatrixNode();
|
||||
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
|
||||
m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode);
|
||||
m_meshnode->grab();
|
||||
|
@ -714,7 +746,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
|||
mat.BackfaceCulling = m_prop.backface_culling;
|
||||
});
|
||||
} else if (m_prop.visual == "mesh") {
|
||||
grabMatrixNode();
|
||||
scene::IAnimatedMesh *mesh = m_client->getMesh(m_prop.mesh, true);
|
||||
if (mesh) {
|
||||
if (!checkMeshNormals(mesh)) {
|
||||
|
@ -741,7 +772,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
|||
} else
|
||||
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
|
||||
} else if (m_prop.visual == "wielditem" || m_prop.visual == "item") {
|
||||
grabMatrixNode();
|
||||
ItemStack item;
|
||||
if (m_prop.wield_item.empty()) {
|
||||
// Old format, only textures are specified.
|
||||
|
@ -761,9 +791,35 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
|||
(m_prop.visual == "wielditem"));
|
||||
|
||||
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 {
|
||||
infostream<<"GenericCAO::addToScene(): \""<<m_prop.visual
|
||||
<<"\" not supported"<<std::endl;
|
||||
m_spritenode = m_smgr->addBillboardSceneNode(m_matrixnode);
|
||||
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 */
|
||||
|
@ -789,8 +845,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
|
|||
updateTextures(m_current_texture_modifier);
|
||||
|
||||
if (scene::ISceneNode *node = getSceneNode()) {
|
||||
if (m_matrixnode)
|
||||
node->setParent(m_matrixnode);
|
||||
node->setParent(m_matrixnode);
|
||||
|
||||
if (auto shadow = RenderingEngine::get_shadow_renderer())
|
||||
shadow->addNodeToShadowList(node);
|
||||
|
@ -861,8 +916,7 @@ void GenericCAO::updateLight(u32 day_night_ratio)
|
|||
if (!pos_ok)
|
||||
light_at_pos = LIGHT_SUN;
|
||||
|
||||
// Initialize with full alpha, otherwise entity won't be visible
|
||||
video::SColor light{0xFFFFFFFF};
|
||||
video::SColor light;
|
||||
|
||||
// Encode light into color, adding a small boost
|
||||
// based on the entity glow.
|
||||
|
@ -965,6 +1019,7 @@ void GenericCAO::updateNodePos()
|
|||
scene::ISceneNode *node = getSceneNode();
|
||||
|
||||
if (node) {
|
||||
assert(m_matrixnode);
|
||||
v3s16 camera_offset = m_env->getCameraOffset();
|
||||
v3f pos = pos_translator.val_current -
|
||||
intToFloat(camera_offset, BS);
|
||||
|
@ -1153,7 +1208,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
|
|||
m_anim_frame = 0;
|
||||
}
|
||||
|
||||
updateTexturePos();
|
||||
updateTextureAnim();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void GenericCAO::updateTexturePos()
|
||||
void GenericCAO::updateTextureAnim()
|
||||
{
|
||||
if(m_spritenode)
|
||||
{
|
||||
|
@ -1279,6 +1334,23 @@ void GenericCAO::updateTexturePos()
|
|||
auto mesh = m_meshnode->getMesh();
|
||||
setMeshBufferTextureCoords(mesh->getMeshBuffer(0), 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);
|
||||
material.MaterialType = m_material_type;
|
||||
material.MaterialTypeParam = m_material_type_param;
|
||||
material.setTexture(0, tsrc->getTextureForMesh(texturestring));
|
||||
|
||||
material.forEachTexture([=] (auto &tex) {
|
||||
|
@ -1333,7 +1404,6 @@ void GenericCAO::updateTextures(std::string mod)
|
|||
// Set material flags and texture
|
||||
video::SMaterial &material = m_animated_meshnode->getMaterial(i);
|
||||
material.MaterialType = m_material_type;
|
||||
material.MaterialTypeParam = m_material_type_param;
|
||||
material.TextureLayers[0].Texture = texture;
|
||||
material.BackfaceCulling = m_prop.backface_culling;
|
||||
|
||||
|
@ -1365,7 +1435,6 @@ void GenericCAO::updateTextures(std::string mod)
|
|||
// Set material flags and texture
|
||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||
material.MaterialType = m_material_type;
|
||||
material.MaterialTypeParam = m_material_type_param;
|
||||
material.setTexture(0, tsrc->getTextureForMesh(texturestring));
|
||||
material.getTextureMatrix(0).makeIdentity();
|
||||
|
||||
|
@ -1532,7 +1601,7 @@ bool GenericCAO::visualExpiryRequired(const ObjectProperties &new_) const
|
|||
/* Visuals do not need to be expired for:
|
||||
* - nametag props: handled by updateNametag()
|
||||
* - textures: handled by updateTextures()
|
||||
* - sprite props: handled by updateTexturePos()
|
||||
* - sprite props: handled by updateTextureAnim()
|
||||
* - glow: handled by updateLight()
|
||||
* - 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
|
||||
return old.backface_culling != new_.backface_culling ||
|
||||
old.is_visible != new_.is_visible ||
|
||||
old.mesh != new_.mesh ||
|
||||
old.shaded != new_.shaded ||
|
||||
old.use_texture_alpha != new_.use_texture_alpha ||
|
||||
old.node != new_.node ||
|
||||
old.mesh != new_.mesh ||
|
||||
old.visual != new_.visual ||
|
||||
old.visual_size != new_.visual_size ||
|
||||
old.wield_item != new_.wield_item ||
|
||||
|
@ -1655,7 +1725,7 @@ void GenericCAO::processMessage(const std::string &data)
|
|||
m_anim_framelength = framelength;
|
||||
m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
|
||||
|
||||
updateTexturePos();
|
||||
updateTextureAnim();
|
||||
} else if (cmd == AO_CMD_SET_PHYSICS_OVERRIDE) {
|
||||
float override_speed = readF32(is);
|
||||
float override_jump = readF32(is);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "clientobject.h"
|
||||
#include "constants.h"
|
||||
#include "itemgroup.h"
|
||||
#include "client/tile.h"
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
@ -27,7 +28,7 @@ struct Nametag;
|
|||
struct MinimapMarker;
|
||||
|
||||
/*
|
||||
SmoothTranslator
|
||||
SmoothTranslator and other helpers
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
|
@ -60,9 +61,21 @@ struct SmoothTranslatorWrappedv3f : SmoothTranslator<v3f>
|
|||
void translate(f32 dtime);
|
||||
};
|
||||
|
||||
struct MeshAnimationInfo {
|
||||
u32 i; /// index of mesh buffer
|
||||
int frame; /// last animation frame
|
||||
TileLayer tile;
|
||||
};
|
||||
|
||||
/*
|
||||
GenericCAO
|
||||
*/
|
||||
|
||||
class GenericCAO : public ClientActiveObject
|
||||
{
|
||||
private:
|
||||
static constexpr auto EMT_INVALID = video::EMT_FORCE_32BIT;
|
||||
|
||||
// Only set at initialization
|
||||
std::string m_name = "";
|
||||
bool m_is_player = false;
|
||||
|
@ -73,6 +86,8 @@ private:
|
|||
scene::ISceneManager *m_smgr = nullptr;
|
||||
Client *m_client = nullptr;
|
||||
aabb3f m_selection_box = aabb3f(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.);
|
||||
|
||||
// Visuals
|
||||
scene::IMeshSceneNode *m_meshnode = nullptr;
|
||||
scene::IAnimatedMeshSceneNode *m_animated_meshnode = nullptr;
|
||||
WieldMeshSceneNode *m_wield_meshnode = nullptr;
|
||||
|
@ -80,6 +95,15 @@ private:
|
|||
scene::IDummyTransformationSceneNode *m_matrixnode = nullptr;
|
||||
Nametag *m_nametag = 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_velocity;
|
||||
v3f m_acceleration;
|
||||
|
@ -87,18 +111,25 @@ private:
|
|||
u16 m_hp = 1;
|
||||
SmoothTranslator<v3f> pos_translator;
|
||||
SmoothTranslatorWrappedv3f rot_translator;
|
||||
// Spritesheet/animation stuff
|
||||
|
||||
// Spritesheet stuff
|
||||
v2f m_tx_size = v2f(1,1);
|
||||
v2s16 m_tx_basepos;
|
||||
bool m_initial_tx_basepos_set = false;
|
||||
bool m_tx_select_horiz_by_yawpitch = false;
|
||||
bool m_animation_loop = true;
|
||||
v2f m_animation_range;
|
||||
float m_animation_speed = 15.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
|
||||
BoneOverrideMap m_bone_override;
|
||||
|
||||
// Attachments
|
||||
object_t m_attachment_parent_id = 0;
|
||||
std::unordered_set<object_t> m_attachment_child_ids;
|
||||
std::string m_attachment_bone = "";
|
||||
|
@ -107,23 +138,13 @@ private:
|
|||
bool m_attached_to_local = 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;
|
||||
float m_reset_textures_timer = -1.0f;
|
||||
// stores texture modifier before punch update
|
||||
std::string m_previous_texture_modifier = "";
|
||||
// last applied texture modifier
|
||||
std::string m_current_texture_modifier = "";
|
||||
bool m_visuals_expired = false;
|
||||
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;
|
||||
|
||||
|
@ -255,7 +276,7 @@ public:
|
|||
|
||||
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
|
||||
// Reason: updateTextures(m_previous_texture_modifier);
|
||||
|
|
|
@ -121,7 +121,7 @@ void MapblockMeshGenerator::drawQuad(const TileSpec &tile, v3f *coords, const v3
|
|||
v2f(1.0, vertical_tiling), v2f(0.0, vertical_tiling)};
|
||||
video::S3DVertex vertices[4];
|
||||
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++) {
|
||||
vertices[j].Pos = coords[j] + cur_node.origin;
|
||||
vertices[j].Normal = normal2;
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
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()) {
|
||||
std::list<FuncSpec> &funcs = i->second.funcs;
|
||||
for (FuncSpec &func : funcs) {
|
||||
|
@ -44,7 +44,7 @@ public:
|
|||
}
|
||||
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()) {
|
||||
i->second.funcs.emplace_back(f, data);
|
||||
} else {
|
||||
|
|
|
@ -278,7 +278,7 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
|
|||
};
|
||||
|
||||
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();
|
||||
if (auto *font = createFont(face))
|
||||
return font;
|
||||
|
|
|
@ -564,6 +564,7 @@ protected:
|
|||
void updatePauseState();
|
||||
void step(f32 dtime);
|
||||
void processClientEvents(CameraOrientation *cam);
|
||||
void updateCameraMode(); // call after changing it
|
||||
void updateCameraOffset();
|
||||
void updateCamera(f32 dtime);
|
||||
void updateSound(f32 dtime);
|
||||
|
@ -665,6 +666,7 @@ private:
|
|||
void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
|
||||
CameraOrientation *cam);
|
||||
void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
|
||||
void handleClientEvent_UpdateCamera(ClientEvent *event, CameraOrientation *cam);
|
||||
|
||||
void updateChat(f32 dtime);
|
||||
|
||||
|
@ -754,7 +756,6 @@ private:
|
|||
f32 m_repeat_dig_time;
|
||||
f32 m_cache_cam_smoothing;
|
||||
|
||||
bool m_enable_relative_mode = false;
|
||||
bool m_invert_mouse;
|
||||
bool m_enable_hotbar_mouse_wheel;
|
||||
bool m_invert_hotbar_mouse_wheel;
|
||||
|
@ -770,9 +771,10 @@ private:
|
|||
bool m_is_paused = false;
|
||||
|
||||
bool m_touch_simulate_aux1 = false;
|
||||
bool m_touch_use_crosshair;
|
||||
inline bool isTouchCrosshairDisabled() {
|
||||
return !m_touch_use_crosshair && camera->getCameraMode() == CAMERA_MODE_FIRST;
|
||||
inline bool isTouchShootlineUsed()
|
||||
{
|
||||
return g_touchcontrols && g_touchcontrols->isShootlineAvailable() &&
|
||||
camera->getCameraMode() == CAMERA_MODE_FIRST;
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
bool m_android_chat_open;
|
||||
|
@ -821,8 +823,6 @@ Game::Game() :
|
|||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("pause_on_lost_focus",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("touch_use_crosshair",
|
||||
&settingChangedCallback, this);
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
@ -899,15 +899,6 @@ bool Game::startup(bool *kill,
|
|||
|
||||
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();
|
||||
|
||||
// address can change if simple_singleplayer_mode
|
||||
|
@ -968,7 +959,7 @@ void Game::run()
|
|||
// Calculate dtime =
|
||||
// m_rendering_engine->run() from this iteration
|
||||
// + Sleep time until the wanted FPS are reached
|
||||
draw_times.limit(device, &dtime, g_menumgr.pausesGame());
|
||||
draw_times.limit(device, &dtime);
|
||||
|
||||
framemarker.start();
|
||||
|
||||
|
@ -1378,10 +1369,8 @@ bool Game::initGui()
|
|||
gui_chat_console = make_irr<GUIChatConsole>(guienv, guienv->getRootGUIElement(),
|
||||
-1, chat_backend, client, &g_menumgr);
|
||||
|
||||
if (shouldShowTouchControls()) {
|
||||
if (shouldShowTouchControls())
|
||||
g_touchcontrols = new TouchControls(device, texture_src);
|
||||
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1921,6 +1910,9 @@ void Game::processKeyInput()
|
|||
toggleFog();
|
||||
} else if (wasKeyDown(KeyType::TOGGLE_UPDATE_CAMERA)) {
|
||||
toggleUpdateCamera();
|
||||
} else if (wasKeyPressed(KeyType::CAMERA_MODE)) {
|
||||
camera->toggleCameraMode();
|
||||
updateCameraMode();
|
||||
} else if (wasKeyPressed(KeyType::TOGGLE_DEBUG)) {
|
||||
toggleDebug();
|
||||
} 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,
|
||||
this results in duplicated input. To avoid that, we don't enable relative
|
||||
mouse mode if we're in touchscreen mode. */
|
||||
if (cur_control) {
|
||||
cur_control->setRelativeMode(m_enable_relative_mode &&
|
||||
!g_touchcontrols && !isMenuActive());
|
||||
}
|
||||
if (cur_control)
|
||||
cur_control->setRelativeMode(!g_touchcontrols && !isMenuActive());
|
||||
|
||||
if ((device->isWindowActive() && device->isWindowFocused()
|
||||
&& !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 = 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;
|
||||
|
||||
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");
|
||||
fps_max = std::max(fps_max, 1.0f);
|
||||
|
@ -2575,6 +2565,7 @@ const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
|
|||
{&Game::handleClientEvent_SetStars},
|
||||
{&Game::handleClientEvent_OverrideDayNigthRatio},
|
||||
{&Game::handleClientEvent_CloudParams},
|
||||
{&Game::handleClientEvent_UpdateCamera},
|
||||
};
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
while (client->hasClientEvents()) {
|
||||
|
@ -2935,12 +2933,7 @@ void Game::updateCamera(f32 dtime)
|
|||
ClientEnvironment &env = client->getEnv();
|
||||
LocalPlayer *player = env.getLocalPlayer();
|
||||
|
||||
/*
|
||||
For interaction purposes, get info about the held item
|
||||
- What item is it?
|
||||
- Is it a usable item?
|
||||
- Can it point to liquids?
|
||||
*/
|
||||
// For interaction purposes, get info about the held item
|
||||
ItemStack playeritem;
|
||||
{
|
||||
ItemStack selected, hand;
|
||||
|
@ -2950,23 +2943,6 @@ void Game::updateCamera(f32 dtime)
|
|||
ToolCapabilities playeritem_toolcap =
|
||||
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 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()
|
||||
{
|
||||
ClientEnvironment &env = client->getEnv();
|
||||
|
@ -2997,8 +2989,13 @@ void Game::updateCameraOffset()
|
|||
|
||||
if (!m_flags.disable_camera_update) {
|
||||
auto *shadow = RenderingEngine::get_shadow_renderer();
|
||||
if (shadow)
|
||||
if (shadow) {
|
||||
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(),
|
||||
camera->getDirection(), camera->getFovMax(), camera_offset,
|
||||
|
@ -3057,6 +3054,9 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||
core::line3d<f32> shootline;
|
||||
|
||||
switch (camera->getCameraMode()) {
|
||||
case CAMERA_MODE_ANY:
|
||||
assert(false);
|
||||
break;
|
||||
case CAMERA_MODE_FIRST:
|
||||
// Shoot from camera position, with bobbing
|
||||
shootline.start = camera->getPosition();
|
||||
|
@ -3073,7 +3073,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||
}
|
||||
shootline.end = shootline.start + camera_direction * BS * d;
|
||||
|
||||
if (g_touchcontrols && isTouchCrosshairDisabled()) {
|
||||
if (isTouchShootlineUsed()) {
|
||||
shootline = g_touchcontrols->getShootline();
|
||||
// Scale shootline to the acual distance the player can reach
|
||||
shootline.end = shootline.start +
|
||||
|
@ -3232,9 +3232,10 @@ PointedThing Game::updatePointedThing(
|
|||
hud->setSelectionPos(pos, camera_offset);
|
||||
GenericCAO* gcao = dynamic_cast<GenericCAO*>(runData.selected_object);
|
||||
if (gcao != nullptr && gcao->getProperties().rotate_selectionbox)
|
||||
hud->setSelectionRotation(gcao->getSceneNode()->getAbsoluteTransformation().getRotationDegrees());
|
||||
hud->setSelectionRotationRadians(gcao->getSceneNode()
|
||||
->getAbsoluteTransformation().getRotationRadians());
|
||||
else
|
||||
hud->setSelectionRotation(v3f());
|
||||
hud->setSelectionRotationRadians(v3f());
|
||||
}
|
||||
hud->setSelectedFaceNormal(result.raw_intersection_normal);
|
||||
} else if (result.type == POINTEDTHING_NODE) {
|
||||
|
@ -3244,17 +3245,15 @@ PointedThing Game::updatePointedThing(
|
|||
n.getSelectionBoxes(nodedef, &boxes,
|
||||
n.getNeighbors(result.node_undersurface, &map));
|
||||
|
||||
f32 d = 0.002 * BS;
|
||||
for (std::vector<aabb3f>::const_iterator i = boxes.begin();
|
||||
i != boxes.end(); ++i) {
|
||||
aabb3f box = *i;
|
||||
f32 d = 0.002f * BS;
|
||||
for (aabb3f box : boxes) {
|
||||
box.MinEdge -= v3f(d, d, d);
|
||||
box.MaxEdge += v3f(d, d, d);
|
||||
selectionboxes->push_back(box);
|
||||
}
|
||||
hud->setSelectionPos(intToFloat(result.node_undersurface, BS),
|
||||
camera_offset);
|
||||
hud->setSelectionRotation(v3f());
|
||||
hud->setSelectionRotationRadians(v3f());
|
||||
hud->setSelectedFaceNormal(result.intersection_normal);
|
||||
}
|
||||
|
||||
|
@ -3449,9 +3448,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||
u8 predicted_param2 = dir.Y < 0 ? 1 : 0;
|
||||
if (selected_def.wallmounted_rotate_vertical) {
|
||||
bool rotate90 = false;
|
||||
v3f fnodepos = v3f(neighborpos.X, neighborpos.Y, neighborpos.Z);
|
||||
v3f ppos = client->getEnv().getLocalPlayer()->getPosition() / BS;
|
||||
v3f pdir = fnodepos - ppos;
|
||||
v3f pdir = v3f::from(neighborpos) - ppos;
|
||||
switch (predicted_f.drawtype) {
|
||||
case NDT_TORCHLIKE: {
|
||||
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) &&
|
||||
(this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
|
||||
|
||||
if (g_touchcontrols && isTouchCrosshairDisabled())
|
||||
if (isTouchShootlineUsed())
|
||||
draw_crosshair = false;
|
||||
|
||||
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_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());
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
@ -283,9 +283,7 @@ void GameFormSpec::showPauseMenuFormSpec(const std::string &formspec, const std:
|
|||
&m_input->joystick, fs_src, txt_dst, "",
|
||||
m_client->getSoundManager());
|
||||
|
||||
// FIXME: can't enable this for now because "fps_max_unfocused" also applies
|
||||
// when the game is paused, making the settings menu much less enjoyable.
|
||||
// m_formspec->doPause = true;
|
||||
m_formspec->doPause = true;
|
||||
}
|
||||
|
||||
void GameFormSpec::showNodeFormspec(const std::string &formspec, const v3s16 &nodepos)
|
||||
|
@ -376,18 +374,18 @@ void GameFormSpec::showPauseMenu()
|
|||
<< strgettext("Continue") << "]";
|
||||
|
||||
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") << "]";
|
||||
} else {
|
||||
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") << "]";
|
||||
|
||||
#ifndef __ANDROID__
|
||||
#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") << "]";
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -880,7 +880,7 @@ void Hud::drawSelectionMesh()
|
|||
core::matrix4 translate;
|
||||
translate.setTranslation(m_selection_pos_with_offset);
|
||||
core::matrix4 rotation;
|
||||
rotation.setRotationDegrees(m_selection_rotation);
|
||||
rotation.setRotationRadians(m_selection_rotation_radians);
|
||||
driver->setTransform(video::ETS_WORLD, translate * rotation);
|
||||
|
||||
if (m_mode == HIGHLIGHT_BOX) {
|
||||
|
@ -965,8 +965,8 @@ void Hud::drawBlockBounds()
|
|||
v3f pmax = v3f(x, y, 1 + radius) * MAP_BLOCKSIZE * BS;
|
||||
|
||||
driver->draw3DLine(
|
||||
base_corner + v3f(pmin.X, pmin.Y, pmin.Z),
|
||||
base_corner + v3f(pmax.X, pmax.Y, pmax.Z),
|
||||
base_corner + pmin,
|
||||
base_corner + pmax,
|
||||
choose_color(block_pos.X, block_pos.Y)
|
||||
);
|
||||
driver->draw3DLine(
|
||||
|
|
|
@ -74,9 +74,15 @@ public:
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -129,7 +135,7 @@ private:
|
|||
std::vector<aabb3f> m_halo_boxes;
|
||||
v3f m_selection_pos;
|
||||
v3f m_selection_pos_with_offset;
|
||||
v3f m_selection_rotation;
|
||||
v3f m_selection_rotation_radians;
|
||||
|
||||
scene::IMesh *m_selection_mesh = nullptr;
|
||||
video::SColor m_selection_mesh_color;
|
||||
|
|
|
@ -285,13 +285,13 @@ void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::I
|
|||
maxsx = minsx + sw / dim.Width;
|
||||
maxsx = rangelim(maxsx, 0, sox + sw);
|
||||
if (minsx > maxsx)
|
||||
SWAP(double, minsx, maxsx);
|
||||
std::swap(minsx, maxsx);
|
||||
minsy = soy + (dy * sh / dim.Height);
|
||||
minsy = rangelim(minsy, 0, soy + sh);
|
||||
maxsy = minsy + sh / dim.Height;
|
||||
maxsy = rangelim(maxsy, 0, soy + sh);
|
||||
if (minsy > maxsy)
|
||||
SWAP(double, minsy, maxsy);
|
||||
std::swap(minsy, maxsy);
|
||||
|
||||
// Total area, and integral of r, g, b values over that area,
|
||||
// initialized to zero, to be summed up in next loops.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -668,7 +654,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||
{
|
||||
PreMeshBuffer &p = collector.prebuffers[layer][i];
|
||||
|
||||
applyTileColor(p);
|
||||
p.applyTileColor();
|
||||
|
||||
// Generate animation data
|
||||
// - Cracks
|
||||
|
@ -701,28 +687,16 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||
|
||||
// Create material
|
||||
video::SMaterial material;
|
||||
material.BackfaceCulling = true;
|
||||
material.FogEnable = true;
|
||||
material.setTexture(0, p.layer.texture);
|
||||
material.forEachTexture([] (auto &tex) {
|
||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_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(
|
||||
p.layer.shader_id).material;
|
||||
p.layer.applyMaterialOptionsWithShaders(material);
|
||||
p.layer.applyMaterialOptions(material, layer);
|
||||
}
|
||||
|
||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
|
|
|
@ -145,8 +145,7 @@ QueuedMeshUpdate *MeshUpdateQueue::pop()
|
|||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
bool must_be_urgent = !m_urgents.empty();
|
||||
for (std::vector<QueuedMeshUpdate*>::iterator i = m_queue.begin();
|
||||
i != m_queue.end(); ++i) {
|
||||
for (auto i = m_queue.begin(); i != m_queue.end(); ++i) {
|
||||
QueuedMeshUpdate *q = *i;
|
||||
if (must_be_urgent && m_urgents.count(q->p) == 0)
|
||||
continue;
|
||||
|
@ -264,8 +263,8 @@ void MeshUpdateManager::updateBlock(Map *map, v3s16 p, bool ack_block_to_server,
|
|||
g_settings->getBool("smooth_lighting")
|
||||
&& !g_settings->getFlag("performance_tradeoffs");
|
||||
if (!m_queue_in.addBlock(map, p, ack_block_to_server, urgent)) {
|
||||
warningstream << "Update requested for non-existent block at ("
|
||||
<< p.X << ", " << p.Y << ", " << p.Z << ")" << std::endl;
|
||||
warningstream << "Update requested for non-existent block at "
|
||||
<< p << std::endl;
|
||||
return;
|
||||
}
|
||||
if (update_neighbors) {
|
||||
|
|
|
@ -18,6 +18,21 @@ struct PreMeshBuffer
|
|||
|
||||
PreMeshBuffer() = default;
|
||||
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
|
||||
|
|
|
@ -78,15 +78,13 @@ void MinimapUpdateThread::doUpdate()
|
|||
while (popBlockUpdate(&update)) {
|
||||
if (update.data) {
|
||||
// Swap two values in the map using single lookup
|
||||
std::pair<std::map<v3s16, MinimapMapblock*>::iterator, bool>
|
||||
result = m_blocks_cache.insert(std::make_pair(update.pos, update.data));
|
||||
auto result = m_blocks_cache.insert(std::make_pair(update.pos, update.data));
|
||||
if (!result.second) {
|
||||
delete result.first->second;
|
||||
result.first->second = update.data;
|
||||
}
|
||||
} else {
|
||||
std::map<v3s16, MinimapMapblock *>::iterator it;
|
||||
it = m_blocks_cache.find(update.pos);
|
||||
auto it = m_blocks_cache.find(update.pos);
|
||||
if (it != m_blocks_cache.end()) {
|
||||
delete it->second;
|
||||
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.Y = blockpos_min.Y; blockpos.Y <= blockpos_max.Y; ++blockpos.Y)
|
||||
for (blockpos.X = blockpos_min.X; blockpos.X <= blockpos_max.X; ++blockpos.X) {
|
||||
std::map<v3s16, MinimapMapblock *>::const_iterator pblock =
|
||||
m_blocks_cache.find(blockpos);
|
||||
auto pblock = m_blocks_cache.find(blockpos);
|
||||
if (pblock == m_blocks_cache.end())
|
||||
continue;
|
||||
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 cos_angle = std::cos(m_angle * core::DEGTORAD);
|
||||
s32 marker_size2 = 0.025 * (float)rect.getWidth();;
|
||||
for (std::list<v2f>::const_iterator
|
||||
i = m_active_markers.begin();
|
||||
for (auto i = m_active_markers.begin();
|
||||
i != m_active_markers.end(); ++i) {
|
||||
v2f posf = *i;
|
||||
if (data->minimap_shape_round) {
|
||||
|
|
|
@ -193,7 +193,7 @@ void Particle::updateVertices(ClientEnvironment *env, video::SColor color)
|
|||
video::S3DVertex *vertices = m_buffer->getVertices(m_index);
|
||||
|
||||
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
|
||||
scale = v2f(1.f, 1.f);
|
||||
|
||||
|
@ -203,7 +203,7 @@ void Particle::updateVertices(ClientEnvironment *env, video::SColor color)
|
|||
v2u32 framesize;
|
||||
texcoord = m_p.animation.getTextureCoords(texsize, m_animation_frame);
|
||||
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;
|
||||
tx1 = m_texpos.X + texcoord.X + framesize_f.X * m_texsize.X;
|
||||
|
|
|
@ -34,9 +34,9 @@ void FpsControl::reset()
|
|||
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_unfocused");
|
||||
const u64 frametime_min = 1000000.0f / std::max(fps_limit, 1.0f);
|
||||
|
|
|
@ -45,7 +45,7 @@ struct FpsControl {
|
|||
|
||||
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; }
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ void DirectionalLight::createSplitMatrices(const Camera *cam)
|
|||
// adjusted frustum boundaries
|
||||
float sfNear = future_frustum.zNear;
|
||||
float sfFar = adjustDist(future_frustum.zFar, cam->getFovY());
|
||||
assert(sfFar - sfNear > 0);
|
||||
|
||||
// adjusted camera positions
|
||||
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.ProjOrthMat.buildProjectionMatrixOrthoLH(radius, radius,
|
||||
0.0f, length, false);
|
||||
future_frustum.camera_offset = cam->getOffset();
|
||||
}
|
||||
|
||||
DirectionalLight::DirectionalLight(const u32 shadowMapResolution,
|
||||
|
@ -86,6 +86,8 @@ DirectionalLight::DirectionalLight(const u32 shadowMapResolution,
|
|||
|
||||
void DirectionalLight::updateCameraOffset(const Camera *cam)
|
||||
{
|
||||
if (future_frustum.zFar == 0.0f) // not initialized
|
||||
return;
|
||||
createSplitMatrices(cam);
|
||||
should_update_map_shadow = true;
|
||||
dirty = true;
|
||||
|
|
|
@ -22,7 +22,6 @@ struct shadowFrustum
|
|||
core::matrix4 ViewMat;
|
||||
v3f position;
|
||||
v3f player;
|
||||
v3s16 camera_offset;
|
||||
};
|
||||
|
||||
class DirectionalLight
|
||||
|
@ -85,6 +84,7 @@ public:
|
|||
return mapRes;
|
||||
}
|
||||
|
||||
/// If true, shadow map needs to be invalidated due to frustum change
|
||||
bool should_update_map_shadow{true};
|
||||
|
||||
void commitFrustum();
|
||||
|
|
|
@ -177,14 +177,15 @@ void ShadowRenderer::removeNodeFromShadowList(scene::ISceneNode *node)
|
|||
node->forEachMaterial([] (auto &mat) {
|
||||
mat.setTexture(TEXTURE_LAYER_SHADOW, nullptr);
|
||||
});
|
||||
for (auto it = m_shadow_node_array.begin(); it != m_shadow_node_array.end();) {
|
||||
if (it->node == node) {
|
||||
it = m_shadow_node_array.erase(it);
|
||||
break;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
|
||||
auto it = std::find(m_shadow_node_array.begin(), m_shadow_node_array.end(), node);
|
||||
if (it == m_shadow_node_array.end()) {
|
||||
infostream << "removeNodeFromShadowList: " << node << " not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
// swap with last, then remove
|
||||
*it = m_shadow_node_array.back();
|
||||
m_shadow_node_array.pop_back();
|
||||
}
|
||||
|
||||
void ShadowRenderer::updateSMTextures()
|
||||
|
@ -254,17 +255,14 @@ void ShadowRenderer::updateSMTextures()
|
|||
if (!m_shadow_node_array.empty()) {
|
||||
bool reset_sm_texture = false;
|
||||
|
||||
// detect if SM should be regenerated
|
||||
// clear texture if requested
|
||||
for (DirectionalLight &light : m_light_list) {
|
||||
if (light.should_update_map_shadow)
|
||||
m_force_update_shadow_map = true;
|
||||
reset_sm_texture |= light.should_update_map_shadow;
|
||||
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;
|
||||
reset_sm_texture = true;
|
||||
}
|
||||
|
||||
video::ITexture* shadowMapTargetTexture = shadowMapClientMapFuture;
|
||||
if (shadowMapTargetTexture == nullptr)
|
||||
|
@ -273,7 +271,7 @@ void ShadowRenderer::updateSMTextures()
|
|||
// Update SM incrementally:
|
||||
for (DirectionalLight &light : m_light_list) {
|
||||
// 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) {
|
||||
cb->MapRes = (f32)m_shadow_map_texture_size;
|
||||
cb->MaxFar = (f32)m_shadow_map_max_distance * BS;
|
||||
|
@ -281,12 +279,9 @@ void ShadowRenderer::updateSMTextures()
|
|||
cb->PerspectiveBiasZ = getPerspectiveBiasZ();
|
||||
cb->CameraPos = light.getFuturePlayerPos();
|
||||
}
|
||||
}
|
||||
|
||||
// set the Render Target
|
||||
// right now we can only render in usual RTT, not
|
||||
// Depth texture is available in irrlicth maybe we
|
||||
// should put some gl* fn here
|
||||
|
||||
// Note that force_update means we're drawing everything one go.
|
||||
|
||||
if (m_current_frame < m_map_shadow_update_frames || m_force_update_shadow_map) {
|
||||
m_driver->setRenderTarget(shadowMapTargetTexture, reset_sm_texture, true,
|
||||
|
|
|
@ -28,7 +28,8 @@ struct NodeToApply
|
|||
E_SHADOW_MODE m = E_SHADOW_MODE::ESM_BOTH) :
|
||||
node(n),
|
||||
shadowMode(m){};
|
||||
bool operator<(const NodeToApply &other) const { return node < other.node; };
|
||||
|
||||
bool operator==(scene::ISceneNode *n) const { return node == n; }
|
||||
|
||||
scene::ISceneNode *node;
|
||||
|
||||
|
@ -68,6 +69,7 @@ public:
|
|||
void removeNodeFromShadowList(scene::ISceneNode *node);
|
||||
|
||||
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 drawDebug();
|
||||
|
||||
|
|
|
@ -4,41 +4,10 @@
|
|||
|
||||
#include "tile.h"
|
||||
|
||||
// Sets everything else except the texture in the material
|
||||
void TileLayer::applyMaterialOptions(video::SMaterial &material) const
|
||||
void TileLayer::applyMaterialOptions(video::SMaterial &material, int layer) const
|
||||
{
|
||||
switch (material_type) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
material.setTexture(0, texture);
|
||||
|
||||
void TileLayer::applyMaterialOptionsWithShaders(video::SMaterial &material) const
|
||||
{
|
||||
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;
|
||||
|
@ -48,4 +17,15 @@ void TileLayer::applyMaterialOptionsWithShaders(video::SMaterial &material) cons
|
|||
material.TextureLayers[0].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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <vector>
|
||||
#include <SMaterial.h>
|
||||
|
||||
enum MaterialType{
|
||||
enum MaterialType : u8 {
|
||||
TILE_MATERIAL_BASIC,
|
||||
TILE_MATERIAL_ALPHA,
|
||||
TILE_MATERIAL_LIQUID_TRANSPARENT,
|
||||
|
@ -84,9 +84,13 @@ struct TileLayer
|
|||
return !(*this == other);
|
||||
}
|
||||
|
||||
void applyMaterialOptions(video::SMaterial &material) const;
|
||||
|
||||
void applyMaterialOptionsWithShaders(video::SMaterial &material) const;
|
||||
/**
|
||||
* Set some material parameters accordingly.
|
||||
* @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?
|
||||
bool isTransparent() const
|
||||
|
@ -98,8 +102,9 @@ struct TileLayer
|
|||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ordered for size, please do not reorder
|
||||
|
@ -113,13 +118,14 @@ struct TileLayer
|
|||
u16 animation_frame_length_ms = 0;
|
||||
u16 animation_frame_count = 1;
|
||||
|
||||
u8 material_type = TILE_MATERIAL_BASIC;
|
||||
MaterialType material_type = TILE_MATERIAL_BASIC;
|
||||
u8 material_flags =
|
||||
//0 // <- DEBUG, Use the one below
|
||||
MATERIAL_FLAG_BACKFACE_CULLING |
|
||||
MATERIAL_FLAG_TILEABLE_HORIZONTAL|
|
||||
MATERIAL_FLAG_TILEABLE_VERTICAL;
|
||||
|
||||
/// @note not owned by this struct
|
||||
std::vector<FrameSpec> *frames = nullptr;
|
||||
|
||||
/*!
|
||||
|
|
|
@ -154,8 +154,7 @@ public:
|
|||
|
||||
int maxdim = MYMAX(dim.Width, dim.Height);
|
||||
|
||||
std::map<int, scene::IMesh*>::iterator
|
||||
it = m_extrusion_meshes.lower_bound(maxdim);
|
||||
auto it = m_extrusion_meshes.lower_bound(maxdim);
|
||||
|
||||
if (it == m_extrusion_meshes.end()) {
|
||||
// no viable resolution found; use largest one
|
||||
|
@ -204,7 +203,6 @@ WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id):
|
|||
// Create the child scene node
|
||||
scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube();
|
||||
m_meshnode = SceneManager->addMeshSceneNode(dummymesh, this, -1);
|
||||
m_meshnode->setReadOnlyMaterials(false);
|
||||
m_meshnode->setVisible(false);
|
||||
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(),
|
||||
&p.indices[0], p.indices.size());
|
||||
|
||||
// Set up material
|
||||
buf->Material.setTexture(0, p.layer.texture);
|
||||
if (layer == 1) {
|
||||
buf->Material.PolygonOffsetSlopeScale = -1;
|
||||
buf->Material.PolygonOffsetDepthBias = -1;
|
||||
}
|
||||
p.layer.applyMaterialOptions(buf->Material);
|
||||
// note: material type is left unset, overriden later
|
||||
p.layer.applyMaterialOptions(buf->Material, layer);
|
||||
|
||||
mesh->addMeshBuffer(buf.get());
|
||||
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();
|
||||
for (u32 i = 0; i < material_count; ++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.MaterialTypeParam = 0.5f;
|
||||
material.forEachTexture([this] (auto &tex) {
|
||||
|
|
|
@ -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:
|
||||
|
@ -101,6 +109,8 @@ CollisionAxis axisAlignedCollision(
|
|||
|
||||
if (speed.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);
|
||||
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;
|
||||
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;
|
||||
for (p.Z = min.Z; p.Z <= max.Z; p.Z++)
|
||||
for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
|
||||
for (p.X = min.X; p.X <= max.X; p.X++) {
|
||||
bool is_position_valid;
|
||||
MapNode n = map->getNode(p, &is_position_valid);
|
||||
v3s16 bp, relp;
|
||||
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) {
|
||||
// Object collides into walkable nodes
|
||||
if (!block) {
|
||||
// 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;
|
||||
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();
|
||||
n.getCollisionBoxes(nodedef, &nodeboxes, neighbors);
|
||||
|
||||
// Calculate float position only once
|
||||
v3f posf = intToFloat(p, BS);
|
||||
for (auto box : nodeboxes) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
// Collide with unloaded nodes (position invalid) and loaded
|
||||
// CONTENT_IGNORE nodes (position valid)
|
||||
// Collide with loaded CONTENT_IGNORE nodes
|
||||
aabb3f box = getNodeBox(p, BS);
|
||||
cinfo.emplace_back(true, 0, p, box);
|
||||
}
|
||||
}
|
||||
|
||||
return any_position_valid;
|
||||
}
|
||||
|
||||
|
@ -335,6 +378,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
|
||||
collisionMoveResult result;
|
||||
|
||||
// Assume no collisions when no velocity and no acceleration
|
||||
if (*speed_f == v3f() && accel_f == v3f())
|
||||
return result;
|
||||
|
||||
/*
|
||||
Calculate new velocity
|
||||
*/
|
||||
|
@ -350,30 +397,19 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
time_notification_done = false;
|
||||
}
|
||||
|
||||
v3f dpos_f = (*speed_f + accel_f * 0.5f * dtime) * dtime;
|
||||
v3f newpos_f = *pos_f + dpos_f;
|
||||
*speed_f += accel_f * dtime;
|
||||
|
||||
// If the object is static, there are no collisions
|
||||
if (dpos_f == v3f())
|
||||
return result;
|
||||
|
||||
// Average speed
|
||||
v3f aspeed_f = *speed_f + accel_f * 0.5f * dtime;
|
||||
// Limit speed for avoiding hangs
|
||||
speed_f->Y = rangelim(speed_f->Y, -5000, 5000);
|
||||
speed_f->X = rangelim(speed_f->X, -5000, 5000);
|
||||
speed_f->Z = rangelim(speed_f->Z, -5000, 5000);
|
||||
aspeed_f = truncate(rangelimv(aspeed_f, -5000.0f, 5000.0f), 10000.0f);
|
||||
|
||||
*speed_f = truncate(*speed_f, 10000.0f);
|
||||
|
||||
/*
|
||||
Collect node boxes in movement range
|
||||
*/
|
||||
// Collect node boxes in movement range
|
||||
|
||||
// cached allocation
|
||||
thread_local std::vector<NearbyCollisionInfo> cinfo;
|
||||
cinfo.clear();
|
||||
|
||||
{
|
||||
// Movement if no collisions
|
||||
v3f newpos_f = *pos_f + aspeed_f * dtime;
|
||||
v3f minpos_f(
|
||||
MYMIN(pos_f->X, newpos_f.X),
|
||||
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) {
|
||||
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;
|
||||
|
||||
int loopcount = 0;
|
||||
|
||||
while(dtime > BS * 1e-10f) {
|
||||
// Avoid infinite loop
|
||||
loopcount++;
|
||||
for (int loopcount = 0;; loopcount++) {
|
||||
if (loopcount >= 100) {
|
||||
warningstream << "collisionMoveSimple: Loop count exceeded, aborting to avoid infinite loop" << std::endl;
|
||||
g_collision_problems_encountered = true;
|
||||
|
@ -431,9 +457,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
f32 nearest_dtime = dtime;
|
||||
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++) {
|
||||
const NearbyCollisionInfo &box_info = cinfo[boxindex];
|
||||
// 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)
|
||||
f32 dtime_tmp = nearest_dtime;
|
||||
CollisionAxis collided = axisAlignedCollision(box_info.box,
|
||||
movingbox, *speed_f, &dtime_tmp);
|
||||
|
||||
movingbox, aspeed_f, &dtime_tmp);
|
||||
if (collided == -1 || dtime_tmp >= nearest_dtime)
|
||||
continue;
|
||||
|
||||
|
@ -455,95 +478,119 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
|
||||
if (nearest_collided == COLLISION_AXIS_NONE) {
|
||||
// No collision with any collision box.
|
||||
*pos_f += truncate(*speed_f * dtime, 100.0f);
|
||||
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
|
||||
} else {
|
||||
// Otherwise, a collision occurred.
|
||||
NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
|
||||
const aabb3f& cbox = nearest_info.box;
|
||||
*pos_f += aspeed_f * dtime;
|
||||
// Final speed:
|
||||
*speed_f += accel_f * dtime;
|
||||
// Limit speed for avoiding hangs
|
||||
*speed_f = truncate(rangelimv(*speed_f, -5000.0f, 5000.0f), 10000.0f);
|
||||
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;
|
||||
stepbox.MinEdge.X += speed_f->X * dtime;
|
||||
stepbox.MinEdge.Z += speed_f->Z * dtime;
|
||||
stepbox.MaxEdge.X += speed_f->X * dtime;
|
||||
stepbox.MaxEdge.Z += speed_f->Z * dtime;
|
||||
// Look slightly ahead for checking the height when stepping
|
||||
// to ensure we also check above the node we collided with
|
||||
// otherwise, might allow glitches such as a stack of stairs
|
||||
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.
|
||||
bool step_up = (nearest_collided != COLLISION_AXIS_Y) && // must not be Y direction
|
||||
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
||||
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
||||
(!wouldCollideWithCeiling(cinfo, stepbox,
|
||||
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
||||
d));
|
||||
step_up = (movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
||||
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
||||
(!wouldCollideWithCeiling(cinfo, stepbox,
|
||||
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
||||
d));
|
||||
}
|
||||
|
||||
// Get bounce multiplier
|
||||
float bounce = -(float)nearest_info.bouncy / 100.0f;
|
||||
// Get bounce multiplier
|
||||
float bounce = -(float)nearest_info.bouncy / 100.0f;
|
||||
|
||||
// Move to the point of collision and reduce dtime by nearest_dtime
|
||||
if (nearest_dtime < 0) {
|
||||
// Handle negative nearest_dtime
|
||||
if (!step_up) {
|
||||
if (nearest_collided == COLLISION_AXIS_X)
|
||||
pos_f->X += speed_f->X * nearest_dtime;
|
||||
if (nearest_collided == COLLISION_AXIS_Y)
|
||||
pos_f->Y += speed_f->Y * nearest_dtime;
|
||||
if (nearest_collided == COLLISION_AXIS_Z)
|
||||
pos_f->Z += speed_f->Z * nearest_dtime;
|
||||
}
|
||||
} else {
|
||||
*pos_f += truncate(*speed_f * nearest_dtime, 100.0f);
|
||||
dtime -= nearest_dtime;
|
||||
// Move to the point of collision and reduce dtime by nearest_dtime
|
||||
if (nearest_dtime < 0) {
|
||||
// Handle negative nearest_dtime
|
||||
// This largely means an "instant" collision, e.g., with the floor.
|
||||
// We use aspeed and nearest_dtime to be consistent with above and resolve this collision
|
||||
if (!step_up) {
|
||||
if (nearest_collided == COLLISION_AXIS_X)
|
||||
pos_f->X += aspeed_f.X * nearest_dtime;
|
||||
if (nearest_collided == COLLISION_AXIS_Y)
|
||||
pos_f->Y += aspeed_f.Y * nearest_dtime;
|
||||
if (nearest_collided == COLLISION_AXIS_Z)
|
||||
pos_f->Z += aspeed_f.Z * 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;
|
||||
if (nearest_info.is_unloaded)
|
||||
is_collision = false;
|
||||
v3f old_speed_f = *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;
|
||||
} 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;
|
||||
if (nearest_info.isObject())
|
||||
info.type = COLLISION_OBJECT;
|
||||
else
|
||||
info.type = COLLISION_NODE;
|
||||
|
||||
info.axis = nearest_collided;
|
||||
info.type = nearest_info.isObject() ? COLLISION_OBJECT : COLLISION_NODE;
|
||||
info.node_p = nearest_info.position;
|
||||
info.object = nearest_info.obj;
|
||||
info.new_pos = *pos_f;
|
||||
info.old_speed = *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.old_speed = old_speed_f;
|
||||
info.new_speed = *speed_f;
|
||||
if (info.new_speed.getDistanceFrom(info.old_speed) < 0.1f * BS)
|
||||
is_collision = false;
|
||||
|
||||
if (is_collision) {
|
||||
info.axis = nearest_collided;
|
||||
result.collisions.push_back(std::move(info));
|
||||
}
|
||||
result.collisions.push_back(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;
|
||||
}
|
||||
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;
|
||||
|
||||
if (box_info.isObject())
|
||||
result.standing_on_object = true;
|
||||
result.standing_on_object = box_info.isObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.collides = !result.collisions.empty();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,8 +140,6 @@ void ModConfiguration::addModsFromConfig(
|
|||
*
|
||||
* Alternative candidates for a modname are stored in `candidates`,
|
||||
* and used in an error message later.
|
||||
*
|
||||
* If not enabled, add `load_mod_modname = false` to world.mt
|
||||
*/
|
||||
for (const auto &modPath : modPaths) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
conf.setBool("load_mod_" + mod.name, false);
|
||||
conf.remove("load_mod_" + mod.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,15 +30,13 @@ void Database_Dummy::loadBlock(const v3s16 &pos, std::string *block)
|
|||
|
||||
bool Database_Dummy::deleteBlock(const v3s16 &pos)
|
||||
{
|
||||
m_database.erase(getBlockAsInteger(pos));
|
||||
return true;
|
||||
return m_database.erase(getBlockAsInteger(pos)) > 0;
|
||||
}
|
||||
|
||||
void Database_Dummy::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
||||
{
|
||||
dst.reserve(m_database.size());
|
||||
for (std::map<s64, std::string>::const_iterator x = m_database.begin();
|
||||
x != m_database.end(); ++x) {
|
||||
for (auto x = m_database.begin(); x != m_database.end(); ++x) {
|
||||
dst.push_back(getIntegerAsBlock(x->first));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,8 +234,7 @@ void PlayerDatabaseFiles::listPlayers(std::vector<std::string> &res)
|
|||
{
|
||||
std::vector<fs::DirListNode> files = fs::GetDirListing(m_savedir);
|
||||
// list files into players directory
|
||||
for (std::vector<fs::DirListNode>::const_iterator it = files.begin(); it !=
|
||||
files.end(); ++it) {
|
||||
for (auto it = files.begin(); it != files.end(); ++it) {
|
||||
// Ignore directories
|
||||
if (it->dir)
|
||||
continue;
|
||||
|
|
|
@ -97,7 +97,7 @@ void Database_PostgreSQL::ping()
|
|||
|
||||
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)
|
||||
|
|
|
@ -9,20 +9,20 @@
|
|||
#include "database.h"
|
||||
#include "util/basic_macros.h"
|
||||
|
||||
class Settings;
|
||||
|
||||
class Database_PostgreSQL: public Database
|
||||
// Template class for PostgreSQL based data storage
|
||||
class Database_PostgreSQL : public Database
|
||||
{
|
||||
public:
|
||||
Database_PostgreSQL(const std::string &connect_string, const char *type);
|
||||
~Database_PostgreSQL();
|
||||
|
||||
void beginSave();
|
||||
void endSave();
|
||||
void beginSave() override;
|
||||
void endSave() override;
|
||||
void rollback();
|
||||
|
||||
bool initialized() const;
|
||||
bool initialized() const override;
|
||||
|
||||
void verifyDatabase() override;
|
||||
|
||||
protected:
|
||||
// Conversion helpers
|
||||
|
@ -73,7 +73,6 @@ protected:
|
|||
}
|
||||
|
||||
void createTableIfNotExists(const std::string &table_name, const std::string &definition);
|
||||
void verifyDatabase();
|
||||
|
||||
// Database initialization
|
||||
void connectToDatabase();
|
||||
|
@ -99,6 +98,12 @@ private:
|
|||
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
|
||||
{
|
||||
public:
|
||||
|
@ -110,8 +115,7 @@ public:
|
|||
bool deleteBlock(const v3s16 &pos);
|
||||
void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
||||
|
||||
void beginSave() { Database_PostgreSQL::beginSave(); }
|
||||
void endSave() { Database_PostgreSQL::endSave(); }
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
|
@ -129,6 +133,8 @@ public:
|
|||
bool removePlayer(const std::string &name);
|
||||
void listPlayers(std::vector<std::string> &res);
|
||||
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
virtual void initStatements();
|
||||
|
@ -143,8 +149,6 @@ public:
|
|||
AuthDatabasePostgreSQL(const std::string &connect_string);
|
||||
virtual ~AuthDatabasePostgreSQL() = default;
|
||||
|
||||
virtual void verifyDatabase() { Database_PostgreSQL::verifyDatabase(); }
|
||||
|
||||
virtual bool getAuth(const std::string &name, AuthEntry &res);
|
||||
virtual bool saveAuth(const AuthEntry &authEntry);
|
||||
virtual bool createAuth(AuthEntry &authEntry);
|
||||
|
@ -152,6 +156,8 @@ public:
|
|||
virtual void listNames(std::vector<std::string> &res);
|
||||
virtual void reload();
|
||||
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
virtual void initStatements();
|
||||
|
@ -176,10 +182,11 @@ public:
|
|||
bool removeModEntries(const std::string &modname);
|
||||
void listMods(std::vector<std::string> *res);
|
||||
|
||||
void beginSave() { Database_PostgreSQL::beginSave(); }
|
||||
void endSave() { Database_PostgreSQL::endSave(); }
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
virtual void initStatements();
|
||||
};
|
||||
|
||||
#undef PARENT_CLASS_FUNCS
|
||||
|
|
|
@ -2,14 +2,6 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
/*
|
||||
SQLite format specification:
|
||||
blocks:
|
||||
(PK) INT id
|
||||
BLOB data
|
||||
*/
|
||||
|
||||
|
||||
#include "database-sqlite3.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
|
||||
// Note: I've seen occasional delays of over 250ms while running minetestmapper.
|
||||
#define BUSY_INFO_TRESHOLD 100 // Print first informational message after 100ms.
|
||||
#define BUSY_WARNING_TRESHOLD 250 // Print warning message after 250ms. Lag is increased.
|
||||
#define BUSY_ERROR_TRESHOLD 1000 // Print error message after 1000ms. Significant lag.
|
||||
#define BUSY_FATAL_TRESHOLD 3000 // Allow SQLITE_BUSY to be returned, which will cause a minetest crash.
|
||||
#define BUSY_ERROR_INTERVAL 10000 // Safety net: report again every 10 seconds
|
||||
enum {
|
||||
BUSY_INFO_TRESHOLD = 100, // Print first informational message.
|
||||
BUSY_WARNING_TRESHOLD = 250, // Print warning message. Significant lag.
|
||||
BUSY_FATAL_TRESHOLD = 3000, // Allow SQLITE_BUSY to be returned back to the caller.
|
||||
BUSY_ERROR_INTERVAL = 10000, // Safety net: report again every 10 seconds
|
||||
};
|
||||
|
||||
|
||||
#define SQLRES(s, r, m) \
|
||||
if ((s) != (r)) { \
|
||||
throw DatabaseException(std::string(m) + ": " +\
|
||||
sqlite3_errmsg(m_database)); \
|
||||
}
|
||||
#define SQLRES(s, r, m) sqlite3_vrfy(s, m, r);
|
||||
#define SQLOK(s, m) SQLRES(s, SQLITE_OK, m)
|
||||
|
||||
#define PREPARE_STATEMENT(name, query) \
|
||||
SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL),\
|
||||
"Failed to prepare query '" query "'")
|
||||
SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL), \
|
||||
std::string("Failed to prepare query \"").append(query).append("\""))
|
||||
|
||||
#define SQLOK_ERRSTREAM(s, m) \
|
||||
if ((s) != SQLITE_OK) { \
|
||||
|
@ -50,52 +38,49 @@ SQLite format specification:
|
|||
<< sqlite3_errmsg(m_database) << std::endl; \
|
||||
}
|
||||
|
||||
#define FINALIZE_STATEMENT(statement) SQLOK_ERRSTREAM(sqlite3_finalize(statement), \
|
||||
"Failed to finalize " #statement)
|
||||
#define FINALIZE_STATEMENT(name) \
|
||||
sqlite3_finalize(m_stmt_##name); /* if this fails who cares */ \
|
||||
m_stmt_##name = nullptr;
|
||||
|
||||
int Database_SQLite3::busyHandler(void *data, int count)
|
||||
{
|
||||
s64 &first_time = reinterpret_cast<s64 *>(data)[0];
|
||||
s64 &prev_time = reinterpret_cast<s64 *>(data)[1];
|
||||
s64 cur_time = porting::getTimeMs();
|
||||
u64 &first_time = reinterpret_cast<u64*>(data)[0];
|
||||
u64 &prev_time = reinterpret_cast<u64*>(data)[1];
|
||||
u64 cur_time = porting::getTimeMs();
|
||||
|
||||
if (count == 0) {
|
||||
first_time = cur_time;
|
||||
prev_time = first_time;
|
||||
} else {
|
||||
while (cur_time < prev_time)
|
||||
cur_time += s64(1)<<32;
|
||||
}
|
||||
|
||||
if (cur_time - first_time < BUSY_INFO_TRESHOLD) {
|
||||
; // do nothing
|
||||
} else if (cur_time - first_time >= BUSY_INFO_TRESHOLD &&
|
||||
prev_time - first_time < BUSY_INFO_TRESHOLD) {
|
||||
const auto total_diff = cur_time - first_time; // time since first call
|
||||
const auto this_diff = prev_time - first_time; // time since last call
|
||||
|
||||
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 "
|
||||
<< cur_time - first_time << " ms." << std::endl;
|
||||
} else if (cur_time - first_time >= BUSY_WARNING_TRESHOLD &&
|
||||
prev_time - first_time < BUSY_WARNING_TRESHOLD) {
|
||||
<< total_diff << " ms." << std::endl;
|
||||
} else if (total_diff >= BUSY_WARNING_TRESHOLD &&
|
||||
this_diff < BUSY_WARNING_TRESHOLD) {
|
||||
warningstream << "SQLite3 database has been locked for "
|
||||
<< cur_time - first_time << " ms." << std::endl;
|
||||
} else if (cur_time - first_time >= BUSY_ERROR_TRESHOLD &&
|
||||
prev_time - first_time < BUSY_ERROR_TRESHOLD) {
|
||||
<< total_diff << " ms; this causes lag." << std::endl;
|
||||
} else if (total_diff >= BUSY_FATAL_TRESHOLD &&
|
||||
this_diff < BUSY_FATAL_TRESHOLD) {
|
||||
errorstream << "SQLite3 database has been locked for "
|
||||
<< cur_time - first_time << " ms; this causes lag." << std::endl;
|
||||
} else if (cur_time - first_time >= BUSY_FATAL_TRESHOLD &&
|
||||
prev_time - first_time < BUSY_FATAL_TRESHOLD) {
|
||||
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) {
|
||||
<< total_diff << " ms - giving up!" << std::endl;
|
||||
} else if (total_diff / BUSY_ERROR_INTERVAL !=
|
||||
this_diff / BUSY_ERROR_INTERVAL) {
|
||||
// Safety net: keep reporting every BUSY_ERROR_INTERVAL
|
||||
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;
|
||||
|
||||
// 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
|
||||
|
||||
if (!fs::CreateAllDirs(m_savedir)) {
|
||||
infostream << "Database_SQLite3: Failed to create directory \""
|
||||
errorstream << "Database_SQLite3: Failed to create directory \""
|
||||
<< m_savedir << "\"" << std::endl;
|
||||
throw FileNotGoodException("Failed to create database "
|
||||
"save directory");
|
||||
|
@ -138,8 +123,11 @@ void Database_SQLite3::openDatabase()
|
|||
|
||||
bool needs_create = !fs::PathExists(dbp);
|
||||
|
||||
SQLOK(sqlite3_open_v2(dbp.c_str(), &m_database,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL),
|
||||
auto flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
#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);
|
||||
|
||||
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 = ")
|
||||
+ itos(g_settings->getU16("sqlite_synchronous"));
|
||||
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),
|
||||
"Failed to enable sqlite3 foreign key support");
|
||||
"Failed to enable SQLite3 foreign key support");
|
||||
}
|
||||
|
||||
void Database_SQLite3::verifyDatabase()
|
||||
|
@ -171,10 +159,47 @@ void Database_SQLite3::verifyDatabase()
|
|||
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()
|
||||
{
|
||||
FINALIZE_STATEMENT(m_stmt_begin)
|
||||
FINALIZE_STATEMENT(m_stmt_end)
|
||||
FINALIZE_STATEMENT(begin)
|
||||
FINALIZE_STATEMENT(end)
|
||||
|
||||
SQLOK_ERRSTREAM(sqlite3_close(m_database), "Failed to close database");
|
||||
}
|
||||
|
@ -191,40 +216,68 @@ MapDatabaseSQLite3::MapDatabaseSQLite3(const std::string &savedir):
|
|||
|
||||
MapDatabaseSQLite3::~MapDatabaseSQLite3()
|
||||
{
|
||||
FINALIZE_STATEMENT(m_stmt_read)
|
||||
FINALIZE_STATEMENT(m_stmt_write)
|
||||
FINALIZE_STATEMENT(m_stmt_list)
|
||||
FINALIZE_STATEMENT(m_stmt_delete)
|
||||
FINALIZE_STATEMENT(read)
|
||||
FINALIZE_STATEMENT(write)
|
||||
FINALIZE_STATEMENT(list)
|
||||
FINALIZE_STATEMENT(delete)
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
" `pos` INT PRIMARY KEY,\n"
|
||||
" `data` BLOB\n"
|
||||
");\n",
|
||||
NULL, NULL, NULL),
|
||||
"`x` INTEGER,"
|
||||
"`y` INTEGER,"
|
||||
"`z` INTEGER,"
|
||||
"`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");
|
||||
}
|
||||
|
||||
void MapDatabaseSQLite3::initStatements()
|
||||
{
|
||||
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`");
|
||||
assert(checkTable("blocks"));
|
||||
m_new_format = checkColumn("blocks", "z");
|
||||
infostream << "MapDatabaseSQLite3: split column format = "
|
||||
<< (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)),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
if (m_new_format) {
|
||||
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)
|
||||
|
@ -237,7 +290,7 @@ bool MapDatabaseSQLite3::deleteBlock(const v3s16 &pos)
|
|||
sqlite3_reset(m_stmt_delete);
|
||||
|
||||
if (!good) {
|
||||
warningstream << "deleteBlock: Block failed to delete "
|
||||
warningstream << "deleteBlock: Failed to delete block "
|
||||
<< pos << ": " << sqlite3_errmsg(m_database) << std::endl;
|
||||
}
|
||||
return good;
|
||||
|
@ -247,9 +300,8 @@ bool MapDatabaseSQLite3::saveBlock(const v3s16 &pos, std::string_view data)
|
|||
{
|
||||
verifyDatabase();
|
||||
|
||||
bindPos(m_stmt_write, pos);
|
||||
SQLOK(sqlite3_bind_blob(m_stmt_write, 2, data.data(), data.size(), NULL),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
int col = bindPos(m_stmt_write, pos);
|
||||
blob_to_sqlite(m_stmt_write, col, data);
|
||||
|
||||
SQLRES(sqlite3_step(m_stmt_write), SQLITE_DONE, "Failed to save block")
|
||||
sqlite3_reset(m_stmt_write);
|
||||
|
@ -264,6 +316,7 @@ void MapDatabaseSQLite3::loadBlock(const v3s16 &pos, std::string *block)
|
|||
bindPos(m_stmt_read, pos);
|
||||
|
||||
if (sqlite3_step(m_stmt_read) != SQLITE_ROW) {
|
||||
block->clear();
|
||||
sqlite3_reset(m_stmt_read);
|
||||
return;
|
||||
}
|
||||
|
@ -271,7 +324,6 @@ void MapDatabaseSQLite3::loadBlock(const v3s16 &pos, std::string *block)
|
|||
auto data = sqlite_to_blob(m_stmt_read, 0);
|
||||
block->assign(data);
|
||||
|
||||
sqlite3_step(m_stmt_read);
|
||||
// We should never get more than 1 row, so ok to reset
|
||||
sqlite3_reset(m_stmt_read);
|
||||
}
|
||||
|
@ -280,8 +332,17 @@ void MapDatabaseSQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
|||
{
|
||||
verifyDatabase();
|
||||
|
||||
while (sqlite3_step(m_stmt_list) == SQLITE_ROW)
|
||||
dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0)));
|
||||
v3s16 p;
|
||||
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);
|
||||
}
|
||||
|
@ -298,35 +359,38 @@ PlayerDatabaseSQLite3::PlayerDatabaseSQLite3(const std::string &savedir):
|
|||
|
||||
PlayerDatabaseSQLite3::~PlayerDatabaseSQLite3()
|
||||
{
|
||||
FINALIZE_STATEMENT(m_stmt_player_load)
|
||||
FINALIZE_STATEMENT(m_stmt_player_add)
|
||||
FINALIZE_STATEMENT(m_stmt_player_update)
|
||||
FINALIZE_STATEMENT(m_stmt_player_remove)
|
||||
FINALIZE_STATEMENT(m_stmt_player_list)
|
||||
FINALIZE_STATEMENT(m_stmt_player_add_inventory)
|
||||
FINALIZE_STATEMENT(m_stmt_player_add_inventory_items)
|
||||
FINALIZE_STATEMENT(m_stmt_player_remove_inventory)
|
||||
FINALIZE_STATEMENT(m_stmt_player_remove_inventory_items)
|
||||
FINALIZE_STATEMENT(m_stmt_player_load_inventory)
|
||||
FINALIZE_STATEMENT(m_stmt_player_load_inventory_items)
|
||||
FINALIZE_STATEMENT(m_stmt_player_metadata_load)
|
||||
FINALIZE_STATEMENT(m_stmt_player_metadata_add)
|
||||
FINALIZE_STATEMENT(m_stmt_player_metadata_remove)
|
||||
FINALIZE_STATEMENT(player_load)
|
||||
FINALIZE_STATEMENT(player_add)
|
||||
FINALIZE_STATEMENT(player_update)
|
||||
FINALIZE_STATEMENT(player_remove)
|
||||
FINALIZE_STATEMENT(player_list)
|
||||
FINALIZE_STATEMENT(player_add_inventory)
|
||||
FINALIZE_STATEMENT(player_add_inventory_items)
|
||||
FINALIZE_STATEMENT(player_remove_inventory)
|
||||
FINALIZE_STATEMENT(player_remove_inventory_items)
|
||||
FINALIZE_STATEMENT(player_load_inventory)
|
||||
FINALIZE_STATEMENT(player_load_inventory_items)
|
||||
FINALIZE_STATEMENT(player_metadata_load)
|
||||
FINALIZE_STATEMENT(player_metadata_add)
|
||||
FINALIZE_STATEMENT(player_metadata_remove)
|
||||
};
|
||||
|
||||
|
||||
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,
|
||||
"CREATE TABLE IF NOT EXISTS `player` ("
|
||||
"`name` VARCHAR(50) NOT NULL,"
|
||||
"`pitch` NUMERIC(11, 4) NOT NULL,"
|
||||
"`yaw` NUMERIC(11, 4) NOT NULL,"
|
||||
"`posX` NUMERIC(11, 4) NOT NULL,"
|
||||
"`posY` NUMERIC(11, 4) NOT NULL,"
|
||||
"`posZ` NUMERIC(11, 4) NOT NULL,"
|
||||
"`name` TEXT NOT NULL,"
|
||||
"`pitch` NUMERIC NOT NULL,"
|
||||
"`yaw` NUMERIC NOT NULL,"
|
||||
"`posX` NUMERIC NOT NULL,"
|
||||
"`posY` NUMERIC NOT NULL,"
|
||||
"`posZ` NUMERIC NOT NULL,"
|
||||
"`hp` INT NOT NULL,"
|
||||
"`breath` INT NOT NULL,"
|
||||
"`creation_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,"
|
||||
|
@ -337,9 +401,9 @@ void PlayerDatabaseSQLite3::createDatabase()
|
|||
|
||||
SQLOK(sqlite3_exec(m_database,
|
||||
"CREATE TABLE IF NOT EXISTS `player_metadata` ("
|
||||
" `player` VARCHAR(50) NOT NULL,"
|
||||
" `metadata` VARCHAR(256) NOT NULL,"
|
||||
" `value` TEXT,"
|
||||
" `player` TEXT NOT NULL,"
|
||||
" `metadata` TEXT NOT NULL,"
|
||||
" `value` TEXT NOT NULL,"
|
||||
" PRIMARY KEY(`player`, `metadata`),"
|
||||
" FOREIGN KEY (`player`) REFERENCES player (`name`) ON DELETE CASCADE );",
|
||||
NULL, NULL, NULL),
|
||||
|
@ -347,7 +411,7 @@ void PlayerDatabaseSQLite3::createDatabase()
|
|||
|
||||
SQLOK(sqlite3_exec(m_database,
|
||||
"CREATE TABLE IF NOT EXISTS `player_inventories` ("
|
||||
" `player` VARCHAR(50) NOT NULL,"
|
||||
" `player` TEXT NOT NULL,"
|
||||
" `inv_id` INT NOT NULL,"
|
||||
" `inv_width` INT NOT NULL,"
|
||||
" `inv_name` TEXT NOT NULL DEFAULT '',"
|
||||
|
@ -359,7 +423,7 @@ void PlayerDatabaseSQLite3::createDatabase()
|
|||
|
||||
SQLOK(sqlite3_exec(m_database,
|
||||
"CREATE TABLE `player_inventory_items` ("
|
||||
" `player` VARCHAR(50) NOT NULL,"
|
||||
" `player` TEXT NOT NULL,"
|
||||
" `inv_id` INT NOT NULL,"
|
||||
" `slot_id` INT NOT NULL,"
|
||||
" `item` TEXT NOT NULL DEFAULT '',"
|
||||
|
@ -401,7 +465,6 @@ void PlayerDatabaseSQLite3::initStatements()
|
|||
"(`player`, `metadata`, `value`) VALUES (?, ?, ?)")
|
||||
PREPARE_STATEMENT(player_metadata_remove, "DELETE FROM `player_metadata` "
|
||||
"WHERE `player` = ?")
|
||||
verbosestream << "ServerEnvironment: SQLite3 database opened (players)." << std::endl;
|
||||
}
|
||||
|
||||
bool PlayerDatabaseSQLite3::playerDataExists(const std::string &name)
|
||||
|
@ -588,27 +651,27 @@ AuthDatabaseSQLite3::AuthDatabaseSQLite3(const std::string &savedir) :
|
|||
|
||||
AuthDatabaseSQLite3::~AuthDatabaseSQLite3()
|
||||
{
|
||||
FINALIZE_STATEMENT(m_stmt_read)
|
||||
FINALIZE_STATEMENT(m_stmt_write)
|
||||
FINALIZE_STATEMENT(m_stmt_create)
|
||||
FINALIZE_STATEMENT(m_stmt_delete)
|
||||
FINALIZE_STATEMENT(m_stmt_list_names)
|
||||
FINALIZE_STATEMENT(m_stmt_read_privs)
|
||||
FINALIZE_STATEMENT(m_stmt_write_privs)
|
||||
FINALIZE_STATEMENT(m_stmt_delete_privs)
|
||||
FINALIZE_STATEMENT(m_stmt_last_insert_rowid)
|
||||
FINALIZE_STATEMENT(read)
|
||||
FINALIZE_STATEMENT(write)
|
||||
FINALIZE_STATEMENT(create)
|
||||
FINALIZE_STATEMENT(delete)
|
||||
FINALIZE_STATEMENT(list_names)
|
||||
FINALIZE_STATEMENT(read_privs)
|
||||
FINALIZE_STATEMENT(write_privs)
|
||||
FINALIZE_STATEMENT(delete_privs)
|
||||
FINALIZE_STATEMENT(last_insert_rowid)
|
||||
}
|
||||
|
||||
void AuthDatabaseSQLite3::createDatabase()
|
||||
{
|
||||
assert(m_database); // Pre-condition
|
||||
assert(m_database);
|
||||
|
||||
SQLOK(sqlite3_exec(m_database,
|
||||
"CREATE TABLE IF NOT EXISTS `auth` ("
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
"`name` VARCHAR(32) UNIQUE,"
|
||||
"`password` VARCHAR(512),"
|
||||
"`last_login` INTEGER"
|
||||
"`name` TEXT UNIQUE NOT NULL,"
|
||||
"`password` TEXT NOT NULL,"
|
||||
"`last_login` INTEGER NOT NULL DEFAULT 0"
|
||||
");",
|
||||
NULL, NULL, NULL),
|
||||
"Failed to create auth table");
|
||||
|
@ -616,7 +679,7 @@ void AuthDatabaseSQLite3::createDatabase()
|
|||
SQLOK(sqlite3_exec(m_database,
|
||||
"CREATE TABLE IF NOT EXISTS `user_privileges` ("
|
||||
"`id` INTEGER,"
|
||||
"`privilege` VARCHAR(32),"
|
||||
"`privilege` TEXT,"
|
||||
"PRIMARY KEY (id, privilege)"
|
||||
"CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES auth (id) ON DELETE CASCADE"
|
||||
");",
|
||||
|
@ -751,18 +814,18 @@ ModStorageDatabaseSQLite3::ModStorageDatabaseSQLite3(const std::string &savedir)
|
|||
|
||||
ModStorageDatabaseSQLite3::~ModStorageDatabaseSQLite3()
|
||||
{
|
||||
FINALIZE_STATEMENT(m_stmt_remove_all)
|
||||
FINALIZE_STATEMENT(m_stmt_remove)
|
||||
FINALIZE_STATEMENT(m_stmt_set)
|
||||
FINALIZE_STATEMENT(m_stmt_has)
|
||||
FINALIZE_STATEMENT(m_stmt_get)
|
||||
FINALIZE_STATEMENT(m_stmt_get_keys)
|
||||
FINALIZE_STATEMENT(m_stmt_get_all)
|
||||
FINALIZE_STATEMENT(remove_all)
|
||||
FINALIZE_STATEMENT(remove)
|
||||
FINALIZE_STATEMENT(set)
|
||||
FINALIZE_STATEMENT(has)
|
||||
FINALIZE_STATEMENT(get)
|
||||
FINALIZE_STATEMENT(get_keys)
|
||||
FINALIZE_STATEMENT(get_all)
|
||||
}
|
||||
|
||||
void ModStorageDatabaseSQLite3::createDatabase()
|
||||
{
|
||||
assert(m_database); // Pre-condition
|
||||
assert(m_database);
|
||||
|
||||
SQLOK(sqlite3_exec(m_database,
|
||||
"CREATE TABLE IF NOT EXISTS `entries` (\n"
|
||||
|
@ -825,8 +888,7 @@ bool ModStorageDatabaseSQLite3::getModEntry(const std::string &modname,
|
|||
verifyDatabase();
|
||||
|
||||
str_to_sqlite(m_stmt_get, 1, modname);
|
||||
SQLOK(sqlite3_bind_blob(m_stmt_get, 2, key.data(), key.size(), NULL),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
blob_to_sqlite(m_stmt_get, 2, key);
|
||||
bool found = sqlite3_step(m_stmt_get) == SQLITE_ROW;
|
||||
if (found) {
|
||||
auto sv = sqlite_to_blob(m_stmt_get, 0);
|
||||
|
@ -845,8 +907,7 @@ bool ModStorageDatabaseSQLite3::hasModEntry(const std::string &modname,
|
|||
verifyDatabase();
|
||||
|
||||
str_to_sqlite(m_stmt_has, 1, modname);
|
||||
SQLOK(sqlite3_bind_blob(m_stmt_has, 2, key.data(), key.size(), NULL),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
blob_to_sqlite(m_stmt_has, 2, key);
|
||||
bool found = sqlite3_step(m_stmt_has) == SQLITE_ROW;
|
||||
if (found)
|
||||
sqlite3_step(m_stmt_has);
|
||||
|
@ -862,10 +923,8 @@ bool ModStorageDatabaseSQLite3::setModEntry(const std::string &modname,
|
|||
verifyDatabase();
|
||||
|
||||
str_to_sqlite(m_stmt_set, 1, modname);
|
||||
SQLOK(sqlite3_bind_blob(m_stmt_set, 2, key.data(), key.size(), NULL),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
SQLOK(sqlite3_bind_blob(m_stmt_set, 3, value.data(), value.size(), NULL),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
blob_to_sqlite(m_stmt_set, 2, key);
|
||||
blob_to_sqlite(m_stmt_set, 3, value);
|
||||
SQLRES(sqlite3_step(m_stmt_set), SQLITE_DONE, "Failed to set mod entry")
|
||||
|
||||
sqlite3_reset(m_stmt_set);
|
||||
|
@ -879,8 +938,7 @@ bool ModStorageDatabaseSQLite3::removeModEntry(const std::string &modname,
|
|||
verifyDatabase();
|
||||
|
||||
str_to_sqlite(m_stmt_remove, 1, modname);
|
||||
SQLOK(sqlite3_bind_blob(m_stmt_remove, 2, key.data(), key.size(), NULL),
|
||||
"Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__));
|
||||
blob_to_sqlite(m_stmt_remove, 2, key);
|
||||
sqlite3_vrfy(sqlite3_step(m_stmt_remove), SQLITE_DONE);
|
||||
int changes = sqlite3_changes(m_database);
|
||||
|
||||
|
@ -906,6 +964,7 @@ void ModStorageDatabaseSQLite3::listMods(std::vector<std::string> *res)
|
|||
{
|
||||
verifyDatabase();
|
||||
|
||||
// FIXME: please don't do this. this should be sqlite3_step like all others.
|
||||
char *errmsg;
|
||||
int status = sqlite3_exec(m_database,
|
||||
"SELECT `modname` FROM `entries` GROUP BY `modname`;",
|
||||
|
|
|
@ -13,27 +13,41 @@ extern "C" {
|
|||
#include "sqlite3.h"
|
||||
}
|
||||
|
||||
// Template class for SQLite3 based data storage
|
||||
class Database_SQLite3 : public Database
|
||||
{
|
||||
public:
|
||||
virtual ~Database_SQLite3();
|
||||
|
||||
void beginSave();
|
||||
void endSave();
|
||||
void beginSave() override;
|
||||
void endSave() override;
|
||||
|
||||
bool initialized() const override { return m_initialized; }
|
||||
|
||||
/// @note not thread-safe
|
||||
void verifyDatabase() override;
|
||||
|
||||
bool initialized() const { return m_initialized; }
|
||||
protected:
|
||||
Database_SQLite3(const std::string &savedir, const std::string &dbname);
|
||||
|
||||
// Open and initialize the database if needed
|
||||
void verifyDatabase();
|
||||
// Check if a specific table exists
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
sqlite3_vrfy(sqlite3_bind_int(s, iCol, val));
|
||||
|
@ -104,12 +118,14 @@ protected:
|
|||
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
|
||||
{
|
||||
if (s != r) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -119,28 +135,37 @@ protected:
|
|||
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;
|
||||
|
||||
// Should prepare the necessary statements.
|
||||
virtual void initStatements() = 0;
|
||||
|
||||
sqlite3 *m_database = nullptr;
|
||||
|
||||
private:
|
||||
// Open the database
|
||||
void openDatabase();
|
||||
|
||||
bool m_initialized = false;
|
||||
|
||||
std::string m_savedir = "";
|
||||
std::string m_dbname = "";
|
||||
const std::string m_savedir;
|
||||
const std::string m_dbname;
|
||||
|
||||
sqlite3_stmt *m_stmt_begin = 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);
|
||||
};
|
||||
|
||||
// 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
|
||||
{
|
||||
public:
|
||||
|
@ -152,16 +177,19 @@ public:
|
|||
bool deleteBlock(const v3s16 &pos);
|
||||
void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
||||
|
||||
void beginSave() { Database_SQLite3::beginSave(); }
|
||||
void endSave() { Database_SQLite3::endSave(); }
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
virtual void initStatements();
|
||||
|
||||
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_write = nullptr;
|
||||
sqlite3_stmt *m_stmt_list = nullptr;
|
||||
|
@ -179,6 +207,8 @@ public:
|
|||
bool removePlayer(const std::string &name);
|
||||
void listPlayers(std::vector<std::string> &res);
|
||||
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
virtual void initStatements();
|
||||
|
@ -216,6 +246,8 @@ public:
|
|||
virtual void listNames(std::vector<std::string> &res);
|
||||
virtual void reload();
|
||||
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
virtual void initStatements();
|
||||
|
@ -251,8 +283,7 @@ public:
|
|||
virtual bool removeModEntries(const std::string &modname);
|
||||
virtual void listMods(std::vector<std::string> *res);
|
||||
|
||||
virtual void beginSave() { Database_SQLite3::beginSave(); }
|
||||
virtual void endSave() { Database_SQLite3::endSave(); }
|
||||
PARENT_CLASS_FUNCS
|
||||
|
||||
protected:
|
||||
virtual void createDatabase();
|
||||
|
@ -267,3 +298,5 @@ private:
|
|||
sqlite3_stmt *m_stmt_remove = nullptr;
|
||||
sqlite3_stmt *m_stmt_remove_all = nullptr;
|
||||
};
|
||||
|
||||
#undef PARENT_CLASS_FUNCS
|
||||
|
|
|
@ -16,7 +16,12 @@ class Database
|
|||
public:
|
||||
virtual void beginSave() = 0;
|
||||
virtual void endSave() = 0;
|
||||
|
||||
/// @return true if database connection is open
|
||||
virtual bool initialized() const { return true; }
|
||||
|
||||
/// Open and initialize the database if needed
|
||||
virtual void verifyDatabase() {};
|
||||
};
|
||||
|
||||
class MapDatabase : public Database
|
||||
|
|
|
@ -112,7 +112,7 @@ void set_default_settings()
|
|||
settings->setDefault("screenshot_format", "png");
|
||||
settings->setDefault("screenshot_quality", "0");
|
||||
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("curl_timeout", "20000");
|
||||
settings->setDefault("curl_parallel_limit", "8");
|
||||
|
@ -243,7 +243,7 @@ void set_default_settings()
|
|||
settings->setDefault("tooltip_show_delay", "400");
|
||||
settings->setDefault("tooltip_append_itemname", "false");
|
||||
settings->setDefault("fps_max", "60");
|
||||
settings->setDefault("fps_max_unfocused", "20");
|
||||
settings->setDefault("fps_max_unfocused", "10");
|
||||
settings->setDefault("viewing_range", "190");
|
||||
settings->setDefault("client_mesh_chunk", "1");
|
||||
settings->setDefault("screen_w", "1024");
|
||||
|
@ -270,7 +270,6 @@ void set_default_settings()
|
|||
settings->setDefault("camera_smoothing", "0.0");
|
||||
settings->setDefault("cinematic_camera_smoothing", "0.7");
|
||||
settings->setDefault("view_bobbing_amount", "1.0");
|
||||
settings->setDefault("fall_bobbing_amount", "0.03");
|
||||
settings->setDefault("enable_3d_clouds", "true");
|
||||
settings->setDefault("soft_clouds", "false");
|
||||
settings->setDefault("cloud_radius", "12");
|
||||
|
@ -422,7 +421,7 @@ void set_default_settings()
|
|||
|
||||
// Network
|
||||
settings->setDefault("enable_ipv6", "true");
|
||||
settings->setDefault("ipv6_server", "false");
|
||||
settings->setDefault("ipv6_server", "true");
|
||||
settings->setDefault("max_packets_per_iteration", "1024");
|
||||
settings->setDefault("port", "30000");
|
||||
settings->setDefault("strict_protocol_version_checking", "false");
|
||||
|
@ -547,6 +546,7 @@ void set_default_settings()
|
|||
settings->setDefault("virtual_joystick_triggers_aux1", "false");
|
||||
settings->setDefault("touch_punch_gesture", "short_tap");
|
||||
settings->setDefault("clickable_chat_weblinks", "true");
|
||||
|
||||
// Altered settings for Android
|
||||
#ifdef __ANDROID__
|
||||
settings->setDefault("screen_w", "0");
|
||||
|
@ -558,9 +558,9 @@ void set_default_settings()
|
|||
settings->setDefault("max_block_generate_distance", "5");
|
||||
settings->setDefault("sqlite_synchronous", "1");
|
||||
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("viewing_range", "50");
|
||||
settings->setDefault("viewing_range", "70");
|
||||
settings->setDefault("leaves_style", "simple");
|
||||
// Note: OpenGL ES 2.0 is not guaranteed to provide depth textures,
|
||||
// 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
|
||||
settings->setDefault("debanding", "false");
|
||||
settings->setDefault("post_processing_texture_bits", "8");
|
||||
// We don't have working certificate verification...
|
||||
settings->setDefault("curl_verify_cert", "false");
|
||||
|
||||
// Apply settings according to screen size
|
||||
|
|
|
@ -106,9 +106,9 @@ EmergeManager::EmergeManager(Server *server, MetricsBackend *mb)
|
|||
m_qlimit_generate = nthreads + 1;
|
||||
|
||||
// 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, 1, 1000000);
|
||||
m_qlimit_diskonly = rangelim(m_qlimit_diskonly, 2, 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++)
|
||||
m_threads.push_back(new EmergeThread(server, i));
|
||||
|
@ -375,8 +375,7 @@ bool EmergeManager::pushBlockEmergeData(
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<std::map<v3s16, BlockEmergeData>::iterator, bool> findres;
|
||||
findres = m_blocks_enqueued.insert(std::make_pair(pos, BlockEmergeData()));
|
||||
auto findres = m_blocks_enqueued.insert(std::make_pair(pos, BlockEmergeData()));
|
||||
|
||||
BlockEmergeData &bedata = findres.first->second;
|
||||
*entry_already_exists = !findres.second;
|
||||
|
@ -707,6 +706,8 @@ void *EmergeThread::run()
|
|||
{
|
||||
ScopeProfiler sp(g_profiler, "EmergeThread: load block - async (sum)");
|
||||
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);
|
||||
}
|
||||
// actually load it, then decide again
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue