Compare commits

..

623 Commits

Author SHA1 Message Date
sfan5
44c2e33c78 Bump version to 5.5.1 2022-05-15 21:53:21 +02:00
rubenwardy
2785dcbbbf Fix broken dependency enabling due to missing enabled field 2022-05-14 18:24:46 +01:00
sfan5
9b03bd3243 Fix Docker build
prometheus-cpp switched to C++14 in April (after we did) so this issue only affects older branches.
2022-05-14 18:51:48 +02:00
Jude Melton-Houghton
8f30456ee3 Fix cooking and fuel crafts with aliases 2022-05-14 18:33:42 +02:00
Octavian
38557ff635 Fix possible unreliable behavior due to uninitialized variables 2022-05-14 18:33:42 +02:00
Lars Müller
7bc2cde4dd HUD: Update selection mesh every frame (#12270)
Fixes outdated selection boxes after entity property changes.
2022-05-14 18:33:42 +02:00
Lars Müller
f065d3a06b Fix Minetest blaming the wrong mod for errors (#12241)
Covers the case where mods insert their callbacks manually into "minetest.registered_<callbacks>" (often to achieve a particular order of execution).
2022-05-14 18:33:42 +02:00
Jude Melton-Houghton
21f7e3a987 Enable dependencies when enabling modpacks (#12202) 2022-05-14 18:33:42 +02:00
Jude Melton-Houghton
9f688bc433 Fix enabling of dependencies with identical names (#12253) 2022-05-14 18:33:42 +02:00
rubenwardy
6e9d31d4fb Fix mods not being recursively enabled
Fixes #12290
2022-05-14 18:33:42 +02:00
sfan5
e81c48526b Declare all bundled libs as static
Otherwise it can happen that these are built as shared depending on the
options passed to CMake, which obviously isn't intended.
2022-05-14 18:33:42 +02:00
SmallJoker
b405985b80 guiScalingFilter: Fix most memory leaks (#12256)
Calls to the cache function ended up creating a new texture regardless whether
the texture is already cached.
2022-05-14 18:33:42 +02:00
rubenwardy
8b010c5a9f ContentDB: Fix ungraceful crash on aliases when list download fails
Fixes #12267 and fixes #12154
2022-05-14 18:33:42 +02:00
sfan5
1e7b5d6fdb Fix synchronization issue at thread start
If a newly started thread immediately exits then m_running would
immediately be set to false again and the caller would be stuck
waiting for m_running to become true forever.
Since a mutex for synchronizing startup already exists we can
simply move the while loop into it.

see also: #5134 which introduced m_start_finished_mutex
2022-05-14 18:33:42 +02:00
sfan5
a55982e7f0 Fix password changing getting stuck if wrong password is entered once 2022-05-14 18:33:42 +02:00
sfan5
1ac378063e Apply disallow_empty_password to password changes too 2022-05-14 18:33:42 +02:00
sfan5
d497c92684 Fix race condition in registration leading to duplicate create_auth calls 2022-05-14 18:33:42 +02:00
paradust7
677dc2c155 Remove HW_buffer_counter after IrrlichtMt fix to remove HWBufferMap (#12232)
Keep code and use version check instead, for backwards compatibility
2022-05-14 18:33:42 +02:00
Alex
beea8deeb5 Fix invalid queued package element and path (#12218) 2022-05-14 18:33:42 +02:00
Giuseppe Bilotta
0d0f1a2fb2 Fix some textures not being sent correctly to older clients
Since b2eb44afc5, a texture defined as
`[combine:16x512:0,0=some_file.png;etc`
will not be sent correctly from a 5.5 server to a 5.4 client due to the
overeager detection of unsupported base modifier `[` introducing a
spurious `blank.png^` before the modifier.

Fix this by whitelisting which base modifiers can be passed through
unchanged to the client, and prefix `blank.png` for the others
(which at the moment is just [png:, but the list may grow larger
as new base modifiers are added.)
2022-05-14 18:33:42 +02:00
paradust7
439701ed7a Fix '[combine' when EVDF_TEXTURE_NPOT is disabled. (#12187)
Stop scaling images to POT immediately when loaded. The 'combine'
modifier hardcodes X and Y coordinates, and so behaves incorrectly
if applied to a scaled image. Images emitted by generateImage()
are already scaled to POT before being used as a texture, so
nothing should break.
2022-05-14 18:33:42 +02:00
ShadowNinja
d945d0129c Fix OOB read in trim("") 2022-05-14 18:33:42 +02:00
Dmitry Kostenko
cc91477308 Avoid negation of comparison operator (luacheck warning) 2022-05-14 18:33:42 +02:00
Daroc Alden
ac139ec03d Fix memory leak in EmergeManager
EmergeManager keeps a copy of the BiomeGen that it creates, but
never deletes it.
2022-05-14 18:33:42 +02:00
Gregor Parzefall
b4f0e834bf Fix footsteps for players whose collision box min y != 0 (#12110) 2022-05-14 18:33:42 +02:00
Daroc Alden
6e6cdc834f Fix undefined behavior in TileLayer (#12125)
Initialize the values properly
2022-05-14 18:33:42 +02:00
Daroc Alden
4b81ae1b35 Fix memory leak from SpatialAreaStore (#12120) 2022-05-14 18:33:42 +02:00
sfan5
d569dc45a8 Fix segfault with autoscale_mode (again)
closes #12100
This time add some asserts so there is no misunderstanding about the NULL-ness of layer->texture.
2022-05-14 18:33:42 +02:00
sfan5
23d49fda29 Clean up ClientReady packet handling
fixes #12073
2022-05-14 18:33:42 +02:00
pecksin
62ad2c3bc1 Use absolute value for bouncy in collision (#11969)
[backport: removed devtest change and protocol_version comparison]
2022-05-14 18:33:42 +02:00
sfan5
25373ad294 Remove awful Mingw32 workarounds
Instead a warning is triggered if an affected compiler is detected.
closes #12022
2022-05-12 11:36:50 +02:00
sfan5
26d0c0fd8d Fix broken server startup if curl is disabled (#12046) 2022-05-12 11:36:39 +02:00
Lars Mueller
3afffcd36b Fix builtin statbar backgrounds
see #12000
2022-05-12 11:36:11 +02:00
sfan5
5440de1785 Merge remote-tracking branch 'origin/stable-5' into HEAD 2022-01-30 23:10:56 +01:00
sfan5
54b805ffd0 Bump version to 5.5.0 2022-01-30 22:58:18 +01:00
sfan5
484a4b518f Add another very awful workaround to prevent a crash on Mingw32
This appears to be the same issue as 70df3d54f3.
Hopefully the next MinGW update will remove the need for this.
2022-01-30 22:57:44 +01:00
sfan5
5e4a01f2de Update credits for 5.5.0 release (#12001) 2022-01-30 21:33:08 +01:00
sfan5
5da204f5bc Get rid of basic_debug last minute
This isn't a revert but rather just disables the codepaths. also see #12011
2022-01-30 21:32:49 +01:00
sfan5
b66477c29f Abort raycasts that go out-of-bounds (#12006) 2022-01-30 21:31:18 +01:00
poi
a0e4b2bf54 Translated using Weblate (Chinese (Simplified))
Currently translated at 93.4% (1323 of 1416 strings)
2022-01-30 19:53:29 +01:00
Nikita Epifanov
98982065ed Translated using Weblate (Russian)
Currently translated at 97.8% (1386 of 1416 strings)
2022-01-30 19:53:29 +01:00
Wuzzy
49adce1a63 Translated using Weblate (German)
Currently translated at 100.0% (1416 of 1416 strings)
2022-01-30 19:53:29 +01:00
Andrij Mizyk
7c393f8658 Translated using Weblate (Ukrainian)
Currently translated at 48.7% (691 of 1416 strings)
2022-01-30 19:53:29 +01:00
waxtatect
fcd06d99c6 Translated using Weblate (French)
Currently translated at 100.0% (1416 of 1416 strings)
2022-01-30 19:53:29 +01:00
BreadW
f3e23ae972 Translated using Weblate (Japanese)
Currently translated at 100.0% (1416 of 1416 strings)
2022-01-30 19:53:29 +01:00
Marian
39f5b05ae9 Translated using Weblate (Slovak)
Currently translated at 100.0% (1416 of 1416 strings)
2022-01-30 19:53:29 +01:00
Yaya - Nurul Azeera Hidayah @ Muhammad Nur Hidayat Yasuyoshi
9205f10208 Translated using Weblate (Malay)
Currently translated at 100.0% (1416 of 1416 strings)
2022-01-30 19:53:29 +01:00
Balázs Kovács
8b9e5b47df Translated using Weblate (Hungarian)
Currently translated at 86.0% (1219 of 1416 strings)
2022-01-30 19:53:29 +01:00
Thomas Wagner Nielsen
17bb2712cb Translated using Weblate (Danish)
Currently translated at 39.9% (566 of 1416 strings)
2022-01-30 19:51:22 +01:00
Wuzzy
9d3135a21b Update German builtin translation 2022-01-30 13:50:07 +01:00
Wuzzy
777fb616b6 Update builtin translation templates 2022-01-30 13:50:07 +01:00
ROllerozxa
172acce352 Fix Minetest logo when installed system-wide 2022-01-30 13:49:52 +01:00
sfan5
f69eead62e Get rid of empty test file 2022-01-30 13:49:26 +01:00
sfan5
a9bccb964f Raise max mapgen limit constant to align with mapblock size 2022-01-30 13:49:26 +01:00
SmallJoker
74a384de0a Auto-update minetest.conf.example 2022-01-29 18:42:55 -05:00
SmallJoker
a27362de6a Disable dynamic shadows for the 5.5.0 release
The dynamic shadows are yet not in the desired state to justify the
inclusion into version 5.5.0. A stable release is long overdue, hence
this allows fixes to continue in 5.6.0-dev to finally release an
acceptable version of the dynamic shadows feature.

Reverting this commit is highly recommended to proceed in development.
2022-01-29 18:42:55 -05:00
sfan5
66e8aae9f2 Get rid of legacy workaround in SQLite backend
tested on Android 11, fixes #11937
2022-01-28 17:16:02 +01:00
sfan5
91c6728eb8 Add game name to server status string 2022-01-28 17:15:10 +01:00
sfan5
22f0c66abb Request execution on dedicated GPU on Windows 2022-01-27 22:30:02 +01:00
sfan5
7aea5cb88f Enable high-res timers on Windows
This should fix issues like #11891, caused by the fps limiting
code being unable to operate correctly.
2022-01-27 22:30:02 +01:00
sfan5
058846d687 Rework drawtime and related timekeeping code to use microseconds 2022-01-27 22:30:02 +01:00
Jude Melton-Houghton
fc161e757c Automatically migrate client mod storage (#11960) 2022-01-27 22:24:30 +01:00
SmallJoker
47735c273c Builtin: Sanity-check /time inputs (#11993)
This enforces the documented bounds for the /time command.
2022-01-27 22:23:14 +01:00
Lars Müller
fe0b2d02bf Define control(bits) as "unset" for entities (#11995) 2022-01-27 22:22:58 +01:00
updatepo.sh
48e508052a Update translations 2022-01-25 23:19:13 +01:00
updatepo.sh
0d0786e414 Update example config and translation .cpp 2022-01-25 23:18:50 +01:00
poi
4f0d7738b3 Translated using Weblate (Chinese (Simplified))
Currently translated at 93.8% (1328 of 1415 strings)
2022-01-25 23:05:57 +01:00
Balázs Kovács
76d7816749 Translated using Weblate (Hungarian)
Currently translated at 85.5% (1210 of 1415 strings)
2022-01-25 23:05:57 +01:00
rubenwardy
8c486aaeae Translated using Weblate (Spanish)
Currently translated at 79.5% (1125 of 1415 strings)
2022-01-25 23:05:57 +01:00
Gao Tiesuan
2c338032ed Translated using Weblate (Chinese (Literary))
Currently translated at 0.6% (9 of 1415 strings)
2022-01-25 23:05:57 +01:00
Gao Tiesuan
94128924b2 Translated using Weblate (Chinese (Simplified))
Currently translated at 92.4% (1308 of 1415 strings)
2022-01-25 23:05:57 +01:00
Gao Tiesuan
319c4d1274 Added translation using Weblate (Chinese (Literary)) 2022-01-25 23:05:57 +01:00
Wuzzy
7a8efa7f4f Translated using Weblate (German)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:57 +01:00
Mehmet Ali
6c3c2b3f92 Translated using Weblate (Turkish)
Currently translated at 98.6% (1396 of 1415 strings)
2022-01-25 23:05:57 +01:00
Yiu Man Ho
f1ac573e9a Translated using Weblate (Chinese (Traditional))
Currently translated at 79.9% (1131 of 1415 strings)
2022-01-25 23:05:57 +01:00
Kisbenedek Márton
0be76c0bf5 Translated using Weblate (Hungarian)
Currently translated at 79.9% (1131 of 1415 strings)
2022-01-25 23:05:57 +01:00
pampogo kiraly
c07aeb0075 Translated using Weblate (Hungarian)
Currently translated at 79.7% (1129 of 1415 strings)
2022-01-25 23:05:57 +01:00
Sebastian Jasiński
4e5de9607b Translated using Weblate (Polish)
Currently translated at 69.8% (988 of 1415 strings)
2022-01-25 23:05:57 +01:00
Yaya - Nurul Azeera Hidayah @ Muhammad Nur Hidayat Yasuyoshi
c6f3dcc009 Translated using Weblate (Malay (Jawi))
Currently translated at 65.3% (925 of 1415 strings)
2022-01-25 23:05:57 +01:00
Mikitko
620ba51375 Translated using Weblate (Russian)
Currently translated at 98.5% (1394 of 1415 strings)
2022-01-25 23:05:57 +01:00
Imre Kristoffer Eilertsen
1a98351212 Translated using Weblate (Norwegian Bokmål)
Currently translated at 56.5% (800 of 1415 strings)
2022-01-25 23:05:57 +01:00
Muhammad Rifqi Priyo Susanto
d4746b349d Translated using Weblate (Indonesian)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:57 +01:00
AFCMS
d9caa1bd48 Translated using Weblate (French)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
Joaquín Villalba
c3a82b9a49 Translated using Weblate (Spanish)
Currently translated at 79.6% (1127 of 1415 strings)
2022-01-25 23:05:56 +01:00
debiankaios
c4b47269a4 Translated using Weblate (German)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
109247019824
b4cc25f25b Translated using Weblate (Bulgarian)
Currently translated at 30.6% (434 of 1415 strings)
2022-01-25 23:05:56 +01:00
Allan Nordhøy
7645c95110 Translated using Weblate (Norwegian Bokmål)
Currently translated at 54.7% (775 of 1415 strings)
2022-01-25 23:05:56 +01:00
Minetest-j45
4decded6ab Translated using Weblate (Spanish)
Currently translated at 79.6% (1127 of 1415 strings)
2022-01-25 23:05:56 +01:00
waxtatect
471031e516 Translated using Weblate (French)
Currently translated at 99.9% (1414 of 1415 strings)
2022-01-25 23:05:56 +01:00
AFCMS
c8d621e0b4 Translated using Weblate (French)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
ssantos
b1ea3a6199 Translated using Weblate (Portuguese)
Currently translated at 98.9% (1400 of 1415 strings)
2022-01-25 23:05:56 +01:00
Mateusz Mendel
bb2d79f930 Translated using Weblate (Polish)
Currently translated at 69.6% (985 of 1415 strings)
2022-01-25 23:05:56 +01:00
Gert-dev
c416394ab2 Translated using Weblate (Dutch)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
pesder
02478d2db6 Translated using Weblate (Chinese (Traditional))
Currently translated at 70.3% (996 of 1415 strings)
2022-01-25 23:05:56 +01:00
Stas Kies
9740a35685 Translated using Weblate (Russian)
Currently translated at 98.5% (1394 of 1415 strings)
2022-01-25 23:05:56 +01:00
xerxstirb
7f1db70919 Translated using Weblate (Swedish)
Currently translated at 58.5% (828 of 1415 strings)
2022-01-25 23:05:56 +01:00
ROllerozxa
02c288fa13 Translated using Weblate (Swedish)
Currently translated at 58.5% (828 of 1415 strings)
2022-01-25 23:05:56 +01:00
Nikita Epifanov
f6ae8b6350 Translated using Weblate (Russian)
Currently translated at 97.6% (1382 of 1415 strings)
2022-01-25 23:05:56 +01:00
Linerly
e59e16161f Translated using Weblate (Indonesian)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
IAmOlive
7b46bcbbb8 Translated using Weblate (Vietnamese)
Currently translated at 20.3% (288 of 1415 strings)
2022-01-25 23:05:56 +01:00
Gabriel Cardoso
9b2dd0c7b3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.2% (1404 of 1415 strings)
2022-01-25 23:05:56 +01:00
BreadW
8eeab37473 Translated using Weblate (Japanese)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
Marian
c745e711ec Translated using Weblate (Slovak)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
abidin toumi
f022f030d0 Translated using Weblate (Arabic)
Currently translated at 37.8% (535 of 1415 strings)
2022-01-25 23:05:56 +01:00
Yaya - Nurul Azeera Hidayah @ Muhammad Nur Hidayat Yasuyoshi
8ab369475f Translated using Weblate (Malay)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
Oğuz Ersen
9d1aed01fc Translated using Weblate (Turkish)
Currently translated at 98.6% (1396 of 1415 strings)
2022-01-25 23:05:56 +01:00
Andrei Stepanov
a2cdc6de33 Translated using Weblate (Russian)
Currently translated at 96.5% (1366 of 1415 strings)
2022-01-25 23:05:56 +01:00
Simone Starace
828ecac826 Translated using Weblate (Italian)
Currently translated at 97.9% (1386 of 1415 strings)
2022-01-25 23:05:56 +01:00
Muhammad Rifqi Priyo Susanto
a0edf2849a Translated using Weblate (Indonesian)
Currently translated at 99.9% (1414 of 1415 strings)
2022-01-25 23:05:56 +01:00
Wuzzy
e7fe20ada6 Translated using Weblate (German)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
waxtatect
37aa8468a0 Translated using Weblate (French)
Currently translated at 100.0% (1415 of 1415 strings)
2022-01-25 23:05:56 +01:00
Jude Melton-Houghton
1b2176a426 Cancel emerge callbacks on shutdown 2022-01-23 00:56:17 +01:00
Vincent Robinson
95a775cd3a Bump formspec version (#11980) 2022-01-23 00:55:43 +01:00
Dmitry Kostenko
71317b8579 Make sure nightRatio is always greater than zero.
To avoid underfined behavior of GLSL pow()
2022-01-22 18:52:12 +01:00
sfan5
f8cef52ea0 Fix consistency of sky sun/moon texture behaviour
Also cleans up related code somewhat.
2022-01-22 11:18:34 -05:00
Zughy
37d80784dd Allow resetting celestial vault elements by leaving its arguments empty (#11922) 2022-01-22 12:42:49 +01:00
sfan5
f66ed2c27f Fix local animation not instantly updating after being set 2022-01-19 23:30:18 +01:00
sfan5
4f6f09590c Free arguments of cancelled minetest.after() jobs 2022-01-19 23:30:18 +01:00
SmallJoker
7c321ad7f5 Main menu: Fix automatic dependency enables on doubleclick
When mods were toggled by double-click, the hard dependencies were no longer enabled automatically.
However, the 'Enabled' checkbox did still work. This commit restores the behaviour as seen before commit c401a06
2022-01-19 18:52:27 +01:00
sfan5
42839fa1db Optimize folder handling in 'files' mod storage backend
This regressed in bf22569019.
2022-01-17 21:49:18 +01:00
sfan5
b02b381af2 Bump IrrlichtMt to 1.9.0mt4 in CI 2022-01-16 15:54:08 +01:00
Dmitry Kostenko
b6555ee6af Reset override material in anaglyph
Reset override material properties before applying the color filter.
2022-01-16 13:10:33 +01:00
Alex
7c93b2d7a3 Give the ASCII console splash a facelift 2022-01-15 17:45:33 +01:00
sfan5
9a12e4499e Minor improvements to Lua sandbox 2022-01-15 17:45:08 +01:00
sfan5
379473b670 Improve situation around race condition with dynamic_add_media during client join 2022-01-15 17:45:08 +01:00
savilli
72b14bd994 Don't call on_dieplayer callback two times (#11874) 2022-01-15 17:44:55 +01:00
sfan5
76e97e85a0 Update compiler versions in CI
downgrade gcc 6 -> 5 to better match our minimum
upgrade gcc and clang by moving two images to ubuntu 20.04
2022-01-15 17:44:22 +01:00
sfan5
a90b2a4d4f Raise minimum compiler versions
Supporting these is not reasonable anymore and effectively we didn't
do that anyway, brokenness was only noticed by chance and a PR to restore
support for gcc 5.x is ready now.
2022-01-15 17:44:22 +01:00
Dmitry Kostenko
97248c6957 Add client/mod_storage.sqlite to .gitignore 2022-01-13 20:43:02 +01:00
SmallJoker
b2eb44afc5 Fix NodeDef backwards compatibility to 5.3.0 (#11942)
1. Fixes crashes on older clients when [png is used as base image
2. Fixes liquid type assertion fails on debug builds
2022-01-12 18:49:14 +01:00
sfan5
4c8c649779 Mainmenu game-related changes (#11887)
fixes:
* Switching between games does not immediately hide creative mode / damage buttons if so specified
* World creation menu has a game selection list even though the menu already provides a gamebar
* Showing gameid in world list is unnecessary
* Choice of mapgen parameters in menu persists between games (and was half-broken)
2022-01-09 21:15:35 +01:00
Lars Mueller
b164e16d1b Copy smoothing note to gui_scaling_filter description 2022-01-09 21:13:54 +01:00
SmallJoker
8fab406c28 Formspec: Fix bgcolor and set_focus checks 2022-01-09 18:47:12 +01:00
sfan5
5eb45e1ea0 Restore pass-through of direction keys (#11924)
This moves relevant code into the PlayerControl class and gets rid of separate keyPressed variable.
2022-01-09 18:46:36 +01:00
sfan5
76dbd0d2d0 Fully remove bitmap font support (#11863)
Freetype is now a build requirement.
2022-01-08 14:53:25 +01:00
Jude Melton-Houghton
bf22569019 Use a database for mod storage (#11763) 2022-01-07 20:28:49 +02:00
Wuzzy
b81948a14c Fix damage wraparound if very high damage (#11872) 2022-01-06 21:16:35 +01:00
Aritz Erkiaga
85da2e284b Fix incorrect bit positions in paramtype documentation 2022-01-06 21:16:23 +01:00
Vincent Robinson
e39b159845 Base formspec coordinate size on padded screensize 2022-01-04 17:47:32 -08:00
SmallJoker
d33ab97434 Inventory: Add ServerEnv checks for calls during script init
This fixes 'minetest.get_inventory' calls to players or nodes during the load phase.
2022-01-04 18:39:27 +01:00
Desour
1965628705 Fix vector.from_string returning a table without vector metatable 2022-01-02 22:15:41 -05:00
Wuzzy
84fdd369d4 Cap damage overlay duration to 1 second (#11871) 2022-01-02 22:14:02 -05:00
x2048
835524654e Fix shadow mapping when PCF is disabled (#11888) 2022-01-02 13:45:55 -08:00
x2048
e030d9cff0 Recalculate normals before adding mesh to the scene 2022-01-02 14:32:13 +01:00
Zughy
8910c7f8ae Better document sky_color scope (#11892) 2022-01-01 22:46:00 +01:00
ShadowNinja
29d2b2ccd0 Print announce error response (#11878)
Fix HTTPFetch caller and request ID to 64 bits
Check that allocated caller ID is not DISCARD
Print body if serverlist request returns error
Don't print control characters from HTTP responses
Document special HTTPFetch caller IDs
Allow unicode to be printed
2022-01-01 22:44:56 +01:00
Vincent Robinson
544b9d5c72 Add padding[] element to formspecs (#11821) 2021-12-30 12:54:47 -08:00
Vincent Robinson
4a16ab3585 Improve TTF support for pixel-style fonts (#11848) 2021-12-30 12:54:21 -08:00
SmallJoker
14c7fae378 Formspec: Unify argument checks (#11851) 2021-12-29 23:58:26 +01:00
sfan5
0ea8df4d64 Socket-related cleanups
Improve error handling on Windows and reduce the size of the `Address` class
2021-12-29 23:01:26 +01:00
ROllerozxa
05573d6d8d Remove unused (de)serializeAttributes() methods 2021-12-29 23:00:16 +01:00
Vitaliy
9b650b9efb Add more neighbors on mesh update (#6765) 2021-12-29 22:59:53 +01:00
SmallJoker
481bb90eac Fix segfault in drawItems() due to missing inventory list
This fixes a nullptr dereference when the specified inventory list is not known.
Happens when HUD elements are sent before the required inventory list is created.
2021-12-29 19:20:49 +01:00
savilli
0fa54531d4 Fix check that denies new clients from a singleplayer session 2021-12-28 14:08:21 +01:00
William L. DeRieux IV
cc64a0405a Automatically use SSE registers for FP operations on i386 (#11853)
use SSE for floating-point operations to avoid issues with improper fp-rounding and
loss of precision when moving fp-data to incompatible or less-precise
registers/storage locations

https://gcc.gnu.org/wiki/FloatingPointMath
https://gcc.gnu.org/wiki/x87note
2021-12-28 14:06:24 +01:00
JosiahWI
7f6306ca96 Restore GCC 5 compatibility (#11778) 2021-12-28 14:05:49 +01:00
sfan5
0c4929f025 Remove wrong function from lua_api.txt 2021-12-19 17:03:16 +01:00
Jude Melton-Houghton
1b664dd870 Use defined evaluation order in profiler
See https://github.com/LuaJIT/LuaJIT/issues/238
2021-12-19 17:03:07 +01:00
sfan5
49f7d2494c Protect font initialization with mutex
fixes #4532
2021-12-18 20:38:33 +01:00
sfan5
b2409b14d0 Refactor trusted mod checking code 2021-12-18 20:37:13 +01:00
sfan5
f405459548 Remove setlocal and setupvalue from debug table whitelist
It's likely that these could be used trick mods into revealing the insecure
environment even if they do everything right (which is already hard enough).
2021-12-18 20:37:13 +01:00
sfan5
8c99f2232b Don't let HTTP API pass through untrusted function
This has been a problem since the first day, oops.
2021-12-18 20:37:13 +01:00
sfan5
8472141b79 Restructure devtest's unittests and run them in CI (#11859) 2021-12-18 20:36:43 +01:00
sfan5
1c5ece8334 Fix eat sound not playing if eating last of stack 2021-12-15 15:36:19 +01:00
sfan5
378175497a Fix some issues with buildbot scripts (#11860) 2021-12-15 14:36:27 +01:00
ROllerozxa
fcf86ded8f Disable inventory if player's inventory formspec is blank (#11827) 2021-12-13 17:43:29 +01:00
sfan5
84efe279bb Fix URL escaping in content store 2021-12-13 17:33:35 +01:00
Wuzzy
f71091bf52 Remove creative/damage info in Esc/Pause menu 2021-12-13 17:33:21 +01:00
Wuzzy
76aa6103e3 Update German locale translation 2021-12-10 12:24:53 +01:00
Wuzzy
1ab3eadd87 Update builtin locale 2021-12-10 12:24:53 +01:00
Francisco
a8c58d5cbb Add pauloue's ItemStack example to docs (#9853) 2021-12-10 12:24:42 +01:00
sfan5
d9d219356a Fix get_bone_position() on unset bones modifying their position
closes #11840
2021-12-06 00:06:49 +01:00
sfan5
ff934d538c Fix various code & correctness issues (#11815) 2021-12-05 14:40:30 +01:00
Richard Liu
7a043b3ebb Fix wireshark packet dissector wrong coordinates (#11826) 2021-12-05 14:34:40 +01:00
Wuzzy
80c3c7e642 Improve error message if using "/help --" (#11796) 2021-12-01 20:22:46 +01:00
SmallJoker
57a59ae92d Network: Delete copy constructor and use std::move instead (#11642)
This is a follow-up change which disables class copies where possible to avoid unnecessary memory movements.
2021-12-01 20:22:33 +01:00
updatepo.sh
1dc1305ada Update translation files 2021-11-27 19:42:26 +01:00
updatepo.sh
a157256706 Update minetest.conf.example and dummy cpp file 2021-11-27 19:41:45 +01:00
ROllerozxa
3ac102c93b Translated using Weblate (Swedish)
Currently translated at 46.0% (643 of 1396 strings)
2021-11-27 19:33:53 +01:00
Ondřej Pfrogner
3332592905 Translated using Weblate (Czech)
Currently translated at 62.9% (879 of 1396 strings)
2021-11-27 19:33:53 +01:00
Johann Lau
42b8167f3d Added translation using Weblate (Yue) 2021-11-27 19:33:53 +01:00
Molly
fc0897682d Translated using Weblate (Dutch)
Currently translated at 97.0% (1355 of 1396 strings)
2021-11-27 19:33:53 +01:00
Vancha March
8d99cddecc Translated using Weblate (Dutch)
Currently translated at 95.3% (1331 of 1396 strings)
2021-11-27 19:33:53 +01:00
Joaquín Villalba
6f9d803d67 Translated using Weblate (Spanish)
Currently translated at 81.8% (1142 of 1396 strings)
2021-11-27 19:33:53 +01:00
Manuel González
c24b02852b Translated using Weblate (Spanish)
Currently translated at 81.8% (1142 of 1396 strings)
2021-11-27 19:33:53 +01:00
109247019824
88731631ab Translated using Weblate (Bulgarian)
Currently translated at 12.6% (177 of 1396 strings)
2021-11-27 19:33:53 +01:00
phlostically
714d4e4a81 Translated using Weblate (Esperanto)
Currently translated at 97.2% (1357 of 1396 strings)
2021-11-27 19:33:53 +01:00
Markus Mikkonen
1935783cc6 Translated using Weblate (Finnish)
Currently translated at 20.9% (292 of 1396 strings)
2021-11-27 19:33:53 +01:00
Ronoaldo Pereira
9f5d35e2aa Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.7% (1392 of 1396 strings)
2021-11-27 19:33:53 +01:00
Jiri Grönroos
6569056bfc Translated using Weblate (Finnish)
Currently translated at 20.9% (292 of 1396 strings)
2021-11-27 19:33:53 +01:00
Heitor
62c3c90120 Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.0% (1355 of 1396 strings)
2021-11-27 19:33:53 +01:00
Tirifto
7d2c99e2c2 Translated using Weblate (Esperanto)
Currently translated at 95.9% (1340 of 1396 strings)
2021-11-27 19:33:53 +01:00
A M
dc73d441b5 Translated using Weblate (Polish)
Currently translated at 71.4% (998 of 1396 strings)
2021-11-27 19:33:53 +01:00
GunChleoc
4866e06e62 Translated using Weblate (Gaelic)
Currently translated at 17.0% (238 of 1396 strings)
2021-11-27 19:33:53 +01:00
Zhaolin Lau
cd3a8f96c6 Translated using Weblate (Chinese (Simplified))
Currently translated at 95.3% (1331 of 1396 strings)
2021-11-27 19:33:53 +01:00
Thiago Carmona Monteiro
0eb829f5de Translated using Weblate (Portuguese (Brazil))
Currently translated at 94.4% (1319 of 1396 strings)
2021-11-27 19:33:53 +01:00
Marian
c062daccc9 Translated using Weblate (Slovak)
Currently translated at 95.2% (1329 of 1396 strings)
2021-11-27 19:33:53 +01:00
phlostically
f57b8f3e8a Translated using Weblate (Esperanto)
Currently translated at 95.2% (1329 of 1396 strings)
2021-11-27 19:33:53 +01:00
Allan Nordhøy
efc99a8d42 Translated using Weblate (Norwegian Bokmål)
Currently translated at 56.0% (783 of 1396 strings)
2021-11-27 19:33:53 +01:00
abidin toumi
ecd4fbc0de Translated using Weblate (Arabic)
Currently translated at 27.1% (379 of 1396 strings)
2021-11-27 19:33:53 +01:00
Oğuz Ersen
3590261c78 Translated using Weblate (Turkish)
Currently translated at 100.0% (1396 of 1396 strings)
2021-11-27 19:33:53 +01:00
Emily Ellis
f8dba7e5cf Translated using Weblate (Chinese (Simplified))
Currently translated at 94.4% (1319 of 1396 strings)
2021-11-27 19:33:53 +01:00
David Leal
dd23991a19 Translated using Weblate (Spanish)
Currently translated at 81.2% (1134 of 1396 strings)
2021-11-27 19:33:53 +01:00
Riceball LEE
6328b2274a Translated using Weblate (Chinese (Simplified))
Currently translated at 92.5% (1292 of 1396 strings)
2021-11-27 19:33:53 +01:00
Yangjun Wang
2e0780b437 Translated using Weblate (Chinese (Simplified))
Currently translated at 92.5% (1292 of 1396 strings)
2021-11-27 19:33:53 +01:00
Чтабс
dfb1e62bc3 Translated using Weblate (Russian)
Currently translated at 100.0% (1396 of 1396 strings)
2021-11-27 19:33:53 +01:00
Stefan Vukanovic
c264e47ee7 Translated using Weblate (Serbian (cyrillic))
Currently translated at 30.4% (425 of 1396 strings)
2021-11-27 19:33:53 +01:00
BreadW
19d5a5066c Translated using Weblate (Japanese)
Currently translated at 99.4% (1389 of 1396 strings)
2021-11-27 19:33:53 +01:00
Lin Happy 666
82f8e24d83 Translated using Weblate (Chinese (Simplified))
Currently translated at 92.3% (1289 of 1396 strings)
2021-11-27 19:33:53 +01:00
Liet Kynes
756261bafe Translated using Weblate (Norwegian Bokmål)
Currently translated at 56.0% (783 of 1396 strings)
2021-11-27 19:33:53 +01:00
Petter Reinholdtsen
a8745948c4 Translated using Weblate (Norwegian Bokmål)
Currently translated at 55.4% (774 of 1396 strings)
2021-11-27 19:33:53 +01:00
Liet Kynes
0ce549f49e Translated using Weblate (Norwegian Bokmål)
Currently translated at 55.4% (774 of 1396 strings)
2021-11-27 19:33:52 +01:00
Er2
7445a72f76 Translated using Weblate (Russian)
Currently translated at 100.0% (1396 of 1396 strings)
2021-11-27 19:33:52 +01:00
Ács Zoltán
5cb9a36916 Translated using Weblate (Hungarian)
Currently translated at 81.9% (1144 of 1396 strings)
2021-11-27 19:33:52 +01:00
Mateusz Mendel
3dbf52a871 Translated using Weblate (Polish)
Currently translated at 70.3% (982 of 1396 strings)
2021-11-27 19:33:52 +01:00
ResuUman
9ca08800e1 Translated using Weblate (Polish)
Currently translated at 70.3% (982 of 1396 strings)
2021-11-27 19:33:52 +01:00
Mateusz Mendel
1556e7eb09 Translated using Weblate (Polish)
Currently translated at 70.3% (982 of 1396 strings)
2021-11-27 19:33:52 +01:00
ResuUman
f5ab059c0f Translated using Weblate (Polish)
Currently translated at 70.3% (982 of 1396 strings)
2021-11-27 19:33:52 +01:00
Mateusz Mendel
8ac17b877a Translated using Weblate (Polish)
Currently translated at 68.7% (960 of 1396 strings)
2021-11-27 19:33:52 +01:00
ResuUman
9da60be08e Translated using Weblate (Polish)
Currently translated at 68.7% (960 of 1396 strings)
2021-11-27 19:33:52 +01:00
Mateusz Mendel
0fc3684613 Translated using Weblate (Polish)
Currently translated at 68.7% (960 of 1396 strings)
2021-11-27 19:33:52 +01:00
ResuUman
c0b977bf32 Translated using Weblate (Polish)
Currently translated at 68.7% (960 of 1396 strings)
2021-11-27 19:33:52 +01:00
Mateusz Mendel
d3fab295ad Translated using Weblate (Polish)
Currently translated at 68.7% (960 of 1396 strings)
2021-11-27 19:33:52 +01:00
ResuUman
58170e36ef Translated using Weblate (Polish)
Currently translated at 68.7% (960 of 1396 strings)
2021-11-27 19:33:52 +01:00
Чтабс
60d6be1329 Translated using Weblate (Russian)
Currently translated at 95.4% (1333 of 1396 strings)
2021-11-27 19:33:52 +01:00
Janar Leas
5929c8f5ca Translated using Weblate (Estonian)
Currently translated at 44.1% (616 of 1396 strings)
2021-11-27 19:33:52 +01:00
Wuzzy
28851ca9b2 Translated using Weblate (German)
Currently translated at 100.0% (1396 of 1396 strings)
2021-11-27 19:33:52 +01:00
Nicolae Crefelean
5f79e9552d Translated using Weblate (Romanian)
Currently translated at 47.6% (665 of 1396 strings)
2021-11-27 19:33:52 +01:00
Jordan Irwin
891290a79f Translated using Weblate (Spanish)
Currently translated at 80.6% (1126 of 1396 strings)
2021-11-27 19:33:52 +01:00
Riceball LEE
e1fbf4795b Translated using Weblate (Chinese (Simplified))
Currently translated at 91.2% (1274 of 1396 strings)
2021-11-27 19:33:52 +01:00
Yangjun Wang
48bb0bb5bb Translated using Weblate (Chinese (Simplified))
Currently translated at 91.2% (1274 of 1396 strings)
2021-11-27 19:33:52 +01:00
waxtatect
b9c1a999ff Translated using Weblate (French)
Currently translated at 94.9% (1325 of 1396 strings)
2021-11-27 19:33:52 +01:00
Yaya - Nurul Azeera Hidayah @ Muhammad Nur Hidayat Yasuyoshi
70ece73da9 Translated using Weblate (Malay)
Currently translated at 100.0% (1396 of 1396 strings)
2021-11-27 19:31:02 +01:00
rubenwardy
51cfb57b4d Update to Android target SDK 30 (#11746) 2021-11-27 00:10:13 +00:00
Corey Powell
413be76c63 Implemented disconnect_player (#10492)
Co-authored-by: rubenwardy <rw@rubenwardy.com>
2021-11-26 19:19:40 +00:00
ROllerozxa
c85aa0030f Remove unused Direct3D shader error/warning (#11793) 2021-11-26 19:33:24 +01:00
sfan5
87ab97da2a Fix find_nodes_in_area misbehaving with out-of-map coordinates (#11770)
This ensures that no overflows (side-effects) happen within the find_nodes_in_area function by limiting coordinates like done in the map generation code.
2021-11-26 19:32:41 +01:00
Lejo
b9051386ae Add Lua bitop library (#9847) 2021-11-26 19:31:05 +01:00
HybridDog
7a1464d783 Minimap: gamma-correct average texture colour calculation (#9249)
This calculates the average texture colour while heeding the sRGB colourspace.
2021-11-26 19:30:49 +01:00
sfan5
206e131854 Add backwards-compatible behaviour if too few CAO textures specified
(#11766)
2021-11-22 17:27:49 +00:00
ExeVirus
52bfbf6ed0 Allow for Game-Specific Menu Music (#11241) 2021-11-22 17:26:46 +00:00
Andrew Kerr
e35cfa589a Add macOS build docs (#11757) 2021-11-19 22:31:15 +00:00
savilli
c9070e54bc Fix local digging animation (#11772) 2021-11-19 22:31:04 +00:00
sfan5
c510037e9a Fix compiler detection in buildbot
it was just half-broken before...
2021-11-10 19:10:32 +01:00
Elijah Duffy
cbf658f83d Lua API: Add rmdir, cpdir and mvdir (#9638)
Co-authored-by: rubenwardy <rw@rubenwardy.com>
2021-11-10 19:10:20 +01:00
sfan5
6db914780e Fix typo in buildbot scripts 2021-11-05 11:12:56 +01:00
Riceball LEE
693f98373b Localize error messages in mainmenu (#11495)
Co-authored-by: sfan5 <sfan5@live.de>
Co-authored-by: rubenwardy <rw@rubenwardy.com>
2021-11-01 12:27:46 +00:00
Wuzzy
6910c8d920 Fix number of tool uses being off by 1..32767 (#11110) 2021-10-31 22:33:33 +00:00
JosiahWI
38ba813c55 Add variable to use existing IrrlichtMt build (#11656)
Co-authored-by: SmallJoker <SmallJoker@users.noreply.github.com>
2021-10-31 22:33:11 +00:00
sfan5
0b95da7ad3 Automatically package MinGW runtime in buildbot 2021-10-31 22:32:48 +00:00
sfan5
ea1396f856 Replace uses of which(1) with command -v 2021-10-31 22:32:48 +00:00
sfan5
4114e3047b Update Android to new dependency repo (#11690) 2021-10-31 22:32:25 +00:00
x2048
cef016d393 Apply shadow only to the naturally lit part of the fragment color (#11722)
Fragment color for nodes is now calculated from:

 * Texture color, highlighted by artificial light if present (light color conveyed via vertex color).
 * Texture color highlighted by natural light (conveyed via vertex color) filtered by shadow.
 * Reflected day/moonlight filtered by shadow (color and intensity), assuming some portion of the light is directly reflected from the materials.
2021-10-31 19:18:30 +01:00
Isabelle COWAN-BERGMAN
532d5b21fd Add joystick layout for DragonRise GameCube controller (#11467) 2021-10-31 19:17:47 +01:00
rubenwardy
8dfeba02b9 Fix crash on hypertext[] with not enough parts
The length check used < rather than <=, disabling the check when the formspec version
matches the client's FORMSPEC_API_VERSION.

Additionally, it was possible to have fewer parts than required if the formspec version
was greater than the client's FORMSPEC_API_VERSION.
2021-10-25 21:39:40 +01:00
sfan5
4ee643f472 Fixes around emerge handling 2021-10-25 20:31:52 +02:00
Jude Melton-Houghton
1e26e45530 Limit stepheight smoothing to the stepheight and stop smoothing during jumps (#11705) 2021-10-25 20:31:14 +02:00
sfan5
660e63dbae Fix item duplication if player dies during interact callback (alternative) (#11662) 2021-10-25 20:30:27 +02:00
Wuzzy
d4b89eb106 Fix no_texture.png activation w/ simple leaves 2021-10-22 11:01:42 +02:00
sfan5
a78124831f Fix incorrect error message in core.encode_png 2021-10-22 10:55:18 +02:00
Lars Müller
0d345dc1bd Fix view bobbing not resetting when resting
partially fixes #11694, also fixes #11692
2021-10-20 21:51:21 +02:00
Wuzzy
86b44ecd82 Add no_texture.png as fallback for unspecified textures 2021-10-20 21:50:16 +02:00
LoneWolfHT
c82ec8b210 Fix compiling on Windows with Visual Studio 2021-10-15 18:16:09 +02:00
rubenwardy
6901c5fae5 Use scoped app storage on Android (#11466)
From November 2021, the Play Store will no longer be accepting
apps which use the deprecated getExternalStorageDirectory() API.

Therefore, this commit replaces uses of deprecated API with the new
scoped API (`getExternalFilesDir()` and `getExternalCacheDir()`).
It also provides a temporary migration to move user data from the
shared external directory to new storage.

Fixes #2097,  #11417 and #11118
2021-10-15 18:14:48 +02:00
Wuzzy
fe7195badb Make /status message easier to read 2021-10-15 18:13:57 +02:00
hecks
02292e03e4 Add embedded PNG texture modifier (#11498) 2021-10-13 17:51:37 +02:00
sfan5
fe5cb2cdfb Remove broken timeout behaviour
Code that relies on `resend_count` was added in 7ea4a03 and 247a1eb, but never worked.
This was fixed in #11607 which caused the problem to surface.
Hence undo the first commit entirely and change the logic of the second.
2021-10-12 20:13:09 +02:00
savilli
6ea558f8ac Fix player HP desync between client and server 2021-10-12 20:12:49 +02:00
SmallJoker
ecc6f4ba25 Remove a few unused functions reported by callcatcher (#11658) 2021-10-12 20:12:20 +02:00
sfan5
6de8d77e17 Move instead of copy during content install if possible 2021-10-07 00:20:01 +02:00
sfan5
2b5075f0e2 Move archive extraction in content store to async job 2021-10-07 00:20:01 +02:00
sfan5
2d5b7b5fb4 Make fs::extractZipFile thread-safe 2021-10-07 00:20:01 +02:00
emixa-d
9fab5d594c Add "MINETEST_MOD_PATH" environment variable (#11515)
This adds an environment variable MINETEST_MOD_PATH.
When it exists, Minetest will look there for mods in addition to ~/.minetest/mods/.
2021-10-07 00:19:41 +02:00
HybridDog
53e126ac49 List only jpg and png as screenshot format options (#11675)
The other formats are no longer supported in Minetest Irrlicht.
2021-10-05 21:54:13 +02:00
lhofhansl
b4b9bee5f2 Reduce shadow jitter (#11668) 2021-10-05 21:54:01 +02:00
Wuzzy
bc71622d21 Fix crash when calling remove/kick/ban_player on start (#11672) 2021-10-05 21:53:47 +02:00
Jude Melton-Houghton
5aa95fef10 Make MetaDataRef:get return nil instead of nothing (#11666) 2021-10-05 15:38:33 +03:00
Wuzzy
4fca601e0c Add get_server_max_lag() (#11671) 2021-10-05 15:35:55 +03:00
Pedro Gimeno
d7e7ade0f6 Add an option -t to force text output in /help
This also improves detection of whether formspecs are available.
2021-10-01 16:22:05 +02:00
x2048
982e03f60d Improvements to colored shadows (#11516) 2021-10-01 16:21:53 +02:00
Wuzzy
21113ad410 Split liquid_viscosity to liquid_viscosity and move_resistance (#10810) 2021-10-01 16:21:24 +02:00
x2048
f5040707fe Order drawlist by distance to the camera when rendering (#11651) 2021-09-27 17:46:08 +02:00
SmallJoker
d51d0f3a5a Various code improvements
* Camera: Fix division by 0 after view bobbing
* Remove ignored constness
* Connection: Improve window size range limits
2021-09-27 17:45:44 +02:00
Wuzzy
918fbe3ec1 Update builtin locale files (#11650) 2021-09-26 18:04:39 +02:00
nia
2dc73d239a Use CMake's GNUInstallDirs for install directories on Unix (#11636)
This makes the installation process honor system-specific
directories (e.g. ${PREFIX}/man instead of ${PREFIX}/share/man on
BSD).
2021-09-26 18:04:30 +02:00
Wuzzy
bc7d05581b Fix several typos in settingtypes.txt (#11623) 2021-09-26 18:04:19 +02:00
TheBrokenRail
3dcf9e963e Touch UI support for desktop builds (#10729) 2021-09-26 18:04:09 +02:00
sfan5
9f85862b7c Fix "Could not create ITexture, texture needs to have a non-empty name" warning 2021-09-22 18:43:40 +02:00
nia
2628316842 Fix src/util/string.cpp on NetBSD
- iconv() prototype changed from traditional Unix defintion
  to POSIX definition in 9.99.x.
- wchar_t is not a valid character set for iconv. Share code
  with Android for using UTF-32.
2021-09-19 20:23:52 +02:00
DS
e79d6154fc Fix client-side performance of chat UI (#11612) 2021-09-19 20:23:35 +02:00
Lars Müller
40ea4ddef1 Fix HUD multiline text alignment (#10795) 2021-09-19 20:23:22 +02:00
sfan5
e0529da5c8 Fix trivial typos 2021-09-19 13:54:20 +02:00
sfan5
16a62426d6 Add feature table entry for new dynamic media API 2021-09-19 13:54:06 +02:00
sfan5
ad076ede85 Add preprocessor check for weird (incorrect) build configurations 2021-09-19 13:53:44 +02:00
sfan5
fd8a8501bc Shave off buffer copies in networking code (#11607) 2021-09-17 18:14:25 +02:00
sfan5
ea250ff5c5 Fix GLES2 discard behaviour (texture transparency) 2021-09-17 18:13:50 +02:00
HybridDog
d1e0f73b77 Hide Wself-assign-overloaded and Wself-move unittest compilation warnings
The warnings occured with the clang compiler
2021-09-17 18:13:04 +02:00
ROllerozxa
6fedee16f0 Readd TGA to the list of valid texture formats. (#11598) 2021-09-15 11:12:24 +01:00
Lars Müller
719a12ecac Chop game background in mainmenu (#10796) 2021-09-14 20:46:02 +02:00
sfan5
4feb799b7e Add Windows-specific CreateTempFile() implementation
Once again MSVC is the only compiler not supporting basic POSIX functionality.
2021-09-14 20:45:41 +02:00
sfan5
b480a3e9fd Fix broken handling of NodemetaChanged packets
fixes #11610
2021-09-12 14:42:01 +02:00
sfan5
75bf9b75ca Make sure relevant std::stringstreams are set to binary 2021-09-11 21:06:57 +02:00
sfan5
766e885a1b Clean up/improve some scriptapi error handling code 2021-09-10 23:16:46 +02:00
Jude Melton-Houghton
7423c4c11e Send to clients node metadata that changed to become empty (#11597) 2021-09-10 23:16:34 +02:00
DS
2cefe51d3b Split vector.new into 3 constructors 2021-09-10 23:16:16 +02:00
sfan5
bbfae0cc67 Dynamic_Add_Media v2 (#11550) 2021-09-09 16:51:35 +02:00
Buckaroo Banzai
bcb6565483 Add missing zstd-libs to final Docker image
Also add `minetestserver --version` command to verify docker build in CI
2021-09-07 15:29:57 +02:00
NeroBurner
7f3401412e Fix movement in random_input mode (#11592) 2021-09-05 19:58:50 +02:00
20kdc
a3e32d81c5 Add hint to error message on how to build with in-tree Irrlicht 2021-09-05 19:57:40 +02:00
Wuzzy
ff9945dc6e Fix falling mesh nodes being half size (#11389) 2021-09-01 22:20:57 +02:00
sfan5
e912008cb3 Update README for zstd changes 2021-09-01 22:20:38 +02:00
sfan5
31d2b9edcd Don't look for zlib and zstd manually on Windows 2021-09-01 22:20:38 +02:00
sfan5
e5edda28ce Drop Ubuntu 16.04 from gitlab-ci, add 20.04 instead 2021-09-01 22:20:38 +02:00
sfan5
70dafcf5da Check for required libzstd APIs in cmake
It's very unlikely that anyone uses a zstd version this old, but if they do fail early.
2021-09-01 22:20:38 +02:00
lhofhansl
d1624a5521 Switch MapBlock compression to zstd (#10788)
* Add zstd support.
* Rearrange serialization order
* Compress entire mapblock

Co-authored-by: sfan5 <sfan5@live.de>
2021-08-31 17:32:31 -07:00
sfan5
beac4a2c98 CI: Bump IrrlichtMt to 1.9.0mt3 2021-08-31 23:57:39 +02:00
pecksin
040aed37ab Remove closing paren as weblink delimiter 2021-08-29 19:30:33 +02:00
sfan5
6a1424f2b1 Async-related script cleanups 2021-08-28 12:15:12 +02:00
fn ⌃ ⌥
0f8a6d78a7 CI: Add macOS workflow (#11454) 2021-08-28 12:14:55 +02:00
savilli
3f1adb49ae Remove redundant on_dieplayer calls 2021-08-28 12:14:16 +02:00
NeroBurner
1d69a23ba4 Joystick sensitivity for player movement (#11262)
This commit deprecates the forward, backward, left, and right binary
inputs currently used for player movement in the PlayerControl struct.
In their place, it adds the movement_speed and movement_direction
values, which represents the player movement is a polar coordinate
system.

movement_speed is a scalar from 0.0 to 1.0. movement_direction is
an angle from 0 to +-Pi:

	       FWD
	        0
	        _
	 LFT   / \   RGT
	-Pi/2 |   | +Pi/2
	       \_/
	       +-Pi
	       BCK

Boolean movement bits will still be set for server telegrams and
Lua script invocations to provide full backward compatibility.
When generating these values from an analog input, a direction is
considered active when it is 22.5 degrees away from either
orthogonal axis.

Co-authored-by: Markus Koch <markus@notsyncing.net>
Co-authored-by: sfan5 <sfan5@live.de>
2021-08-27 20:24:24 +02:00
Treer
149d8fc8d6 Add group-based tool filtering for node drops (#10141)
Supports both AND and OR requirements, e.g.

 * "a tool that's in any of these groups"
 * "a tool that's in all of these groups"
2021-08-27 20:23:20 +02:00
Lean Rada
d36dca3aba Optimize vector length calculations (#11549) 2021-08-27 20:22:35 +02:00
Loïc Blot
a7188bd6f5 Add debian 11 to Gitlab-CI (#11571)
* feat(gitlab-ci): add debian 11 support
2021-08-27 11:19:15 +02:00
Loïc Blot
ff3aa18436 fix: update to alpine 3.14 (#11570) 2021-08-24 14:52:05 +02:00
JosiahWI
ef84c3b8b9 Set policies through CMake 3.9 to allow enabling IPO (#11560) 2021-08-23 22:13:47 +02:00
Wuzzy
63e8224636 Fix 6th line of infotext being cut off in half (#11456) 2021-08-23 22:13:17 +02:00
SmallJoker
eea488ed75 Inventory: Fix rare out-of-bounds access
Co-authored-by: Thomas--S <info@thomas-stangl.de>
2021-08-23 14:10:17 +02:00
DS
dad87a360b Use utf-8 for the Irrlicht clipboard (#11538) 2021-08-23 14:09:50 +02:00
sfan5
fad835cf64 Fix server-only builds on older CMake versions (#11566)
closes #11564
2021-08-23 13:33:25 +02:00
SmallJoker
0c1e9603db HUD: Reject and warn on invalid stat types (#11548)
This comes into play on older servers which do not know the "stat" type.
Warnings are only logged once to avoid spam within globalstep callbacks
2021-08-21 20:04:04 +02:00
sfan5
a72d13064f Allow lib/irrlichtmt to work for server builds (headers-only) 2021-08-21 13:53:59 +02:00
Wuzzy
6fd8aede48 Show status message when changing block bounds (#11556) 2021-08-21 13:53:49 +02:00
sfan5
e7b05beb7d Validate staticdata and object property length limits (#11511)
Some games provide users with enough freedom to create items
with metadata longer than 64KB, preventing this from causing
issues is on them but we'll still do the minimum not to abort
the server if this happens.
2021-08-19 20:14:22 +02:00
Wuzzy
1320c51d8e Fix scaled world-aligned textures being aligned inconsistently for non-normal drawtypes 2021-08-19 20:14:04 +02:00
rubenwardy
24b66dede0 Add fwgettext util function 2021-08-19 20:13:25 +02:00
SmallJoker
3b842a7e02 Fix inconsistent integer comparison warnings 2021-08-17 20:00:47 +02:00
Wuzzy
2eec997e97 Clarify the meaning of "rightclick"/"use" in documentation (#11471) 2021-08-16 17:57:07 +02:00
Lean Rada
328d949225 Start sprite animation at the beginning (#11509)
When setting a sprite animation, do not keep the last animation's frame number. Setting a new animation should start the animation at the start of the new animation.
2021-08-16 17:56:38 +02:00
sfan5
4419e311a9 Cap iterations of imageCleanTransparent sanely
fixes #11513 performance regression with 256x textures
2021-08-16 17:56:11 +02:00
Treer
963fbd1572 Fix access violation in create_schematic() (#11534)
fixes #11533

Schematics saved from y locations greater than 0 would cause an access violation if layer probabilities were specified
2021-08-16 17:55:35 +02:00
SmallJoker
b3b075ea02 Fix segfault caused by shadow map on exit 2021-08-12 20:08:39 +02:00
Hugues Ross
47c146120a Add disable_settings to game.conf to get rid of "Enable Damage"/"Creative Mode"/"Host Server" checkboxes (#11524)
This adds support for disable_settings to game.conf. In this you can specify a list of settings that should not be visible in the "local game" (or however it is called nowadays) tab. Enable Damage, Creative Mode and Host Server are supported.

Co-authored-by: Wuzzy <Wuzzy2@mail.ru>
Co-authored-by: Aaron Suen <warr1024@gmail.com>
Co-authored-by: rubenwardy <rw@rubenwardy.com>
2021-08-12 20:08:12 +02:00
x2048
442e48b84f Move updating shadows outside of RenderingCore::drawAll. (#11491)
Fixes indirect rendering modes such as some 3D modes mentioned in #11437 and undersampled rendering.
Does not fully fix anaglyph 3d mode.
2021-08-12 20:07:09 +02:00
DS
0709946c75 Fix a segfault caused by wrong textdomain lines in translation files (#11530)
* The problem were lines like these:
  "# textdomain:"
* str_split does not add an empty last part if there is a delimiter
  at the end, but this was probably assumed here.
2021-08-12 20:06:18 +02:00
hecks
eefa39e47b Remove statement semicolons from a lua script 2021-08-09 21:03:18 +02:00
DS
1ab29f1716 Fix GUIEditBoxWithScrollBar using a smaller steps than intlGUIEditBox (#11519) 2021-08-08 18:59:45 +02:00
Pevernow
c6eddb0bae Gettext support on Android (#11435)
Co-authored-by: sfan5 <sfan5@live.de>
Co-authored-by: =?UTF-8?q?Olivier=20Samyn=20=F0=9F=8E=BB?= <code@oleastre.be>
2021-08-08 18:59:07 +02:00
SmallJoker
4a3728d828 OpenAL: Free buffers on quit 2021-08-03 20:29:55 +02:00
rubenwardy
bee50ca7fa ContentDB: Add support for package aliases / renaming (#11484) 2021-08-02 20:05:10 +01:00
SmallJoker
32cb9d0828 Mods: Combine mod loading checks and deprection logging (#11503)
This limits the logged deprecation messages to the mods that are loaded
Unifies the mod naming convention check for CSM & SSM
2021-07-31 19:54:52 +02:00
Wuzzy
e7cd4cfa25 Fix /emergeblocks crashing in debug builds (#11461)
The reason for the bug was an u16 overflow, thus failing the assert. This only happened in Debug build but not in Release builds.
2021-07-31 19:54:40 +02:00
sfan5
0257e7150f Update IrrlichtMt-related stuff in README 2021-07-31 13:26:17 +02:00
hecks
1e2b638881 Remove unsupported formats from the media enumerator 2021-07-29 22:42:47 +02:00
hecktest
28c98f9fa5 Remove unsupported extensions from list in tile.cpp 2021-07-29 21:47:08 +02:00
hecks
80d12dbedb Add a simple PNG image encoder with Lua API (#11485)
* Add a simple PNG image encoder with Lua API
Add ColorSpec to RGBA converter
Make a safety wrapper for the encoder
Create devtest examples

Co-authored-by: hecktest <>
Co-authored-by: sfan5 <sfan5@live.de>
2021-07-29 05:10:10 +02:00
sfan5
2866918f32 buildbot: Readd missing IrrlichtMt DLLs 2021-07-27 20:37:51 +02:00
sfan5
6e8aebf432 Add bold, italic and monospace font styling for HUD text elements (#11478)
Co-authored-by: Elias Fleckenstein <eliasfleckenstein@web.de>
2021-07-27 19:11:46 +02:00
JosiahWI
cf136914cf Take advantage of IrrlichtMt CMake target (#11287)
With the CMake changes to IrrlichtMt, it's now possible to use a target for IrrlichtMt.
Besides greatly improving the ease of setting up IrrlichtMt for users building the client, it removes the need for Minetest's CMake to include transitive dependencies such as image libraries, cleaning it up a tiny bit. The PR works by finding the IrrlichtMt package and linking to the target it provides. If the package isn't found and it isn't building the client, it will still fall back to using just the headers of old Irrlicht or IrrlichtMt.
2021-07-27 19:11:27 +02:00
Wuzzy
216728cc5e Improve documentation of tools (#11128) 2021-07-27 19:09:14 +02:00
rubenwardy
9c145ba0d8 ContentDB: Add reason to downloads (#10876) 2021-07-27 19:08:49 +02:00
x2048
bf3acbf388 Distribute shadow map update over multiple frames to reduce stutter (#11422)
Reduces stutter and freezes when playing.

 * Maintains double SM and SM Color textures
 * Light frustum update triggers incremental generation of shadow map into secondary 'future' textures.
 * Every incremental update renders a portion of the shadow draw list (split equally).
 * After defined number of frames (currently, 4), 'future' and 'current' textures are swapped, and DirectionalLight 'commits' the new frustum to use when rendering shadows on screen.

Co-authored-by: sfan5 <sfan5@live.de>
2021-07-25 12:36:23 +02:00
x2048
ff2d2a6e93 Add smooth light-shadow transition at noon (#11430)
Node faces with normals pointing East/West (+X/-X) will transition between light
and shadow at noon. This code makes the transition smooth.
2021-07-25 12:35:12 +02:00
random-geek
5d27cc5096 Document glasslikeliquidlevel merge bits (#11479) 2021-07-25 12:34:53 +02:00
hecks
a049e8267f Remove unused ITextSceneNode header (#11476)
Co-authored-by: hecktest <>
2021-07-22 00:55:20 +02:00
hecks
850293bae6 Remove unused header includes 2021-07-21 22:07:13 +02:00
sfan5
6caed7073c Fix no locales being generated when APPLY_LOCALE_BLACKLIST=0
Also enable `ky` which appears to work fine.
2021-07-20 17:58:47 +02:00
SmallJoker
40bee27e56 CSM: Do not index files within hidden directories
CSM would previously scan for files within .git or .svn directories, and also special files such as .gitignore
2021-07-17 16:44:06 +02:00
Wuzzy
f4d8cc0f0b Add wallmounted support for plantlike and plantlike_rooted nodes (#11379) 2021-07-15 21:19:59 +02:00
Hugues Ross
68143ed8ec Fix documented default colors for set_sky 2021-07-14 17:14:45 +02:00
Wuzzy
6cdb150c8b Remove hardcoded "You died." message in chat (#11443) 2021-07-12 20:32:27 +02:00
Wuzzy
b7b5aad027 Fix revoke debug privs not reliably turn off stuff (#11409) 2021-07-12 20:32:18 +02:00
sfan5
5c89a0e12a Fix build on Ubuntu 16.04 and macOS
Apparently the C++ standard library is supposed to provide
specializations of std::hash for enums (even in C++11)
but those don't always work for whatever reason.
2021-07-12 12:03:39 +02:00
x2048
effb5356ca Avoid draw list and shadow map update in the same frame to reduce dtime jitter (#11393)
* Separate draw list and shadows update to reduce jitter

* Avoid draw list update and shadow update in the same frame

* Force-update shadows when camera offset changes
2021-07-11 10:57:29 -07:00
x2048
f5706d444b Improve shadow rendering with non-default camera FOV (#11385)
* Adjust minimum filter radius for perspective

* Expand shadow frustum when camera FOV changes, reuse FOV distance adjustment from numeric.cpp

* Read shadow_soft_radius setting as float

* Use adaptive filter radius to accomodate for PSM distortion

* Adjust filter radius for texture resolution
2021-07-11 08:15:19 -07:00
hecks
1d25d1f7ad Refactor video driver name retrieval (#11413)
Co-authored-by: hecktest <>
2021-07-11 09:50:34 +02:00
hecktest
29522017a3 Fix typo in lua_api.txt 2021-07-10 16:37:18 -07:00
SmallJoker
b93bbfde2c Script API: Fix segfault in remove_detached_inventory
when minetest.remove_detached_inventory is called on script init, the environment is yet not set up,
hence m_env is still nullptr until all scripts are loaded
2021-07-10 14:34:36 +02:00
Lean Rada
42fbc757b1 Use persistence instead of persist in NoiseParams examples 2021-07-10 14:19:33 +02:00
Warr1024
52128ae11e Add API for mods to hook liquid transformation events (#11405)
Add API for mods to hook liquid transformation events

Without this API, there is no reliable way for mods to be
notified when liquid transform modifies nodes and mods are
forced to poll for changes.  This allows mods to detect
changes to flowing liquid nodes and liquid renewal using
event-driven logic.
2021-07-09 09:08:40 -04:00
hecks
e9bc59e376 Add .editorconfig (#11412)
* Add an .editorconfig to the repo root folder, providing code style hints for some text editors and making the code render properly in github.

Co-authored-by: hecktest <>
2021-07-03 23:05:15 +02:00
SmallJoker
062fd2190e Auth API: Error when accessed prior to ServerEnv init (#11398) 2021-06-30 20:42:26 +02:00
hecks
827a7852e2 Remove unsupported video drivers (#11395)
This completely removes any mention of the software and D3D drivers from MT, preventing the user from accidentally attempting to use them. Users who need a software renderer should be asked to install Mesa drivers which offer superior fidelity and performance over the 'burningsvideo' driver.
2021-06-30 20:42:15 +02:00
AFCMS
8cc04e0cb4 Run on_grant and on_revoke callbacks after privs change (#11387)
Callbacks were run too early. This changes the order to call after the privs are updated.
2021-06-30 20:40:45 +02:00
SmallJoker
f2fd443262 Inventory: Make addList() consistent (#11382)
Fixes list clearing for inv:set_list() using same size, since 2db6b07.
addList() now clears the list in all cases. Use setSize() to resize without clearing.
2021-06-30 20:39:38 +02:00
sfan5
72927b73ca Fix spurious shadow enablement in mainmenu
fixes #11394
2021-06-30 17:10:28 +02:00
NeroBurner
fa4dee0e62 Use user provided lib/irrlichtmt if available (#11276)
Use user provided lib/irrlichtmt if available

Make it possible for a user to provide the IrrlichtMt dependency as
subdirectory at `lib/irrlichtmt`.
The subdirectory is added with the `EXCLUDE_FROM_ALL` flag to prevent
`libirrlichtmt.a` or other header files to be installed.

This enables the user to do the following to satisfy the IrrlichtMt
dependency:

git clone --depth 1 https://github.com/minetest/irrlicht.git lib/irrlichtmt
cmake . -DRUN_IN_PLACE=TRUE
2021-06-29 10:57:19 +03:00
Wuzzy
63fc728a84 Require 'basic_debug' priv to view gameplay-relevant debug info, require 'debug' priv to view wireframe (#9315)
Fixes #7245.
2021-06-24 21:21:19 +03:00
Wuzzy
51bf4a6e26 Perform some quality assurance for translation strings (#11375) 2021-06-23 17:35:50 +01:00
sfan5
c60a146e22 Rework Settings to support arbitrary hierarchies (#11352) 2021-06-23 15:22:31 +02:00
Juozas
cec0dfcbbd Buildbot: Use posix on Win64 builds if available (#11355)
Use posix mingw-w64 toolchain on Win64 builds where applicable, avoids
many build errors when using buildwin64.sh to build 64 bit builds on
Ubuntu based Linux distributions
2021-06-22 19:59:09 +02:00
SmallJoker
a8b7c8ff38 Server: Ignore whitespace-only chat messages 2021-06-22 19:47:18 +02:00
Wuzzy
b5c09ada79 Document hypertext escaping (#11374) 2021-06-22 13:42:40 +01:00
NeroBurner
a7143c2a8c Move build/android directory to root of project (#11283) 2021-06-21 20:51:42 +01:00
Wuzzy
7fdbf3f231 Update builtin locale (#11371) 2021-06-21 18:55:55 +01:00
William L. DeRieux IV
9d2e7fc983 Strip carriage returns from lines in settingtypes.txt (#11338)
Co-authored-by: SmallJoker <SmallJoker@users.noreply.github.com>
2021-06-21 18:55:48 +01:00
Bensuperpc
4b9a51ff0d Update Dockerfile and improve build speed (#11313)
Use ninja to build image, rename docker build steps: builder and runtime, add argument for docker image version

Signed-off-by: Bensuperpc <bensuperpc@gmail.com>
2021-06-21 18:55:38 +01:00
Wuzzy
b28523bf38 Fix some typos in builtin (#11370) 2021-06-21 17:30:29 +01:00
SmallJoker
2db6b07de1 Inventory: show error on invalid list names (#11368) 2021-06-20 17:21:50 +02:00
sfence
b10091be9b Add min_y and max_y checks for Active Block Modifiers (ABM) (#11333)
This check can be used by ABM to reduce CPU usage.
2021-06-20 17:21:35 +02:00
pecksin
1805775f3d Make chat web links clickable (#11092)
If enabled in minetest.conf, provides colored, clickable (middle-mouse or ctrl-left-mouse) weblinks in chat output, to open the OS' default web browser.
2021-06-20 17:20:24 +02:00
rubenwardy
e1b297a14b Add roadmap (#10536) 2021-06-17 04:15:30 +01:00
updatepo.sh
88bda3d914 Update translation files 2021-06-16 18:28:05 +02:00
updatepo.sh
cb5dd0dae4 Update minetest.conf.example and dummy translation file 2021-06-16 18:27:45 +02:00
Riceball LEE
ce0541fc0e Translated using Weblate (Chinese (Simplified))
Currently translated at 95.1% (1290 of 1356 strings)
2021-06-16 18:23:10 +02:00
David Leal
165986beb0 Translated using Weblate (Spanish)
Currently translated at 81.5% (1106 of 1356 strings)
2021-06-16 18:23:10 +02:00
Tirifto
3474b97921 Translated using Weblate (Esperanto)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Yiu Man Ho
5915941eba Translated using Weblate (Chinese (Traditional))
Currently translated at 75.6% (1026 of 1356 strings)
2021-06-16 18:23:10 +02:00
Allan Nordhøy
8575d68d49 Translated using Weblate (Norwegian Bokmål)
Currently translated at 58.1% (789 of 1356 strings)
2021-06-16 18:23:10 +02:00
telmo bruno silva seabra
42aa81befd Translated using Weblate (Esperanto)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Avyukt More
392408401c Translated using Weblate (Marathi)
Currently translated at 8.6% (117 of 1356 strings)
2021-06-16 18:23:10 +02:00
Avyukt More
dd3409c961 Added translation using Weblate (Marathi) 2021-06-16 18:23:10 +02:00
Andrei Stepanov
1a5279e911 Translated using Weblate (Russian)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Andrij Mizyk
a3b480e300 Translated using Weblate (Ukrainian)
Currently translated at 44.6% (606 of 1356 strings)
2021-06-16 18:23:10 +02:00
Nicolae Crefelean
79a2c6f49d Translated using Weblate (Romanian)
Currently translated at 48.7% (661 of 1356 strings)
2021-06-16 18:23:10 +02:00
THANOS SIOURDAKIS
07e7d71bac Translated using Weblate (Greek)
Currently translated at 12.0% (164 of 1356 strings)
2021-06-16 18:23:10 +02:00
Gian M
873feb2619 Added translation using Weblate (Filipino) 2021-06-16 18:23:10 +02:00
Omer I.S
a189ce20b1 Translated using Weblate (Hebrew)
Currently translated at 44.3% (601 of 1356 strings)
2021-06-16 18:23:10 +02:00
phlostically
53e82d0b25 Translated using Weblate (Esperanto)
Currently translated at 98.7% (1339 of 1356 strings)
2021-06-16 18:23:10 +02:00
ferrumcccp
dfe9f2c925 Translated using Weblate (Chinese (Simplified))
Currently translated at 94.8% (1286 of 1356 strings)
2021-06-16 18:23:10 +02:00
ludemys
fd63faa3f3 Translated using Weblate (Spanish)
Currently translated at 81.4% (1104 of 1356 strings)
2021-06-16 18:23:10 +02:00
David Leal
72ae97d8ef Translated using Weblate (Spanish)
Currently translated at 81.4% (1104 of 1356 strings)
2021-06-16 18:23:10 +02:00
ludemys
3c761f86c2 Translated using Weblate (Spanish)
Currently translated at 81.0% (1099 of 1356 strings)
2021-06-16 18:23:10 +02:00
Kornelijus Tvarijanavičius
a09db258ee Translated using Weblate (Lithuanian)
Currently translated at 16.5% (224 of 1356 strings)
2021-06-16 18:23:10 +02:00
waxtatect
875e9d4c6f Translated using Weblate (French)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Brian Gaucher
d3fb83db6b Translated using Weblate (French)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Markus Mikkonen
3cc14d58d4 Translated using Weblate (Finnish)
Currently translated at 3.2% (44 of 1356 strings)
2021-06-16 18:23:10 +02:00
Tviljan
33509b13b7 Translated using Weblate (Finnish)
Currently translated at 3.2% (44 of 1356 strings)
2021-06-16 18:23:10 +02:00
Edward
686dcc7c59 Translated using Weblate (Russian)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
ssantos
3a2f9859fe Translated using Weblate (Portuguese)
Currently translated at 93.2% (1264 of 1356 strings)
2021-06-16 18:23:10 +02:00
waxtatect
ca254e4e4c Translated using Weblate (French)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
David Leal
a66b4f69e9 Translated using Weblate (Spanish)
Currently translated at 79.7% (1081 of 1356 strings)
2021-06-16 18:23:10 +02:00
Timur Seber
398815c0c5 Translated using Weblate (Tatar)
Currently translated at 0.4% (6 of 1356 strings)
2021-06-16 18:23:10 +02:00
François Delpierre
bc49e3a8d1 Translated using Weblate (French)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
waxtatect
45ee5c9f03 Translated using Weblate (French)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Timur Seber
36af92443c Added translation using Weblate (Tatar) 2021-06-16 18:23:10 +02:00
BreadW
20dd05b343 Translated using Weblate (Japanese)
Currently translated at 99.8% (1354 of 1356 strings)
2021-06-16 18:23:10 +02:00
GnuPGを使うべきだ
34da979ef6 Translated using Weblate (Japanese)
Currently translated at 99.7% (1353 of 1356 strings)
2021-06-16 18:23:10 +02:00
ItsWidee
5b11a6a800 Translated using Weblate (French)
Currently translated at 98.0% (1330 of 1356 strings)
2021-06-16 18:23:10 +02:00
François Delpierre
f8e9ea38da Translated using Weblate (French)
Currently translated at 96.6% (1311 of 1356 strings)
2021-06-16 18:23:10 +02:00
Dainis
6405188f68 Translated using Weblate (Latvian)
Currently translated at 28.6% (388 of 1356 strings)
2021-06-16 18:23:10 +02:00
Konstantin Yeliseyev
4b6402a005 Translated using Weblate (Russian)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
ResuUman
f922a78d13 Translated using Weblate (Polish)
Currently translated at 72.4% (982 of 1356 strings)
2021-06-16 18:23:10 +02:00
Mateusz Mendel
ac46a4e7b3 Translated using Weblate (Polish)
Currently translated at 72.4% (982 of 1356 strings)
2021-06-16 18:23:10 +02:00
gnu-ewm
6393d32332 Translated using Weblate (Polish)
Currently translated at 71.6% (972 of 1356 strings)
2021-06-16 18:23:10 +02:00
Alessandro Mandelli
aac0d36a1d Translated using Weblate (Italian)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:10 +02:00
Hatlábú Farkas
9c8c7cfa13 Translated using Weblate (Hungarian)
Currently translated at 75.8% (1028 of 1356 strings)
2021-06-16 18:23:10 +02:00
ItsWidee
a016189bb0 Translated using Weblate (French)
Currently translated at 96.5% (1309 of 1356 strings)
2021-06-16 18:23:10 +02:00
matiasC
116957e131 Translated using Weblate (Spanish)
Currently translated at 79.5% (1079 of 1356 strings)
2021-06-16 18:23:10 +02:00
Joaquín Villalba
e64c299983 Translated using Weblate (Spanish)
Currently translated at 79.5% (1079 of 1356 strings)
2021-06-16 18:23:10 +02:00
AnthonyDe
dc6c43db7d Translated using Weblate (Spanish)
Currently translated at 79.5% (1079 of 1356 strings)
2021-06-16 18:23:10 +02:00
Michalis
900996c9f1 Translated using Weblate (Greek)
Currently translated at 8.8% (120 of 1356 strings)
2021-06-16 18:23:10 +02:00
Yangjun Wang
2e21b4a1b4 Translated using Weblate (Chinese (Simplified))
Currently translated at 94.7% (1285 of 1356 strings)
2021-06-16 18:23:10 +02:00
Liu Tao
9352c26404 Translated using Weblate (Chinese (Simplified))
Currently translated at 94.7% (1285 of 1356 strings)
2021-06-16 18:23:10 +02:00
Yangjun Wang
5b2b3464c0 Translated using Weblate (Chinese (Simplified))
Currently translated at 92.5% (1255 of 1356 strings)
2021-06-16 18:23:10 +02:00
David Leal
2bc00862d3 Translated using Weblate (Spanish)
Currently translated at 79.0% (1072 of 1356 strings)
2021-06-16 18:23:10 +02:00
Joaquín Villalba
819fbefc12 Translated using Weblate (Spanish)
Currently translated at 78.0% (1059 of 1356 strings)
2021-06-16 18:23:09 +02:00
David Leal
1784d5f741 Translated using Weblate (Spanish)
Currently translated at 78.0% (1059 of 1356 strings)
2021-06-16 18:23:09 +02:00
Agustin Calderon
b9456c1a0c Translated using Weblate (Spanish)
Currently translated at 78.0% (1059 of 1356 strings)
2021-06-16 18:23:09 +02:00
abidin toumi
6e8e0d10c8 Translated using Weblate (Arabic)
Currently translated at 25.7% (349 of 1356 strings)
2021-06-16 18:23:09 +02:00
Tirifto
0403de57ed Translated using Weblate (Esperanto)
Currently translated at 94.6% (1283 of 1356 strings)
2021-06-16 18:23:09 +02:00
Oğuz Ersen
a70dfcaed9 Translated using Weblate (Turkish)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:09 +02:00
THANOS SIOURDAKIS
67b6f9771c Translated using Weblate (Greek)
Currently translated at 8.8% (120 of 1356 strings)
2021-06-16 18:23:09 +02:00
Yaya - Nurul Azeera Hidayah @ Muhammad Nur Hidayat Yasuyoshi
afecda0a7d Translated using Weblate (Malay)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:09 +02:00
winniepee
fa303ae12e Translated using Weblate (Chinese (Simplified))
Currently translated at 92.4% (1254 of 1356 strings)
2021-06-16 18:23:09 +02:00
Ayes
4bc56034cf Translated using Weblate (Estonian)
Currently translated at 39.5% (536 of 1356 strings)
2021-06-16 18:23:09 +02:00
Wuzzy
a065e22f97 Translated using Weblate (German)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:09 +02:00
Marian
8231516bca Translated using Weblate (Slovak)
Currently translated at 100.0% (1356 of 1356 strings)
2021-06-16 18:23:09 +02:00
narrnika
af7160b859 Translated using Weblate (Russian)
Currently translated at 99.3% (1347 of 1356 strings)
2021-06-16 18:21:11 +02:00
Mateusz Mendel
ec5e149c7a Translated using Weblate (Polish)
Currently translated at 71.2% (966 of 1356 strings)
2021-06-16 18:21:11 +02:00
Giov4
d6debece16 Translated using Weblate (Italian)
Currently translated at 99.7% (1352 of 1356 strings)
2021-06-16 18:21:11 +02:00
sfan5
edf098db63 Drop --videomodes, fullscreen_bpp and high_precision_fpu settings
These have been pointless for a while.
2021-06-16 17:41:34 +02:00
Wuzzy
dc165fe942 Message for empty list output in /haspriv & /mods (#11149) 2021-06-12 18:48:21 +02:00
benrob0329
fbcf0fab8e falling.lua - Fix Meshnodes Being Too Big (#11307) 2021-06-12 18:48:14 +02:00
Liso
c47313db65 Shadow mapping render pass (#11244)
Co-authored-by: x2048 <codeforsmile@gmail.com>
2021-06-06 18:51:21 +02:00
sfan5
46f42e15c4 Fix check that given IRRLICHT_LIBRARY exists 2021-06-05 13:36:52 +02:00
Muhammad Rifqi Priyo Susanto
40acfc938c Android: Do not submit text after pressing Enter key for multi-line text (#11298)
Regular EditText is used for multi-line text to not close the dialog after pressing back button.
New button is added for submitting multi-line text.
2021-06-04 21:22:53 +02:00
DS
8f085e02a1 Add metatables to lua vectors (#11039)
Add backwards-compatible metatable functions for vectors.
2021-06-04 21:22:33 +02:00
sfan5
e15cae9fa0 fontengine: Fix crash loading PNG/XML fonts from paths without dot
fixes #11096
2021-06-01 19:47:41 +02:00
SmallJoker
c9144ae5e2 Add core.compare_block_status function (#11247)
Makes it possible to check the status of the mapblock in a future-extensible way.
2021-05-30 20:24:12 +02:00
Lars Müller
89f3991351 Fix base64 validation and add unittests (#10515)
Implement proper padding character checks
2021-05-30 20:23:12 +02:00
sfan5
1bc753f655 Use safe_file_write to save forceloaded blocks 2021-05-30 11:40:14 +02:00
sfan5
f30dcdb504 Fix procession ordering issue in content_cao 2021-05-30 11:40:14 +02:00
sfan5
2c53f03c18 Remove unused version detection from FindLuaJIT.cmake 2021-05-30 11:40:14 +02:00
sfan5
758e3aa1ca Fix background color of formspec text fields 2021-05-30 11:40:14 +02:00
sfan5
a0047d6edc script: Replace calls to depreated luaL_openlib 2021-05-30 11:40:14 +02:00
sfan5
a12017c564 Provide exact error message if postgres connection string missing 2021-05-30 11:40:14 +02:00
Wuzzy
d7a4479eb3 Fix misleading /shutdown command syntax 2021-05-29 11:45:04 +02:00
SmallJoker
5bf72468f3 UnitSAO: Prevent circular attachments 2021-05-29 11:44:48 +02:00
Wuzzy
ff48619a85 Fix cloud fog being broken for high clouds 2021-05-29 11:44:31 +02:00
savilli
673c29f7ea Fix client crash on when con::PeerNotFoundException is thrown (#11286) 2021-05-24 19:40:35 +02:00
SmallJoker
93f43c890b GUIEditBox: Allow selecting and copying read-only texts 2021-05-22 14:39:41 +02:00
sfan5
4152227f17 CI: add workaround to fix clang builds
see https://github.com/actions/virtual-environments/issues/3376
2021-05-17 17:12:37 +02:00
sfan5
b56a028d6b Fix curl_timeout being ignored for Lua HTTP fetches 2021-05-17 17:12:30 +02:00
Lejo
d44f1aabbb Fix list of libraries included in AppImage 2021-05-15 23:56:33 +02:00
Dmitry Marakasov
53dca4f95f Use --image-base instead of -Ttext-segment for lld linker on FreeBSD (#9367) (#11263) 2021-05-15 10:15:03 +02:00
sfan5
69c70dd319 Fix swapped vertex colors on GLES2 2021-05-11 21:15:39 +02:00
sfan5
2443f1e235 Fix overlays for 2D-drawn items
fixes #11248
2021-05-08 19:44:43 +02:00
lhofhansl
7c2826cbc0 Fix build for newer versions of GCC (#11246) 2021-05-06 19:24:30 +02:00
Wuzzy
1bb8449734 Improve liquid documentation (#11158) 2021-05-06 19:24:11 +02:00
Loic Blot
225d4541ff fix: extractZipFile is not part of Client but more generic.
This solve a crash from mainmenu while extracting the zip
2021-05-06 16:01:52 +02:00
sfan5
ba40b39500 Add basic client-server test to CI 2021-05-05 22:49:44 +02:00
sfan5
08f1a7fbed Use Irrlicht functions to query npot texture support 2021-05-05 22:49:44 +02:00
Loic Blot
de85bc9227 fix: some code tidy about includes & irr namespaces 2021-05-03 19:49:19 +02:00
Loic Blot
48d5abd5be refacto: remove get_gui_env & draw_load_screen from RenderingEngine singleton 2021-05-03 19:49:19 +02:00
Loic Blot
a93712458b fix: don't use RenderingEngine singleton when it's possible 2021-05-03 19:49:19 +02:00
Loic Blot
5a02c376ea refacto: RenderingEngine::get_scene_manager() is now not callable from singleton
This permits to make evidence that we have some bad object passing on various code parts. I fixed majority of them to reduce the scope of passed objects

Unfortunately, for some edge cases i should have to expose ISceneManager from client, this should be fixed in the future when our POO will be cleaner client side (we have a mix of rendering and processing in majority of the client objects, it works but it's not clean)
2021-05-03 19:49:19 +02:00
Loic Blot
ccdd886e27 refacto: Hud: make driver, client, player, inventory, tsrc private & drop unused guienv
also fix c_content.h, on client it includes the src/client/hud.h instead of src/hud.h, which leads to wrong file dependency on the lua stack
2021-05-03 19:49:19 +02:00
Loic Blot
a47a00228b refacto: drop unused Hud::smgr 2021-05-03 19:49:19 +02:00
Loic Blot
809e68fdc0 refacto: don't use RenderingEngine singleton on CAO
* we don't need on CAO side more than SceneManager, and temporary. Pass only required SceneManager as a parameter to build CAO and add them to the current scene
* Use temporary the RenderingEngine singleton from ClientEnvironment, waitfor for better solution
* Make ClientActiveObject::addToScene virtual function mandatory to be defined by children to ensure we don't forget to properly define it
2021-05-03 19:49:19 +02:00
Loic Blot
1bc855646e refacto: protect some RenderingEngine::get_scene_manager
* protect it from Camera, Sky, ClientMap object calls
* rename Game::sky to Game::m_sky
2021-05-03 19:49:19 +02:00
Loic Blot
258101a910 refacto: RenderingEngine is now better hidden
* No more access to the singleton instance from everywhere (RenderingEngine::get_instance dropped)
* RenderingEngine::get_timer_time is now non static
* RenderingEngine::draw_menu_scene is now non static
* RenderingEngine::draw_scene is now non static
* RenderingEngine::{initialize,finalize} are now non static
* RenderingEngine::run is now non static
* RenderingEngine::getWindowSize now have a static helper. It was mandatory to hide the global get_instance access
2021-05-03 19:49:19 +02:00
Loic Blot
74125a74d3 refacto: hide mesh_cache inside the rendering engine
This permit cleaner access to meshCache and ensure we don't access to it from all the code
2021-05-03 19:49:19 +02:00
Loic Blot
e0716384d6 refacto: add RenderingEngine::cleanupMeshCache
This permits to prevent client to own the mesh cache cleanup logic. It's better in RenderingEngine
2021-05-03 19:49:19 +02:00
Loic Blot
e34d28af9f refacto: rendering engine singleton removal step 1 (filesystem)
Make the RenderingEngine filesystem member non accessible from everywhere

This permits also to determine that some lua code has directly a logic to extract zip file. Move this logic inside client, it's not the lua stack role to perform a such complex operation

Found also another irrlicht <1.8 compat code to remove
2021-05-03 19:49:19 +02:00
Loic Blot
bc1888ff21 fix: drop old irrlicht <1.8 compat on Client::loadMedia 2021-05-03 19:49:19 +02:00
sfan5
83a7b48bb1 Fix Windows pipelines on Gitlab-CI 2021-04-28 09:18:05 +02:00
Wuzzy
228f1c6770 Fix rotation for falling mesh degrotate nodes (#11159) 2021-04-28 08:38:47 +02:00
sfan5
734fb2c811 Add helpful error messages if Irrlicht library / include dir are set incorrectly (#11232) 2021-04-28 08:38:18 +02:00
sfan5
9660ae288a Update library versions in buildbot (#11229) 2021-04-27 11:50:40 +02:00
Wuzzy
776015c350 Rename “Irrlicht” to “IrrlichtMt” in documentation 2021-04-23 21:37:45 +02:00
Vincent Robinson
074e6a67de Add minetest.colorspec_to_colorstring (#10425) 2021-04-23 21:37:24 +02:00
sfan5
3e2145d662 Fix two CMake build issues
* PostgreSQL fallback code missed the includes (closes #11219)
* build failed when Freetype enabled but not found
2021-04-21 20:26:43 +02:00
sfan5
daf862a38a Fix devtest Lua error
fallback_image() was removed in 3e1904fa8c,
which was written after this PR but merged before it.
2021-04-21 16:42:34 +02:00
sfan5
a24899bf2d Look for PostgreSQL library properly and fix CI 2021-04-20 19:50:34 +02:00
sfan5
1da73418cd Enable cleanTransparent filter for mipmapping and improve its' algorithm (#11145) 2021-04-20 19:50:19 +02:00
Wuzzy
90a7bd6a0a Put torch/signlike node on floor if no paramtype2 (#11074) 2021-04-20 19:50:03 +02:00
Seth Traverse
16e5b39e1d Add a key to toggle map block bounds (#11172)
It's often useful to know where the map block boundaries are for doing server admin work and the like.
Adds three modes: single mapblock, range of 5, and disabled.
2021-04-20 19:23:31 +02:00
sfan5
0077982fb7 GLES fixes (#11205)
* Consistently set float precision for GLES

* Enable DPI scaling on Windows+GLES
2021-04-18 16:07:13 +02:00
sfan5
623f0a8613 Isolate library tables between sandbox and insecure env 2021-04-18 16:06:42 +02:00
sfan5
52c0384bd1 Fix ignored OpenGLES2 include path and cmake warning 2021-04-16 23:39:16 +02:00
benrob0329
a106bfd456 Also return the ObjectRef from minetest.spawn_falling_node() (#11184) 2021-04-13 20:02:43 +02:00
SmallJoker
bbe120308f Attachments: Avoid data loss caused by set_attach() in callbacks (#11181) 2021-04-13 20:02:18 +02:00
sfan5
4d0fef8ae8 Buildbot changes to allow out-of-tree builds (#11180)
* Do proper out-of-tree builds with buildbot
* Don't write to bin/ for cross builds
     * This allows safely building multiple builds from the same source dir, e.g. with the buildbot.
* Disable Gettext (by default) and Freetype (entirely) for server builds
2021-04-11 17:10:06 +02:00
Wuzzy
4b8209d9a4 Modifying fall damage via armor group (#11080)
Adds a new fall_damage_add_percent armor group which influences the fall damage in addition to the existing node group.
2021-04-11 17:09:37 +02:00
sfan5
0abc1e98ed Fix server favorites not saving when client/serverlist/ doesn't exist already (#11152) 2021-04-09 22:36:10 +02:00
Wuzzy
a0e7a4a0df Update German builtin translation 2021-04-09 22:34:18 +02:00
Wuzzy
8c7e214875 Update builtin locale files 2021-04-09 22:34:18 +02:00
Wuzzy
e89e6c8380 Don't reseed stars when changing star count 2021-04-09 22:33:45 +02:00
sfan5
57218aa9d1 Update Android build config 2021-04-09 21:16:45 +02:00
yw05
85163b531f Make edit boxes respond to string input (IME) (#11156)
Make edit boxes respond to string input events (introduced in minetest/irrlicht#23) that are usually triggered by entering text with an IME.
2021-04-05 15:56:29 +02:00
DS
2332527765 Add vector.to_string and vector.from_string (#10323)
Writing vectors as strings is very common and should belong to `vector.*`. `minetest.pos_to_string` is also too long to write, implies that one should only use it for positions and leaves no spaces after the commas.
2021-04-05 15:55:56 +02:00
sfan5
19c283546c Don't apply connection timeout limit to locally hosted servers
fixes #11085
2021-04-05 15:21:43 +02:00
SmallJoker
c11208c4b5 Game: Scale damage flash to max HP
The flash intensity is calculated proportionally to the maximal HP.
2021-04-05 13:38:50 +02:00
sfan5
f0bad0e2ba Reserve vectors before pushing and other code quality changes (#11161) 2021-04-05 13:38:31 +02:00
Wuzzy
3e1904fa8c Devtest: Remove testnodes_show_fallback_image 2021-04-05 13:37:58 +02:00
Loic Blot
88783679cf fix(ci): ensure we build on docker only modifications 2021-04-02 14:40:22 +02:00
Loic Blot
5de849713e fix(docker): reduce the number of required libraries on build 2021-04-02 14:40:22 +02:00
Loic Blot
78da79b60f fix: use irrlicht fork instead of the standard library 2021-04-02 14:40:22 +02:00
Loic Blot
c4b048fbb3 fix: don't send the whole local context to the docker image 2021-04-02 14:40:22 +02:00
sfan5
024d47e0d3 CGUITTFont optimizations (#11136) 2021-04-02 00:20:16 +02:00
sfan5
34888a914e Sort out cURL timeouts and increase default 2021-04-02 00:19:39 +02:00
Vincent Robinson
3560691c0a Add math.round and fix vector.round (#10803) 2021-04-02 00:18:58 +02:00
sfan5
1e4913cd76 Irrlicht support code maintenance 2021-03-31 13:15:47 +02:00
sfan5
0d90ed6d92 Draw items as 2D images (instead of meshes) when possible 2021-03-30 21:50:39 +02:00
Lars Müller
88d1fcfe23 Block & report player self-interaction (#11137) 2021-03-30 21:49:50 +02:00
SmallJoker
f4118a4fde Consistent title bar + render information in mainmenu (#10764) 2021-03-30 21:49:15 +02:00
sfan5
f345d00a43 Add entry in features table for degrotate changes 2021-03-30 14:40:09 +02:00
Wuzzy
6c9be39db0 Fix wield image of plantlike_rooted (#11067) 2021-03-30 00:27:46 +02:00
Vitaliy
3b78a22371 Degrotate support for mesh nodes (#7840) 2021-03-30 00:25:11 +02:00
Emojigit
fde2785fe3 Update language choices in settingtypes.txt (#11124) 2021-03-29 19:58:39 +02:00
Wuzzy
7ad8ca62dc Clean up various misleading and/or confusing messages and texts related to priv changes (#11126) 2021-03-29 19:57:48 +02:00
Wuzzy
7c24a9ebef Update CONTRIBUTING info on translating builtin 2021-03-29 19:56:20 +02:00
sfan5
8d89f5f0cc Replace fallback font nonsense with automatic per-glyph fallback (#11084) 2021-03-29 19:55:24 +02:00
sfan5
5f4c78a77d Fix broken include check and correct Gitlab-CI script 2021-03-26 23:12:19 +01:00
HybridDog
fc1512cca6 Translate chatcommand delay message and replace minetest with core (#11113) 2021-03-26 20:59:05 +01:00
sfan5
6a26d6d15a Adjust build config for Irrlicht changes (again) 2021-03-26 20:58:45 +01:00
Loic Blot
298bb3d8f7 Drop irrUString from MT, it's owned by irrlicht now 2021-03-26 20:58:45 +01:00
Desour
437d011968 Fix attached-to-object sounds having a higher reference distance 2021-03-23 15:43:40 +01:00
sfan5
2da1eee394 Fix broken BiomeGen abstraction (#11107) 2021-03-23 15:43:26 +01:00
Jean-Patrick Guerrero
c9eba8440d Fix segfault for model[] without animation speed 2021-03-21 23:23:30 +01:00
Hugues Ross
afe988d83d lua_api.txt: Fix style selector examples 2021-03-21 23:23:14 +01:00
Vitaliy
44ed05ddf0 Restore minimal normal texture support (for minimap shading) 2021-03-21 23:22:22 +01:00
sfan5
531e7ef8eb Serialize tool capabilities JSON without whitespace
fixes #11087
2021-03-20 22:06:17 +01:00
sfan5
042131d91d Mainmenu: Improve "Join Game" tab (#11078) 2021-03-20 19:48:25 +01:00
SmallJoker
05719913ac Schematic: Properly deal with before/after node resolving and document (#11011)
This fixes an out-of-bounds index access when the node resolver was already applied to the schematic (i.e. biome decoration).
Also improves the handling of the two cases: prior node resolving (m_nodenames), and after node resolving (manual lookup)
2021-03-20 13:02:15 +01:00
Wuzzy
a8cc3bdb08 Builtin: Translatable join, leave, profiler msgs (#11064) 2021-03-19 21:46:11 +01:00
Zughy
ee2d46dcbe Builtin: Italian translation (#11038) 2021-03-19 21:45:46 +01:00
Elias Fleckenstein
492110a640 Check for duplicate login in TOSERVER_INIT handler (#11017)
i.e. checks for duplicate logins before sending all media data to the client.
2021-03-19 21:45:29 +01:00
Elias Åström
59a1b53d67 Scale mouse/joystick sensitivity depending on FOV (#11007) 2021-03-19 21:43:01 +01:00
sfan5
96d4df995c Drop old text input workarounds (#11089)
* Drop unused intlGUIEditBox

* Drop unnecessary Linux text input workarounds
2021-03-19 18:44:32 +01:00
Jean-Patrick Guerrero
285ba74723 GUIScene: Clear depth buffer + replace deprecated clearZBuffer calls 2021-03-16 23:28:16 +01:00
Jean-Patrick Guerrero
66b5c08664 Fix deprecated calls with Irrlicht 1.9 2021-03-16 23:27:15 +01:00
Wuzzy
62e3593944 Tweak duration_to_string formatting 2021-03-16 18:37:46 +01:00
Wuzzy
9113538142 DevTest: Formspec tests, children getter, better lighttool (#10918) 2021-03-16 18:37:24 +01:00
Wuzzy
88f514ad7a Devtest: Fix missing log level in minetest.log (#11068) 2021-03-15 10:13:15 +01:00
HybridDog
88b052cbea Chatcommands: Show the execution time if the command takes a long time (#10472) 2021-03-13 11:18:25 +01:00
sfan5
051bc9e662 Enable Irrlicht debug logging with --trace 2021-03-12 20:56:02 +01:00
sfan5
1bc85a47cb Avoid unnecessary copies during media/mesh loading 2021-03-12 20:56:02 +01:00
sfan5
cff35cf0b3 Handle mesh load failure without crashing 2021-03-12 20:56:02 +01:00
sfan5
f213376b35 Update Gitlab-CI configuration too 2021-03-12 20:55:51 +01:00
sfan5
bb1c4badfb Clean up cmake DLL installation and other minor things 2021-03-12 20:55:51 +01:00
sfan5
75eb28b959 CI: update configurations for Irrlicht fork 2021-03-09 21:53:17 +01:00
sfan5
91c9313c87 Switch Irrlicht dependency to our own fork
-> https://github.com/minetest/irrlicht
2021-03-09 21:53:17 +01:00
sfan5
3579dd2186 Restore Irrlicht 1.9 support 2021-03-09 21:53:17 +01:00
Lejo
13b50f55a4 Fix missing jsoncpp in the Docker image 2021-03-09 00:57:12 +01:00
sfan5
bf8fb2672e Use place_param2 client-side for item appearance & prediction (#11024) 2021-03-09 00:56:53 +01:00
Wuzzy
a21402b38f Translate builtin into German (server-side) (#11032) 2021-03-08 20:27:48 +01:00
Wuzzy
c48bbfd067 Fix misleading chat messages of /clearobjects (#10690) 2021-03-08 20:27:32 +01:00
SmallJoker
176f5866cb Protect dropping from far node inventories
Also changes if/if to switch/case
2021-03-07 17:18:02 +01:00
SmallJoker
fc864029b9 Protect per-player detached inventory actions 2021-03-07 17:18:02 +01:00
Wuzzy
d9b78d6492 Predict failing placement of ignore nodes 2021-03-07 14:26:50 +01:00
sfan5
dcb30a593d Set ENABLE_SYSTEM_JSONCPP to TRUE by default 2021-03-07 14:26:09 +01:00
sfan5
593d5f4465 Clean up ClientEvent hudadd/hudchange internals 2021-03-06 23:02:10 +01:00
sfan5
dd228fd92e buildbot: Drop i586-mingw32msvc, add i686-w64-mingw32-posix detection 2021-03-06 23:01:50 +01:00
sfan5
1c7b69f9cf Fix function override warnings in mg_ore.h 2021-03-06 14:21:08 +01:00
Vitaliy
abb0c99a6c Pause animations while game is paused (#10658)
Pauses all mesh animations while game is paused.
2021-03-05 16:30:01 +01:00
Wuzzy
cafad6ac03 Translate builtin (#10693)
This PR is the second attempt to translate builtin.
Server-sent translation files can be added to `builtin/locale/`, whereas client-side translations depend on gettext.
2021-03-05 16:29:48 +01:00
sfan5
ac8ac19169 Protect mg_name and mg_flags from being set by Lua (#11010) 2021-03-04 20:38:28 +01:00
Elias Fleckenstein
5b42b5a8c2 Add mod.conf to preview clientmod (#11020) 2021-03-04 20:37:41 +01:00
Muhammad Rifqi Priyo Susanto
1abb83b1ab Use vec4 for varTexCoord in interlaced shader (#11004)
Somewhen in the past, inTexCoord0 was a vec2. Now, it is a vec4.
2021-03-01 13:37:32 +01:00
SmallJoker
3a2f55bc19 Settings: Push groups in to_table as well 2021-03-01 12:14:41 +01:00
Elias Fleckenstein
c401a06f8a Make pkgmgr handle modpacks containing modpacks properly
fixes #10550
2021-03-01 12:13:47 +01:00
rubenwardy
ccdaf5de54 Disable clang-format, clean up scripts 2021-03-01 12:12:52 +01:00
rubenwardy
b390bd2ea5 pkgmgr: Fix crash when .conf release field is invalid
Fixes #10942
2021-02-28 17:11:41 +00:00
hecks
225e69063f Keep mapblocks in memory if they're in range (#10714)
Some other minor parts of clientmap.cpp have been cleaned up along the way
2021-02-26 21:23:46 +01:00
savilli
3edb1ddb81 Fix hud_change and hud_remove after hud_add (#10997) 2021-02-26 21:21:20 +01:00
Lars Müller
b5eda416ce Slap u64 on everything time-y (#10984) 2021-02-24 12:05:17 +01:00
Yaman Qalieh
d51d0d77c4 Allow toggling of texture pack by double clicking 2021-02-24 11:50:19 +01:00
rubenwardy
9f6167fc3b Deprecate not providing mod.conf 2021-02-24 11:47:50 +01:00
HybridDog
92f4c68c0c Restructure teleport command code (#9706) 2021-02-24 11:46:39 +01:00
Wuzzy
827224635b Use "Aux1" key name consistently everywhere 2021-02-24 11:45:30 +01:00
sfan5
02d64a51ee Continue with 5.5.0-dev 2021-02-23 19:50:44 +01:00
572 changed files with 89911 additions and 33258 deletions

4
.dockerignore Normal file
View File

@@ -0,0 +1,4 @@
./cmake-build-*
./build/*
./cache/*
Dockerfile

9
.editorconfig Executable file
View File

@@ -0,0 +1,9 @@
[*]
end_of_line = lf
[*.{cpp,h,lua,txt,glsl,md,c,cmake,java,gradle}]
charset = utf8
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true

View File

@@ -10,13 +10,31 @@ Contributions are welcome! Here's how you can help:
## Code
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and [clone](https://help.github.com/articles/cloning-a-repository/) your fork.
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and
[clone](https://help.github.com/articles/cloning-a-repository/) your fork.
2. Before you start coding, consider opening an [issue at Github](https://github.com/minetest/minetest/issues) to discuss the suitability and implementation of your intended contribution with the core developers. If you are planning to start some very significant coding, you would benefit from first discussing on our IRC development channel [#minetest-dev](http://www.minetest.net/irc/). Note that a proper IRC client is required to speak on this channel.
2. Before you start coding, consider opening an
[issue at Github](https://github.com/minetest/minetest/issues) to discuss the
suitability and implementation of your intended contribution with the core
developers.
Any Pull Request that isn't a bug fix and isn't covered by
[the roadmap](../doc/direction.md) will be closed within a week unless it
receives a concept approval from a Core Developer. For this reason, it is
recommended that you open an issue for any such pull requests before doing
the work, to avoid disappointment.
You may also benefit from discussing on our IRC development channel
[#minetest-dev](http://www.minetest.net/irc/). Note that a proper IRC client
is required to speak on this channel.
3. Start coding!
- Refer to the [Lua API](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt), [Developer Wiki](http://dev.minetest.net/Main_Page) and other [documentation](https://github.com/minetest/minetest/tree/master/doc).
- Follow the [C/C++](http://dev.minetest.net/Code_style_guidelines) and [Lua](http://dev.minetest.net/Lua_code_style_guidelines) code style guidelines.
- Refer to the
[Lua API](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt),
[Developer Wiki](http://dev.minetest.net/Main_Page) and other
[documentation](https://github.com/minetest/minetest/tree/master/doc).
- Follow the [C/C++](http://dev.minetest.net/Code_style_guidelines) and
[Lua](http://dev.minetest.net/Lua_code_style_guidelines) code style guidelines.
- Check your code works as expected and document any changes to the Lua API.
4. Commit & [push](https://help.github.com/articles/pushing-to-a-remote/) your changes to a new branch (not `master`, one change per branch)
@@ -33,67 +51,115 @@ Contributions are welcome! Here's how you can help:
5. Once you are happy with your changes, submit a pull request.
- Open the [pull-request form](https://github.com/minetest/minetest/pull/new/master).
- Add a description explaining what you've done (or if it's a work-in-progress - what you need to do).
- Add a description explaining what you've done (or if it's a
work-in-progress - what you need to do).
- Make sure to fill out the pull request template.
### A pull-request is considered merge-able when:
1. It follows the roadmap in some way and fits the whole picture of the project: [roadmap introduction](http://c55.me/blog/?p=1491), [roadmap continued](https://forum.minetest.net/viewtopic.php?t=9177)
1. It follows [the roadmap](../doc/direction.md) in some way and fits the whole
picture of the project.
2. It works.
3. It follows the code style for [C/C++](http://dev.minetest.net/Code_style_guidelines) or [Lua](http://dev.minetest.net/Lua_code_style_guidelines).
4. The code's interfaces are well designed, regardless of other aspects that might need more work in the future.
3. It follows the code style for
[C/C++](http://dev.minetest.net/Code_style_guidelines) or
[Lua](http://dev.minetest.net/Lua_code_style_guidelines).
4. The code's interfaces are well designed, regardless of other aspects that
might need more work in the future.
5. It uses protocols and formats which include the required compatibility.
### Important note about automated GitHub checks
When you submit a pull request, GitHub automatically runs checks on the Minetest Engine combined with your changes. One of these checks is called 'cpp lint / clang format', which checks code formatting. Because formatting for readability requires human judgement this check often fails and often makes unsuitable formatting requests which make code readability worse.
When you submit a pull request, GitHub automatically runs checks on the Minetest
Engine combined with your changes. One of these checks is called 'cpp lint /
clang format', which checks code formatting. Because formatting for readability
requires human judgement this check often fails and often makes unsuitable
formatting requests which make code readability worse.
If this check fails, look at the details to check for any clear mistakes and correct those. However, you should not apply everything ClangFormat requests. Ignore requests that make code readability worse and any other clearly unsuitable requests. Discuss in the pull request with a core developer about how to progress.
If this check fails, look at the details to check for any clear mistakes and
correct those. However, you should not apply everything ClangFormat requests.
Ignore requests that make code readability worse and any other clearly
unsuitable requests. Discuss in the pull request with a core developer about how
to progress.
## Issues
If you experience an issue, we would like to know the details - especially when a stable release is on the way.
If you experience an issue, we would like to know the details - especially when
a stable release is on the way.
1. Do a quick search on GitHub to check if the issue has already been reported.
2. Is it an issue with the Minetest *engine*? If not, report it [elsewhere](http://www.minetest.net/development/#reporting-issues).
3. [Open an issue](https://github.com/minetest/minetest/issues/new) and describe the issue you are having - you could include:
2. Is it an issue with the Minetest *engine*? If not, report it
[elsewhere](http://www.minetest.net/development/#reporting-issues).
3. [Open an issue](https://github.com/minetest/minetest/issues/new) and describe
the issue you are having - you could include:
- Error logs (check the bottom of the `debug.txt` file).
- Screenshots.
- Ways you have tried to solve the issue, and whether they worked or not.
- Your Minetest version and the content (games, mods or texture packs) you have installed.
- Your platform (e.g. Windows 10 or Ubuntu 15.04 x64).
After reporting you should aim to answer questions or clarifications as this helps pinpoint the cause of the issue (if you don't do this your issue may be closed after 1 month).
After reporting you should aim to answer questions or clarifications as this
helps pinpoint the cause of the issue (if you don't do this your issue may be
closed after 1 month).
## Feature requests
Feature requests are welcome but take a moment to see if your idea follows the roadmap in some way and fits the whole picture of the project: [roadmap introduction](http://c55.me/blog/?p=1491), [roadmap continued](https://forum.minetest.net/viewtopic.php?t=9177). You should provide a clear explanation with as much detail as possible.
Feature requests are welcome but take a moment to see if your idea follows
[the roadmap](../doc/direction.md) in some way and fits the whole picture of
the project. You should provide a clear explanation with as much detail as
possible.
## Translations
Translations of Minetest are performed using Weblate. You can access the project page with a list of current languages [here](https://hosted.weblate.org/projects/minetest/minetest/).
The core translations of Minetest are performed using Weblate. You can access
the project page with a list of current languages
[here](https://hosted.weblate.org/projects/minetest/minetest/).
Builtin (the component which contains things like server messages, chat command
descriptions, privilege descriptions) is translated separately; it needs to be
translated by editing a `.tr` text file. See
[Translation](https://dev.minetest.net/Translation) for more information.
## Donations
If you'd like to monetarily support Minetest development, you can find donation methods on [our website](http://www.minetest.net/development/#donate).
If you'd like to monetarily support Minetest development, you can find donation
methods on [our website](http://www.minetest.net/development/#donate).
# Maintaining
*This is a concise version of the [Rules & Guidelines](http://dev.minetest.net/Category:Rules_and_Guidelines) on the developer wiki.*
* This is a concise version of the
[Rules & Guidelines](http://dev.minetest.net/Category:Rules_and_Guidelines) on the developer wiki.*
These notes are for those who have push access Minetest (core developers / maintainers).
- See the [project organisation](http://dev.minetest.net/Organisation) for the people involved.
## Concept approvals and roadmaps
If a Pull Request is not a bug fix:
* If it matches a goal in [the roadmap](../doc/direction.md), then the PR should
be labelled as "Roadmap" and the goal stated by number in the description.
* If it doesn't match a goal, then it needs to receive a concept approval within
a week of being opened to remain open. This 1 week deadline does not apply to
PRs opened before the roadmap was adopted; instead, they may remain open or be
closed as needed. Use the "Concept Approved" label. Issues can be marked as
"Concept Approved" to give preapproval to future PRs.
## Reviewing pull requests
Pull requests should be reviewed and, if appropriate, checked if they achieve their intended purpose. You can show that you are in the process of, or will review the pull request by commenting *"Looks good"* or something similar.
Pull requests should be reviewed and, if appropriate, checked if they achieve
their intended purpose. You can show that you are in the process of, or will
review the pull request by commenting *"Looks good"* or something similar.
**If the pull-request is not [merge-able](#a-pull-request-is-considered-merge-able-when):**
Submit a comment explaining to the author what they need to change to make the pull-request merge-able.
Submit a comment explaining to the author what they need to change to make the
pull-request merge-able.
- If the author comments or makes changes to the pull-request, it can be reviewed again.
- If no response is made from the author within 1 month (when improvements are suggested or a question is asked), it can be closed.
- If the author comments or makes changes to the pull-request, it can be
reviewed again.
- If no response is made from the author within 1 month (when improvements are
suggested or a question is asked), it can be closed.
**If the pull-request is [merge-able](#a-pull-request-is-considered-merge-able-when):**

View File

@@ -3,6 +3,7 @@ Add compact, short information about your PR for easier understanding:
- Goal of the PR
- How does the PR work?
- Does it resolve any reported issue?
- Does this relate to a goal in [the roadmap](../doc/direction.md)?
- If not a bug fix, why is this PR needed? What usecases does it solve?
## To do

View File

@@ -21,13 +21,13 @@ on:
jobs:
build:
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Install deps
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends gettext openjdk-11-jdk-headless
- name: Build with Gradle
run: cd android; ./gradlew assemblerelease
- name: Save armeabi artifact

View File

@@ -13,6 +13,8 @@ on:
- 'util/buildbot/**'
- 'util/ci/**'
- '.github/workflows/**.yml'
- 'Dockerfile'
- '.dockerignore'
pull_request:
paths:
- 'lib/**.[ch]'
@@ -24,51 +26,53 @@ on:
- 'util/buildbot/**'
- 'util/ci/**'
- '.github/workflows/**.yml'
- 'Dockerfile'
- '.dockerignore'
jobs:
# This is our minor gcc compiler
gcc_6:
# Older gcc version (should be close to our minimum supported version)
gcc_5:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps g++-6
install_linux_deps g++-5
- name: Build
run: |
./util/ci/build.sh
env:
CC: gcc-6
CXX: g++-6
CC: gcc-5
CXX: g++-5
- name: Test
run: |
./bin/minetest --run-unittests
# This is the current gcc compiler (available in bionic)
gcc_8:
runs-on: ubuntu-18.04
# Current gcc version
gcc_10:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps g++-8
install_linux_deps g++-10
- name: Build
run: |
./util/ci/build.sh
env:
CC: gcc-8
CXX: g++-8
CC: gcc-10
CXX: g++-10
- name: Test
run: |
./bin/minetest --run-unittests
# This is our minor clang compiler
# Older clang version (should be close to our minimum supported version)
clang_3_9:
runs-on: ubuntu-18.04
steps:
@@ -76,7 +80,7 @@ jobs:
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-3.9
install_linux_deps clang-3.9 gdb
- name: Build
run: |
@@ -85,26 +89,30 @@ jobs:
CC: clang-3.9
CXX: clang++-3.9
- name: Test
- name: Unittest
run: |
./bin/minetest --run-unittests
# This is the current clang version
clang_9:
runs-on: ubuntu-18.04
- name: Integration test + devtest
run: |
./util/test_multiplayer.sh
# Current clang version
clang_10:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-9 valgrind libluajit-5.1-dev
install_linux_deps clang-10 valgrind libluajit-5.1-dev
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-9
CXX: clang++-9
CC: clang-10
CXX: clang++-10
CMAKE_FLAGS: "-DREQUIRE_LUAJIT=1"
- name: Test
@@ -124,7 +132,7 @@ jobs:
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-9
install_linux_deps --old-irr clang-9
- name: Build prometheus-cpp
run: |
@@ -142,29 +150,6 @@ jobs:
run: |
./bin/minetestserver --run-unittests
# Build without freetype (client-only)
clang_9_no_freetype:
name: "clang_9 (FREETYPE=0)"
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-9
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-9
CXX: clang++-9
CMAKE_FLAGS: "-DENABLE_FREETYPE=0 -DBUILD_SERVER=0"
- name: Test
run: |
./bin/minetest --run-unittests
docker:
name: "Docker image"
runs-on: ubuntu-18.04
@@ -172,7 +157,8 @@ jobs:
- uses: actions/checkout@v2
- name: Build docker image
run: |
docker build .
docker build . -t minetest:latest
docker run --rm minetest:latest /usr/local/bin/minetestserver --version
win32:
name: "MinGW cross-compiler (32-bit)"
@@ -212,11 +198,14 @@ jobs:
msvc:
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
runs-on: windows-2019
runs-on: windows-2019
#### Disabled due to Irrlicht switch
if: false
#### Disabled due to Irrlicht switch
env:
VCPKG_VERSION: 0bf3923f9fab4001c00f0f429682a0853b5749e0
# 2020.11
vcpkg_packages: irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit
vcpkg_packages: irrlicht zlib zstd curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit
strategy:
fail-fast: false
matrix:

View File

@@ -24,20 +24,21 @@ on:
- '.github/workflows/**.yml'
jobs:
clang_format:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Install clang-format
run: |
sudo apt-get install clang-format-9 -qyy
- name: Run clang-format
run: |
source ./util/ci/lint.sh
perform_lint
env:
CLANG_FORMAT: clang-format-9
# clang_format:
# runs-on: ubuntu-18.04
# steps:
# - uses: actions/checkout@v2
# - name: Install clang-format
# run: |
# sudo apt-get install clang-format-9 -qyy
#
# - name: Run clang-format
# run: |
# source ./util/ci/clang-format.sh
# check_format
# env:
# CLANG_FORMAT: clang-format-9
clang_tidy:
runs-on: ubuntu-18.04

66
.github/workflows/macos.yml vendored Normal file
View File

@@ -0,0 +1,66 @@
name: macos
# build on c/cpp changes or workflow changes
on:
push:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- '.github/workflows/macos.yml'
pull_request:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- '.github/workflows/macos.yml'
env:
IRRLICHT_TAG: 1.9.0mt4
MINETEST_GAME_REPO: https://github.com/minetest/minetest_game.git
MINETEST_GAME_BRANCH: master
MINETEST_GAME_NAME: minetest_game
jobs:
build:
runs-on: macos-10.15
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
pkgs=(cmake freetype gettext gmp hiredis jpeg jsoncpp leveldb libogg libpng libvorbis luajit zstd)
brew update
brew install ${pkgs[@]}
brew unlink $(brew ls --formula)
brew link ${pkgs[@]}
- name: Build
run: |
git clone -b $MINETEST_GAME_BRANCH $MINETEST_GAME_REPO games/$MINETEST_GAME_NAME
rm -rvf games/$MINETEST_GAME_NAME/.git
git clone https://github.com/minetest/irrlicht -b $IRRLICHT_TAG lib/irrlichtmt
mkdir cmakebuild
cd cmakebuild
cmake .. \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14 \
-DCMAKE_FIND_FRAMEWORK=LAST \
-DCMAKE_INSTALL_PREFIX=../build/macos/ \
-DRUN_IN_PLACE=FALSE \
-DENABLE_FREETYPE=TRUE -DENABLE_GETTEXT=TRUE
make -j2
make install
- name: Test
run: |
./build/macos/minetest.app/Contents/MacOS/minetest --run-unittests
- uses: actions/upload-artifact@v2
with:
name: minetest-macos
path: ./build/macos/

14
.gitignore vendored
View File

@@ -87,8 +87,8 @@ src/test_config.h
src/cmake_config.h
src/cmake_config_githash.h
src/unittest/test_world/world.mt
src/lua/build/
locale/
games/devtest/mods/testnodes/textures/testnodes_generated_*.png
/locale/
.directory
*.cbp
*.layout
@@ -107,3 +107,13 @@ CMakeDoxy*
compile_commands.json
*.apk
*.zip
# Visual Studio
*.vcxproj*
*.sln
.vs/
# Optional user provided library folder
lib/irrlichtmt
# Generated mod storage database
client/mod_storage.sqlite

View File

@@ -9,16 +9,20 @@ stages:
- deploy
variables:
IRRLICHT_TAG: "1.9.0mt4"
MINETEST_GAME_REPO: "https://github.com/minetest/minetest_game.git"
CONTAINER_IMAGE: registry.gitlab.com/$CI_PROJECT_PATH
.build_template:
stage: build
before_script:
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential git cmake libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libleveldb-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev
script:
- git clone https://github.com/minetest/irrlicht -b $IRRLICHT_TAG lib/irrlichtmt
- mkdir cmakebuild
- mkdir -p artifact/minetest/usr/
- cd cmakebuild
- cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DENABLE_SYSTEM_JSONCPP=TRUE -DBUILD_SERVER=TRUE ..
- cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE ..
- make -j2
- make install
artifacts:
@@ -30,7 +34,7 @@ variables:
.debpkg_template:
stage: package
before_script:
- apt-get update -y
- apt-get update
- apt-get install -y git
- mkdir -p build/deb/minetest/DEBIAN/
- cp misc/debpkg-control build/deb/minetest/DEBIAN/control
@@ -39,7 +43,9 @@ variables:
- git clone $MINETEST_GAME_REPO build/deb/minetest/usr/share/minetest/games/minetest_game
- rm -rf build/deb/minetest/usr/share/minetest/games/minetest/.git
- sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/JPEG_PLACEHOLDER/'$JPEG_PKG'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/JSONCPP_PLACEHOLDER/'$JSONCPP_PKG'/g' build/deb/minetest/DEBIAN/control
- cd build/deb/ && dpkg-deb -b minetest/ && mv minetest.deb ../../
artifacts:
expire_in: 90 day
@@ -49,7 +55,7 @@ variables:
.debpkg_install:
stage: deploy
before_script:
- apt-get update -y
- apt-get update -qy
script:
- apt-get install -y ./*.deb
- minetest --version
@@ -63,9 +69,6 @@ variables:
build:debian-9:
extends: .build_template
image: debian:9
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:debian-9:
extends: .debpkg_template
@@ -73,7 +76,9 @@ package:debian-9:
needs:
- build:debian-9
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1v5
JPEG_PKG: libjpeg62-turbo
deploy:debian-9:
extends: .debpkg_install
@@ -86,9 +91,6 @@ deploy:debian-9:
build:debian-10:
extends: .build_template
image: debian:10
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:debian-10:
extends: .debpkg_template
@@ -96,7 +98,9 @@ package:debian-10:
needs:
- build:debian-10
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1d
JPEG_PKG: libjpeg62-turbo
deploy:debian-10:
extends: .debpkg_install
@@ -104,41 +108,37 @@ deploy:debian-10:
needs:
- package:debian-10
# Bullseye
build:debian-11:
extends: .build_template
image: debian:11
package:debian-11:
extends: .debpkg_template
image: debian:11
needs:
- build:debian-11
variables:
JSONCPP_PKG: libjsoncpp24
LEVELDB_PKG: libleveldb1d
JPEG_PKG: libjpeg62-turbo
deploy:debian-11:
extends: .debpkg_install
image: debian:11
needs:
- package:debian-11
##
## Ubuntu
##
# Xenial
build:ubuntu-16.04:
extends: .build_template
image: ubuntu:xenial
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-16.04:
extends: .debpkg_template
image: ubuntu:xenial
needs:
- build:ubuntu-16.04
variables:
LEVELDB_PKG: libleveldb1v5
deploy:ubuntu-16.04:
extends: .debpkg_install
image: ubuntu:xenial
needs:
- package:ubuntu-16.04
# Bionic
build:ubuntu-18.04:
extends: .build_template
image: ubuntu:bionic
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-18.04:
extends: .debpkg_template
@@ -146,7 +146,9 @@ package:ubuntu-18.04:
needs:
- build:ubuntu-18.04
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1v5
JPEG_PKG: libjpeg-turbo8
deploy:ubuntu-18.04:
extends: .debpkg_install
@@ -154,6 +156,28 @@ deploy:ubuntu-18.04:
needs:
- package:ubuntu-18.04
# Focal
build:ubuntu-20.04:
extends: .build_template
image: ubuntu:focal
package:ubuntu-20.04:
extends: .debpkg_template
image: ubuntu:focal
needs:
- build:ubuntu-20.04
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1d
JPEG_PKG: libjpeg-turbo8
deploy:ubuntu-20.04:
extends: .debpkg_install
image: ubuntu:focal
needs:
- package:ubuntu-20.04
##
## Fedora
##
@@ -163,36 +187,23 @@ build:fedora-28:
extends: .build_template
image: fedora:28
before_script:
- dnf -y install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel
- dnf -y install make git gcc gcc-c++ kernel-devel cmake libjpeg-devel libpng-devel libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-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
##
## MinGW for Windows
##
.generic_win_template:
image: ubuntu:bionic
image: ubuntu:focal
before_script:
- apt-get update -y
- apt-get install -y wget xz-utils unzip git cmake gettext
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get install -y wget xz-utils unzip git cmake gettext
- wget -nv http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz
- tar -xaf mingw.tar.xz -C /usr
.build_win_template:
extends: .generic_win_template
stage: build
artifacts:
expire_in: 1h
paths:
- build/minetest/_build/*
.package_win_template:
extends: .generic_win_template
stage: package
script:
- unzip build/minetest/_build/minetest-*.zip
- cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libgcc*.dll minetest-*-win*/bin/
- cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libstdc++*.dll minetest-*-win*/bin/
- cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libwinpthread*.dll minetest-*-win*/bin/
artifacts:
expire_in: 90 day
paths:
@@ -201,29 +212,16 @@ build:fedora-28:
build:win32:
extends: .build_win_template
script:
- ./util/buildbot/buildwin32.sh build
- EXISTING_MINETEST_DIR=$PWD ./util/buildbot/buildwin32.sh build
- unzip -q build/build/*.zip
variables:
WIN_ARCH: "i686"
package:win32:
extends: .package_win_template
needs:
- build:win32
variables:
WIN_ARCH: "i686"
build:win64:
extends: .build_win_template
script:
- ./util/buildbot/buildwin64.sh build
variables:
WIN_ARCH: "x86_64"
package:win64:
extends: .package_win_template
needs:
- build:win64
- EXISTING_MINETEST_DIR=$PWD ./util/buildbot/buildwin64.sh build
- unzip -q build/build/*.zip
variables:
WIN_ARCH: "x86_64"
@@ -274,7 +272,7 @@ package:appimage-client:
- build:ubuntu-18.04
before_script:
- apt-get update -y
- apt-get install -y git wget
- apt-get install -y git
# Collect files
- mkdir AppDir
- cp -a artifact/minetest/usr/ AppDir/usr/

View File

@@ -20,7 +20,7 @@ read_globals = {
string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn", "indexof", "insert_all"}},
math = {fields = {"hypot"}},
math = {fields = {"hypot", "round"}},
}
globals = {

View File

@@ -24,18 +24,21 @@ AppDir:
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-security main universe
include:
- libirrlicht1.8
- libxxf86vm1
- libgl1-mesa-glx
- libsqlite3-0
- libogg0
- libvorbis0a
- libopenal1
- libc6
- libcurl3-gnutls
- libfreetype6
- zlib1g
- libgmp10
- libgl1
- libjpeg-turbo8
- libjsoncpp1
- libleveldb1v5
- libopenal1
- libpng16-16
- libsqlite3-0
- libstdc++6
- libvorbisfile3
- libx11-6
- libxxf86vm1
- zlib1g
files:
exclude:

View File

@@ -1,19 +1,24 @@
cmake_minimum_required(VERSION 3.5)
cmake_policy(SET CMP0025 OLD)
# Set policies up to 3.9 since we want to enable the IPO option
if(${CMAKE_VERSION} VERSION_LESS 3.9)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.9)
endif()
# This can be read from ${PROJECT_NAME} after project() is called
project(minetest)
set(PROJECT_NAME_CAPITALIZED "Minetest")
set(CMAKE_CXX_STANDARD 11)
set(GCC_MINIMUM_VERSION "4.8")
set(CLANG_MINIMUM_VERSION "3.4")
set(GCC_MINIMUM_VERSION "5.1")
set(CLANG_MINIMUM_VERSION "3.5")
# Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing
set(VERSION_MAJOR 5)
set(VERSION_MINOR 4)
set(VERSION_PATCH 2)
set(VERSION_MINOR 5)
set(VERSION_PATCH 1)
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Change to false for releases
@@ -21,7 +26,7 @@ set(DEVELOPMENT_BUILD FALSE)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
if(VERSION_EXTRA)
set(VERSION_STRING ${VERSION_STRING}-${VERSION_EXTRA})
set(VERSION_STRING "${VERSION_STRING}-${VERSION_EXTRA}")
elseif(DEVELOPMENT_BUILD)
set(VERSION_STRING "${VERSION_STRING}-dev")
endif()
@@ -47,7 +52,6 @@ set(BUILD_CLIENT TRUE CACHE BOOL "Build client")
set(BUILD_SERVER FALSE CACHE BOOL "Build server")
set(BUILD_UNITTESTS TRUE CACHE BOOL "Build unittests")
set(WARN_ALL TRUE CACHE BOOL "Enable -Wall for Release build")
if(NOT CMAKE_BUILD_TYPE)
@@ -59,8 +63,62 @@ endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
set(IRRLICHTMT_BUILD_DIR "" CACHE PATH "Path to IrrlichtMt build directory.")
if(NOT "${IRRLICHTMT_BUILD_DIR}" STREQUAL "")
find_package(IrrlichtMt QUIET
PATHS "${IRRLICHTMT_BUILD_DIR}"
NO_DEFAULT_PATH
)
if(NOT TARGET IrrlichtMt::IrrlichtMt)
# find_package() searches certain subdirectories. ${PATH}/cmake is not
# the only one, but it is the one where IrrlichtMt is supposed to export
# IrrlichtMtConfig.cmake
message(FATAL_ERROR "Could not find IrrlichtMtConfig.cmake in ${IRRLICHTMT_BUILD_DIR}/cmake.")
endif()
# This is done here so that relative search paths are more reasonable
find_package(Irrlicht)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/lib/irrlichtmt")
message(STATUS "Using user-provided IrrlichtMt at subdirectory 'lib/irrlichtmt'")
if(BUILD_CLIENT)
# tell IrrlichtMt to create a static library
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared library" FORCE)
add_subdirectory(lib/irrlichtmt EXCLUDE_FROM_ALL)
unset(BUILD_SHARED_LIBS CACHE)
if(NOT TARGET IrrlichtMt)
message(FATAL_ERROR "IrrlichtMt project is missing a CMake target?!")
endif()
else()
add_library(IrrlichtMt::IrrlichtMt INTERFACE IMPORTED)
set_target_properties(IrrlichtMt::IrrlichtMt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/irrlichtmt/include")
endif()
else()
find_package(IrrlichtMt QUIET)
if(NOT TARGET IrrlichtMt::IrrlichtMt)
string(CONCAT explanation_msg
"The Minetest team has forked Irrlicht to make their own customizations. "
"It can be found here: https://github.com/minetest/irrlicht\n"
"For example use: git clone --depth=1 https://github.com/minetest/irrlicht lib/irrlichtmt\n")
if(BUILD_CLIENT)
message(FATAL_ERROR "IrrlichtMt is required to build the client, but it was not found.\n${explanation_msg}")
endif()
include(MinetestFindIrrlichtHeaders)
if(NOT IRRLICHT_INCLUDE_DIR)
message(FATAL_ERROR "Irrlicht or IrrlichtMt headers are required to build the server, but none found.\n${explanation_msg}")
endif()
message(STATUS "Found Irrlicht headers: ${IRRLICHT_INCLUDE_DIR}")
add_library(IrrlichtMt::IrrlichtMt INTERFACE IMPORTED)
# Note that we can't use target_include_directories() since that doesn't work for IMPORTED targets before CMake 3.11
set_target_properties(IrrlichtMt::IrrlichtMt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${IRRLICHT_INCLUDE_DIR}")
endif()
endif()
if(TARGET IrrlichtMt::IrrlichtMt)
message(STATUS "Found IrrlichtMt ${IrrlichtMt_VERSION}")
endif()
# Installation
@@ -91,15 +149,16 @@ elseif(UNIX) # Linux, BSD etc
set(ICONDIR "unix/icons")
set(LOCALEDIR "locale")
else()
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}")
set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
set(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}")
set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man")
include(GNUInstallDirs)
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}")
set(BINDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
set(DOCDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}")
set(MANDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_MANDIR}")
set(EXAMPLE_CONF_DIR ${DOCDIR})
set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/share/applications")
set(APPDATADIR "${CMAKE_INSTALL_PREFIX}/share/metainfo")
set(ICONDIR "${CMAKE_INSTALL_PREFIX}/share/icons")
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/share/locale")
set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/applications")
set(APPDATADIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/metainfo")
set(ICONDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/icons")
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}")
endif()
endif()
@@ -169,7 +228,6 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/devtest" DESTINATION "${SHA
if(BUILD_CLIENT)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client/shaders" DESTINATION "${SHAREDIR}/client")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}")
if(RUN_IN_PLACE)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/clientmods" DESTINATION "${SHAREDIR}")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client/serverlist" DESTINATION "${SHAREDIR}/client")
@@ -203,10 +261,10 @@ endif()
find_package(GMP REQUIRED)
find_package(Json REQUIRED)
find_package(Lua REQUIRED)
# JsonCPP doesn't compile well on GCC 4.8
if(NOT ENABLE_SYSTEM_JSONCPP)
set(GCC_MINIMUM_VERSION "4.9")
if(NOT USE_LUAJIT)
set(LUA_BIT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/bitop)
set(LUA_BIT_LIBRARY bitop)
add_subdirectory(lib/bitop)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@@ -214,7 +272,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message(FATAL_ERROR "Insufficient gcc version, found ${CMAKE_CXX_COMPILER_VERSION}. "
"Version ${GCC_MINIMUM_VERSION} or higher is required.")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?Clang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${CLANG_MINIMUM_VERSION}")
message(FATAL_ERROR "Insufficient clang version, found ${CMAKE_CXX_COMPILER_VERSION}. "
"Version ${CLANG_MINIMUM_VERSION} or higher is required.")
@@ -223,7 +281,6 @@ endif()
# Subdirectories
# Be sure to add all relevant definitions above this
add_subdirectory(src)

View File

@@ -1,6 +1,8 @@
FROM alpine:3.11
ARG DOCKER_IMAGE=alpine:3.14
FROM $DOCKER_IMAGE AS builder
ENV MINETEST_GAME_VERSION master
ENV IRRLICHT_VERSION master
COPY .git /usr/src/minetest/.git
COPY CMakeLists.txt /usr/src/minetest/CMakeLists.txt
@@ -18,23 +20,25 @@ COPY textures /usr/src/minetest/textures
WORKDIR /usr/src/minetest
RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \
jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \
libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \
gmp-dev jsoncpp-dev postgresql-dev luajit-dev ca-certificates && \
RUN apk add --no-cache git build-base cmake sqlite-dev curl-dev zlib-dev zstd-dev \
gmp-dev jsoncpp-dev postgresql-dev ninja luajit-dev ca-certificates && \
git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \
rm -fr ./games/minetest_game/.git
WORKDIR /usr/src/
RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ && \
RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ -b v1.0.0 && \
mkdir prometheus-cpp/build && \
cd prometheus-cpp/build && \
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_BUILD_TYPE=Release \
-DENABLE_TESTING=0 && \
make -j2 && \
make install
-DENABLE_TESTING=0 \
-GNinja && \
ninja && \
ninja install
RUN git clone --depth=1 https://github.com/minetest/irrlicht/ -b ${IRRLICHT_VERSION} && \
cp -r irrlicht/include /usr/include/irrlichtmt
WORKDIR /usr/src/minetest
RUN mkdir build && \
@@ -45,21 +49,23 @@ RUN mkdir build && \
-DBUILD_SERVER=TRUE \
-DENABLE_PROMETHEUS=TRUE \
-DBUILD_UNITTESTS=FALSE \
-DBUILD_CLIENT=FALSE && \
make -j2 && \
make install
-DBUILD_CLIENT=FALSE \
-GNinja && \
ninja && \
ninja install
FROM alpine:3.11
ARG DOCKER_IMAGE=alpine:3.14
FROM $DOCKER_IMAGE AS runtime
RUN apk add --no-cache sqlite-libs curl gmp libstdc++ libgcc libpq luajit && \
RUN apk add --no-cache sqlite-libs curl gmp libstdc++ libgcc libpq luajit jsoncpp zstd-libs && \
adduser -D minetest --uid 30000 -h /var/lib/minetest && \
chown -R minetest:minetest /var/lib/minetest
WORKDIR /var/lib/minetest
COPY --from=0 /usr/local/share/minetest /usr/local/share/minetest
COPY --from=0 /usr/local/bin/minetestserver /usr/local/bin/minetestserver
COPY --from=0 /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/minetest.conf
COPY --from=builder /usr/local/share/minetest /usr/local/share/minetest
COPY --from=builder /usr/local/bin/minetestserver /usr/local/bin/minetestserver
COPY --from=builder /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/minetest.conf
USER minetest:minetest

View File

@@ -14,6 +14,9 @@ https://www.apache.org/licenses/LICENSE-2.0.html
Textures by Zughy are under CC BY-SA 4.0
https://creativecommons.org/licenses/by-sa/4.0/
textures/base/pack/server_public.png is under CC-BY 4.0, taken from Twitter's Twemoji set
https://creativecommons.org/licenses/by/4.0/
Authors of media files
-----------------------
Everything not listed in here:
@@ -39,10 +42,10 @@ erlehmann:
misc/minetest.svg
textures/base/pack/logo.png
JRottm
JRottm:
textures/base/pack/player_marker.png
srifqi
srifqi:
textures/base/pack/chat_hide_btn.png
textures/base/pack/chat_show_btn.png
textures/base/pack/joystick_bg.png
@@ -58,6 +61,9 @@ Zughy:
textures/base/pack/cdb_update.png
textures/base/pack/cdb_viewonline.png
appgurueu:
textures/base/pack/server_incompatible.png
License of Minetest source code
-------------------------------
@@ -81,7 +87,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Irrlicht
---------------
This program uses the Irrlicht Engine. http://irrlicht.sourceforge.net/
This program uses IrrlichtMt, Minetest's fork of
the Irrlicht Engine. http://irrlicht.sourceforge.net/
The Irrlicht Engine License

151
README.md
View File

@@ -68,7 +68,7 @@ Some can be changed in the key config dialog in the settings tab.
| P | Enable/disable pitch move mode |
| J | Enable/disable fast mode (needs fast privilege) |
| H | Enable/disable noclip mode (needs noclip privilege) |
| E | Move fast in fast mode |
| E | Aux1 (Move fast in fast mode. Games may add special features) |
| C | Cycle through camera modes |
| V | Cycle through minimap modes |
| Shift + V | Change minimap orientation |
@@ -132,29 +132,31 @@ Compiling
| Dependency | Version | Commentary |
|------------|---------|------------|
| GCC | 4.9+ | Can be replaced with Clang 3.4+ |
| CMake | 2.6+ | |
| Irrlicht | 1.7.3+ | |
| SQLite3 | 3.0+ | |
| GCC | 5.1+ | or Clang 3.5+ |
| CMake | 3.5+ | |
| IrrlichtMt | - | Custom version of Irrlicht, see https://github.com/minetest/irrlicht |
| Freetype | 2.0+ | |
| SQLite3 | 3+ | |
| Zstd | 1.0+ | |
| LuaJIT | 2.0+ | Bundled Lua 5.1 is used if not present |
| GMP | 5.0.0+ | Bundled mini-GMP is used if not present |
| JsonCPP | 1.0.0+ | Bundled JsonCPP is used if not present |
For Debian/Ubuntu users:
sudo apt install g++ make libc6-dev libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
sudo apt install g++ make libc6-dev cmake libpng-dev libjpeg-dev libxxf86vm-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
For Fedora users:
sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel
sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-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
For Arch users:
sudo pacman -S base-devel libcurl-gnutls cmake libxxf86vm irrlicht libpng sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses
sudo pacman -S base-devel libcurl-gnutls cmake libxxf86vm libpng sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses zstd
For Alpine users:
sudo apk add build-base irrlicht-dev cmake bzip2-dev libpng-dev jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev
sudo apk add build-base cmake libpng-dev jpeg-dev libxxf86vm-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
#### Download
@@ -177,6 +179,10 @@ Download minetest_game (otherwise only the "Development Test" game is available)
git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game
Download IrrlichtMt to `lib/irrlichtmt`, it will be used to satisfy the IrrlichtMt dependency that way:
git clone --depth 1 https://github.com/minetest/irrlicht.git lib/irrlichtmt
Download source, without using Git:
wget https://github.com/minetest/minetest/archive/master.tar.gz
@@ -191,6 +197,14 @@ Download minetest_game, without using Git:
mv minetest_game-master minetest_game
cd ..
Download IrrlichtMt, without using Git:
cd lib/
wget https://github.com/minetest/irrlicht/archive/master.tar.gz
tar xf master.tar.gz
mv irrlicht-master irrlichtmt
cd ..
#### Build
Build a version that runs directly from the source directory:
@@ -209,8 +223,15 @@ Run it:
- You can disable the client build by specifying `-DBUILD_CLIENT=FALSE`.
- You can select between Release and Debug build by `-DCMAKE_BUILD_TYPE=<Debug or Release>`.
- Debug build is slower, but gives much more useful output in a debugger.
- If you build a bare server you don't need to have Irrlicht installed.
- In that case use `-DIRRLICHT_SOURCE_DIR=/the/irrlicht/source`.
- If you build a bare server you don't need to have the Irrlicht or IrrlichtMt library installed.
- In that case use `-DIRRLICHT_INCLUDE_DIR=/some/where/irrlicht/include`.
- Minetest will use the IrrlichtMt package that is found first, given by the following order:
1. Specified `IRRLICHTMT_BUILD_DIR` CMake variable
2. `${PROJECT_SOURCE_DIR}/lib/irrlichtmt` (if existent)
3. Installation of IrrlichtMt in the system-specific library paths
4. For server builds with disabled `BUILD_CLIENT` variable, the headers from `IRRLICHT_INCLUDE_DIR` will be used.
- NOTE: Changing the IrrlichtMt build directory (includes system installs) requires regenerating the CMake cache (`rm CMakeCache.txt`)
### CMake options
@@ -227,9 +248,8 @@ General options and their default values:
MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible
ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http
ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal)
ENABLE_FREETYPE=ON - Build with FreeType2; Allows using TTF fonts
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations
ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by Irrlicht)
ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by IrrlichtMt)
ENABLE_LEVELDB=ON - Build with LevelDB; Enables use of LevelDB map backend
ENABLE_POSTGRESQL=ON - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended)
ENABLE_REDIS=ON - Build with libhiredis; Enables use of Redis map backend
@@ -238,33 +258,31 @@ General options and their default values:
ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua)
ENABLE_PROMETHEUS=OFF - Build with Prometheus metrics exporter (listens on tcp/30000 by default)
ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp)
ENABLE_SYSTEM_JSONCPP=OFF - Use JsonCPP from system
ENABLE_SYSTEM_JSONCPP=ON - Use JsonCPP from system
OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference
RUN_IN_PLACE=FALSE - Create a portable install (worlds, settings etc. in current directory)
USE_GPROF=FALSE - Enable profiling using GProf
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
ENABLE_TOUCH=FALSE - Enable Touchscreen support (requires support by IrrlichtMt)
Library specific options:
BZIP2_INCLUDE_DIR - Linux only; directory where bzlib.h is located
BZIP2_LIBRARY - Linux only; path to libbz2.a/libbz2.so
CURL_DLL - Only if building with cURL on Windows; path to libcurl.dll
CURL_INCLUDE_DIR - Only if building with cURL; directory where curl.h is located
CURL_LIBRARY - Only if building with cURL; path to libcurl.a/libcurl.so/libcurl.lib
EGL_INCLUDE_DIR - Only if building with GLES; directory that contains egl.h
EGL_LIBRARY - Only if building with GLES; path to libEGL.a/libEGL.so
FREETYPE_INCLUDE_DIR_freetype2 - Only if building with FreeType 2; directory that contains an freetype directory with files such as ftimage.h in it
FREETYPE_INCLUDE_DIR_ft2build - Only if building with FreeType 2; directory that contains ft2build.h
FREETYPE_LIBRARY - Only if building with FreeType 2; path to libfreetype.a/libfreetype.so/freetype.lib
FREETYPE_DLL - Only if building with FreeType 2 on Windows; path to libfreetype.dll
GETTEXT_DLL - Only when building with gettext on Windows; path to libintl3.dll
GETTEXT_ICONV_DLL - Only when building with gettext on Windows; path to libiconv2.dll
EXTRA_DLL - Only on Windows; optional paths to additional DLLs that should be packaged
FREETYPE_INCLUDE_DIR_freetype2 - Directory that contains files such as ftimage.h
FREETYPE_INCLUDE_DIR_ft2build - Directory that contains ft2build.h
FREETYPE_LIBRARY - Path to libfreetype.a/libfreetype.so/freetype.lib
FREETYPE_DLL - Only on Windows; path to libfreetype-6.dll
GETTEXT_DLL - Only when building with gettext on Windows; paths to libintl + libiconv DLLs
GETTEXT_INCLUDE_DIR - Only when building with gettext; directory that contains iconv.h
GETTEXT_LIBRARY - Only when building with gettext on Windows; path to libintl.dll.a
GETTEXT_MSGFMT - Only when building with gettext; path to msgfmt/msgfmt.exe
IRRLICHT_DLL - Only on Windows; path to Irrlicht.dll
IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h
IRRLICHT_LIBRARY - Path to libIrrlicht.a/libIrrlicht.so/libIrrlicht.dll.a/Irrlicht.lib
IRRLICHT_DLL - Only on Windows; path to IrrlichtMt.dll
IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h (usable for server build only)
LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h
LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a
LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll
@@ -276,7 +294,6 @@ Library specific options:
SPATIAL_LIBRARY - Only when building with LibSpatial; path to libspatialindex_c.so/spatialindex-32.lib
LUA_INCLUDE_DIR - Only if you want to use LuaJIT; directory where luajit.h is located
LUA_LIBRARY - Only if you want to use LuaJIT; path to libluajit.a/libluajit.so
MINGWM10_DLL - Only if compiling with MinGW; path to mingwm10.dll
OGG_DLL - Only if building with sound on Windows; path to libogg.dll
OGG_INCLUDE_DIR - Only if building with sound; directory that contains an ogg directory which contains ogg.h
OGG_LIBRARY - Only if building with sound; path to libogg.a/libogg.so/libogg.dll.a
@@ -287,17 +304,19 @@ Library specific options:
OPENGLES2_LIBRARY - Only if building with GLES; path to libGLESv2.a/libGLESv2.so
SQLITE3_INCLUDE_DIR - Directory that contains sqlite3.h
SQLITE3_LIBRARY - Path to libsqlite3.a/libsqlite3.so/sqlite3.lib
VORBISFILE_DLL - Only if building with sound on Windows; path to libvorbisfile-3.dll
VORBISFILE_LIBRARY - Only if building with sound; path to libvorbisfile.a/libvorbisfile.so/libvorbisfile.dll.a
VORBIS_DLL - Only if building with sound on Windows; path to libvorbis-0.dll
VORBIS_DLL - Only if building with sound on Windows; paths to vorbis DLLs
VORBIS_INCLUDE_DIR - Only if building with sound; directory that contains a directory vorbis with vorbisenc.h inside
VORBIS_LIBRARY - Only if building with sound; path to libvorbis.a/libvorbis.so/libvorbis.dll.a
XXF86VM_LIBRARY - Only on Linux; path to libXXf86vm.a/libXXf86vm.so
ZLIB_DLL - Only on Windows; path to zlib1.dll
ZLIB_INCLUDE_DIR - Directory that contains zlib.h
ZLIB_LIBRARY - Path to libz.a/libz.so/zlib.lib
ZSTD_DLL - Only on Windows; path to libzstd.dll
ZSTD_INCLUDE_DIR - Directory that contains zstd.h
ZSTD_LIBRARY - Path to libzstd.a/libzstd.so/ztd.lib
### Compiling on Windows
### Compiling on Windows using MSVC
### Requirements
@@ -310,16 +329,14 @@ Library specific options:
It is highly recommended to use vcpkg as package manager.
#### a) Using vcpkg to install dependencies
After you successfully built vcpkg you can easily install the required libraries:
```powershell
vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit gmp jsoncpp --triplet x64-windows
vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp opengl-registry --triplet x64-windows
```
- **Don't forget about IrrlichtMt.** The easiest way is to clone it to `lib/irrlichtmt` as described in the Linux section.
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
- `freetype` is optional, it allows true-type font rendering.
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
- `gmp` and `jsoncpp` are optional, otherwise the bundled versions will be compiled
@@ -327,10 +344,6 @@ There are other optional libraries, but they are not tested if they can build an
Use `--triplet` to specify the target triplet, e.g. `x64-windows` or `x86-windows`.
#### b) Compile the dependencies on your own
This is outdated and not recommended. Follow the instructions on https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build
### Compile Minetest
#### a) Using the vcpkg toolchain and CMake GUI
@@ -354,17 +367,11 @@ This is outdated and not recommended. Follow the instructions on https://dev.min
Run the following script in PowerShell:
```powershell
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=OFF -DENABLE_CURSES=OFF -DENABLE_SYSTEM_JSONCPP=ON
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=OFF -DENABLE_CURSES=OFF
cmake --build . --config Release
```
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.
#### c) Using your own compiled libraries
**This is outdated and not recommended**
Follow the instructions on https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build
### Windows Installer using WiX Toolset
Requirements:
@@ -378,6 +385,60 @@ Build the binaries as described above, but make sure you unselect `RUN_IN_PLACE`
Open the generated project file with Visual Studio. Right-click **Package** and choose **Generate**.
It may take some minutes to generate the installer.
### Compiling on MacOS
#### Requirements
- [Homebrew](https://brew.sh/)
- [Git](https://git-scm.com/downloads)
Install dependencies with homebrew:
```
brew install cmake freetype gettext gmp hiredis jpeg jsoncpp leveldb libogg libpng libvorbis luajit zstd
```
#### Download
Download source (this is the URL to the latest of source repository, which might not work at all times) using Git:
```bash
git clone --depth 1 https://github.com/minetest/minetest.git
cd minetest
```
Download minetest_game (otherwise only the "Development Test" game is available) using Git:
```
git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game
```
Download Minetest's fork of Irrlicht:
```
git clone --depth 1 https://github.com/minetest/irrlicht.git lib/irrlichtmt
```
#### Build
```bash
mkdir cmakebuild
cd cmakebuild
cmake .. \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14 \
-DCMAKE_FIND_FRAMEWORK=LAST \
-DCMAKE_INSTALL_PREFIX=../build/macos/ \
-DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE
make -j$(nproc)
make install
```
#### Run
```
open ./build/macos/minetest.app
```
Docker
------

View File

@@ -1,12 +1,12 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
compileSdkVersion 30
buildToolsVersion '30.0.3'
ndkVersion '22.0.7026061'
ndkVersion "$ndk_version"
defaultConfig {
applicationId 'net.minetest.minetest'
minSdkVersion 16
targetSdkVersion 29
targetSdkVersion 30
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
versionCode project.versionCode
}
@@ -68,7 +68,7 @@ task prepareAssets() {
from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders"
}
copy {
from "../native/deps/Android/Irrlicht/shaders" into "${assetsFolder}/client/shaders/Irrlicht"
from "../native/deps/armeabi-v7a/Irrlicht/Shaders" into "${assetsFolder}/client/shaders/Irrlicht"
}
copy {
from "${projRoot}/fonts" include "*.ttf" into "${assetsFolder}/fonts"
@@ -76,10 +76,13 @@ task prepareAssets() {
copy {
from "${projRoot}/games/${gameToCopy}" into "${assetsFolder}/games/${gameToCopy}"
}
/*copy {
// ToDo: fix broken locales
from "${projRoot}/po" into "${assetsFolder}/po"
}*/
fileTree("${projRoot}/po").include("**/*.po").forEach { poFile ->
def moPath = "${assetsFolder}/locale/${poFile.parentFile.name}/LC_MESSAGES/"
file(moPath).mkdirs()
exec {
commandLine 'msgfmt', '-o', "${moPath}/minetest.mo", poFile
}
}
copy {
from "${projRoot}/textures" into "${assetsFolder}/textures"
}
@@ -109,5 +112,5 @@ android.applicationVariants.all { variant ->
dependencies {
implementation project(':native')
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
}

View File

@@ -19,8 +19,6 @@
android:label="@string/label"
android:requestLegacyExternalStorage="true"
android:resizeableActivity="false"
android:hasFragileUserData="true"
android:isGame="true"
tools:ignore="UnusedAttribute">
<meta-data
@@ -32,7 +30,8 @@
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
android:maxAspectRatio="3.0"
android:screenOrientation="sensorLandscape"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -46,7 +45,8 @@
android:launchMode="singleTask"
android:maxAspectRatio="3.0"
android:screenOrientation="sensorLandscape"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>

View File

@@ -30,7 +30,9 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.appcompat.app.AlertDialog;
@@ -85,9 +87,19 @@ public class GameActivity extends NativeActivity {
private void showDialogUI(String hint, String current, int editType) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
EditText editText = new CustomEditText(this);
builder.setView(editText);
LinearLayout container = new LinearLayout(this);
container.setOrientation(LinearLayout.VERTICAL);
builder.setView(container);
AlertDialog alertDialog = builder.create();
EditText editText;
// For multi-line, do not close the dialog after pressing back button
if (editType == 1) {
editText = new EditText(this);
} else {
editText = new CustomEditText(this);
}
container.addView(editText);
editText.setMaxLines(8);
editText.requestFocus();
editText.setHint(hint);
editText.setText(current);
@@ -103,8 +115,9 @@ public class GameActivity extends NativeActivity {
else
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setSelection(editText.getText().length());
editText.setOnKeyListener((view, KeyCode, event) -> {
if (KeyCode == KeyEvent.KEYCODE_ENTER) {
editText.setOnKeyListener((view, keyCode, event) -> {
// For multi-line, do not submit the text after pressing Enter key
if (keyCode == KeyEvent.KEYCODE_ENTER && editType != 1) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
messageReturnCode = 0;
messageReturnValue = editText.getText().toString();
@@ -113,6 +126,18 @@ public class GameActivity extends NativeActivity {
}
return false;
});
// For multi-line, add Done button since Enter key does not submit text
if (editType == 1) {
Button doneButton = new Button(this);
container.addView(doneButton);
doneButton.setText(R.string.ime_dialog_done);
doneButton.setOnClickListener((view -> {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
messageReturnCode = 0;
messageReturnValue = editText.getText().toString();
alertDialog.dismiss();
}));
}
alertDialog.show();
alertDialog.setOnCancelListener(dialog -> {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

View File

@@ -101,7 +101,8 @@ public class MainActivity extends AppCompatActivity {
mTextView = findViewById(R.id.textView);
sharedPreferences = getSharedPreferences(SETTINGS, Context.MODE_PRIVATE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
checkPermission();
else
checkAppVersion();

View File

@@ -32,6 +32,7 @@ import android.os.Environment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import java.io.File;
@@ -200,6 +201,10 @@ public class UnzipService extends IntentService {
* Migrates user data from deprecated external storage to app scoped storage
*/
private void migrate(Notification.Builder notificationBuilder, File newLocation) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return;
}
File oldLocation = new File(Environment.getExternalStorageDirectory(), "Minetest");
if (!oldLocation.isDirectory())
return;

View File

@@ -1,21 +1,22 @@
// 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", 4) // Version Minor
project.ext.set("versionPatch", 2) // Version Patch
project.ext.set("versionMinor", 5) // Version Minor
project.ext.set("versionPatch", 1) // Version Patch
project.ext.set("versionExtra", "") // Version Extra
project.ext.set("versionCode", 36) // Android Version Code
project.ext.set("versionCode", 40) // Android Version Code
// NOTE: +2 after each release!
// +1 for ARM and +1 for ARM64 APK's, because
// each APK must have a larger `versionCode` than the previous
buildscript {
ext.ndk_version = '23.0.7599858'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.1'
classpath 'com.android.tools.build:gradle:7.0.3'
classpath 'de.undercouch:gradle-download-task:4.1.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -1,6 +1,5 @@
#Fri Jan 08 17:52:00 UTC 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip

2
android/gradlew vendored
View File

@@ -98,7 +98,7 @@ location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
command -v java >/dev/null || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."

View File

@@ -1,411 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="aux_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/aux_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-341.34157"
inkscape:cy="210.02973"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="false"
inkscape:snap-page="true"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-to-guides="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-others="true"
inkscape:snap-bbox-midpoints="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:48.47851181px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#d9d9d9;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
x="67.78315"
y="85.59491"
id="text4716"
transform="scale(1.0078883,0.99217343)"><tspan
sodipodi:role="line"
id="tspan4714"
x="67.78315"
y="85.59491"
style="fill:#d9d9d9;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">AUX</tspan></text>
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> </g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -2,12 +2,12 @@ apply plugin: 'com.android.library'
apply plugin: 'de.undercouch.download'
android {
compileSdkVersion 29
compileSdkVersion 30
buildToolsVersion '30.0.3'
ndkVersion '22.0.7026061'
ndkVersion "$ndk_version"
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
targetSdkVersion 30
externalNativeBuild {
ndkBuild {
arguments '-j' + Runtime.getRuntime().availableProcessors(),
@@ -50,54 +50,19 @@ android {
}
// get precompiled deps
def folder = 'minetest_android_deps_binaries'
def deps_ref = "342eb18b7512462585a33bc9eef0b68298087151"
task downloadDeps(type: Download) {
src 'https://github.com/minetest/' + folder + '/archive/' + deps_ref + '.zip'
src 'https://github.com/minetest/minetest_android_deps/releases/download/latest/deps.zip'
dest new File(buildDir, 'deps.zip')
overwrite false
}
task getDeps(dependsOn: downloadDeps, type: Copy) {
def deps = file('deps')
def f = file("$buildDir/" + folder + "-" + deps_ref)
if (!deps.exists() && !f.exists()) {
def deps = new File(buildDir.parent, 'deps')
if (!deps.exists()) {
deps.mkdir()
from zipTree(downloadDeps.dest)
into buildDir
}
doLast {
if (!deps.exists()) {
file(f).renameTo(file(deps))
}
}
}
// get sqlite
def sqlite_ver = '3340000'
task downloadSqlite(dependsOn: getDeps, type: Download) {
src 'https://www.sqlite.org/2020/sqlite-amalgamation-' + sqlite_ver + '.zip'
dest new File(buildDir, 'sqlite.zip')
overwrite false
}
task getSqlite(dependsOn: downloadSqlite, type: Copy) {
def sqlite = file('deps/Android/sqlite')
def f = file("$buildDir/sqlite-amalgamation-" + sqlite_ver)
if (!sqlite.exists() && !f.exists()) {
from zipTree(downloadSqlite.dest)
into buildDir
}
doLast {
if (!sqlite.exists()) {
file(f).renameTo(file(sqlite))
}
into deps
}
}
preBuild.dependsOn getDeps
preBuild.dependsOn getSqlite

View File

@@ -4,64 +4,82 @@ LOCAL_PATH := $(call my-dir)/..
include $(CLEAR_VARS)
LOCAL_MODULE := Curl
LOCAL_SRC_FILES := deps/Android/Curl/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libcurl.a
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libcurl.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmbedcrypto
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libmbedcrypto.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmbedtls
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libmbedtls.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmbedx509
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libmbedx509.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Freetype
LOCAL_SRC_FILES := deps/Android/Freetype/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libfreetype.a
LOCAL_SRC_FILES := deps/$(APP_ABI)/Freetype/libfreetype.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Iconv
LOCAL_SRC_FILES := deps/$(APP_ABI)/Iconv/libiconv.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcharset
LOCAL_SRC_FILES := deps/$(APP_ABI)/Iconv/libcharset.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Irrlicht
LOCAL_SRC_FILES := deps/Android/Irrlicht/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libIrrlicht.a
LOCAL_SRC_FILES := deps/$(APP_ABI)/Irrlicht/libIrrlichtMt.a
include $(PREBUILT_STATIC_LIBRARY)
#include $(CLEAR_VARS)
#LOCAL_MODULE := LevelDB
#LOCAL_SRC_FILES := deps/Android/LevelDB/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libleveldb.a
#include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := LuaJIT
LOCAL_SRC_FILES := deps/Android/LuaJIT/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libluajit.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mbedTLS
LOCAL_SRC_FILES := deps/Android/mbedTLS/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libmbedtls.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mbedx509
LOCAL_SRC_FILES := deps/Android/mbedTLS/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libmbedx509.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mbedcrypto
LOCAL_SRC_FILES := deps/Android/mbedTLS/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libmbedcrypto.a
LOCAL_SRC_FILES := deps/$(APP_ABI)/LuaJIT/libluajit.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := OpenAL
LOCAL_SRC_FILES := deps/Android/OpenAL-Soft/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libopenal.a
LOCAL_SRC_FILES := deps/$(APP_ABI)/OpenAL-Soft/libopenal.a
include $(PREBUILT_STATIC_LIBRARY)
# You can use `OpenSSL and Crypto` instead `mbedTLS mbedx509 mbedcrypto`,
#but it increase APK size on ~0.7MB
#include $(CLEAR_VARS)
#LOCAL_MODULE := OpenSSL
#LOCAL_SRC_FILES := deps/Android/OpenSSL/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libssl.a
#include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Gettext
LOCAL_SRC_FILES := deps/$(APP_ABI)/Gettext/libintl.a
include $(PREBUILT_STATIC_LIBRARY)
#include $(CLEAR_VARS)
#LOCAL_MODULE := Crypto
#LOCAL_SRC_FILES := deps/Android/OpenSSL/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libcrypto.a
#include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := SQLite3
LOCAL_SRC_FILES := deps/$(APP_ABI)/SQLite/libsqlite3.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Vorbis
LOCAL_SRC_FILES := deps/Android/Vorbis/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libvorbis.a
LOCAL_SRC_FILES := deps/$(APP_ABI)/Vorbis/libvorbis.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libvorbisfile
LOCAL_SRC_FILES := deps/$(APP_ABI)/Vorbis/libvorbisfile.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libogg
LOCAL_SRC_FILES := deps/$(APP_ABI)/Vorbis/libogg.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Zstd
LOCAL_SRC_FILES := deps/$(APP_ABI)/Zstd/libzstd.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
@@ -73,9 +91,9 @@ LOCAL_CFLAGS += \
-DENABLE_GLES=1 \
-DUSE_CURL=1 \
-DUSE_SOUND=1 \
-DUSE_FREETYPE=1 \
-DUSE_LEVELDB=0 \
-DUSE_LUAJIT=1 \
-DUSE_GETTEXT=1 \
-DVERSION_MAJOR=${versionMajor} \
-DVERSION_MINOR=${versionMinor} \
-DVERSION_PATCH=${versionPatch} \
@@ -97,16 +115,16 @@ LOCAL_C_INCLUDES := \
../../src/script \
../../lib/gmp \
../../lib/jsoncpp \
deps/Android/Curl/include \
deps/Android/Freetype/include \
deps/Android/Irrlicht/include \
deps/Android/LevelDB/include \
deps/Android/libiconv/include \
deps/Android/libiconv/libcharset/include \
deps/Android/LuaJIT/src \
deps/Android/OpenAL-Soft/include \
deps/Android/sqlite \
deps/Android/Vorbis/include
deps/$(APP_ABI)/Curl/include \
deps/$(APP_ABI)/Freetype/include/freetype2 \
deps/$(APP_ABI)/Irrlicht/include \
deps/$(APP_ABI)/Gettext/include \
deps/$(APP_ABI)/Iconv/include \
deps/$(APP_ABI)/LuaJIT/include \
deps/$(APP_ABI)/OpenAL-Soft/include \
deps/$(APP_ABI)/SQLite/include \
deps/$(APP_ABI)/Vorbis/include \
deps/$(APP_ABI)/Zstd/include
LOCAL_SRC_FILES := \
$(wildcard ../../src/client/*.cpp) \
@@ -189,25 +207,24 @@ LOCAL_SRC_FILES := \
../../src/voxel.cpp \
../../src/voxelalgorithms.cpp
# LevelDB backend is disabled
# ../../src/database/database-leveldb.cpp
# GMP
LOCAL_SRC_FILES += ../../lib/gmp/mini-gmp.c
# JSONCPP
LOCAL_SRC_FILES += ../../lib/jsoncpp/jsoncpp.cpp
# iconv
LOCAL_SRC_FILES += \
deps/Android/libiconv/lib/iconv.c \
deps/Android/libiconv/libcharset/lib/localcharset.c
# SQLite3
LOCAL_SRC_FILES += deps/Android/sqlite/sqlite3.c
LOCAL_STATIC_LIBRARIES += Curl Freetype Irrlicht OpenAL mbedTLS mbedx509 mbedcrypto Vorbis LuaJIT android_native_app_glue $(PROFILER_LIBS) #LevelDB
#OpenSSL Crypto
LOCAL_STATIC_LIBRARIES += \
Curl libmbedcrypto libmbedtls libmbedx509 \
Freetype \
Iconv libcharset \
Irrlicht \
LuaJIT \
OpenAL \
Gettext \
SQLite3 \
Vorbis libvorbisfile libogg \
Zstd
LOCAL_STATIC_LIBRARIES += android_native_app_glue $(PROFILER_LIBS)
LOCAL_LDLIBS := -lEGL -lGLESv1_CM -lGLESv2 -landroid -lOpenSLES

View File

@@ -5,22 +5,22 @@ NDK_TOOLCHAIN_VERSION := clang
APP_SHORT_COMMANDS := true
APP_MODULES := Minetest
APP_CPPFLAGS := -Ofast -fvisibility=hidden -fexceptions -Wno-deprecated-declarations -Wno-extra-tokens
APP_CPPFLAGS := -O2 -fvisibility=hidden
ifeq ($(APP_ABI),armeabi-v7a)
APP_CPPFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb
APP_CPPFLAGS += -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb
endif
#ifeq ($(APP_ABI),x86)
#APP_CPPFLAGS += -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32 -funroll-loops
#endif
ifeq ($(APP_ABI),x86)
APP_CPPFLAGS += -mssse3 -mfpmath=sse -funroll-loops
endif
ifndef NDEBUG
APP_CPPFLAGS := -g -D_DEBUG -O0 -fno-omit-frame-pointer -fexceptions
APP_CPPFLAGS := -g -Og -fno-omit-frame-pointer
endif
APP_CFLAGS := $(APP_CPPFLAGS) -Wno-parentheses-equality #-Werror=shorten-64-to-32
APP_CXXFLAGS := $(APP_CPPFLAGS) -frtti -std=gnu++17
APP_CFLAGS := $(APP_CPPFLAGS) -Wno-inconsistent-missing-override -Wno-parentheses-equality
APP_CXXFLAGS := $(APP_CPPFLAGS) -fexceptions -frtti -std=gnu++17
APP_LDFLAGS := -Wl,--no-warn-mismatch,--gc-sections,--icf=safe
ifeq ($(APP_ABI),arm64-v8a)

View File

@@ -1,16 +1,10 @@
core.log("info", "Initializing Asynchronous environment")
function core.job_processor(serialized_func, serialized_param)
local func = loadstring(serialized_func)
function core.job_processor(func, serialized_param)
local param = core.deserialize(serialized_param)
local retval = nil
if type(func) == "function" then
retval = core.serialize(func(param))
else
core.log("error", "ASYNC WORKER: Unable to deserialize function")
end
local retval = core.serialize(func(param))
return retval or core.serialize(nil)
end

View File

@@ -1,6 +1,5 @@
-- Minetest: builtin/client/chatcommands.lua
core.register_on_sending_chat_message(function(message)
if message:sub(1,2) == ".." then
return false
@@ -8,7 +7,7 @@ core.register_on_sending_chat_message(function(message)
local first_char = message:sub(1,1)
if first_char == "/" or first_char == "." then
core.display_chat_message(core.gettext("issued command: ") .. message)
core.display_chat_message(core.gettext("Issued command: ") .. message)
end
if first_char ~= "." then
@@ -19,7 +18,7 @@ core.register_on_sending_chat_message(function(message)
param = param or ""
if not cmd then
core.display_chat_message(core.gettext("-!- Empty command"))
core.display_chat_message("-!- " .. core.gettext("Empty command."))
return true
end
@@ -36,7 +35,7 @@ core.register_on_sending_chat_message(function(message)
core.display_chat_message(result)
end
else
core.display_chat_message(core.gettext("-!- Invalid command: ") .. cmd)
core.display_chat_message("-!- " .. core.gettext("Invalid command: ") .. cmd)
end
return true
@@ -66,7 +65,7 @@ core.register_chatcommand("clear_chat_queue", {
description = core.gettext("Clear the out chat queue"),
func = function(param)
core.clear_out_chat_queue()
return true, core.gettext("The out chat queue is now empty")
return true, core.gettext("The out chat queue is now empty.")
end,
})

View File

@@ -2,7 +2,6 @@
-- handled by the engine.
core.register_on_death(function()
core.display_chat_message("You died.")
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
"label[4.85,1.35;" .. fgettext("You died") ..
"]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]"

View File

@@ -7,5 +7,4 @@ dofile(clientpath .. "register.lua")
dofile(commonpath .. "after.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(clientpath .. "chatcommands.lua")
dofile(commonpath .. "vector.lua")
dofile(clientpath .. "death_formspec.lua")

View File

@@ -1,4 +1,3 @@
core.callback_origins = {}
local getinfo = debug.getinfo

View File

@@ -37,7 +37,14 @@ function core.after(after, func, ...)
arg = {...},
mod_origin = core.get_last_run_mod(),
}
jobs[#jobs + 1] = new_job
time_next = math.min(time_next, expire)
return { cancel = function() new_job.func = function() end end }
return {
cancel = function()
new_job.func = function() end
new_job.args = {}
end
}
end

View File

@@ -1,7 +1,47 @@
-- Minetest: builtin/common/chatcommands.lua
-- For server-side translations (if INIT == "game")
-- Otherwise, use core.gettext
local S = core.get_translator("__builtin")
core.registered_chatcommands = {}
-- Interpret the parameters of a command, separating options and arguments.
-- Input: command, param
-- command: name of command
-- param: parameters of command
-- Returns: opts, args
-- opts is a string of option letters, or false on error
-- args is an array with the non-option arguments in order, or an error message
-- Example: for this command line:
-- /command a b -cd e f -g
-- the function would receive:
-- a b -cd e f -g
-- and it would return:
-- "cdg", {"a", "b", "e", "f"}
-- Negative numbers are taken as arguments. Long options (--option) are
-- currently rejected as reserved.
local function getopts(command, param)
local opts = ""
local args = {}
for match in param:gmatch("%S+") do
if match:byte(1) == 45 then -- 45 = '-'
local second = match:byte(2)
if second == 45 then
return false, S("Invalid parameters (see /help @1).", command)
elseif second and (second < 48 or second > 57) then -- 48 = '0', 57 = '9'
opts = opts .. match:sub(2)
else
-- numeric, add it to args
args[#args + 1] = match
end
else
args[#args + 1] = match
end
end
return opts, args
end
function core.register_chatcommand(cmd, def)
def = def or {}
def.params = def.params or ""
@@ -29,35 +69,30 @@ function core.override_chatcommand(name, redefinition)
core.registered_chatcommands[name] = chatcommand
end
local cmd_marker = "/"
local function gettext(...)
return ...
end
local function gettext_replace(text, replace)
return text:gsub("$1", replace)
end
if INIT == "client" then
cmd_marker = "."
gettext = core.gettext
gettext_replace = fgettext_ne
local function format_help_line(cmd, def)
local cmd_marker = INIT == "client" and "." or "/"
local msg = core.colorize("#00ffff", cmd_marker .. cmd)
if def.params and def.params ~= "" then
msg = msg .. " " .. def.params
end
if def.description and def.description ~= "" then
msg = msg .. ": " .. def.description
end
return msg
end
local function do_help_cmd(name, param)
local function format_help_line(cmd, def)
local msg = core.colorize("#00ffff", cmd_marker .. cmd)
if def.params and def.params ~= "" then
msg = msg .. " " .. def.params
end
if def.description and def.description ~= "" then
msg = msg .. ": " .. def.description
end
return msg
local opts, args = getopts("help", param)
if not opts then
return false, args
end
if param == "" then
if #args > 1 then
return false, S("Too many arguments, try using just /help <command>")
end
local use_gui = INIT ~= "client" and core.get_player_by_name(name)
use_gui = use_gui and not opts:find("t")
if #args == 0 and not use_gui then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
@@ -65,10 +100,25 @@ local function do_help_cmd(name, param)
end
end
table.sort(cmds)
return true, gettext("Available commands: ") .. table.concat(cmds, " ") .. "\n"
.. gettext_replace("Use '$1help <cmd>' to get more information,"
.. " or '$1help all' to list everything.", cmd_marker)
elseif param == "all" then
local msg
if INIT == "game" then
msg = S("Available commands: @1",
table.concat(cmds, " ")) .. "\n"
.. S("Use '/help <cmd>' to get more "
.. "information, or '/help all' to list "
.. "everything.")
else
msg = core.gettext("Available commands: ")
.. table.concat(cmds, " ") .. "\n"
.. core.gettext("Use '.help <cmd>' to get more "
.. "information, or '.help all' to list "
.. "everything.")
end
return true, msg
elseif #args == 0 or (args[1] == "all" and use_gui) then
core.show_general_help_formspec(name)
return true
elseif args[1] == "all" then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
@@ -76,19 +126,35 @@ local function do_help_cmd(name, param)
end
end
table.sort(cmds)
return true, gettext("Available commands:").."\n"..table.concat(cmds, "\n")
elseif INIT == "game" and param == "privs" then
local msg
if INIT == "game" then
msg = S("Available commands:")
else
msg = core.gettext("Available commands:")
end
return true, msg.."\n"..table.concat(cmds, "\n")
elseif INIT == "game" and args[1] == "privs" then
if use_gui then
core.show_privs_help_formspec(name)
return true
end
local privs = {}
for priv, def in pairs(core.registered_privileges) do
privs[#privs + 1] = priv .. ": " .. def.description
end
table.sort(privs)
return true, "Available privileges:\n"..table.concat(privs, "\n")
return true, S("Available privileges:").."\n"..table.concat(privs, "\n")
else
local cmd = param
local cmd = args[1]
local def = core.registered_chatcommands[cmd]
if not def then
return false, gettext("Command not available: ")..cmd
local msg
if INIT == "game" then
msg = S("Command not available: @1", cmd)
else
msg = core.gettext("Command not available: ") .. cmd
end
return false, msg
else
return true, format_help_line(cmd, def)
end
@@ -97,16 +163,16 @@ end
if INIT == "client" then
core.register_chatcommand("help", {
params = gettext("[all | <cmd>]"),
description = gettext("Get help for commands"),
params = core.gettext("[all | <cmd>]"),
description = core.gettext("Get help for commands"),
func = function(param)
return do_help_cmd(nil, param)
end,
})
else
core.register_chatcommand("help", {
params = "[all | privs | <cmd>]",
description = "Get help for commands or list privileges",
params = S("[all | privs | <cmd>] [-t]"),
description = S("Get help for commands or list privileges (-t: output in chat)"),
func = do_help_cmd,
})
end

View File

@@ -20,7 +20,8 @@ local LIST_FORMSPEC_DESCRIPTION = [[
button_exit[5,7;3,1;quit;%s]
]]
local formspec_escape = core.formspec_escape
local F = core.formspec_escape
local S = core.get_translator("__builtin")
local check_player_privs = core.check_player_privs
@@ -51,22 +52,23 @@ core.after(0, load_mod_command_tree)
local function build_chatcommands_formspec(name, sel, copy)
local rows = {}
rows[1] = "#FFF,0,Command,Parameters"
rows[1] = "#FFF,0,"..F(S("Command"))..","..F(S("Parameters"))
local description = "For more information, click on any entry in the list.\n" ..
"Double-click to copy the entry to the chat history."
local description = S("For more information, click on "
.. "any entry in the list.").. "\n" ..
S("Double-click to copy the entry to the chat history.")
for i, data in ipairs(mod_cmds) do
rows[#rows + 1] = COLOR_BLUE .. ",0," .. formspec_escape(data[1]) .. ","
rows[#rows + 1] = COLOR_BLUE .. ",0," .. F(data[1]) .. ","
for j, cmds in ipairs(data[2]) do
local has_priv = check_player_privs(name, cmds[2].privs)
rows[#rows + 1] = ("%s,1,%s,%s"):format(
has_priv and COLOR_GREEN or COLOR_GRAY,
cmds[1], formspec_escape(cmds[2].params))
cmds[1], F(cmds[2].params))
if sel == #rows then
description = cmds[2].description
if copy then
core.chat_send_player(name, ("Command: %s %s"):format(
core.chat_send_player(name, S("Command: @1 @2",
core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params))
end
end
@@ -74,9 +76,9 @@ local function build_chatcommands_formspec(name, sel, copy)
end
return LIST_FORMSPEC_DESCRIPTION:format(
"Available commands: (see also: /help <cmd>)",
F(S("Available commands: (see also: /help <cmd>)")),
table.concat(rows, ","), sel or 0,
description, "Close"
F(description), F(S("Close"))
)
end
@@ -91,19 +93,19 @@ local function build_privs_formspec(name)
table.sort(privs, function(a, b) return a[1] < b[1] end)
local rows = {}
rows[1] = "#FFF,0,Privilege,Description"
rows[1] = "#FFF,0,"..F(S("Privilege"))..","..F(S("Description"))
local player_privs = core.get_player_privs(name)
for i, data in ipairs(privs) do
rows[#rows + 1] = ("%s,0,%s,%s"):format(
player_privs[data[1]] and COLOR_GREEN or COLOR_GRAY,
data[1], formspec_escape(data[2].description))
data[1], F(data[2].description))
end
return LIST_FORMSPEC:format(
"Available privileges:",
F(S("Available privileges:")),
table.concat(rows, ","),
"Close"
F(S("Close"))
)
end
@@ -123,30 +125,12 @@ core.register_on_player_receive_fields(function(player, formname, fields)
end
end)
local help_command = core.registered_chatcommands["help"]
local old_help_func = help_command.func
help_command.func = function(name, param)
local admin = core.settings:get("name")
-- If the admin ran help, put the output in the chat buffer as well to
-- work with the server terminal
if param == "privs" then
core.show_formspec(name, "__builtin:help_privs",
build_privs_formspec(name))
if name ~= admin then
return true
end
end
if param == "" or param == "all" then
core.show_formspec(name, "__builtin:help_cmds",
build_chatcommands_formspec(name))
if name ~= admin then
return true
end
end
return old_help_func(name, param)
function core.show_general_help_formspec(name)
core.show_formspec(name, "__builtin:help_cmds",
build_chatcommands_formspec(name))
end
function core.show_privs_help_formspec(name)
core.show_formspec(name, "__builtin:help_privs",
build_privs_formspec(name))
end

View File

@@ -209,14 +209,7 @@ end
--------------------------------------------------------------------------------
function math.hypot(x, y)
local t
x = math.abs(x)
y = math.abs(y)
t = math.min(x, y)
x = math.max(x, y)
if x == 0 then return 0 end
t = t / x
return x * math.sqrt(1 + t * t)
return math.sqrt(x * x + y * y)
end
--------------------------------------------------------------------------------
@@ -244,6 +237,15 @@ function math.factorial(x)
return v
end
function math.round(x)
if x >= 0 then
return math.floor(x + 0.5)
end
return math.ceil(x - 0.5)
end
function core.formspec_escape(text)
if text ~= nil then
text = string.gsub(text,"\\","\\\\")
@@ -423,21 +425,19 @@ function core.string_to_pos(value)
return nil
end
local p = {}
p.x, p.y, p.z = string.match(value, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
if p.x and p.y and p.z then
p.x = tonumber(p.x)
p.y = tonumber(p.y)
p.z = tonumber(p.z)
return p
local x, y, z = string.match(value, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
if x and y and z then
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
return vector.new(x, y, z)
end
p = {}
p.x, p.y, p.z = string.match(value, "^%( *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+) *%)$")
if p.x and p.y and p.z then
p.x = tonumber(p.x)
p.y = tonumber(p.y)
p.z = tonumber(p.z)
return p
x, y, z = string.match(value, "^%( *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+) *%)$")
if x and y and z then
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
return vector.new(x, y, z)
end
return nil
end
@@ -532,7 +532,7 @@ if INIT == "mainmenu" then
end
end
if INIT == "client" or INIT == "mainmenu" then
if core.gettext then -- for client and mainmenu
function fgettext_ne(text, ...)
text = core.gettext(text)
local arg = {n=select('#', ...), ...}

View File

@@ -1,4 +1,5 @@
_G.core = {}
dofile("builtin/common/vector.lua")
dofile("builtin/common/misc_helpers.lua")
describe("string", function()
@@ -55,8 +56,8 @@ end)
describe("pos", function()
it("from string", function()
assert.same({ x = 10, y = 5.1, z = -2}, core.string_to_pos("10.0, 5.1, -2"))
assert.same({ x = 10, y = 5.1, z = -2}, core.string_to_pos("( 10.0, 5.1, -2)"))
assert.equal(vector.new(10, 5.1, -2), core.string_to_pos("10.0, 5.1, -2"))
assert.equal(vector.new(10, 5.1, -2), core.string_to_pos("( 10.0, 5.1, -2)"))
assert.is_nil(core.string_to_pos("asd, 5, -2)"))
end)

View File

@@ -3,6 +3,7 @@ _G.core = {}
_G.setfenv = require 'busted.compatibility'.setfenv
dofile("builtin/common/serialize.lua")
dofile("builtin/common/vector.lua")
describe("serialize", function()
it("works", function()
@@ -53,4 +54,16 @@ describe("serialize", function()
assert.is_nil(test_out.func)
assert.equals(test_out.foo, "bar")
end)
it("vectors work", function()
local v = vector.new(1, 2, 3)
assert.same({{x = 1, y = 2, z = 3}}, core.deserialize(core.serialize({v})))
assert.same({x = 1, y = 2, z = 3}, core.deserialize(core.serialize(v)))
-- abuse
v = vector.new(1, 2, 3)
v.a = "bla"
assert.same({x = 1, y = 2, z = 3, a = "bla"},
core.deserialize(core.serialize(v)))
end)
end)

View File

@@ -4,14 +4,20 @@ dofile("builtin/common/vector.lua")
describe("vector", function()
describe("new()", function()
it("constructs", function()
assert.same({ x = 0, y = 0, z = 0 }, vector.new())
assert.same({ x = 1, y = 2, z = 3 }, vector.new(1, 2, 3))
assert.same({ x = 3, y = 2, z = 1 }, vector.new({ x = 3, y = 2, z = 1 }))
assert.same({x = 0, y = 0, z = 0}, vector.new())
assert.same({x = 1, y = 2, z = 3}, vector.new(1, 2, 3))
assert.same({x = 3, y = 2, z = 1}, vector.new({x = 3, y = 2, z = 1}))
assert.is_true(vector.check(vector.new()))
assert.is_true(vector.check(vector.new(1, 2, 3)))
assert.is_true(vector.check(vector.new({x = 3, y = 2, z = 1})))
local input = vector.new({ x = 3, y = 2, z = 1 })
local output = vector.new(input)
assert.same(input, output)
assert.are_not.equal(input, output)
assert.equal(input, output)
assert.is_false(rawequal(input, output))
assert.equal(input, input:new())
end)
it("throws on invalid input", function()
@@ -25,27 +31,286 @@ describe("vector", function()
end)
end)
it("equal()", function()
local function assertE(a, b)
assert.is_true(vector.equals(a, b))
end
local function assertNE(a, b)
assert.is_false(vector.equals(a, b))
end
assertE({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
assertE({x = -1, y = 0, z = 1}, {x = -1, y = 0, z = 1})
local a = { x = 2, y = 4, z = -10 }
assertE(a, a)
assertNE({x = -1, y = 0, z = 1}, a)
it("zero()", function()
assert.same({x = 0, y = 0, z = 0}, vector.zero())
assert.same(vector.new(), vector.zero())
assert.equal(vector.new(), vector.zero())
assert.is_true(vector.check(vector.zero()))
end)
it("add()", function()
assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 }))
it("copy()", function()
local v = vector.new(1, 2, 3)
assert.same(v, vector.copy(v))
assert.same(vector.new(v), vector.copy(v))
assert.equal(vector.new(v), vector.copy(v))
assert.is_true(vector.check(vector.copy(v)))
end)
it("indexes", function()
local some_vector = vector.new(24, 42, 13)
assert.equal(24, some_vector[1])
assert.equal(24, some_vector.x)
assert.equal(42, some_vector[2])
assert.equal(42, some_vector.y)
assert.equal(13, some_vector[3])
assert.equal(13, some_vector.z)
some_vector[1] = 100
assert.equal(100, some_vector.x)
some_vector.x = 101
assert.equal(101, some_vector[1])
some_vector[2] = 100
assert.equal(100, some_vector.y)
some_vector.y = 102
assert.equal(102, some_vector[2])
some_vector[3] = 100
assert.equal(100, some_vector.z)
some_vector.z = 103
assert.equal(103, some_vector[3])
end)
it("direction()", function()
local a = vector.new(1, 0, 0)
local b = vector.new(1, 42, 0)
assert.equal(vector.new(0, 1, 0), vector.direction(a, b))
assert.equal(vector.new(0, 1, 0), a:direction(b))
end)
it("distance()", function()
local a = vector.new(1, 0, 0)
local b = vector.new(3, 42, 9)
assert.is_true(math.abs(43 - vector.distance(a, b)) < 1.0e-12)
assert.is_true(math.abs(43 - a:distance(b)) < 1.0e-12)
assert.equal(0, vector.distance(a, a))
assert.equal(0, b:distance(b))
end)
it("length()", function()
local a = vector.new(0, 0, -23)
assert.equal(0, vector.length(vector.new()))
assert.equal(23, vector.length(a))
assert.equal(23, a:length())
end)
it("normalize()", function()
local a = vector.new(0, 0, -23)
assert.equal(vector.new(0, 0, -1), vector.normalize(a))
assert.equal(vector.new(0, 0, -1), a:normalize())
assert.equal(vector.new(), vector.normalize(vector.new()))
end)
it("floor()", function()
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(0, 0, -1), vector.floor(a))
assert.equal(vector.new(0, 0, -1), a:floor())
end)
it("round()", function()
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(0, 1, -1), vector.round(a))
assert.equal(vector.new(0, 1, -1), a:round())
end)
it("apply()", function()
local i = 0
local f = function(x)
i = i + 1
return x + i
end
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(1, 1, 0), vector.apply(a, math.ceil))
assert.equal(vector.new(1, 1, 0), a:apply(math.ceil))
assert.equal(vector.new(0.1, 0.9, 0.5), vector.apply(a, math.abs))
assert.equal(vector.new(0.1, 0.9, 0.5), a:apply(math.abs))
assert.equal(vector.new(1.1, 2.9, 2.5), vector.apply(a, f))
assert.equal(vector.new(4.1, 5.9, 5.5), a:apply(f))
end)
it("equals()", function()
local function assertE(a, b)
assert.is_true(vector.equals(a, b))
end
local function assertNE(a, b)
assert.is_false(vector.equals(a, b))
end
assertE({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
assertE({x = -1, y = 0, z = 1}, {x = -1, y = 0, z = 1})
assertE({x = -1, y = 0, z = 1}, vector.new(-1, 0, 1))
local a = {x = 2, y = 4, z = -10}
assertE(a, a)
assertNE({x = -1, y = 0, z = 1}, a)
assert.equal(vector.new(1, 2, 3), vector.new(1, 2, 3))
assert.is_true(vector.new(1, 2, 3):equals(vector.new(1, 2, 3)))
assert.not_equal(vector.new(1, 2, 3), vector.new(1, 2, 4))
assert.is_true(vector.new(1, 2, 3) == vector.new(1, 2, 3))
assert.is_false(vector.new(1, 2, 3) == vector.new(1, 3, 3))
end)
it("metatable is same", function()
local a = vector.new()
local b = vector.new(1, 2, 3)
assert.equal(true, vector.check(a))
assert.equal(true, vector.check(b))
assert.equal(vector.metatable, getmetatable(a))
assert.equal(vector.metatable, getmetatable(b))
assert.equal(vector.metatable, a.metatable)
end)
it("sort()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(0.5, 232, -2)
local sorted = {vector.new(0.5, 2, -2), vector.new(1, 232, 3)}
assert.same(sorted, {vector.sort(a, b)})
assert.same(sorted, {a:sort(b)})
end)
it("angle()", function()
assert.equal(math.pi, vector.angle(vector.new(-1, -2, -3), vector.new(1, 2, 3)))
assert.equal(math.pi/2, vector.new(0, 1, 0):angle(vector.new(1, 0, 0)))
end)
it("dot()", function()
assert.equal(-14, vector.dot(vector.new(-1, -2, -3), vector.new(1, 2, 3)))
assert.equal(0, vector.new():dot(vector.new(1, 2, 3)))
end)
it("cross()", function()
local a = vector.new(-1, -2, 0)
local b = vector.new(1, 2, 3)
assert.equal(vector.new(-6, 3, 0), vector.cross(a, b))
assert.equal(vector.new(-6, 3, 0), a:cross(b))
end)
it("offset()", function()
assert.same({ x = 41, y = 52, z = 63 }, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
assert.same({x = 41, y = 52, z = 63}, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
assert.equal(vector.new(41, 52, 63), vector.offset(vector.new(1, 2, 3), 40, 50, 60))
assert.equal(vector.new(41, 52, 63), vector.new(1, 2, 3):offset(40, 50, 60))
end)
it("is()", function()
local some_table1 = {foo = 13, [42] = 1, "bar", 2}
local some_table2 = {1, 2, 3}
local some_table3 = {x = 1, 2, 3}
local some_table4 = {1, 2, z = 3}
local old = {x = 1, y = 2, z = 3}
local real = vector.new(1, 2, 3)
assert.is_false(vector.check(nil))
assert.is_false(vector.check(1))
assert.is_false(vector.check(true))
assert.is_false(vector.check("foo"))
assert.is_false(vector.check(some_table1))
assert.is_false(vector.check(some_table2))
assert.is_false(vector.check(some_table3))
assert.is_false(vector.check(some_table4))
assert.is_false(vector.check(old))
assert.is_true(vector.check(real))
assert.is_true(real:check())
end)
it("global pairs", function()
local out = {}
local vec = vector.new(10, 20, 30)
for k, v in pairs(vec) do
out[k] = v
end
assert.same({x = 10, y = 20, z = 30}, out)
end)
it("abusing works", function()
local v = vector.new(1, 2, 3)
v.a = 1
assert.equal(1, v.a)
local a_is_there = false
for key, value in pairs(v) do
if key == "a" then
a_is_there = true
assert.equal(value, 1)
break
end
end
assert.is_true(a_is_there)
end)
it("add()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(1, 4, 3)
local c = vector.new(2, 6, 6)
assert.equal(c, vector.add(a, {x = 1, y = 4, z = 3}))
assert.equal(c, vector.add(a, b))
assert.equal(c, a:add(b))
assert.equal(c, a + b)
assert.equal(c, b + a)
end)
it("subtract()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(2, 4, 3)
local c = vector.new(-1, -2, 0)
assert.equal(c, vector.subtract(a, {x = 2, y = 4, z = 3}))
assert.equal(c, vector.subtract(a, b))
assert.equal(c, a:subtract(b))
assert.equal(c, a - b)
assert.equal(c, -b + a)
end)
it("multiply()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(2, 4, 3)
local c = vector.new(2, 8, 9)
local s = 2
local d = vector.new(2, 4, 6)
assert.equal(c, vector.multiply(a, {x = 2, y = 4, z = 3}))
assert.equal(c, vector.multiply(a, b))
assert.equal(d, vector.multiply(a, s))
assert.equal(d, a:multiply(s))
assert.equal(d, a * s)
assert.equal(d, s * a)
assert.equal(-a, -1 * a)
end)
it("divide()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(2, 4, 3)
local c = vector.new(0.5, 0.5, 1)
local s = 2
local d = vector.new(0.5, 1, 1.5)
assert.equal(c, vector.divide(a, {x = 2, y = 4, z = 3}))
assert.equal(c, vector.divide(a, b))
assert.equal(d, vector.divide(a, s))
assert.equal(d, a:divide(s))
assert.equal(d, a / s)
assert.equal(d, 1/s * a)
assert.equal(-a, a / -1)
end)
it("to_string()", function()
local v = vector.new(1, 2, 3.14)
assert.same("(1, 2, 3.14)", vector.to_string(v))
assert.same("(1, 2, 3.14)", v:to_string())
assert.same("(1, 2, 3.14)", tostring(v))
end)
it("from_string()", function()
local v = vector.new(1, 2, 3.14)
assert.is_true(vector.check(vector.from_string("(1, 2, 3.14)")))
assert.same({v, 13}, {vector.from_string("(1, 2, 3.14)")})
assert.same({v, 12}, {vector.from_string("(1,2 ,3.14)")})
assert.same({v, 12}, {vector.from_string("(1,2,3.14,)")})
assert.same({v, 11}, {vector.from_string("(1 2 3.14)")})
assert.same({v, 15}, {vector.from_string("( 1, 2, 3.14 )")})
assert.same({v, 15}, {vector.from_string(" ( 1, 2, 3.14) ")})
assert.same({vector.new(), 8}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ")})
assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 8)})
assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 9)})
assert.same(nil, vector.from_string("nothing"))
end)
-- This function is needed because of floating point imprecision.

View File

@@ -1,73 +1,126 @@
--[[
Vector helpers
Note: The vector.*-functions must be able to accept old vectors that had no metatables
]]
-- localize functions
local setmetatable = setmetatable
vector = {}
function vector.new(a, b, c)
if type(a) == "table" then
assert(a.x and a.y and a.z, "Invalid vector passed to vector.new()")
return {x=a.x, y=a.y, z=a.z}
elseif a then
assert(b and c, "Invalid arguments for vector.new()")
return {x=a, y=b, z=c}
end
return {x=0, y=0, z=0}
local metatable = {}
vector.metatable = metatable
local xyz = {"x", "y", "z"}
-- only called when rawget(v, key) returns nil
function metatable.__index(v, key)
return rawget(v, xyz[key]) or vector[key]
end
-- only called when rawget(v, key) returns nil
function metatable.__newindex(v, key, value)
rawset(v, xyz[key] or key, value)
end
-- constructors
local function fast_new(x, y, z)
return setmetatable({x = x, y = y, z = z}, metatable)
end
function vector.new(a, b, c)
if a and b and c then
return fast_new(a, b, c)
end
-- deprecated, use vector.copy and vector.zero directly
if type(a) == "table" then
return vector.copy(a)
else
assert(not a, "Invalid arguments for vector.new()")
return vector.zero()
end
end
function vector.zero()
return fast_new(0, 0, 0)
end
function vector.copy(v)
assert(v.x and v.y and v.z, "Invalid vector passed to vector.copy()")
return fast_new(v.x, v.y, v.z)
end
function vector.from_string(s, init)
local x, y, z, np = string.match(s, "^%s*%(%s*([^%s,]+)%s*[,%s]%s*([^%s,]+)%s*[,%s]" ..
"%s*([^%s,]+)%s*[,%s]?%s*%)()", init)
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
if not (x and y and z) then
return nil
end
return fast_new(x, y, z), np
end
function vector.to_string(v)
return string.format("(%g, %g, %g)", v.x, v.y, v.z)
end
metatable.__tostring = vector.to_string
function vector.equals(a, b)
return a.x == b.x and
a.y == b.y and
a.z == b.z
end
metatable.__eq = vector.equals
-- unary operations
function vector.length(v)
return math.hypot(v.x, math.hypot(v.y, v.z))
return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
end
-- Note: we can not use __len because it is already used for primitive table length
function vector.normalize(v)
local len = vector.length(v)
if len == 0 then
return {x=0, y=0, z=0}
return fast_new(0, 0, 0)
else
return vector.divide(v, len)
end
end
function vector.floor(v)
return {
x = math.floor(v.x),
y = math.floor(v.y),
z = math.floor(v.z)
}
return vector.apply(v, math.floor)
end
function vector.round(v)
return {
x = math.floor(v.x + 0.5),
y = math.floor(v.y + 0.5),
z = math.floor(v.z + 0.5)
}
return fast_new(
math.round(v.x),
math.round(v.y),
math.round(v.z)
)
end
function vector.apply(v, func)
return {
x = func(v.x),
y = func(v.y),
z = func(v.z)
}
return fast_new(
func(v.x),
func(v.y),
func(v.z)
)
end
function vector.distance(a, b)
local x = a.x - b.x
local y = a.y - b.y
local z = a.z - b.z
return math.hypot(x, math.hypot(y, z))
return math.sqrt(x * x + y * y + z * z)
end
function vector.direction(pos1, pos2)
return vector.normalize({
x = pos2.x - pos1.x,
y = pos2.y - pos1.y,
z = pos2.z - pos1.z
})
return vector.subtract(pos2, pos1):normalize()
end
function vector.angle(a, b)
@@ -82,70 +135,137 @@ function vector.dot(a, b)
end
function vector.cross(a, b)
return {
x = a.y * b.z - a.z * b.y,
y = a.z * b.x - a.x * b.z,
z = a.x * b.y - a.y * b.x
}
return fast_new(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x
)
end
function metatable.__unm(v)
return fast_new(-v.x, -v.y, -v.z)
end
-- add, sub, mul, div operations
function vector.add(a, b)
if type(b) == "table" then
return {x = a.x + b.x,
y = a.y + b.y,
z = a.z + b.z}
return fast_new(
a.x + b.x,
a.y + b.y,
a.z + b.z
)
else
return {x = a.x + b,
y = a.y + b,
z = a.z + b}
return fast_new(
a.x + b,
a.y + b,
a.z + b
)
end
end
function metatable.__add(a, b)
return fast_new(
a.x + b.x,
a.y + b.y,
a.z + b.z
)
end
function vector.subtract(a, b)
if type(b) == "table" then
return {x = a.x - b.x,
y = a.y - b.y,
z = a.z - b.z}
return fast_new(
a.x - b.x,
a.y - b.y,
a.z - b.z
)
else
return {x = a.x - b,
y = a.y - b,
z = a.z - b}
return fast_new(
a.x - b,
a.y - b,
a.z - b
)
end
end
function metatable.__sub(a, b)
return fast_new(
a.x - b.x,
a.y - b.y,
a.z - b.z
)
end
function vector.multiply(a, b)
if type(b) == "table" then
return {x = a.x * b.x,
y = a.y * b.y,
z = a.z * b.z}
return fast_new(
a.x * b.x,
a.y * b.y,
a.z * b.z
)
else
return {x = a.x * b,
y = a.y * b,
z = a.z * b}
return fast_new(
a.x * b,
a.y * b,
a.z * b
)
end
end
function metatable.__mul(a, b)
if type(a) == "table" then
return fast_new(
a.x * b,
a.y * b,
a.z * b
)
else
return fast_new(
a * b.x,
a * b.y,
a * b.z
)
end
end
function vector.divide(a, b)
if type(b) == "table" then
return {x = a.x / b.x,
y = a.y / b.y,
z = a.z / b.z}
return fast_new(
a.x / b.x,
a.y / b.y,
a.z / b.z
)
else
return {x = a.x / b,
y = a.y / b,
z = a.z / b}
return fast_new(
a.x / b,
a.y / b,
a.z / b
)
end
end
function metatable.__div(a, b)
-- scalar/vector makes no sense
return fast_new(
a.x / b,
a.y / b,
a.z / b
)
end
-- misc stuff
function vector.offset(v, x, y, z)
return {x = v.x + x,
y = v.y + y,
z = v.z + z}
return fast_new(
v.x + x,
v.y + y,
v.z + z
)
end
function vector.sort(a, b)
return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)},
{x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)}
return fast_new(math.min(a.x, b.x), math.min(a.y, b.y), math.min(a.z, b.z)),
fast_new(math.max(a.x, b.x), math.max(a.y, b.y), math.max(a.z, b.z))
end
function vector.check(v)
return getmetatable(v) == metatable
end
local function sin(x)
@@ -213,7 +333,7 @@ end
function vector.dir_to_rotation(forward, up)
forward = vector.normalize(forward)
local rot = {x = math.asin(forward.y), y = -math.atan2(forward.x, forward.z), z = 0}
local rot = vector.new(math.asin(forward.y), -math.atan2(forward.x, forward.z), 0)
if not up then
return rot
end
@@ -221,7 +341,7 @@ function vector.dir_to_rotation(forward, up)
"Invalid vectors passed to vector.dir_to_rotation().")
up = vector.normalize(up)
-- Calculate vector pointing up with roll = 0, just based on forward vector.
local forwup = vector.rotate({x = 0, y = 1, z = 0}, rot)
local forwup = vector.rotate(vector.new(0, 1, 0), rot)
-- 'forwup' and 'up' are now in a plane with 'forward' as normal.
-- The angle between them is the absolute of the roll value we're looking for.
rot.z = vector.angle(forwup, up)

View File

@@ -58,26 +58,20 @@ end
--------------------------------------------------------------------------------
local function get_formspec(self)
local formspec = ""
if not self.hidden and (self.parent == nil or not self.parent.hidden) then
if self.parent == nil then
local tsize = self.tablist[self.last_tab_index].tabsize or
{width=self.width, height=self.height}
formspec = formspec ..
string.format("size[%f,%f,%s]",tsize.width,tsize.height,
dump(self.fixed_size))
end
formspec = formspec .. self:tab_header()
formspec = formspec ..
self.tablist[self.last_tab_index].get_formspec(
self,
self.tablist[self.last_tab_index].name,
self.tablist[self.last_tab_index].tabdata,
self.tablist[self.last_tab_index].tabsize
)
if self.hidden or (self.parent ~= nil and self.parent.hidden) then
return ""
end
local tab = self.tablist[self.last_tab_index]
local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize)
if self.parent == nil and not prepend then
local tsize = tab.tabsize or {width=self.width, height=self.height}
prepend = string.format("size[%f,%f,%s]", tsize.width, tsize.height,
dump(self.fixed_size))
end
local formspec = (prepend or "") .. self:tab_header() .. content
return formspec
end
@@ -97,14 +91,9 @@ local function handle_buttons(self,fields)
return true
end
if self.tablist[self.last_tab_index].button_handler ~= nil then
return
self.tablist[self.last_tab_index].button_handler(
self,
fields,
self.tablist[self.last_tab_index].name,
self.tablist[self.last_tab_index].tabdata
)
local tab = self.tablist[self.last_tab_index]
if tab.button_handler ~= nil then
return tab.button_handler(self, fields, tab.name, tab.tabdata)
end
return false
@@ -122,14 +111,9 @@ local function handle_events(self,event)
return true
end
if self.tablist[self.last_tab_index].evt_handler ~= nil then
return
self.tablist[self.last_tab_index].evt_handler(
self,
event,
self.tablist[self.last_tab_index].name,
self.tablist[self.last_tab_index].tabdata
)
local tab = self.tablist[self.last_tab_index]
if tab.evt_handler ~= nil then
return tab.evt_handler(self, event, tab.name, tab.tabdata)
end
return false

View File

@@ -63,7 +63,7 @@ function ui.update()
-- handle errors
if gamedata ~= nil and gamedata.reconnect_requested then
local error_message = core.formspec_escape(
gamedata.errormessage or "<none available>")
gamedata.errormessage or fgettext("<none available>"))
formspec = {
"size[14,8]",
"real_coordinates[true]",

View File

@@ -87,6 +87,10 @@ core.builtin_auth_handler = {
core.settings:get("default_password")))
end
auth_entry.privileges = privileges
core_auth.save(auth_entry)
-- Run grant callbacks
for priv, _ in pairs(privileges) do
if not auth_entry.privileges[priv] then
@@ -100,9 +104,6 @@ core.builtin_auth_handler = {
core.run_priv_callbacks(name, priv, nil, "revoke")
end
end
auth_entry.privileges = privileges
core_auth.save(auth_entry)
core.notify_authentication_modified(name)
end,
reload = function()

File diff suppressed because it is too large Load Diff

View File

@@ -39,7 +39,7 @@ local gravity = tonumber(core.settings:get("movement_gravity")) or 9.81
core.register_entity(":__builtin:falling_node", {
initial_properties = {
visual = "item",
visual_size = {x = SCALE, y = SCALE, z = SCALE},
visual_size = vector.new(SCALE, SCALE, SCALE),
textures = {},
physical = true,
is_visible = false,
@@ -84,9 +84,6 @@ core.register_entity(":__builtin:falling_node", {
local textures
if def.tiles and def.tiles[1] then
local tile = def.tiles[1]
if def.drawtype == "torchlike" and def.paramtype2 ~= "wallmounted" then
tile = def.tiles[2] or def.tiles[1]
end
if type(tile) == "table" then
tile = tile.name
end
@@ -99,7 +96,7 @@ core.register_entity(":__builtin:falling_node", {
local vsize
if def.visual_scale then
local s = def.visual_scale
vsize = {x = s, y = s, z = s}
vsize = vector.new(s, s, s)
end
self.object:set_properties({
is_visible = true,
@@ -114,15 +111,21 @@ core.register_entity(":__builtin:falling_node", {
itemstring = core.itemstring_with_palette(itemstring, node.param2)
end
-- FIXME: solution needed for paramtype2 == "leveled"
local vsize
if def.visual_scale then
local s = def.visual_scale * SCALE
vsize = {x = s, y = s, z = s}
-- Calculate size of falling node
local s = {}
s.x = (def.visual_scale or 1) * SCALE
s.y = s.x
s.z = s.x
-- Compensate for wield_scale
if def.wield_scale then
s.x = s.x / def.wield_scale.x
s.y = s.y / def.wield_scale.y
s.z = s.z / def.wield_scale.z
end
self.object:set_properties({
is_visible = true,
wield_item = itemstring,
visual_size = vsize,
visual_size = s,
glow = def.light_source,
})
end
@@ -147,11 +150,7 @@ core.register_entity(":__builtin:falling_node", {
-- Rotate entity
if def.drawtype == "torchlike" then
if def.paramtype2 == "wallmounted" then
self.object:set_yaw(math.pi*0.25)
else
self.object:set_yaw(-math.pi*0.25)
end
self.object:set_yaw(math.pi*0.25)
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"
@@ -165,8 +164,13 @@ core.register_entity(":__builtin:falling_node", {
if euler then
self.object:set_rotation(euler)
end
elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted") then
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
@@ -208,6 +212,14 @@ core.register_entity(":__builtin:falling_node", {
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,
@@ -222,7 +234,7 @@ core.register_entity(":__builtin:falling_node", {
on_activate = function(self, staticdata)
self.object:set_armor_groups({immortal = 1})
self.object:set_acceleration({x = 0, y = -gravity, z = 0})
self.object:set_acceleration(vector.new(0, -gravity, 0))
local ds = core.deserialize(staticdata)
if ds and ds.node then
@@ -298,7 +310,7 @@ core.register_entity(":__builtin:falling_node", {
if self.floats then
local pos = self.object:get_pos()
local bcp = vector.round({x = pos.x, y = pos.y - 0.7, z = pos.z})
local bcp = pos:offset(0, -0.7, 0):round()
local bcn = core.get_node(bcp)
local bcd = core.registered_nodes[bcn.name]
@@ -339,13 +351,12 @@ core.register_entity(":__builtin:falling_node", {
-- TODO: this hack could be avoided in the future if objects
-- could choose who to collide with
local vel = self.object:get_velocity()
self.object:set_velocity({
x = vel.x,
y = player_collision.old_velocity.y,
z = vel.z
})
self.object:set_pos(vector.add(self.object:get_pos(),
{x = 0, y = -0.5, z = 0}))
self.object:set_velocity(vector.new(
vel.x,
player_collision.old_velocity.y,
vel.z
))
self.object:set_pos(self.object:get_pos():offset(0, -0.5, 0))
end
return
elseif bcn.name == "ignore" then
@@ -407,7 +418,7 @@ local function convert_to_falling_node(pos, node)
obj:get_luaentity():set_node(node, metatable)
core.remove_node(pos)
return true
return true, obj
end
function core.spawn_falling_node(pos)
@@ -425,7 +436,7 @@ local function drop_attached_node(p)
if def and def.preserve_metadata then
local oldmeta = core.get_meta(p):to_table().fields
-- Copy pos and node because the callback can modify them.
local pos_copy = {x=p.x, y=p.y, z=p.z}
local pos_copy = vector.new(p)
local node_copy = {name=n.name, param1=n.param1, param2=n.param2}
local drop_stacks = {}
for k, v in pairs(drops) do
@@ -450,14 +461,14 @@ end
function builtin_shared.check_attached_node(p, n)
local def = core.registered_nodes[n.name]
local d = {x = 0, y = 0, z = 0}
local d = vector.new()
if def.paramtype2 == "wallmounted" or
def.paramtype2 == "colorwallmounted" then
-- The fallback vector here is in case 'wallmounted to dir' is nil due
-- to voxelmanip placing a wallmounted node without resetting a
-- pre-existing param2 value that is out-of-range for wallmounted.
-- The fallback vector corresponds to param2 = 0.
d = core.wallmounted_to_dir(n.param2) or {x = 0, y = 1, z = 0}
d = core.wallmounted_to_dir(n.param2) or vector.new(0, 1, 0)
else
d.y = -1
end
@@ -477,7 +488,7 @@ end
function core.check_single_for_falling(p)
local n = core.get_node(p)
if core.get_item_group(n.name, "falling_node") ~= 0 then
local p_bottom = {x = p.x, y = p.y - 1, z = p.z}
local p_bottom = vector.offset(p, 0, -1, 0)
-- Only spawn falling node if node below is loaded
local n_bottom = core.get_node_or_nil(p_bottom)
local d_bottom = n_bottom and core.registered_nodes[n_bottom.name]
@@ -516,17 +527,17 @@ end
-- Down first as likely case, but always before self. The same with sides.
-- Up must come last, so that things above self will also fall all at once.
local check_for_falling_neighbors = {
{x = -1, y = -1, z = 0},
{x = 1, y = -1, z = 0},
{x = 0, y = -1, z = -1},
{x = 0, y = -1, z = 1},
{x = 0, y = -1, z = 0},
{x = -1, y = 0, z = 0},
{x = 1, y = 0, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1},
{x = 0, y = 0, z = 0},
{x = 0, y = 1, z = 0},
vector.new(-1, -1, 0),
vector.new( 1, -1, 0),
vector.new( 0, -1, -1),
vector.new( 0, -1, 1),
vector.new( 0, -1, 0),
vector.new(-1, 0, 0),
vector.new( 1, 0, 0),
vector.new( 0, 0, 1),
vector.new( 0, 0, -1),
vector.new( 0, 0, 0),
vector.new( 0, 1, 0),
}
function core.check_for_falling(p)

View File

@@ -19,6 +19,9 @@ core.features = {
object_step_has_moveresult = true,
direct_velocity_on_players = true,
use_texture_alpha_string_modes = true,
degrotate_240_steps = true,
abm_min_max_y = true,
dynamic_add_media_table = true,
}
function core.has_feature(arg)

View File

@@ -86,12 +86,6 @@ local function read_file(filename)
return core.deserialize(t) or {}
end
local function write_file(filename, table)
local f = io.open(filename, "w")
f:write(core.serialize(table))
f:close()
end
blocks_forceloaded = read_file(wpath.."/force_loaded.txt")
for _, __ in pairs(blocks_forceloaded) do
total_forceloaded = total_forceloaded + 1
@@ -106,7 +100,8 @@ end)
-- persists the currently forceloaded blocks to disk
local function persist_forceloaded_blocks()
write_file(wpath.."/force_loaded.txt", blocks_forceloaded)
local data = core.serialize(blocks_forceloaded)
core.safe_file_write(wpath.."/force_loaded.txt", data)
end
-- periodical forceload persistence

View File

@@ -7,8 +7,6 @@ local gamepath = scriptpath .. "game".. DIR_DELIM
-- not exposed to outer context
local builtin_shared = {}
dofile(commonpath .. "vector.lua")
dofile(gamepath .. "constants.lua")
assert(loadfile(gamepath .. "item.lua"))(builtin_shared)
dofile(gamepath .. "register.lua")

View File

@@ -92,12 +92,12 @@ end
-- Table of possible dirs
local facedir_to_dir = {
{x= 0, y=0, z= 1},
{x= 1, y=0, z= 0},
{x= 0, y=0, z=-1},
{x=-1, y=0, z= 0},
{x= 0, y=-1, z= 0},
{x= 0, y=1, z= 0},
vector.new( 0, 0, 1),
vector.new( 1, 0, 0),
vector.new( 0, 0, -1),
vector.new(-1, 0, 0),
vector.new( 0, -1, 0),
vector.new( 0, 1, 0),
}
-- Mapping from facedir value to index in facedir_to_dir.
local facedir_to_dir_map = {
@@ -136,12 +136,12 @@ end
-- table of dirs in wallmounted order
local wallmounted_to_dir = {
[0] = {x = 0, y = 1, z = 0},
{x = 0, y = -1, z = 0},
{x = 1, y = 0, z = 0},
{x = -1, y = 0, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1},
[0] = vector.new( 0, 1, 0),
vector.new( 0, -1, 0),
vector.new( 1, 0, 0),
vector.new(-1, 0, 0),
vector.new( 0, 0, 1),
vector.new( 0, 0, -1),
}
function core.wallmounted_to_dir(wallmounted)
return wallmounted_to_dir[wallmounted % 8]
@@ -152,12 +152,12 @@ function core.dir_to_yaw(dir)
end
function core.yaw_to_dir(yaw)
return {x = -math.sin(yaw), y = 0, z = math.cos(yaw)}
return vector.new(-math.sin(yaw), 0, math.cos(yaw))
end
function core.is_colored_paramtype(ptype)
return (ptype == "color") or (ptype == "colorfacedir") or
(ptype == "colorwallmounted")
(ptype == "colorwallmounted") or (ptype == "colordegrotate")
end
function core.strip_param2_color(param2, paramtype2)
@@ -168,11 +168,25 @@ function core.strip_param2_color(param2, paramtype2)
param2 = math.floor(param2 / 32) * 32
elseif paramtype2 == "colorwallmounted" then
param2 = math.floor(param2 / 8) * 8
elseif paramtype2 == "colordegrotate" then
param2 = math.floor(param2 / 32) * 32
end
-- paramtype2 == "color" requires no modification.
return param2
end
local function has_all_groups(tbl, required_groups)
if type(required_groups) == "string" then
return (tbl[required_groups] or 0) ~= 0
end
for _, group in ipairs(required_groups) do
if (tbl[group] or 0) == 0 then
return false
end
end
return true
end
function core.get_node_drops(node, toolname)
-- Compatibility, if node is string
local nodename = node
@@ -212,7 +226,7 @@ function core.get_node_drops(node, toolname)
if item.rarity ~= nil then
good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
end
if item.tools ~= nil then
if item.tools ~= nil or item.tool_groups ~= nil then
good_tool = false
end
if item.tools ~= nil and toolname then
@@ -227,6 +241,27 @@ function core.get_node_drops(node, toolname)
end
end
end
if item.tool_groups ~= nil and toolname then
local tooldef = core.registered_items[toolname]
if tooldef ~= nil and type(tooldef.groups) == "table" then
if type(item.tool_groups) == "string" then
-- tool_groups can be a string which specifies the required group
good_tool = core.get_item_group(toolname, item.tool_groups) ~= 0
else
-- tool_groups can be a list of sufficient requirements.
-- i.e. if any item in the list can be satisfied then the tool is good
assert(type(item.tool_groups) == "table")
for _, required_groups in ipairs(item.tool_groups) do
-- required_groups can be either a string (a single group),
-- or an array of strings where all must be in tooldef.groups
good_tool = has_all_groups(tooldef.groups, required_groups)
if good_tool then
break
end
end
end
end
end
if good_rarity and good_tool then
got_count = got_count + 1
for _, add_item in ipairs(item.items) do
@@ -288,12 +323,12 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
end
-- Place above pointed node
local place_to = {x = above.x, y = above.y, z = above.z}
local place_to = vector.new(above)
-- If node under is buildable_to, place into it instead (eg. snow)
if olddef_under.buildable_to then
log("info", "node under is buildable to")
place_to = {x = under.x, y = under.y, z = under.z}
place_to = vector.new(under)
end
if core.is_protected(place_to, playername) then
@@ -313,22 +348,14 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
newnode.param2 = def.place_param2
elseif (def.paramtype2 == "wallmounted" or
def.paramtype2 == "colorwallmounted") and not param2 then
local dir = {
x = under.x - above.x,
y = under.y - above.y,
z = under.z - above.z
}
local dir = vector.subtract(under, above)
newnode.param2 = core.dir_to_wallmounted(dir)
-- Calculate the direction for furnaces and chests and stuff
elseif (def.paramtype2 == "facedir" or
def.paramtype2 == "colorfacedir") and not param2 then
local placer_pos = placer and placer:get_pos()
if placer_pos then
local dir = {
x = above.x - placer_pos.x,
y = above.y - placer_pos.y,
z = above.z - placer_pos.z
}
local dir = vector.subtract(above, placer_pos)
newnode.param2 = core.dir_to_facedir(dir)
log("info", "facedir: " .. newnode.param2)
end
@@ -345,6 +372,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
color_divisor = 8
elseif def.paramtype2 == "colorfacedir" then
color_divisor = 32
elseif def.paramtype2 == "colordegrotate" then
color_divisor = 32
end
if color_divisor then
local color = math.floor(metatable.palette_index / color_divisor)
@@ -380,7 +409,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
-- Run callback
if def.after_place_node and not prevent_after_place then
-- Deepcopy place_to and pointed_thing because callback can modify it
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
local place_to_copy = vector.new(place_to)
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
if def.after_place_node(place_to_copy, placer, itemstack,
pointed_thing_copy) then
@@ -391,7 +420,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
-- Run script hook
for _, callback in ipairs(core.registered_on_placenodes) do
-- Deepcopy pos, node and pointed_thing because callback can modify them
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
local place_to_copy = vector.new(place_to)
local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
@@ -470,34 +499,41 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed
return result
end
end
-- read definition before potentially emptying the stack
local def = itemstack:get_definition()
if itemstack:take_item() ~= nil then
user:set_hp(user:get_hp() + hp_change)
if itemstack:take_item():is_empty() then
return itemstack
end
if def and def.sound and def.sound.eat then
core.sound_play(def.sound.eat, {
pos = user:get_pos(),
max_hear_distance = 16
}, true)
end
if def and def.sound and def.sound.eat then
core.sound_play(def.sound.eat, {
pos = user:get_pos(),
max_hear_distance = 16
}, true)
end
if replace_with_item then
if itemstack:is_empty() then
itemstack:add_item(replace_with_item)
-- Changing hp might kill the player causing mods to do who-knows-what to the
-- inventory, so do this before set_hp().
if replace_with_item then
if itemstack:is_empty() then
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
-- Check if inv is null, since non-players don't have one
if inv and inv:room_for_item("main", {name=replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local inv = user:get_inventory()
-- Check if inv is null, since non-players don't have one
if inv and inv:room_for_item("main", {name=replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local pos = user:get_pos()
pos.y = math.floor(pos.y + 0.5)
core.add_item(pos, replace_with_item)
end
local pos = user:get_pos()
pos.y = math.floor(pos.y + 0.5)
core.add_item(pos, replace_with_item)
end
end
end
return itemstack
user:set_wielded_item(itemstack)
user:set_hp(user:get_hp() + hp_change)
return nil -- don't overwrite wield item a second time
end
function core.item_eat(hp_change, replace_with_item)
@@ -537,11 +573,11 @@ function core.handle_node_drops(pos, drops, digger)
for _, dropped_item in pairs(drops) do
local left = give_item(dropped_item)
if not left:is_empty() then
local p = {
x = pos.x + math.random()/2-0.25,
y = pos.y + math.random()/2-0.25,
z = pos.z + math.random()/2-0.25,
}
local p = vector.offset(pos,
math.random()/2-0.25,
math.random()/2-0.25,
math.random()/2-0.25
)
core.add_item(p, left)
end
end
@@ -578,7 +614,7 @@ function core.node_dig(pos, node, digger)
if wielded then
local wdef = wielded:get_definition()
local tp = wielded:get_tool_capabilities()
local dp = core.get_dig_params(def and def.groups, tp)
local dp = core.get_dig_params(def and def.groups, tp, wielded:get_wear())
if wdef and wdef.after_use then
wielded = wdef.after_use(wielded, digger, node, dp) or wielded
else
@@ -600,7 +636,7 @@ function core.node_dig(pos, node, digger)
if def and def.preserve_metadata then
local oldmeta = core.get_meta(pos):to_table().fields
-- Copy pos and node because the callback can modify them.
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
local pos_copy = vector.new(pos)
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
local drop_stacks = {}
for k, v in pairs(drops) do
@@ -632,7 +668,7 @@ function core.node_dig(pos, node, digger)
-- Run callback
if def and def.after_dig_node then
-- Copy pos and node because callback can modify them
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
local pos_copy = vector.new(pos)
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
def.after_dig_node(pos_copy, node_copy, oldmetadata, digger)
end
@@ -640,12 +676,10 @@ function core.node_dig(pos, node, digger)
-- Run script hook
for _, callback in ipairs(core.registered_on_dignodes) do
local origin = core.callback_origins[callback]
if origin then
core.set_last_run_mod(origin.mod)
end
core.set_last_run_mod(origin.mod)
-- Copy pos and node because callback can modify them
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
local pos_copy = vector.new(pos)
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
callback(pos_copy, node_copy, digger)
end
@@ -688,7 +722,7 @@ core.nodedef_default = {
groups = {},
inventory_image = "",
wield_image = "",
wield_scale = {x=1,y=1,z=1},
wield_scale = vector.new(1, 1, 1),
stack_max = default_stack_max,
usable = false,
liquids_pointable = false,
@@ -747,7 +781,7 @@ core.craftitemdef_default = {
groups = {},
inventory_image = "",
wield_image = "",
wield_scale = {x=1,y=1,z=1},
wield_scale = vector.new(1, 1, 1),
stack_max = default_stack_max,
liquids_pointable = false,
tool_capabilities = nil,
@@ -766,7 +800,7 @@ core.tooldef_default = {
groups = {},
inventory_image = "",
wield_image = "",
wield_scale = {x=1,y=1,z=1},
wield_scale = vector.new(1, 1, 1),
stack_max = 1,
liquids_pointable = false,
tool_capabilities = nil,
@@ -785,7 +819,7 @@ core.noneitemdef_default = { -- This is used for the hand and unknown items
groups = {},
inventory_image = "",
wield_image = "",
wield_scale = {x=1,y=1,z=1},
wield_scale = vector.new(1, 1, 1),
stack_max = default_stack_max,
liquids_pointable = false,
tool_capabilities = nil,

View File

@@ -1,9 +1,21 @@
-- Minetest: builtin/misc.lua
local S = core.get_translator("__builtin")
--
-- Misc. API functions
--
-- @spec core.kick_player(String, String) :: Boolean
function core.kick_player(player_name, reason)
if type(reason) == "string" then
reason = "Kicked: " .. reason
else
reason = "Kicked."
end
return core.disconnect_player(player_name, reason)
end
function core.check_player_privs(name, ...)
if core.is_player(name) then
name = name:get_player_name()
@@ -42,15 +54,15 @@ end
function core.send_join_message(player_name)
if not core.is_singleplayer() then
core.chat_send_all("*** " .. player_name .. " joined the game.")
core.chat_send_all("*** " .. S("@1 joined the game.", player_name))
end
end
function core.send_leave_message(player_name, timed_out)
local announcement = "*** " .. player_name .. " left the game."
local announcement = "*** " .. S("@1 left the game.", player_name)
if timed_out then
announcement = announcement .. " (timed out)"
announcement = "*** " .. S("@1 left the game (timed out).", player_name)
end
core.chat_send_all(announcement)
end
@@ -117,13 +129,12 @@ end
function core.get_position_from_hash(hash)
local pos = {}
pos.x = (hash % 65536) - 32768
local x = (hash % 65536) - 32768
hash = math.floor(hash / 65536)
pos.y = (hash % 65536) - 32768
local y = (hash % 65536) - 32768
hash = math.floor(hash / 65536)
pos.z = (hash % 65536) - 32768
return pos
local z = (hash % 65536) - 32768
return vector.new(x, y, z)
end
@@ -213,7 +224,7 @@ function core.is_area_protected(minp, maxp, player_name, interval)
local y = math.floor(yf + 0.5)
for xf = minp.x, maxp.x, d.x do
local x = math.floor(xf + 0.5)
local pos = {x = x, y = y, z = z}
local pos = vector.new(x, y, z)
if core.is_protected(pos, player_name) then
return pos
end
@@ -239,7 +250,7 @@ end
-- HTTP callback interface
function core.http_add_fetch(httpenv)
core.set_http_api_lua(function(httpenv)
httpenv.fetch = function(req, callback)
local handle = httpenv.fetch_async(req)
@@ -255,7 +266,8 @@ function core.http_add_fetch(httpenv)
end
return httpenv
end
end)
core.set_http_api_lua = nil
function core.close_formspec(player_name, formname)
@@ -268,24 +280,44 @@ function core.cancel_shutdown_requests()
end
-- Callback handling for dynamic_add_media
-- Used for callback handling with dynamic_add_media
core.dynamic_media_callbacks = {}
local dynamic_add_media_raw = core.dynamic_add_media_raw
core.dynamic_add_media_raw = nil
function core.dynamic_add_media(filepath, callback)
local ret = dynamic_add_media_raw(filepath)
if ret == false then
return ret
-- PNG encoder safety wrapper
local o_encode_png = core.encode_png
function core.encode_png(width, height, data, compression)
if type(width) ~= "number" then
error("Incorrect type for 'width', expected number, got " .. type(width))
end
if callback == nil then
core.log("deprecated", "Calling minetest.dynamic_add_media without "..
"a callback is deprecated and will stop working in future versions.")
else
-- At the moment async loading is not actually implemented, so we
-- immediately call the callback ourselves
for _, name in ipairs(ret) do
callback(name)
if type(height) ~= "number" then
error("Incorrect type for 'height', expected number, got " .. type(height))
end
local expected_byte_count = width * height * 4
if type(data) ~= "table" and type(data) ~= "string" then
error("Incorrect type for 'data', expected table or string, got " .. type(data))
end
local data_length = type(data) == "table" and #data * 4 or string.len(data)
if data_length ~= expected_byte_count then
error(string.format(
"Incorrect length of 'data', width and height imply %d bytes but %d were provided",
expected_byte_count,
data_length
))
end
if type(data) == "table" then
local dataBuf = {}
for i = 1, #data do
dataBuf[i] = core.colorspec_to_bytes(data[i])
end
data = table.concat(dataBuf)
end
return true
return o_encode_png(width, height, data, compression or 6)
end

View File

@@ -1,5 +1,7 @@
-- Minetest: builtin/privileges.lua
local S = core.get_translator("__builtin")
--
-- Privileges
--
@@ -15,7 +17,7 @@ function core.register_privilege(name, param)
def.give_to_admin = def.give_to_singleplayer
end
if def.description == nil then
def.description = "(no description)"
def.description = S("(no description)")
end
end
local def
@@ -28,71 +30,76 @@ function core.register_privilege(name, param)
core.registered_privileges[name] = def
end
core.register_privilege("interact", "Can interact with things and modify the world")
core.register_privilege("shout", "Can speak in chat")
core.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges")
core.register_privilege("privs", "Can modify privileges")
core.register_privilege("interact", S("Can interact with things and modify the world"))
core.register_privilege("shout", S("Can speak in chat"))
local basic_privs =
core.string_to_privs((core.settings:get("basic_privs") or "shout,interact"))
local basic_privs_desc = S("Can modify basic privileges (@1)",
core.privs_to_string(basic_privs, ', '))
core.register_privilege("basic_privs", basic_privs_desc)
core.register_privilege("privs", S("Can modify privileges"))
core.register_privilege("teleport", {
description = "Can teleport self",
description = S("Can teleport self"),
give_to_singleplayer = false,
})
core.register_privilege("bring", {
description = "Can teleport other players",
description = S("Can teleport other players"),
give_to_singleplayer = false,
})
core.register_privilege("settime", {
description = "Can set the time of day using /time",
description = S("Can set the time of day using /time"),
give_to_singleplayer = false,
})
core.register_privilege("server", {
description = "Can do server maintenance stuff",
description = S("Can do server maintenance stuff"),
give_to_singleplayer = false,
give_to_admin = true,
})
core.register_privilege("protection_bypass", {
description = "Can bypass node protection in the world",
description = S("Can bypass node protection in the world"),
give_to_singleplayer = false,
})
core.register_privilege("ban", {
description = "Can ban and unban players",
description = S("Can ban and unban players"),
give_to_singleplayer = false,
give_to_admin = true,
})
core.register_privilege("kick", {
description = "Can kick players",
description = S("Can kick players"),
give_to_singleplayer = false,
give_to_admin = true,
})
core.register_privilege("give", {
description = "Can use /give and /giveme",
description = S("Can use /give and /giveme"),
give_to_singleplayer = false,
})
core.register_privilege("password", {
description = "Can use /setpassword and /clearpassword",
description = S("Can use /setpassword and /clearpassword"),
give_to_singleplayer = false,
give_to_admin = true,
})
core.register_privilege("fly", {
description = "Can use fly mode",
description = S("Can use fly mode"),
give_to_singleplayer = false,
})
core.register_privilege("fast", {
description = "Can use fast mode",
description = S("Can use fast mode"),
give_to_singleplayer = false,
})
core.register_privilege("noclip", {
description = "Can fly through solid nodes using noclip mode",
description = S("Can fly through solid nodes using noclip mode"),
give_to_singleplayer = false,
})
core.register_privilege("rollback", {
description = "Can use the rollback functionality",
description = S("Can use the rollback functionality"),
give_to_singleplayer = false,
})
core.register_privilege("debug", {
description = "Allows enabling various debug options that may affect gameplay",
description = S("Can enable wireframe"),
give_to_singleplayer = false,
give_to_admin = true,
})
core.register_can_bypass_userlimit(function(name, ip)

View File

@@ -1,5 +1,7 @@
-- Minetest: builtin/misc_register.lua
local S = core.get_translator("__builtin")
--
-- Make raw registration functions inaccessible to anyone except this file
--
@@ -326,7 +328,7 @@ end
core.register_item(":unknown", {
type = "none",
description = "Unknown Item",
description = S("Unknown Item"),
inventory_image = "unknown_item.png",
on_place = core.item_place,
on_secondary_use = core.item_secondary_use,
@@ -336,7 +338,7 @@ core.register_item(":unknown", {
})
core.register_node(":air", {
description = "Air",
description = S("Air"),
inventory_image = "air.png",
wield_image = "air.png",
drawtype = "airlike",
@@ -353,7 +355,7 @@ core.register_node(":air", {
})
core.register_node(":ignore", {
description = "Ignore",
description = S("Ignore"),
inventory_image = "ignore.png",
wield_image = "ignore.png",
drawtype = "airlike",
@@ -366,11 +368,12 @@ core.register_node(":ignore", {
air_equivalent = true,
drop = "",
groups = {not_in_creative_inventory=1},
node_placement_prediction = "",
on_place = function(itemstack, placer, pointed_thing)
core.chat_send_player(
placer:get_player_name(),
core.colorize("#FF0000",
"You can't place 'ignore' nodes!"))
S("You can't place 'ignore' nodes!")))
return ""
end,
})
@@ -400,8 +403,14 @@ function core.override_item(name, redefinition)
register_item_raw(item)
end
core.callback_origins = {}
do
local default = {mod = "??", name = "??"}
core.callback_origins = setmetatable({}, {
__index = function()
return default
end
})
end
function core.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table")
@@ -416,9 +425,7 @@ function core.run_callbacks(callbacks, mode, ...)
local ret = nil
for i = 1, cb_len do
local origin = core.callback_origins[callbacks[i]]
if origin then
core.set_last_run_mod(origin.mod)
end
core.set_last_run_mod(origin.mod)
local cb_ret = callbacks[i](...)
if mode == 0 and i == 1 then
@@ -607,6 +614,7 @@ core.registered_on_modchannel_message, core.register_on_modchannel_message = mak
core.registered_on_player_inventory_actions, core.register_on_player_inventory_action = make_registration()
core.registered_allow_player_inventory_actions, core.register_allow_player_inventory_action = make_registration()
core.registered_on_rightclickplayers, core.register_on_rightclickplayer = make_registration()
core.registered_on_liquid_transformed, core.register_on_liquid_transformed = make_registration()
--
-- Compatibility for on_mapgen_init()

View File

@@ -1,39 +1,39 @@
-- cache setting
local enable_damage = core.settings:get_bool("enable_damage")
local health_bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "heart.png",
text2 = "heart_gone.png",
number = core.PLAYER_MAX_HP_DEFAULT,
item = core.PLAYER_MAX_HP_DEFAULT,
direction = 0,
size = {x = 24, y = 24},
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
}
local breath_bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble.png",
text2 = "bubble_gone.png",
number = core.PLAYER_MAX_BREATH_DEFAULT,
item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
direction = 0,
size = {x = 24, y = 24},
offset = {x = 25, y= -(48 + 24 + 16)},
local bar_definitions = {
hp = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "heart.png",
text2 = "heart_gone.png",
number = core.PLAYER_MAX_HP_DEFAULT,
item = core.PLAYER_MAX_HP_DEFAULT,
direction = 0,
size = {x = 24, y = 24},
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
},
breath = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble.png",
text2 = "bubble_gone.png",
number = core.PLAYER_MAX_BREATH_DEFAULT * 2,
item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
direction = 0,
size = {x = 24, y = 24},
offset = {x = 25, y= -(48 + 24 + 16)},
},
}
local hud_ids = {}
local function scaleToDefault(player, field)
-- Scale "hp" or "breath" to the default dimensions
local function scaleToHudMax(player, field)
-- Scale "hp" or "breath" to the hud maximum dimensions
local current = player["get_" .. field](player)
local nominal = core["PLAYER_MAX_" .. field:upper() .. "_DEFAULT"]
local max_display = math.max(nominal,
math.max(player:get_properties()[field .. "_max"], current))
return current / max_display * nominal
local nominal = bar_definitions[field].item
local max_display = math.max(player:get_properties()[field .. "_max"], current)
return math.ceil(current / max_display * nominal)
end
local function update_builtin_statbars(player)
@@ -55,9 +55,9 @@ local function update_builtin_statbars(player)
local immortal = player:get_armor_groups().immortal == 1
if flags.healthbar and enable_damage and not immortal then
local number = scaleToDefault(player, "hp")
local number = scaleToHudMax(player, "hp")
if hud.id_healthbar == nil then
local hud_def = table.copy(health_bar_definition)
local hud_def = table.copy(bar_definitions.hp)
hud_def.number = number
hud.id_healthbar = player:hud_add(hud_def)
else
@@ -73,9 +73,9 @@ local function update_builtin_statbars(player)
local breath = player:get_breath()
local breath_max = player:get_properties().breath_max
if show_breathbar and breath <= breath_max then
local number = 2 * scaleToDefault(player, "breath")
local number = scaleToHudMax(player, "breath")
if not hud.id_breathbar and breath < breath_max then
local hud_def = table.copy(breath_bar_definition)
local hud_def = table.copy(bar_definitions.breath)
hud_def.number = number
hud.id_breathbar = player:hud_add(hud_def)
elseif hud.id_breathbar then
@@ -145,7 +145,7 @@ function core.hud_replace_builtin(hud_name, definition)
end
if hud_name == "health" then
health_bar_definition = definition
bar_definitions.hp = definition
for name, ids in pairs(hud_ids) do
local player = core.get_player_by_name(name)
@@ -159,7 +159,7 @@ function core.hud_replace_builtin(hud_name, definition)
end
if hud_name == "breath" then
breath_bar_definition = definition
bar_definitions.breath = definition
for name, ids in pairs(hud_ids) do
local player = core.get_player_by_name(name)

View File

@@ -1,6 +1,6 @@
VoxelArea = {
MinEdge = {x=1, y=1, z=1},
MaxEdge = {x=0, y=0, z=0},
MinEdge = vector.new(1, 1, 1),
MaxEdge = vector.new(0, 0, 0),
ystride = 0,
zstride = 0,
}
@@ -19,11 +19,11 @@ end
function VoxelArea:getExtent()
local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
return {
x = MaxEdge.x - MinEdge.x + 1,
y = MaxEdge.y - MinEdge.y + 1,
z = MaxEdge.z - MinEdge.z + 1,
}
return vector.new(
MaxEdge.x - MinEdge.x + 1,
MaxEdge.y - MinEdge.y + 1,
MaxEdge.z - MinEdge.z + 1
)
end
function VoxelArea:getVolume()

View File

@@ -30,6 +30,7 @@ local clientpath = scriptdir .. "client" .. DIR_DELIM
local commonpath = scriptdir .. "common" .. DIR_DELIM
local asyncpath = scriptdir .. "async" .. DIR_DELIM
dofile(commonpath .. "vector.lua")
dofile(commonpath .. "strict.lua")
dofile(commonpath .. "serialize.lua")
dofile(commonpath .. "misc_helpers.lua")

View File

@@ -0,0 +1,245 @@
# textdomain: __builtin
Empty command.=Leerer Befehl.
Invalid command: @1=Ungültiger Befehl: @1
Invalid command usage.=Ungültige Befehlsverwendung.
(@1 s)= (@1 s)
Command execution took @1 s=Befehlsausführung brauchte @1 s
You don't have permission to run this command (missing privileges: @1).=Sie haben keine Erlaubnis, diesen Befehl auszuführen (fehlende Privilegien: @1).
Unable to get position of player @1.=Konnte Position vom Spieler @1 nicht ermitteln.
Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Ungültiges Gebietsformat. Erwartet: (x1,y1,z1) (x2,y2,z2)
<action>=<Aktion>
Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Chataktion zeigen (z.B. wird „/me isst Pizza“ zu „<Spielername> isst Pizza“)
Show the name of the server owner=Den Namen des Servereigentümers zeigen
The administrator of this server is @1.=Der Administrator dieses Servers ist @1.
There's no administrator named in the config file.=In der Konfigurationsdatei wurde kein Administrator angegeben.
@1 does not have any privileges.=@1 hat keine Privilegien.
Privileges of @1: @2=Privilegien von @1: @2
[<name>]=[<Name>]
Show privileges of yourself or another player=Ihre eigenen Privilegien oder die eines anderen Spielers anzeigen
Player @1 does not exist.=Spieler @1 existiert nicht.
<privilege>=<Privileg>
Return list of all online players with privilege=Liste aller Spieler mit einem Privileg ausgeben
Invalid parameters (see /help haspriv).=Ungültige Parameter (siehe „/help haspriv“).
Unknown privilege!=Unbekanntes Privileg!
No online player has the "@1" privilege.=Kein online spielender Spieler hat das „@1“-Privileg.
Players online with the "@1" privilege: @2=Derzeit online spielende Spieler mit dem „@1“-Privileg: @2
Your privileges are insufficient.=Ihre Privilegien sind unzureichend.
Your privileges are insufficient. '@1' only allows you to grant: @2=Ihre Privilegien sind unzureichend. Mit „@1“ können Sie nur folgendes gewähren: @2
Unknown privilege: @1=Unbekanntes Privileg: @1
@1 granted you privileges: @2=@1 gewährte Ihnen Privilegien: @2
<name> (<privilege> [, <privilege2> [<...>]] | all)=<Name> (<Privileg> [, <Privileg2> [<...>]] | all)
Give privileges to player=Privileg an Spieler vergeben
Invalid parameters (see /help grant).=Ungültige Parameter (siehe „/help grant“).
<privilege> [, <privilege2> [<...>]] | all=<Privileg> [, <Privileg2> [<...>]] | all
Grant privileges to yourself=Privilegien an Ihnen selbst vergeben
Invalid parameters (see /help grantme).=Ungültige Parameter (siehe „/help grantme“).
Your privileges are insufficient. '@1' only allows you to revoke: @2=Ihre Privilegien sind unzureichend. Mit „@1“ können Sie nur folgendes entziehen: @2
Note: Cannot revoke in singleplayer: @1=Anmerkung: Im Einzelspielermodus kann man folgendes nicht entziehen: @1
Note: Cannot revoke from admin: @1=Anmerkung: Vom Admin kann man folgendes nicht entziehen: @1
No privileges were revoked.=Es wurden keine Privilegien entzogen.
@1 revoked privileges from you: @2=@1 entfernte Privilegien von Ihnen: @2
Remove privileges from player=Privilegien von Spieler entfernen
Invalid parameters (see /help revoke).=Ungültige Parameter (siehe „/help revoke“).
Revoke privileges from yourself=Privilegien von Ihnen selbst entfernen
Invalid parameters (see /help revokeme).=Ungültige Parameter (siehe „/help revokeme“).
<name> <password>=<Name> <Passwort>
Set player's password=Passwort von Spieler setzen
Name field required.=Namensfeld benötigt.
Your password was cleared by @1.=Ihr Passwort wurde von @1 geleert.
Password of player "@1" cleared.=Passwort von Spieler „@1“ geleert.
Your password was set by @1.=Ihr Passwort wurde von @1 gesetzt.
Password of player "@1" set.=Passwort von Spieler „@1“ gesetzt.
<name>=<Name>
Set empty password for a player=Leeres Passwort für einen Spieler setzen
Reload authentication data=Authentifizierungsdaten erneut laden
Done.=Fertig.
Failed.=Fehlgeschlagen.
Remove a player's data=Daten eines Spielers löschen
Player "@1" removed.=Spieler „@1“ gelöscht.
No such player "@1" to remove.=Es gibt keinen Spieler „@1“, der gelöscht werden könnte.
Player "@1" is connected, cannot remove.=Spieler „@1“ ist verbunden, er kann nicht gelöscht werden.
Unhandled remove_player return code @1.=Nicht berücksichtigter remove_player-Rückgabewert @1.
Cannot teleport out of map bounds!=Eine Teleportation außerhalb der Kartengrenzen ist nicht möglich!
Cannot get player with name @1.=Spieler mit Namen @1 kann nicht gefunden werden.
Cannot teleport, @1 is attached to an object!=Teleportation nicht möglich, @1 ist an einem Objekt befestigt!
Teleporting @1 to @2.=Teleportation von @1 nach @2
One does not teleport to oneself.=Man teleportiert sich doch nicht zu sich selbst.
Cannot get teleportee with name @1.=Der zu teleportierende Spieler mit Namen @1 kann nicht gefunden werden.
Cannot get target player with name @1.=Zielspieler mit Namen @1 kann nicht gefunden werden.
Teleporting @1 to @2 at @3.=Teleportation von @1 zu @2 bei @3
<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>,<Y>,<Z> | <zu_Name> | <Name> <X>,<Y>,<Z> | <Name> <zu_Name>
Teleport to position or player=Zu Position oder Spieler teleportieren
You don't have permission to teleport other players (missing privilege: @1).=Sie haben nicht die Erlaubnis, andere Spieler zu teleportieren (fehlendes Privileg: @1).
([-n] <name> <value>) | <name>=([-n] <Name> <Wert>) | <Name>
Set or read server configuration setting=Serverkonfigurationseinstellung setzen oder lesen
Failed. Use '/set -n <name> <value>' to create a new setting.=Fehlgeschlagen. Benutzen Sie „/set -n <Name> <Wert>“, um eine neue Einstellung zu erstellen.
@1 @= @2=@1 @= @2
<not set>=<nicht gesetzt>
Invalid parameters (see /help set).=Ungültige Parameter (siehe „/help set“).
Finished emerging @1 blocks in @2ms.=Fertig mit Erzeugung von @1 Blöcken in @2 ms.
emergeblocks update: @1/@2 blocks emerged (@3%)=emergeblocks-Update: @1/@2 Kartenblöcke geladen (@3%)
(here [<radius>]) | (<pos1> <pos2>)=(here [<Radius>]) | (<Pos1> <Pos2>)
Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Lade (oder, wenn nicht existent, generiere) Kartenblöcke im Gebiet zwischen Pos1 und Pos2 (<Pos1> und <Pos2> müssen in Klammern stehen)
Started emerge of area ranging from @1 to @2.=Start des Ladevorgangs des Gebiets zwischen @1 und @2.
Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Kartenblöcke innerhalb des Gebiets zwischen Pos1 und Pos2 löschen (<Pos1> und <Pos2> müssen in Klammern stehen)
Successfully cleared area ranging from @1 to @2.=Gebiet zwischen @1 und @2 erfolgreich geleert.
Failed to clear one or more blocks in area.=Fehlgeschlagen: Ein oder mehrere Kartenblöcke im Gebiet konnten nicht geleert werden.
Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Setzt das Licht im Gebiet zwischen Pos1 und Pos2 zurück (<Pos1> und <Pos2> müssen in Klammern stehen)
Successfully reset light in the area ranging from @1 to @2.=Das Licht im Gebiet zwischen @1 und @2 wurde erfolgreich zurückgesetzt.
Failed to load one or more blocks in area.=Fehlgeschlagen: Ein oder mehrere Kartenblöcke im Gebiet konnten nicht geladen werden.
List mods installed on the server=Installierte Mods auf dem Server auflisten
No mods installed.=Es sind keine Mods installiert.
Cannot give an empty item.=Ein leerer Gegenstand kann nicht gegeben werden.
Cannot give an unknown item.=Ein unbekannter Gegenstand kann nicht gegeben werden.
Giving 'ignore' is not allowed.=„ignore“ darf nicht gegeben werden.
@1 is not a known player.=@1 ist kein bekannter Spieler.
@1 partially added to inventory.=@1 teilweise ins Inventar eingefügt.
@1 could not be added to inventory.=@1 konnte nicht ins Inventar eingefügt werden.
@1 added to inventory.=@1 zum Inventar hinzugefügt.
@1 partially added to inventory of @2.=@1 teilweise ins Inventar von @2 eingefügt.
@1 could not be added to inventory of @2.=@1 konnte nicht ins Inventar von @2 eingefügt werden.
@1 added to inventory of @2.=@1 ins Inventar von @2 eingefügt.
<name> <ItemString> [<count> [<wear>]]=<Name> <ItemString> [<Anzahl> [<Abnutzung>]]
Give item to player=Gegenstand an Spieler geben
Name and ItemString required.=Name und ItemString benötigt.
<ItemString> [<count> [<wear>]]=<ItemString> [<Anzahl> [<Abnutzung>]]
Give item to yourself=Gegenstand Ihnen selbst geben
ItemString required.=ItemString benötigt.
<EntityName> [<X>,<Y>,<Z>]=<EntityName> [<X>,<Y>,<Z>]
Spawn entity at given (or your) position=Entity an angegebener (oder Ihrer eigenen) Position spawnen
EntityName required.=EntityName benötigt.
Unable to spawn entity, player is nil.=Entity konnte nicht gespawnt werden, Spieler ist nil.
Cannot spawn an unknown entity.=Ein unbekanntes Entity kann nicht gespawnt werden.
Invalid parameters (@1).=Ungültige Parameter (@1).
@1 spawned.=@1 gespawnt.
@1 failed to spawn.=@1 konnte nicht gespawnt werden.
Destroy item in hand=Gegenstand in der Hand zerstören
Unable to pulverize, no player.=Konnte nicht pulverisieren, kein Spieler.
Unable to pulverize, no item in hand.=Konnte nicht pulverisieren, kein Gegenstand in der Hand.
An item was pulverized.=Ein Gegenstand wurde pulverisiert.
[<range>] [<seconds>] [<limit>]=[<Reichweite>] [<Sekunden>] [<Limit>]
Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Überprüfen, wer als letztes einen Node oder einen Node in der Nähe innerhalb der in <Sekunden> angegebenen Zeitspanne angefasst hat. Standard: Reichweite @= 0, Sekunden @= 86400 @= 24h, Limit @= 5. <Sekunden> auf „inf“ setzen, um Zeitlimit zu deaktivieren.
Rollback functions are disabled.=Rollback-Funktionen sind deaktiviert.
That limit is too high!=Dieses Limit ist zu hoch!
Checking @1 ...=Überprüfe @1 ...
Nobody has touched the specified location in @1 seconds.=Niemand hat die angegebene Position seit @1 Sekunden angefasst.
@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 vor @5 Sekunden.
Punch a node (range@=@1, seconds@=@2, limit@=@3).=Hauen Sie einen Node (Reichweite@=@1, Sekunden@=@2, Limit@=@3).
(<name> [<seconds>]) | (:<actor> [<seconds>])=(<Name> [<Sekunden>]) | (:<Akteur> [<Sekunden>])
Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Aktionen eines Spielers zurückrollen. Standard für <Sekunden> ist 60. <Sekunden> auf „inf“ setzen, um Zeitlimit zu deaktivieren
Invalid parameters. See /help rollback and /help rollback_check.=Ungültige Parameter. Siehe /help rollback und /help rollback_check.
Reverting actions of player '@1' since @2 seconds.=Die Aktionen des Spielers „@1“ seit @2 Sekunden werden rückgängig gemacht.
Reverting actions of @1 since @2 seconds.=Die Aktionen von @1 seit @2 Sekunden werden rückgängig gemacht.
(log is too long to show)=(Protokoll ist zu lang für die Anzeige)
Reverting actions succeeded.=Die Aktionen wurden erfolgreich rückgängig gemacht.
Reverting actions FAILED.=FEHLGESCHLAGEN: Die Aktionen konnten nicht rückgängig gemacht werden.
Show server status=Serverstatus anzeigen
This command was disabled by a mod or game.=Dieser Befehl wurde von einer Mod oder einem Spiel deaktiviert.
[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0..24000>]
Show or set time of day=Tageszeit anzeigen oder setzen
Current time is @1:@2.=Es ist jetzt @1:@2 Uhr.
You don't have permission to run this command (missing privilege: @1).=Sie haben nicht die Erlaubnis, diesen Befehl auszuführen (fehlendes Privileg: @1).
Invalid time (must be between 0 and 24000).=Ungültige Zeit (muss zwischen 0 und 24000 liegen).
Time of day changed.=Tageszeit geändert.
Invalid hour (must be between 0 and 23 inclusive).=Ungültige Stunde (muss zwischen 0 und 23 inklusive liegen).
Invalid minute (must be between 0 and 59 inclusive).=Ungültige Minute (muss zwischen 0 und 59 inklusive liegen).
Show day count since world creation=Anzahl Tage seit der Erschaffung der Welt anzeigen
Current day is @1.=Aktueller Tag ist @1.
[<delay_in_seconds> | -1] [-r] [<message>]=[<Verzögerung_in_Sekunden> | -1] [-r] [<Nachricht>]
Shutdown server (-1 cancels a delayed shutdown, -r allows players to reconnect)=Server herunterfahren (-1 bricht einen verzögerten Abschaltvorgang ab, -r erlaubt Spielern, sich wiederzuverbinden)
Server shutting down (operator request).=Server wird heruntergefahren (Betreiberanfrage).
Ban the IP of a player or show the ban list=Die IP eines Spielers verbannen oder die Bannliste anzeigen
The ban list is empty.=Die Bannliste ist leer.
Ban list: @1=Bannliste: @1
Player is not online.=Spieler ist nicht online.
Failed to ban player.=Konnte Spieler nicht verbannen.
Banned @1.=@1 verbannt.
<name> | <IP_address>=<Name> | <IP_Adresse>
Remove IP ban belonging to a player/IP=Einen IP-Bann auf einen Spieler zurücknehmen
Failed to unban player/IP.=Konnte Bann auf Spieler/IP nicht zurücknehmen.
Unbanned @1.=Bann auf @1 zurückgenommen.
<name> [<reason>]=<Name> [<Grund>]
Kick a player=Spieler hinauswerfen
Failed to kick player @1.=Spieler @1 konnte nicht hinausgeworfen werden.
Kicked @1.=@1 hinausgeworfen.
[full | quick]=[full | quick]
Clear all objects in world=Alle Objekte in der Welt löschen
Invalid usage, see /help clearobjects.=Ungültige Verwendung, siehe /help clearobjects.
Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Lösche alle Objekte. Dies kann eine lange Zeit dauern. Eine Netzwerkzeitüberschreitung könnte für Sie auftreten. (von @1)
Cleared all objects.=Alle Objekte gelöscht.
<name> <message>=<Name> <Nachricht>
Send a direct message to a player=Eine Direktnachricht an einen Spieler senden
Invalid usage, see /help msg.=Ungültige Verwendung, siehe /help msg.
The player @1 is not online.=Der Spieler @1 ist nicht online.
DM from @1: @2=DN von @1: @2
Message sent.=Nachricht gesendet.
Get the last login time of a player or yourself=Den letzten Loginzeitpunkt eines Spielers oder Ihren eigenen anfragen
@1's last login time was @2.=Letzter Loginzeitpunkt von @1 war @2.
@1's last login time is unknown.=Letzter Loginzeitpunkt von @1 ist unbekannt.
Clear the inventory of yourself or another player=Das Inventar von Ihnen oder einem anderen Spieler leeren
You don't have permission to clear another player's inventory (missing privilege: @1).=Sie haben nicht die Erlaubnis, das Inventar eines anderen Spielers zu leeren (fehlendes Privileg: @1).
@1 cleared your inventory.=@1 hat Ihr Inventar geleert.
Cleared @1's inventory.=Inventar von @1 geleert.
Player must be online to clear inventory!=Spieler muss online sein, um das Inventar leeren zu können!
Players can't be killed, damage has been disabled.=Spieler können nicht getötet werden, Schaden ist deaktiviert.
Player @1 is not online.=Spieler @1 ist nicht online.
You are already dead.=Sie sind schon tot.
@1 is already dead.=@1 ist bereits tot.
@1 has been killed.=@1 wurde getötet.
Kill player or yourself=Einen Spieler oder Sie selbst töten
Invalid parameters (see /help @1).=Ungültige Parameter (siehe „/help @1“).
Too many arguments, try using just /help <command>=Zu viele Argumente. Probieren Sie es mit „/help <Befehl>“
Available commands: @1=Verfügbare Befehle: @1
Use '/help <cmd>' to get more information, or '/help all' to list everything.=„/help <Befehl>“ benutzen, um mehr Informationen zu erhalten, oder „/help all“, um alles aufzulisten.
Available commands:=Verfügbare Befehle:
Command not available: @1=Befehl nicht verfügbar: @1
[all | privs | <cmd>] [-t]=[all | privs | <Befehl>] [-t]
Get help for commands or list privileges (-t: output in chat)=Hilfe für Befehle erhalten oder Privilegien auflisten (-t: Ausgabe im Chat)
Available privileges:=Verfügbare Privilegien:
Command=Befehl
Parameters=Parameter
For more information, click on any entry in the list.=Für mehr Informationen klicken Sie auf einen beliebigen Eintrag in der Liste.
Double-click to copy the entry to the chat history.=Doppelklicken, um den Eintrag in die Chathistorie einzufügen.
Command: @1 @2=Befehl: @1 @2
Available commands: (see also: /help <cmd>)=Verfügbare Befehle: (siehe auch: /help <Befehl>)
Close=Schließen
Privilege=Privileg
Description=Beschreibung
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<Filter>] | dump [<Filter>] | save [<Format> [<Filter>]]
Handle the profiler and profiling data=Den Profiler und Profilingdaten verwalten
Statistics written to action log.=Statistiken zum Aktionsprotokoll geschrieben.
Statistics were reset.=Statistiken wurden zurückgesetzt.
Usage: @1=Verwendung: @1
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format kann entweder „txt“, „csv“, „lua“, „json“ oder „json_pretty“ sein (die Struktur kann sich in Zukunft ändern).
@1 joined the game.=@1 ist dem Spiel beigetreten.
@1 left the game.=@1 hat das Spiel verlassen.
@1 left the game (timed out).=@1 hat das Spiel verlassen (Netzwerkzeitüberschreitung).
(no description)=(keine Beschreibung)
Can interact with things and modify the world=Kann mit Dingen interagieren und die Welt verändern
Can speak in chat=Kann im Chat sprechen
Can modify basic privileges (@1)=Kann grundlegende Privilegien anpassen (@1)
Can modify privileges=Kann Privilegien anpassen
Can teleport self=Kann sich selbst teleportieren
Can teleport other players=Kann andere Spieler teleportieren
Can set the time of day using /time=Kann die Tageszeit mit /time setzen
Can do server maintenance stuff=Kann Serverwartungsdinge machen
Can bypass node protection in the world=Kann den Schutz auf Blöcken in der Welt umgehen
Can ban and unban players=Kann Spieler verbannen und entbannen
Can kick players=Kann Spieler hinauswerfen
Can use /give and /giveme=Kann /give und /giveme benutzen
Can use /setpassword and /clearpassword=Kann /setpassword und /clearpassword benutzen
Can use fly mode=Kann den Flugmodus benutzen
Can use fast mode=Kann den Schnellmodus benutzen
Can fly through solid nodes using noclip mode=Kann durch feste Blöcke mit dem Geistmodus fliegen
Can use the rollback functionality=Kann die Rollback-Funktionalität benutzen
Can view more debug info that might give a gameplay advantage=Kann zusätzliche Debuginformationen betrachten, welche einen spielerischen Vorteil geben könnten
Can enable wireframe=Kann Drahtmodell aktivieren
Unknown Item=Unbekannter Gegenstand
Air=Luft
Ignore=Ignorieren
You can't place 'ignore' nodes!=Sie können keine „ignore“-Blöcke platzieren!
Values below show absolute/relative times spend per server step by the instrumented function.=Die unten angegebenen Werte zeigen absolute/relative Zeitspannen, die je Server-Step von der instrumentierten Funktion in Anspruch genommen wurden.
A total of @1 sample(s) were taken.=Es wurden insgesamt @1 Datenpunkt(e) aufgezeichnet.
The output is limited to '@1'.=Die Ausgabe ist beschränkt auf „@1“.
Saving of profile failed: @1=Speichern des Profils fehlgeschlagen: @1
Profile saved to @1=Profil abgespeichert nach @1

View File

@@ -0,0 +1,258 @@
# textdomain: __builtin
Empty command.=Comando vuoto.
Invalid command: @1=Comando non valido: @1
Invalid command usage.=Utilizzo del comando non valido.
(@1 s)=
Command execution took @1 s=
You don't have permission to run this command (missing privileges: @1).=Non hai il permesso di eseguire questo comando (privilegi mancanti: @1).
Unable to get position of player @1.=Impossibile ottenere la posizione del giocatore @1.
Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Formato dell'area non corretto. Richiesto: (x1,y1,z1) (x2,y2,z2)
<action>=<azione>
Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Mostra un'azione in chat (es. `/me ordina una pizza` mostra `<nome giocatore> ordina una pizza`)
Show the name of the server owner=Mostra il nome del proprietario del server
The administrator of this server is @1.=L'amministratore di questo server è @1.
There's no administrator named in the config file.=Non c'è nessun amministratore nel file di configurazione.
@1 does not have any privileges.=
Privileges of @1: @2=Privilegi di @1: @2
[<name>]=[<nome>]
Show privileges of yourself or another player=Mostra i privilegi propri o di un altro giocatore
Player @1 does not exist.=Il giocatore @1 non esiste.
<privilege>=<privilegio>
Return list of all online players with privilege=Ritorna una lista di tutti i giocatori connessi col tale privilegio
Invalid parameters (see /help haspriv).=Parametri non validi (vedi /help haspriv).
Unknown privilege!=Privilegio sconosciuto!
No online player has the "@1" privilege.=
Players online with the "@1" privilege: @2=Giocatori connessi con il privilegio "@1": @2
Your privileges are insufficient.=I tuoi privilegi sono insufficienti.
Your privileges are insufficient. '@1' only allows you to grant: @2=
Unknown privilege: @1=Privilegio sconosciuto: @1
@1 granted you privileges: @2=@1 ti ha assegnato i seguenti privilegi: @2
<name> (<privilege> [, <privilege2> [<...>]] | all)=
Give privileges to player=Dà privilegi al giocatore
Invalid parameters (see /help grant).=Parametri non validi (vedi /help grant).
<privilege> [, <privilege2> [<...>]] | all=
Grant privileges to yourself=Assegna dei privilegi a te stessǝ
Invalid parameters (see /help grantme).=Parametri non validi (vedi /help grantme).
Your privileges are insufficient. '@1' only allows you to revoke: @2=
Note: Cannot revoke in singleplayer: @1=
Note: Cannot revoke from admin: @1=
No privileges were revoked.=
@1 revoked privileges from you: @2=@1 ti ha revocato i seguenti privilegi: @2
Remove privileges from player=Rimuove privilegi dal giocatore
Invalid parameters (see /help revoke).=Parametri non validi (vedi /help revoke).
Revoke privileges from yourself=Revoca privilegi a te stessǝ
Invalid parameters (see /help revokeme).=Parametri non validi (vedi /help revokeme).
<name> <password>=<nome> <password>
Set player's password=Imposta la password del giocatore
Name field required.=Campo "nome" richiesto.
Your password was cleared by @1.=La tua password è stata resettata da @1.
Password of player "@1" cleared.=Password del giocatore "@1" resettata.
Your password was set by @1.=La tua password è stata impostata da @1.
Password of player "@1" set.=Password del giocatore "@1" impostata.
<name>=<nome>
Set empty password for a player=Imposta una password vuota a un giocatore
Reload authentication data=Ricarica i dati d'autenticazione
Done.=Fatto.
Failed.=Errore.
Remove a player's data=Rimuove i dati di un giocatore
Player "@1" removed.=Giocatore "@1" rimosso.
No such player "@1" to remove.=Non è presente nessun giocatore "@1" da rimuovere.
Player "@1" is connected, cannot remove.=Il giocatore "@1" è connesso, non può essere rimosso.
Unhandled remove_player return code @1.=Codice ritornato da remove_player non gestito (@1).
Cannot teleport out of map bounds!=Non ci si può teletrasportare fuori dai limiti della mappa!
Cannot get player with name @1.=Impossibile trovare il giocatore chiamato @1.
Cannot teleport, @1 is attached to an object!=Impossibile teletrasportare, @1 è attaccato a un oggetto!
Teleporting @1 to @2.=Teletrasportando @1 da @2.
One does not teleport to oneself.=Non ci si può teletrasportare su se stessi.
Cannot get teleportee with name @1.=Impossibile trovare il giocatore chiamato @1 per il teletrasporto
Cannot get target player with name @1.=Impossibile trovare il giocatore chiamato @1 per il teletrasporto
Teleporting @1 to @2 at @3.=Teletrasportando @1 da @2 a @3
<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>,<Y>,<Z> | <da_nome> | <nome> <X>,<Y>,<Z> | <nome> <da_nome>
Teleport to position or player=Teletrasporta a una posizione o da un giocatore
You don't have permission to teleport other players (missing privilege: @1).=Non hai il permesso di teletrasportare altri giocatori (privilegio mancante: @1).
([-n] <name> <value>) | <name>=([-n] <nome> <valore>) | <nome>
Set or read server configuration setting=Imposta o ottieni le configurazioni del server
Failed. Use '/set -n <name> <value>' to create a new setting.=Errore. Usa 'set -n <nome> <valore>' per creare una nuova impostazione
@1 @= @2=@1 @= @2
<not set>=<non impostato>
Invalid parameters (see /help set).=Parametri non validi (vedi /help set).
Finished emerging @1 blocks in @2ms.=Finito di emergere @1 blocchi in @2ms
emergeblocks update: @1/@2 blocks emerged (@3%)=aggiornamento emergeblocks: @1/@2 blocchi emersi (@3%)
(here [<radius>]) | (<pos1> <pos2>)=(here [<raggio>]) | (<pos1> <pos2>)
Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Carica (o, se non esiste, genera) blocchi mappa contenuti nell'area tra pos1 e pos2 (<pos1> e <pos2> vanno tra parentesi)
Started emerge of area ranging from @1 to @2.=Iniziata emersione dell'area tra @1 e @2.
Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Cancella i blocchi mappa contenuti nell'area tra pos1 e pos2 (<pos1> e <pos2> vanno tra parentesi)
Successfully cleared area ranging from @1 to @2.=Area tra @1 e @2 ripulita con successo.
Failed to clear one or more blocks in area.=Errore nel ripulire uno o più blocchi mappa nell'area
Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Reimposta l'illuminazione nell'area tra pos1 e po2 (<pos1> e <pos2> vanno tra parentesi)
Successfully reset light in the area ranging from @1 to @2.=Luce nell'area tra @1 e @2 reimpostata con successo.
Failed to load one or more blocks in area.=Errore nel caricare uno o più blocchi mappa nell'area.
List mods installed on the server=Elenca le mod installate nel server
No mods installed.=
Cannot give an empty item.=Impossibile dare un oggetto vuoto.
Cannot give an unknown item.=Impossibile dare un oggetto sconosciuto.
Giving 'ignore' is not allowed.=Non è permesso dare 'ignore'.
@1 is not a known player.=@1 non è un giocatore conosciuto.
@1 partially added to inventory.=@1 parzialmente aggiunto all'inventario.
@1 could not be added to inventory.=@1 non può essere aggiunto all'inventario.
@1 added to inventory.=@1 aggiunto all'inventario.
@1 partially added to inventory of @2.=@1 parzialmente aggiunto all'inventario di @2.
@1 could not be added to inventory of @2.=Non è stato possibile aggiungere @1 all'inventario di @2.
@1 added to inventory of @2.=@1 aggiunto all'inventario di @2.
<name> <ItemString> [<count> [<wear>]]=<nome> <NomeOggetto> [<quantità> [<usura>]]
Give item to player=Dà oggetti ai giocatori
Name and ItemString required.=Richiesti nome e NomeOggetto.
<ItemString> [<count> [<wear>]]=<NomeOggetto> [<quantità> [<usura>]]
Give item to yourself=Dà oggetti a te stessǝ
ItemString required.=Richiesto NomeOggetto.
<EntityName> [<X>,<Y>,<Z>]=<NomeEntità> [<X>,<Y>,<Z>]
Spawn entity at given (or your) position=Genera un'entità alla data coordinata (o la tua)
EntityName required.=Richiesto NomeEntità
Unable to spawn entity, player is nil.=Impossibile generare l'entità, il giocatore è nil.
Cannot spawn an unknown entity.=Impossibile generare un'entità sconosciuta.
Invalid parameters (@1).=Parametri non validi (@1).
@1 spawned.=Generata entità @1.
@1 failed to spawn.=Errore nel generare @1
Destroy item in hand=Distrugge l'oggetto in mano
Unable to pulverize, no player.=Impossibile polverizzare, nessun giocatore.
Unable to pulverize, no item in hand.=Impossibile polverizzare, nessun oggetto in mano.
An item was pulverized.=Un oggetto è stato polverizzato.
[<range>] [<seconds>] [<limit>]=[<raggio>] [<secondi>] [<limite>]
Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Controlla chi è l'ultimo giocatore che ha toccato un nodo o un nodo nelle sue vicinanze, negli ultimi secondi indicati. Di base: raggio @= 0, secondi @= 86400 @= 24h, limite @= 5.
Rollback functions are disabled.=Le funzioni di rollback sono disabilitate.
That limit is too high!=Il limite è troppo alto!
Checking @1 ...=Controllando @1 ...
Nobody has touched the specified location in @1 seconds.=Nessuno ha toccato il punto specificato negli ultimi @1 secondi.
@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 @5 secondi fa.
Punch a node (range@=@1, seconds@=@2, limit@=@3).=Colpisce un nodo (raggio@=@1, secondi@=@2, limite@=@3)
(<name> [<seconds>]) | (:<actor> [<seconds>])=(<nome> [<secondi>]) | (:<attore> [<secondi>])
Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Riavvolge le azioni di un giocatore. Di base, <secondi> è 60. Imposta <secondi> a inf per nessun limite di tempo
Invalid parameters. See /help rollback and /help rollback_check.=Parametri non validi. Vedi /help rollback e /help rollback_check.
Reverting actions of player '@1' since @2 seconds.=Riavvolge le azioni del giocatore '@1' avvenute negli ultimi @2 secondi.
Reverting actions of @1 since @2 seconds.=Riavvolge le azioni di @1 avvenute negli ultimi @2 secondi.
(log is too long to show)=(il log è troppo lungo per essere mostrato)
Reverting actions succeeded.=Riavvolgimento azioni avvenuto con successo.
Reverting actions FAILED.=Errore nel riavvolgere le azioni.
Show server status=Mostra lo stato del server
This command was disabled by a mod or game.=Questo comando è stato disabilitato da una mod o dal gioco.
[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0..24000>]
Show or set time of day=Mostra o imposta l'orario della giornata
Current time is @1:@2.=Orario corrente: @1:@2.
You don't have permission to run this command (missing privilege: @1).=Non hai il permesso di eseguire questo comando (privilegio mancante: @1)
Invalid time (must be between 0 and 24000).=
Time of day changed.=Orario della giornata cambiato.
Invalid hour (must be between 0 and 23 inclusive).=Ora non valida (deve essere tra 0 e 23 inclusi)
Invalid minute (must be between 0 and 59 inclusive).=Minuto non valido (deve essere tra 0 e 59 inclusi)
Show day count since world creation=Mostra il conteggio dei giorni da quando il mondo è stato creato
Current day is @1.=Giorno attuale: @1.
[<delay_in_seconds> | -1] [-r] [<message>]=
Shutdown server (-1 cancels a delayed shutdown, -r allows players to reconnect)=
Server shutting down (operator request).=Arresto del server in corso (per richiesta dell'operatore)
Ban the IP of a player or show the ban list=Bandisce l'IP del giocatore o mostra la lista di quelli banditi
The ban list is empty.=La lista banditi è vuota.
Ban list: @1=Lista banditi: @1
Player is not online.=Il giocatore non è connesso.
Failed to ban player.=Errore nel bandire il giocatore.
Banned @1.=@1 banditǝ.
<name> | <IP_address>=<nome> | <indirizzo_IP>
Remove IP ban belonging to a player/IP=Perdona l'IP appartenente a un giocatore/IP
Failed to unban player/IP.=Errore nel perdonare il giocatore/IP
Unbanned @1.=@1 perdonatǝ
<name> [<reason>]=<nome> [<ragione>]
Kick a player=Caccia un giocatore
Failed to kick player @1.=Errore nel cacciare il giocatore @1.
Kicked @1.=@1 cacciatǝ.
[full | quick]=[full | quick]
Clear all objects in world=Elimina tutti gli oggetti/entità nel mondo
Invalid usage, see /help clearobjects.=Uso incorretto, vedi /help clearobjects.
Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Eliminando tutti gli oggetti/entità. Questo potrebbe richiedere molto tempo e farti eventualmente crashare. (di @1)
Cleared all objects.=Tutti gli oggetti sono stati eliminati.
<name> <message>=<nome> <messaggio>
Send a direct message to a player=Invia un messaggio privato al giocatore
Invalid usage, see /help msg.=Uso incorretto, vedi /help msg
The player @1 is not online.=Il giocatore @1 non è connesso.
DM from @1: @2=Messaggio privato da @1: @2
Message sent.=Messaggio inviato.
Get the last login time of a player or yourself=Ritorna l'ultimo accesso di un giocatore o di te stessǝ
@1's last login time was @2.=L'ultimo accesso di @1 è avvenuto il @2
@1's last login time is unknown.=L'ultimo accesso di @1 non è conosciuto
Clear the inventory of yourself or another player=Svuota l'inventario tuo o di un altro giocatore
You don't have permission to clear another player's inventory (missing privilege: @1).=Non hai il permesso di svuotare l'inventario di un altro giocatore (privilegio mancante: @1).
@1 cleared your inventory.=@1 ha svuotato il tuo inventario.
Cleared @1's inventory.=L'inventario di @1 è stato svuotato.
Player must be online to clear inventory!=Il giocatore deve essere connesso per svuotarne l'inventario!
Players can't be killed, damage has been disabled.=I giocatori non possono essere uccisi, il danno è disabilitato.
Player @1 is not online.=Il giocatore @1 non è connesso.
You are already dead.=Sei già mortǝ.
@1 is already dead.=@1 è già mortǝ.
@1 has been killed.=@1 è stato uccisǝ.
Kill player or yourself=Uccide un giocatore o te stessǝ
Invalid parameters (see /help @1).=
Too many arguments, try using just /help <command>=
Available commands: @1=Comandi disponibili: @1
Use '/help <cmd>' to get more information, or '/help all' to list everything.=Usa '/help <comando>' per ottenere più informazioni, o '/help all' per elencare tutti i comandi.
Available commands:=Comandi disponibili:
Command not available: @1=Comando non disponibile: @1
[all | privs | <cmd>] [-t]=
Get help for commands or list privileges (-t: output in chat)=
Available privileges:=Privilegi disponibili:
Command=Comando
Parameters=Parametri
For more information, click on any entry in the list.=Per più informazioni, clicca su una qualsiasi voce dell'elenco.
Double-click to copy the entry to the chat history.=Doppio click per copiare la voce nella cronologia della chat.
Command: @1 @2=Comando: @1 @2
Available commands: (see also: /help <cmd>)=Comandi disponibili: (vedi anche /help <comando>)
Close=Chiudi
Privilege=Privilegio
Description=Descrizione
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtro>] | dump [<filtro>] | save [<formato> [<filtro>]] | reset
Handle the profiler and profiling data=Gestisce il profiler e i dati da esso elaborati
Statistics written to action log.=Statistiche scritte nel log delle azioni.
Statistics were reset.=Le statistiche sono state resettate.
Usage: @1=Utilizzo: @1
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=I formati supportati sono txt, csv, lua, json e json_pretty (le strutture potrebbero essere soggetti a cambiamenti).
@1 joined the game.=
@1 left the game.=
@1 left the game (timed out).=
(no description)=(nessuna descrizione)
Can interact with things and modify the world=Si può interagire con le cose e modificare il mondo
Can speak in chat=Si può parlare in chat
Can modify basic privileges (@1)=
Can modify privileges=Si possono modificare i privilegi
Can teleport self=Si può teletrasportare se stessз
Can teleport other players=Si possono teletrasportare gli altri giocatori
Can set the time of day using /time=Si può impostate l'orario della giornata tramite /time
Can do server maintenance stuff=Si possono eseguire operazioni di manutenzione del server
Can bypass node protection in the world=Si può aggirare la protezione dei nodi nel mondo
Can ban and unban players=Si possono bandire e perdonare i giocatori
Can kick players=Si possono cacciare i giocatori
Can use /give and /giveme=Si possono usare /give e /give me
Can use /setpassword and /clearpassword=Si possono usare /setpassword e /clearpassword
Can use fly mode=Si può usare la modalità volo
Can use fast mode=Si può usare la modalità rapida
Can fly through solid nodes using noclip mode=Si può volare attraverso i nodi solidi con la modalità incorporea
Can use the rollback functionality=Si può usare la funzione di rollback
Can view more debug info that might give a gameplay advantage=
Can enable wireframe=
Unknown Item=Oggetto sconosciuto
Air=Aria
Ignore=Ignora
You can't place 'ignore' nodes!=Non puoi piazzare nodi 'ignore'!
Values below show absolute/relative times spend per server step by the instrumented function.=
A total of @1 sample(s) were taken.=
The output is limited to '@1'.=
Saving of profile failed: @1=
Profile saved to @1=
##### not used anymore #####
Invalid time.=Orario non valido.
[all | privs | <cmd>]=[all | privs | <comando>]
Get help for commands or list privileges=Richiama la finestra d'aiuto dei comandi o dei privilegi
Allows enabling various debug options that may affect gameplay=Permette di abilitare varie opzioni di debug che potrebbero influenzare l'esperienza di gioco
[<delay_in_seconds> | -1] [reconnect] [<message>]=[<ritardo_in_secondi> | -1] [reconnect] [<messaggio>]
Shutdown server (-1 cancels a delayed shutdown)=Arresta il server (-1 annulla un arresto programmato)
<name> (<privilege> | all)=<nome> (<privilegio> | all)
<privilege> | all=<privilegio> | all
Can modify 'shout' and 'interact' privileges=Si possono modificare i privilegi 'shout' e 'interact'

245
builtin/locale/template.txt Normal file
View File

@@ -0,0 +1,245 @@
# textdomain: __builtin
Empty command.=
Invalid command: @1=
Invalid command usage.=
(@1 s)=
Command execution took @1 s=
You don't have permission to run this command (missing privileges: @1).=
Unable to get position of player @1.=
Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=
<action>=
Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=
Show the name of the server owner=
The administrator of this server is @1.=
There's no administrator named in the config file.=
@1 does not have any privileges.=
Privileges of @1: @2=
[<name>]=
Show privileges of yourself or another player=
Player @1 does not exist.=
<privilege>=
Return list of all online players with privilege=
Invalid parameters (see /help haspriv).=
Unknown privilege!=
No online player has the "@1" privilege.=
Players online with the "@1" privilege: @2=
Your privileges are insufficient.=
Your privileges are insufficient. '@1' only allows you to grant: @2=
Unknown privilege: @1=
@1 granted you privileges: @2=
<name> (<privilege> [, <privilege2> [<...>]] | all)=
Give privileges to player=
Invalid parameters (see /help grant).=
<privilege> [, <privilege2> [<...>]] | all=
Grant privileges to yourself=
Invalid parameters (see /help grantme).=
Your privileges are insufficient. '@1' only allows you to revoke: @2=
Note: Cannot revoke in singleplayer: @1=
Note: Cannot revoke from admin: @1=
No privileges were revoked.=
@1 revoked privileges from you: @2=
Remove privileges from player=
Invalid parameters (see /help revoke).=
Revoke privileges from yourself=
Invalid parameters (see /help revokeme).=
<name> <password>=
Set player's password=
Name field required.=
Your password was cleared by @1.=
Password of player "@1" cleared.=
Your password was set by @1.=
Password of player "@1" set.=
<name>=
Set empty password for a player=
Reload authentication data=
Done.=
Failed.=
Remove a player's data=
Player "@1" removed.=
No such player "@1" to remove.=
Player "@1" is connected, cannot remove.=
Unhandled remove_player return code @1.=
Cannot teleport out of map bounds!=
Cannot get player with name @1.=
Cannot teleport, @1 is attached to an object!=
Teleporting @1 to @2.=
One does not teleport to oneself.=
Cannot get teleportee with name @1.=
Cannot get target player with name @1.=
Teleporting @1 to @2 at @3.=
<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=
Teleport to position or player=
You don't have permission to teleport other players (missing privilege: @1).=
([-n] <name> <value>) | <name>=
Set or read server configuration setting=
Failed. Use '/set -n <name> <value>' to create a new setting.=
@1 @= @2=
<not set>=
Invalid parameters (see /help set).=
Finished emerging @1 blocks in @2ms.=
emergeblocks update: @1/@2 blocks emerged (@3%)=
(here [<radius>]) | (<pos1> <pos2>)=
Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=
Started emerge of area ranging from @1 to @2.=
Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=
Successfully cleared area ranging from @1 to @2.=
Failed to clear one or more blocks in area.=
Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=
Successfully reset light in the area ranging from @1 to @2.=
Failed to load one or more blocks in area.=
List mods installed on the server=
No mods installed.=
Cannot give an empty item.=
Cannot give an unknown item.=
Giving 'ignore' is not allowed.=
@1 is not a known player.=
@1 partially added to inventory.=
@1 could not be added to inventory.=
@1 added to inventory.=
@1 partially added to inventory of @2.=
@1 could not be added to inventory of @2.=
@1 added to inventory of @2.=
<name> <ItemString> [<count> [<wear>]]=
Give item to player=
Name and ItemString required.=
<ItemString> [<count> [<wear>]]=
Give item to yourself=
ItemString required.=
<EntityName> [<X>,<Y>,<Z>]=
Spawn entity at given (or your) position=
EntityName required.=
Unable to spawn entity, player is nil.=
Cannot spawn an unknown entity.=
Invalid parameters (@1).=
@1 spawned.=
@1 failed to spawn.=
Destroy item in hand=
Unable to pulverize, no player.=
Unable to pulverize, no item in hand.=
An item was pulverized.=
[<range>] [<seconds>] [<limit>]=
Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=
Rollback functions are disabled.=
That limit is too high!=
Checking @1 ...=
Nobody has touched the specified location in @1 seconds.=
@1 @2 @3 -> @4 @5 seconds ago.=
Punch a node (range@=@1, seconds@=@2, limit@=@3).=
(<name> [<seconds>]) | (:<actor> [<seconds>])=
Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=
Invalid parameters. See /help rollback and /help rollback_check.=
Reverting actions of player '@1' since @2 seconds.=
Reverting actions of @1 since @2 seconds.=
(log is too long to show)=
Reverting actions succeeded.=
Reverting actions FAILED.=
Show server status=
This command was disabled by a mod or game.=
[<0..23>:<0..59> | <0..24000>]=
Show or set time of day=
Current time is @1:@2.=
You don't have permission to run this command (missing privilege: @1).=
Invalid time (must be between 0 and 24000).=
Time of day changed.=
Invalid hour (must be between 0 and 23 inclusive).=
Invalid minute (must be between 0 and 59 inclusive).=
Show day count since world creation=
Current day is @1.=
[<delay_in_seconds> | -1] [-r] [<message>]=
Shutdown server (-1 cancels a delayed shutdown, -r allows players to reconnect)=
Server shutting down (operator request).=
Ban the IP of a player or show the ban list=
The ban list is empty.=
Ban list: @1=
Player is not online.=
Failed to ban player.=
Banned @1.=
<name> | <IP_address>=
Remove IP ban belonging to a player/IP=
Failed to unban player/IP.=
Unbanned @1.=
<name> [<reason>]=
Kick a player=
Failed to kick player @1.=
Kicked @1.=
[full | quick]=
Clear all objects in world=
Invalid usage, see /help clearobjects.=
Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=
Cleared all objects.=
<name> <message>=
Send a direct message to a player=
Invalid usage, see /help msg.=
The player @1 is not online.=
DM from @1: @2=
Message sent.=
Get the last login time of a player or yourself=
@1's last login time was @2.=
@1's last login time is unknown.=
Clear the inventory of yourself or another player=
You don't have permission to clear another player's inventory (missing privilege: @1).=
@1 cleared your inventory.=
Cleared @1's inventory.=
Player must be online to clear inventory!=
Players can't be killed, damage has been disabled.=
Player @1 is not online.=
You are already dead.=
@1 is already dead.=
@1 has been killed.=
Kill player or yourself=
Invalid parameters (see /help @1).=
Too many arguments, try using just /help <command>=
Available commands: @1=
Use '/help <cmd>' to get more information, or '/help all' to list everything.=
Available commands:=
Command not available: @1=
[all | privs | <cmd>] [-t]=
Get help for commands or list privileges (-t: output in chat)=
Available privileges:=
Command=
Parameters=
For more information, click on any entry in the list.=
Double-click to copy the entry to the chat history.=
Command: @1 @2=
Available commands: (see also: /help <cmd>)=
Close=
Privilege=
Description=
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=
Handle the profiler and profiling data=
Statistics written to action log.=
Statistics were reset.=
Usage: @1=
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=
@1 joined the game.=
@1 left the game.=
@1 left the game (timed out).=
(no description)=
Can interact with things and modify the world=
Can speak in chat=
Can modify basic privileges (@1)=
Can modify privileges=
Can teleport self=
Can teleport other players=
Can set the time of day using /time=
Can do server maintenance stuff=
Can bypass node protection in the world=
Can ban and unban players=
Can kick players=
Can use /give and /giveme=
Can use /setpassword and /clearpassword=
Can use fly mode=
Can use fast mode=
Can fly through solid nodes using noclip mode=
Can use the rollback functionality=
Can view more debug info that might give a gameplay advantage=
Can enable wireframe=
Unknown Item=
Air=
Ignore=
You can't place 'ignore' nodes!=
Values below show absolute/relative times spend per server step by the instrumented function.=
A total of @1 sample(s) were taken.=
The output is limited to '@1'.=
Saving of profile failed: @1=
Profile saved to @1=

View File

@@ -14,14 +14,11 @@
--You should have received a copy of the GNU Lesser General Public License along
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
-- Global menu data
--------------------------------------------------------------------------------
menudata = {}
--------------------------------------------------------------------------------
-- Local cached values
--------------------------------------------------------------------------------
local min_supp_proto, max_supp_proto
function common_update_cached_supp_proto()
@@ -29,14 +26,12 @@ function common_update_cached_supp_proto()
max_supp_proto = core.get_max_supp_proto()
end
common_update_cached_supp_proto()
--------------------------------------------------------------------------------
-- Menu helper functions
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Menu helper functions
local function render_client_count(n)
if n > 99 then return '99+'
elseif n >= 0 then return tostring(n)
if n > 999 then return '99+'
elseif n >= 0 then return tostring(n)
else return '?' end
end
@@ -50,21 +45,7 @@ local function configure_selected_world_params(idx)
end
end
--------------------------------------------------------------------------------
function image_column(tooltip, flagname)
return "image,tooltip=" .. core.formspec_escape(tooltip) .. "," ..
"0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," ..
"1=" .. core.formspec_escape(defaulttexturedir ..
(flagname and "server_flags_" .. flagname .. ".png" or "blank.png")) .. "," ..
"2=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," ..
"3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," ..
"4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," ..
"5=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png")
end
--------------------------------------------------------------------------------
function render_serverlist_row(spec, is_favorite)
function render_serverlist_row(spec)
local text = ""
if spec.name then
text = text .. core.formspec_escape(spec.name:trim())
@@ -75,31 +56,29 @@ function render_serverlist_row(spec, is_favorite)
end
end
local grey_out = not is_server_protocol_compat(spec.proto_min, spec.proto_max)
local grey_out = not spec.is_compatible
local details
if is_favorite then
details = "1,"
else
details = "0,"
end
local details = {}
if spec.ping then
local ping = spec.ping * 1000
if ping <= 50 then
details = details .. "2,"
elseif ping <= 100 then
details = details .. "3,"
elseif ping <= 250 then
details = details .. "4,"
if spec.lag or spec.ping then
local lag = (spec.lag or 0) * 1000 + (spec.ping or 0) * 250
if lag <= 125 then
table.insert(details, "1")
elseif lag <= 175 then
table.insert(details, "2")
elseif lag <= 250 then
table.insert(details, "3")
else
details = details .. "5,"
table.insert(details, "4")
end
else
details = details .. "0,"
table.insert(details, "0")
end
if spec.clients and spec.clients_max then
table.insert(details, ",")
local color = (grey_out and "#aaaaaa") or ((spec.is_favorite and "#ddddaa") or "#ffffff")
if spec.clients and (spec.clients_max or 0) > 0 then
local clients_percent = 100 * spec.clients / spec.clients_max
-- Choose a color depending on how many clients are connected
@@ -110,68 +89,59 @@ function render_serverlist_row(spec, is_favorite)
elseif clients_percent <= 60 then clients_color = '#a1e587' -- 0-60%: green
elseif clients_percent <= 90 then clients_color = '#ffdc97' -- 60-90%: yellow
elseif clients_percent == 100 then clients_color = '#dd5b5b' -- full server: red (darker)
else clients_color = '#ffba97' -- 90-100%: orange
else clients_color = '#ffba97' -- 90-100%: orange
end
details = details .. clients_color .. ',' ..
render_client_count(spec.clients) .. ',/,' ..
render_client_count(spec.clients_max) .. ','
elseif grey_out then
details = details .. '#aaaaaa,?,/,?,'
table.insert(details, clients_color)
table.insert(details, render_client_count(spec.clients) .. " / " ..
render_client_count(spec.clients_max))
else
details = details .. ',?,/,?,'
table.insert(details, color)
table.insert(details, "?")
end
if spec.creative then
details = details .. "1,"
table.insert(details, "1") -- creative icon
else
details = details .. "0,"
end
if spec.damage then
details = details .. "1,"
else
details = details .. "0,"
table.insert(details, "0")
end
if spec.pvp then
details = details .. "1,"
table.insert(details, "2") -- pvp icon
elseif spec.damage then
table.insert(details, "1") -- heart icon
else
details = details .. "0,"
table.insert(details, "0")
end
return details .. (grey_out and '#aaaaaa,' or ',') .. text
end
table.insert(details, color)
table.insert(details, text)
--------------------------------------------------------------------------------
os.tempfolder = function()
local temp = core.get_temp_path()
return temp .. DIR_DELIM .. "MT_" .. math.random(0, 10000)
return table.concat(details, ",")
end
--------------------------------------------------------------------------------
---------------------------------------------------------------------------------
os.tmpname = function()
local path = os.tempfolder()
io.open(path, "w"):close()
return path
error('do not use') -- instead use core.get_temp_path()
end
--------------------------------------------------------------------------------
function menu_render_worldlist()
local retval = ""
function menu_render_worldlist(show_gameid)
local retval = {}
local current_worldlist = menudata.worldlist:get_list()
local row
for i, v in ipairs(current_worldlist) do
if retval ~= "" then retval = retval .. "," end
retval = retval .. core.formspec_escape(v.name) ..
" \\[" .. core.formspec_escape(v.gameid) .. "\\]"
row = v.name
if show_gameid == nil or show_gameid == true then
row = row .. " [" .. v.gameid .. "]"
end
retval[#retval+1] = core.formspec_escape(row)
end
return retval
return table.concat(retval, ",")
end
--------------------------------------------------------------------------------
function menu_handle_key_up_down(fields, textlist, settingname)
local oldidx, newidx = core.get_textlist_index(textlist), 1
if fields.key_up or fields.key_down then
@@ -188,7 +158,6 @@ function menu_handle_key_up_down(fields, textlist, settingname)
return false
end
--------------------------------------------------------------------------------
function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency)
local textlines = core.wrap_text(text, textlen, true)
local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width ..
@@ -206,7 +175,6 @@ function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transp
return retval
end
--------------------------------------------------------------------------------
function is_server_protocol_compat(server_proto_min, server_proto_max)
if (not server_proto_min) or (not server_proto_max) then
-- There is no info. Assume the best and act as if we would be compatible.
@@ -214,7 +182,7 @@ function is_server_protocol_compat(server_proto_min, server_proto_max)
end
return min_supp_proto <= server_proto_max and max_supp_proto >= server_proto_min
end
--------------------------------------------------------------------------------
function is_server_protocol_compat_or_error(server_proto_min, server_proto_max)
if not is_server_protocol_compat(server_proto_min, server_proto_max) then
local server_prot_ver_info, client_prot_ver_info
@@ -242,7 +210,7 @@ function is_server_protocol_compat_or_error(server_proto_min, server_proto_max)
return true
end
--------------------------------------------------------------------------------
function menu_worldmt(selected, setting, value)
local world = menudata.worldlist:get_list()[selected]
if world then

View File

@@ -25,7 +25,7 @@ end
-- Unordered preserves the original order of the ContentDB API,
-- before the package list is ordered based on installed state.
local store = { packages = {}, packages_full = {}, packages_full_unordered = {} }
local store = { packages = {}, packages_full = {}, packages_full_unordered = {}, aliases = {} }
local http = core.get_http_api()
@@ -57,34 +57,77 @@ local filter_types_type = {
"txp",
}
local REASON_NEW = "new"
local REASON_UPDATE = "update"
local REASON_DEPENDENCY = "dependency"
local function download_package(param)
if core.download_file(param.package.url, param.filename) then
return {
filename = param.filename,
successful = true,
}
else
core.log("error", "downloading " .. dump(param.package.url) .. " failed")
return {
successful = false,
}
-- encodes for use as URL parameter or path component
local function urlencode(str)
return str:gsub("[^%a%d()._~-]", function(char)
return string.format("%%%02X", string.byte(char))
end)
end
assert(urlencode("sample text?") == "sample%20text%3F")
local function get_download_url(package, reason)
local base_url = core.settings:get("contentdb_url")
local ret = base_url .. ("/packages/%s/releases/%d/download/"):format(
package.url_part, package.release)
if reason then
ret = ret .. "?reason=" .. reason
end
return ret
end
local function start_install(package)
local function download_and_extract(param)
local package = param.package
local filename = core.get_temp_path(true)
if filename == "" or not core.download_file(param.url, filename) then
core.log("error", "Downloading " .. dump(param.url) .. " failed")
return {
msg = fgettext("Failed to download $1", package.name)
}
end
local tempfolder = core.get_temp_path()
if tempfolder ~= "" then
tempfolder = tempfolder .. DIR_DELIM .. "MT_" .. math.random(1, 1024000)
if not core.extract_zip(filename, tempfolder) then
tempfolder = nil
end
else
tempfolder = nil
end
os.remove(filename)
if not tempfolder then
return {
msg = fgettext("Install: Unsupported file type or broken archive"),
}
end
return {
path = tempfolder
}
end
local function start_install(package, reason)
local params = {
package = package,
filename = os.tempfolder() .. "_MODNAME_" .. package.name .. ".zip",
url = get_download_url(package, reason),
}
number_downloading = number_downloading + 1
local function callback(result)
if result.successful then
local path, msg = pkgmgr.install(package.type,
result.filename, package.name,
package.path)
if result.msg then
gamedata.errormessage = result.msg
else
local path, msg = pkgmgr.install_dir(package.type, result.path, package.name, package.path)
core.delete_dir(result.path)
if not path then
gamedata.errormessage = msg
else
@@ -122,9 +165,6 @@ local function start_install(package)
conf:write()
end
end
os.remove(result.filename)
else
gamedata.errormessage = fgettext("Failed to download $1", package.name)
end
package.downloading = false
@@ -135,7 +175,7 @@ local function start_install(package)
if next then
table.remove(download_queue, 1)
start_install(next)
start_install(next.package, next.reason)
end
ui.update()
@@ -144,19 +184,19 @@ local function start_install(package)
package.queued = false
package.downloading = true
if not core.handle_async(download_package, params, callback) then
if not core.handle_async(download_and_extract, params, callback) then
core.log("error", "ERROR: async event failed")
gamedata.errormessage = fgettext("Failed to download $1", package.name)
return
end
end
local function queue_download(package)
local function queue_download(package, reason)
local max_concurrent_downloads = tonumber(core.settings:get("contentdb_max_concurrent_downloads"))
if number_downloading < max_concurrent_downloads then
start_install(package)
start_install(package, reason)
else
table.insert(download_queue, package)
table.insert(download_queue, { package = package, reason = reason })
package.queued = true
end
end
@@ -169,7 +209,7 @@ local function get_raw_dependencies(package)
local url_fmt = "/api/packages/%s/dependencies/?only_hard=1&protocol_version=%s&engine_version=%s"
local version = core.get_version()
local base_url = core.settings:get("contentdb_url")
local url = base_url .. url_fmt:format(package.id, core.get_max_supp_proto(), version.string)
local url = base_url .. url_fmt:format(package.url_part, core.get_max_supp_proto(), urlencode(version.string))
local response = http.fetch_sync({ url = url })
if not response.succeeded then
@@ -407,12 +447,12 @@ function install_dialog.handle_submit(this, fields)
end
if fields.install_all then
queue_download(install_dialog.package)
queue_download(install_dialog.package, REASON_NEW)
if install_dialog.will_install_deps then
for _, dep in pairs(install_dialog.dependencies) do
if not dep.is_optional and not dep.installed and dep.package then
queue_download(dep.package)
queue_download(dep.package, REASON_DEPENDENCY)
end
end
end
@@ -544,33 +584,43 @@ function store.load()
local base_url = core.settings:get("contentdb_url")
local url = base_url ..
"/api/packages/?type=mod&type=game&type=txp&protocol_version=" ..
core.get_max_supp_proto() .. "&engine_version=" .. version.string
core.get_max_supp_proto() .. "&engine_version=" .. urlencode(version.string)
for _, item in pairs(core.settings:get("contentdb_flag_blacklist"):split(",")) do
item = item:trim()
if item ~= "" then
url = url .. "&hide=" .. item
url = url .. "&hide=" .. urlencode(item)
end
end
local timeout = tonumber(core.settings:get("curl_file_download_timeout"))
local response = http.fetch_sync({ url = url, timeout = timeout })
local response = http.fetch_sync({ url = url })
if not response.succeeded then
return
end
store.packages_full = core.parse_json(response.data) or {}
store.aliases = {}
for _, package in pairs(store.packages_full) do
package.url = base_url .. "/packages/" ..
package.author .. "/" .. package.name ..
"/releases/" .. package.release .. "/download/"
local name_len = #package.name
-- This must match what store.update_paths() does!
package.id = package.author:lower() .. "/"
if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then
package.id = package.author:lower() .. "/" .. package.name:sub(1, name_len - 5)
package.id = package.id .. package.name:sub(1, name_len - 5)
else
package.id = package.author:lower() .. "/" .. package.name
package.id = package.id .. package.name
end
package.url_part = urlencode(package.author) .. "/" .. urlencode(package.name)
if package.aliases then
for _, alias in ipairs(package.aliases) do
-- We currently don't support name changing
local suffix = "/" .. package.name
if alias:sub(-#suffix) == suffix then
store.aliases[alias:lower()] = package.id
end
end
end
end
@@ -584,7 +634,8 @@ function store.update_paths()
pkgmgr.refresh_globals()
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
if mod.author and mod.release > 0 then
mod_hash[mod.author:lower() .. "/" .. mod.name] = mod
local id = mod.author:lower() .. "/" .. mod.name
mod_hash[store.aliases[id] or id] = mod
end
end
@@ -592,14 +643,16 @@ function store.update_paths()
pkgmgr.update_gamelist()
for _, game in pairs(pkgmgr.games) do
if game.author ~= "" and game.release > 0 then
game_hash[game.author:lower() .. "/" .. game.id] = game
local id = game.author:lower() .. "/" .. game.id
game_hash[store.aliases[id] or id] = game
end
end
local txp_hash = {}
for _, txp in pairs(pkgmgr.get_texture_packs()) do
if txp.author and txp.release > 0 then
txp_hash[txp.author:lower() .. "/" .. txp.name] = txp
local id = txp.author:lower() .. "/" .. txp.name
txp_hash[store.aliases[id] or id] = txp
end
end
@@ -809,8 +862,7 @@ function store.get_formspec(dlgdata)
formspec[#formspec + 1] = "cdb_downloading.png;3;400;]"
elseif package.queued then
formspec[#formspec + 1] = left_base
formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir)
formspec[#formspec + 1] = "cdb_queued.png;queued]"
formspec[#formspec + 1] = "cdb_queued.png;queued;]"
elseif not package.path then
local elem_name = "install_" .. i .. ";"
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#71aa34]"
@@ -915,7 +967,7 @@ function store.handle_submit(this, fields)
local package = store.packages_full[i]
if package.path and package.installed_release < package.release and
not (package.downloading or package.queued) then
queue_download(package)
queue_download(package, REASON_UPDATE)
end
end
return true
@@ -948,7 +1000,7 @@ function store.handle_submit(this, fields)
this:hide()
dlg:show()
else
queue_download(package)
queue_download(package, package.path and REASON_UPDATE or REASON_NEW)
end
end
@@ -973,9 +1025,9 @@ function store.handle_submit(this, fields)
end
if fields["view_" .. i] then
local url = ("%s/packages/%s/%s?protocol_version=%d"):format(
core.settings:get("contentdb_url"),
package.author, package.name, core.get_max_supp_proto())
local url = ("%s/packages/%s?protocol_version=%d"):format(
core.settings:get("contentdb_url"), package.url_part,
core.get_max_supp_proto())
core.open_url(url)
return true
end

View File

@@ -15,7 +15,8 @@
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local worldname = ""
-- cf. tab_local, the gamebar already provides game selection so we hide the list from here
local hide_gamelist = PLATFORM ~= "Android"
local function table_to_flags(ftable)
-- Convert e.g. { jungles = true, caves = false } to "jungles,nocaves"
@@ -31,9 +32,8 @@ local function strflag(flags, flag)
return (flags[flag] == true) and "true" or "false"
end
local cb_caverns = { "caverns", fgettext("Caverns"), "caverns",
local cb_caverns = { "caverns", fgettext("Caverns"),
fgettext("Very large caverns deep in the underground") }
local tt_sea_rivers = fgettext("Sea level rivers")
local flag_checkboxes = {
v5 = {
@@ -41,39 +41,38 @@ local flag_checkboxes = {
},
v7 = {
cb_caverns,
{ "ridges", fgettext("Rivers"), "ridges", tt_sea_rivers },
{ "mountains", fgettext("Mountains"), "mountains" },
{ "floatlands", fgettext("Floatlands (experimental)"), "floatlands",
{ "ridges", fgettext("Rivers"), fgettext("Sea level rivers") },
{ "mountains", fgettext("Mountains") },
{ "floatlands", fgettext("Floatlands (experimental)"),
fgettext("Floating landmasses in the sky") },
},
carpathian = {
cb_caverns,
{ "rivers", fgettext("Rivers"), "rivers", tt_sea_rivers },
{ "rivers", fgettext("Rivers"), fgettext("Sea level rivers") },
},
valleys = {
{ "altitude-chill", fgettext("Altitude chill"), "altitude_chill",
{ "altitude_chill", fgettext("Altitude chill"),
fgettext("Reduces heat with altitude") },
{ "altitude-dry", fgettext("Altitude dry"), "altitude_dry",
{ "altitude_dry", fgettext("Altitude dry"),
fgettext("Reduces humidity with altitude") },
{ "humid-rivers", fgettext("Humid rivers"), "humid_rivers",
{ "humid_rivers", fgettext("Humid rivers"),
fgettext("Increases humidity around rivers") },
{ "vary-river-depth", fgettext("Vary river depth"), "vary_river_depth",
{ "vary_river_depth", fgettext("Vary river depth"),
fgettext("Low humidity and high heat causes shallow or dry rivers") },
},
flat = {
cb_caverns,
{ "hills", fgettext("Hills"), "hills" },
{ "lakes", fgettext("Lakes"), "lakes" },
{ "hills", fgettext("Hills") },
{ "lakes", fgettext("Lakes") },
},
fractal = {
{ "terrain", fgettext("Additional terrain"), "terrain",
{ "terrain", fgettext("Additional terrain"),
fgettext("Generate non-fractal terrain: Oceans and underground") },
},
v6 = {
{ "trees", fgettext("Trees and jungle grass"), "trees" },
{ "flat", fgettext("Flat terrain"), "flat" },
{ "mudflow", fgettext("Mud flow"), "mudflow",
fgettext("Terrain surface erosion") },
{ "trees", fgettext("Trees and jungle grass") },
{ "flat", fgettext("Flat terrain") },
{ "mudflow", fgettext("Mud flow"), fgettext("Terrain surface erosion") },
-- Biome settings are in mgv6_biomes below
},
}
@@ -105,38 +104,26 @@ local function create_world_formspec(dialogdata)
"button[4.75,2.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
end
local current_mg = dialogdata.mg
local mapgens = core.get_mapgen_names()
local current_seed = core.settings:get("fixed_map_seed") or ""
local current_mg = core.settings:get("mg_name")
local gameid = core.settings:get("menu_last_game")
local flags = {
main = core.settings:get_flags("mg_flags"),
v5 = core.settings:get_flags("mgv5_spflags"),
v6 = core.settings:get_flags("mgv6_spflags"),
v7 = core.settings:get_flags("mgv7_spflags"),
fractal = core.settings:get_flags("mgfractal_spflags"),
carpathian = core.settings:get_flags("mgcarpathian_spflags"),
valleys = core.settings:get_flags("mgvalleys_spflags"),
flat = core.settings:get_flags("mgflat_spflags"),
}
local flags = dialogdata.flags
local gameidx = 0
if gameid ~= nil then
local _
_, gameidx = pkgmgr.find_by_gameid(gameid)
if gameidx == nil then
gameidx = 0
end
local game, gameidx = pkgmgr.find_by_gameid(gameid)
if game == nil and hide_gamelist then
-- should never happen but just pick the first game
game = pkgmgr.get_game(1)
gameidx = 1
core.settings:set("menu_last_game", game.id)
elseif game == nil then
gameidx = 0
end
local game_by_gameidx = core.get_game(gameidx)
local disallowed_mapgen_settings = {}
if game_by_gameidx ~= nil then
local gamepath = game_by_gameidx.path
local gameconfig = Settings(gamepath.."/game.conf")
if game ~= nil then
local gameconfig = Settings(game.path.."/game.conf")
local allowed_mapgens = (gameconfig:get("allowed_mapgens") or ""):split()
for key, value in pairs(allowed_mapgens) do
@@ -156,7 +143,7 @@ local function create_world_formspec(dialogdata)
end
end
if disallowed_mapgens then
if #disallowed_mapgens > 0 then
for i = #mapgens, 1, -1 do
if table.indexof(disallowed_mapgens, mapgens[i]) > 0 then
table.remove(mapgens, i)
@@ -172,23 +159,29 @@ local function create_world_formspec(dialogdata)
local mglist = ""
local selindex
local i = 1
local first_mg
for k,v in pairs(mapgens) do
if not first_mg then
first_mg = v
do -- build the list of mapgens
local i = 1
local first_mg
for k, v in pairs(mapgens) do
if not first_mg then
first_mg = v
end
if current_mg == v then
selindex = i
end
i = i + 1
mglist = mglist .. core.formspec_escape(v) .. ","
end
if current_mg == v then
selindex = i
if not selindex then
selindex = 1
current_mg = first_mg
end
i = i + 1
mglist = mglist .. v .. ","
mglist = mglist:sub(1, -2)
end
if not selindex then
selindex = 1
current_mg = first_mg
end
mglist = mglist:sub(1, -2)
-- The logic of the flag element IDs is as follows:
-- "flag_main_foo-bar-baz" controls dialogdata.flags["main"]["foo_bar_baz"]
-- see the buttonhandler for the implementation of this
local mg_main_flags = function(mapgen, y)
if mapgen == "singlenode" then
@@ -198,11 +191,11 @@ local function create_world_formspec(dialogdata)
return "", y
end
local form = "checkbox[0," .. y .. ";flag_mg_caves;" ..
local form = "checkbox[0," .. y .. ";flag_main_caves;" ..
fgettext("Caves") .. ";"..strflag(flags.main, "caves").."]"
y = y + 0.5
form = form .. "checkbox[0,"..y..";flag_mg_dungeons;" ..
form = form .. "checkbox[0,"..y..";flag_main_dungeons;" ..
fgettext("Dungeons") .. ";"..strflag(flags.main, "dungeons").."]"
y = y + 0.5
@@ -213,7 +206,7 @@ local function create_world_formspec(dialogdata)
else
d_tt = fgettext("Structures appearing on the terrain, typically trees and plants")
end
form = form .. "checkbox[0,"..y..";flag_mg_decorations;" ..
form = form .. "checkbox[0,"..y..";flag_main_decorations;" ..
d_name .. ";" ..
strflag(flags.main, "decorations").."]" ..
"tooltip[flag_mg_decorations;" ..
@@ -221,7 +214,7 @@ local function create_world_formspec(dialogdata)
"]"
y = y + 0.5
form = form .. "tooltip[flag_mg_caves;" ..
form = form .. "tooltip[flag_main_caves;" ..
fgettext("Network of tunnels and caves")
.. "]"
return form, y
@@ -235,13 +228,13 @@ local function create_world_formspec(dialogdata)
return "", y
end
local form = ""
for _,tab in pairs(flag_checkboxes[mapgen]) do
local id = "flag_mg"..mapgen.."_"..tab[1]
for _, tab in pairs(flag_checkboxes[mapgen]) do
local id = "flag_"..mapgen.."_"..tab[1]:gsub("_", "-")
form = form .. ("checkbox[0,%f;%s;%s;%s]"):
format(y, id, tab[2], strflag(flags[mapgen], tab[3]))
format(y, id, tab[2], strflag(flags[mapgen], tab[1]))
if tab[4] then
form = form .. "tooltip["..id..";"..tab[4].."]"
if tab[3] then
form = form .. "tooltip["..id..";"..tab[3].."]"
end
y = y + 0.5
end
@@ -277,16 +270,14 @@ local function create_world_formspec(dialogdata)
-- biomeblend
y = y + 0.55
form = form .. "checkbox[0,"..y..";flag_mgv6_biomeblend;" ..
form = form .. "checkbox[0,"..y..";flag_v6_biomeblend;" ..
fgettext("Biome blending") .. ";"..strflag(flags.v6, "biomeblend").."]" ..
"tooltip[flag_mgv6_biomeblend;" ..
"tooltip[flag_v6_biomeblend;" ..
fgettext("Smooth transition between biomes") .. "]"
return form, y
end
current_seed = core.formspec_escape(current_seed)
local y_start = 0.0
local y = y_start
local str_flags, str_spflags
@@ -323,21 +314,27 @@ local function create_world_formspec(dialogdata)
"container[0,0]"..
"field[0.3,0.6;6,0.5;te_world_name;" ..
fgettext("World name") ..
";" .. core.formspec_escape(worldname) .. "]" ..
";" .. core.formspec_escape(dialogdata.worldname) .. "]" ..
"set_focus[te_world_name;false]" ..
"field[0.3,1.7;6,0.5;te_seed;" ..
fgettext("Seed") ..
";".. current_seed .. "]" ..
";".. core.formspec_escape(dialogdata.seed) .. "]" ..
"label[0,2;" .. fgettext("Mapgen") .. "]"..
"dropdown[0,2.5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" ..
"dropdown[0,2.5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]"
"label[0,3.35;" .. fgettext("Game") .. "]"..
"textlist[0,3.85;5.8,"..gamelist_height..";games;" ..
pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" ..
"container[0,4.5]" ..
devtest_only ..
"container_end[]" ..
if not hide_gamelist or devtest_only ~= "" then
retval = retval ..
"label[0,3.35;" .. fgettext("Game") .. "]"..
"textlist[0,3.85;5.8,"..gamelist_height..";games;" ..
pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" ..
"container[0,4.5]" ..
devtest_only ..
"container_end[]"
end
retval = retval ..
"container_end[]" ..
-- Right side
@@ -360,9 +357,20 @@ local function create_world_buttonhandler(this, fields)
fields["key_enter"] then
local worldname = fields["te_world_name"]
local gameindex = core.get_textlist_index("games")
local game, gameindex
if hide_gamelist then
game, gameindex = pkgmgr.find_by_gameid(core.settings:get("menu_last_game"))
else
gameindex = core.get_textlist_index("games")
game = pkgmgr.get_game(gameindex)
end
if gameindex ~= nil then
local message
if game == nil then
message = fgettext("No game selected")
end
if message == nil then
-- For unnamed worlds use the generated name 'world<number>',
-- where the number increments: it is set to 1 larger than the largest
-- generated name number found.
@@ -377,36 +385,48 @@ local function create_world_buttonhandler(this, fields)
worldname = "world" .. worldnum_max + 1
end
core.settings:set("fixed_map_seed", fields["te_seed"])
local message
if not menudata.worldlist:uid_exists_raw(worldname) then
core.settings:set("mg_name",fields["dd_mapgen"])
message = core.create_world(worldname,gameindex)
else
if menudata.worldlist:uid_exists_raw(worldname) then
message = fgettext("A world named \"$1\" already exists", worldname)
end
if message ~= nil then
gamedata.errormessage = message
else
core.settings:set("menu_last_game",pkgmgr.games[gameindex].id)
if this.data.update_worldlist_filter then
menudata.worldlist:set_filtercriteria(pkgmgr.games[gameindex].id)
mm_texture.update("singleplayer", pkgmgr.games[gameindex].id)
end
menudata.worldlist:refresh()
core.settings:set("mainmenu_last_selected_world",
menudata.worldlist:raw_index_by_uid(worldname))
end
else
gamedata.errormessage = fgettext("No game selected")
end
if message == nil then
this.data.seed = fields["te_seed"]
this.data.mg = fields["dd_mapgen"]
-- actual names as used by engine
local settings = {
fixed_map_seed = this.data.seed,
mg_name = this.data.mg,
mg_flags = table_to_flags(this.data.flags.main),
mgv5_spflags = table_to_flags(this.data.flags.v5),
mgv6_spflags = table_to_flags(this.data.flags.v6),
mgv7_spflags = table_to_flags(this.data.flags.v7),
mgfractal_spflags = table_to_flags(this.data.flags.fractal),
mgcarpathian_spflags = table_to_flags(this.data.flags.carpathian),
mgvalleys_spflags = table_to_flags(this.data.flags.valleys),
mgflat_spflags = table_to_flags(this.data.flags.flat),
}
message = core.create_world(worldname, gameindex, settings)
end
if message == nil then
core.settings:set("menu_last_game", game.id)
if this.data.update_worldlist_filter then
menudata.worldlist:set_filtercriteria(game.id)
end
menudata.worldlist:refresh()
core.settings:set("mainmenu_last_selected_world",
menudata.worldlist:raw_index_by_uid(worldname))
end
gamedata.errormessage = message
this:delete()
return true
end
worldname = fields.te_world_name
this.data.worldname = fields["te_world_name"]
this.data.seed = fields["te_seed"]
if fields["games"] then
local gameindex = core.get_textlist_index("games")
@@ -417,22 +437,11 @@ local function create_world_buttonhandler(this, fields)
for k,v in pairs(fields) do
local split = string.split(k, "_", nil, 3)
if split and split[1] == "flag" then
local setting
if split[2] == "mg" then
setting = "mg_flags"
else
setting = split[2].."_spflags"
end
-- We replaced the underscore of flag names with a dash.
local flag = string.gsub(split[3], "-", "_")
local ftable = core.settings:get_flags(setting)
if v == "true" then
ftable[flag] = true
else
ftable[flag] = false
end
local flags = table_to_flags(ftable)
core.settings:set(setting, flags)
local ftable = this.data.flags[split[2]]
assert(ftable)
ftable[flag] = v == "true"
return true
end
end
@@ -446,18 +455,16 @@ local function create_world_buttonhandler(this, fields)
local entry = core.formspec_escape(fields["mgv6_biomes"])
for b=1, #mgv6_biomes do
if entry == mgv6_biomes[b][1] then
local ftable = core.settings:get_flags("mgv6_spflags")
local ftable = this.data.flags.v6
ftable.jungles = mgv6_biomes[b][2].jungles
ftable.snowbiomes = mgv6_biomes[b][2].snowbiomes
local flags = table_to_flags(ftable)
core.settings:set("mgv6_spflags", flags)
return true
end
end
end
if fields["dd_mapgen"] then
core.settings:set("mg_name", fields["dd_mapgen"])
this.data.mg = fields["dd_mapgen"]
return true
end
@@ -466,12 +473,27 @@ end
function create_create_world_dlg(update_worldlistfilter)
worldname = ""
local retval = dialog_create("sp_create_world",
create_world_formspec,
create_world_buttonhandler,
nil)
retval.update_worldlist_filter = update_worldlistfilter
retval.data = {
update_worldlist_filter = update_worldlistfilter,
worldname = "",
-- settings the world is created with:
seed = core.settings:get("fixed_map_seed") or "",
mg = core.settings:get("mg_name"),
flags = {
main = core.settings:get_flags("mg_flags"),
v5 = core.settings:get_flags("mgv5_spflags"),
v6 = core.settings:get_flags("mgv6_spflags"),
v7 = core.settings:get_flags("mgv7_spflags"),
fractal = core.settings:get_flags("mgfractal_spflags"),
carpathian = core.settings:get_flags("mgcarpathian_spflags"),
valleys = core.settings:get_flags("mgvalleys_spflags"),
flat = core.settings:get_flags("mgflat_spflags"),
}
}
return retval
end

View File

@@ -31,6 +31,10 @@ end
-- returns error message, or nil
local function parse_setting_line(settings, line, read_all, base_level, allow_secure)
-- strip carriage returns (CR, /r)
line = line:gsub("\r", "")
-- comment
local comment = line:match("^#" .. CHAR_CLASSES.SPACE .. "*(.*)$")
if comment then
@@ -620,7 +624,7 @@ local function create_change_setting_formspec(dialogdata)
-- Third row
add_field(0.3, "te_octaves", fgettext("Octaves"), t[7])
add_field(3.6, "te_persist", fgettext("Persistance"), t[8])
add_field(3.6, "te_persist", fgettext("Persistence"), t[8])
add_field(6.9, "te_lacun", fgettext("Lacunarity"), t[9])
height = height + 1.1

View File

@@ -16,23 +16,25 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
mm_texture = {}
mm_game_theme = {}
--------------------------------------------------------------------------------
function mm_texture.init()
mm_texture.defaulttexturedir = core.get_texturepath() .. DIR_DELIM .. "base" ..
function mm_game_theme.init()
mm_game_theme.defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM
mm_texture.basetexturedir = mm_texture.defaulttexturedir
mm_game_theme.basetexturedir = mm_game_theme.defaulttexturedir
mm_texture.texturepack = core.settings:get("texture_path")
mm_game_theme.texturepack = core.settings:get("texture_path")
mm_texture.gameid = nil
mm_game_theme.gameid = nil
mm_game_theme.music_handle = nil
end
--------------------------------------------------------------------------------
function mm_texture.update(tab,gamedetails)
function mm_game_theme.update(tab,gamedetails)
if tab ~= "singleplayer" then
mm_texture.reset()
mm_game_theme.reset()
return
end
@@ -40,50 +42,54 @@ function mm_texture.update(tab,gamedetails)
return
end
mm_texture.update_game(gamedetails)
mm_game_theme.update_game(gamedetails)
end
--------------------------------------------------------------------------------
function mm_texture.reset()
mm_texture.gameid = nil
function mm_game_theme.reset()
mm_game_theme.gameid = nil
local have_bg = false
local have_overlay = mm_texture.set_generic("overlay")
local have_overlay = mm_game_theme.set_generic("overlay")
if not have_overlay then
have_bg = mm_texture.set_generic("background")
have_bg = mm_game_theme.set_generic("background")
end
mm_texture.clear("header")
mm_texture.clear("footer")
mm_game_theme.clear("header")
mm_game_theme.clear("footer")
core.set_clouds(false)
mm_texture.set_generic("footer")
mm_texture.set_generic("header")
mm_game_theme.set_generic("footer")
mm_game_theme.set_generic("header")
if not have_bg then
if core.settings:get_bool("menu_clouds") then
core.set_clouds(true)
else
mm_texture.set_dirt_bg()
mm_game_theme.set_dirt_bg()
end
end
if mm_game_theme.music_handle ~= nil then
core.sound_stop(mm_game_theme.music_handle)
end
end
--------------------------------------------------------------------------------
function mm_texture.update_game(gamedetails)
if mm_texture.gameid == gamedetails.id then
function mm_game_theme.update_game(gamedetails)
if mm_game_theme.gameid == gamedetails.id then
return
end
local have_bg = false
local have_overlay = mm_texture.set_game("overlay",gamedetails)
local have_overlay = mm_game_theme.set_game("overlay",gamedetails)
if not have_overlay then
have_bg = mm_texture.set_game("background",gamedetails)
have_bg = mm_game_theme.set_game("background",gamedetails)
end
mm_texture.clear("header")
mm_texture.clear("footer")
mm_game_theme.clear("header")
mm_game_theme.clear("footer")
core.set_clouds(false)
if not have_bg then
@@ -91,34 +97,34 @@ function mm_texture.update_game(gamedetails)
if core.settings:get_bool("menu_clouds") then
core.set_clouds(true)
else
mm_texture.set_dirt_bg()
mm_game_theme.set_dirt_bg()
end
end
mm_texture.set_game("footer",gamedetails)
mm_texture.set_game("header",gamedetails)
mm_game_theme.set_game("footer",gamedetails)
mm_game_theme.set_game("header",gamedetails)
mm_texture.gameid = gamedetails.id
mm_game_theme.gameid = gamedetails.id
end
--------------------------------------------------------------------------------
function mm_texture.clear(identifier)
function mm_game_theme.clear(identifier)
core.set_background(identifier,"")
end
--------------------------------------------------------------------------------
function mm_texture.set_generic(identifier)
function mm_game_theme.set_generic(identifier)
--try texture pack first
if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM .."menu_" ..
if mm_game_theme.texturepack ~= nil then
local path = mm_game_theme.texturepack .. DIR_DELIM .."menu_" ..
identifier .. ".png"
if core.set_background(identifier,path) then
return true
end
end
if mm_texture.defaulttexturedir ~= nil then
local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" ..
if mm_game_theme.defaulttexturedir ~= nil then
local path = mm_game_theme.defaulttexturedir .. DIR_DELIM .."menu_" ..
identifier .. ".png"
if core.set_background(identifier,path) then
return true
@@ -129,14 +135,16 @@ function mm_texture.set_generic(identifier)
end
--------------------------------------------------------------------------------
function mm_texture.set_game(identifier, gamedetails)
function mm_game_theme.set_game(identifier, gamedetails)
if gamedetails == nil then
return false
end
if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM ..
mm_game_theme.set_music(gamedetails)
if mm_game_theme.texturepack ~= nil then
local path = mm_game_theme.texturepack .. DIR_DELIM ..
gamedetails.id .. "_menu_" .. identifier .. ".png"
if core.set_background(identifier, path) then
return true
@@ -171,9 +179,10 @@ function mm_texture.set_game(identifier, gamedetails)
return false
end
function mm_texture.set_dirt_bg()
if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM .."default_dirt.png"
--------------------------------------------------------------------------------
function mm_game_theme.set_dirt_bg()
if mm_game_theme.texturepack ~= nil then
local path = mm_game_theme.texturepack .. DIR_DELIM .."default_dirt.png"
if core.set_background("background", path, true, 128) then
return true
end
@@ -183,3 +192,12 @@ function mm_texture.set_dirt_bg()
local minimalpath = defaulttexturedir .. "menu_bg.png"
core.set_background("background", minimalpath, true, 128)
end
--------------------------------------------------------------------------------
function mm_game_theme.set_music(gamedetails)
if mm_game_theme.music_handle ~= nil then
core.sound_stop(mm_game_theme.music_handle)
end
local music_path = gamedetails.path .. DIR_DELIM .. "menu" .. DIR_DELIM .. "theme"
mm_game_theme.music_handle = core.sound_play(music_path, true)
end

View File

@@ -35,7 +35,7 @@ dofile(menupath .. DIR_DELIM .. "async_event.lua")
dofile(menupath .. DIR_DELIM .. "common.lua")
dofile(menupath .. DIR_DELIM .. "pkgmgr.lua")
dofile(menupath .. DIR_DELIM .. "serverlistmgr.lua")
dofile(menupath .. DIR_DELIM .. "textures.lua")
dofile(menupath .. DIR_DELIM .. "game_theme.lua")
dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua")
@@ -49,7 +49,7 @@ local tabs = {}
tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua")
tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
tabs.about = dofile(menupath .. DIR_DELIM .. "tab_about.lua")
tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua")
tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua")
@@ -87,7 +87,7 @@ local function init_globals()
core.settings:set("menu_last_game", default_game)
end
mm_texture.init()
mm_game_theme.init()
-- Create main tabview
local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0})
@@ -98,7 +98,7 @@ local function init_globals()
tv_main:add(tabs.content)
tv_main:add(tabs.settings)
tv_main:add(tabs.credits)
tv_main:add(tabs.about)
tv_main:set_global_event_handler(main_event_handler)
tv_main:set_fixed_size(false)
@@ -113,7 +113,7 @@ local function init_globals()
if tv_main.current_tab == "local" then
local game = pkgmgr.find_by_gameid(core.settings:get("menu_last_game"))
if game == nil then
mm_texture.reset()
mm_game_theme.reset()
end
end
@@ -121,8 +121,6 @@ local function init_globals()
tv_main:show()
ui.update()
core.sound_play("main_menu", true)
end
init_globals()

View File

@@ -181,21 +181,6 @@ function pkgmgr.get_texture_packs()
end
--------------------------------------------------------------------------------
function pkgmgr.extract(modfile)
if modfile.type == "zip" then
local tempfolder = os.tempfolder()
if tempfolder ~= nil and
tempfolder ~= "" then
core.create_dir(tempfolder)
if core.extract_zip(modfile.name,tempfolder) then
return tempfolder
end
end
end
return nil
end
function pkgmgr.get_folder_type(path)
local testfile = io.open(path .. DIR_DELIM .. "init.lua","r")
if testfile ~= nil then
@@ -451,7 +436,7 @@ function pkgmgr.enable_mod(this, toset)
local enabled_mods = {}
toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, mod)
if not toset then
if next(enabled_mods) == nil then
-- Mod(s) were disabled, so no dependencies need to be enabled
table.sort(toggled_mods)
core.log("info", "Following mods were disabled: " ..
@@ -461,11 +446,16 @@ function pkgmgr.enable_mod(this, toset)
-- Enable mods' depends after activation
-- Make a list of mod ids indexed by their names
-- Make a list of mod ids indexed by their names. Among mods with the
-- same name, enabled mods take precedence, after which game mods take
-- precedence, being last in the mod list.
local mod_ids = {}
for id, mod2 in pairs(list) do
if mod2.type == "mod" and not mod2.is_modpack then
mod_ids[mod2.name] = id
local prev_id = mod_ids[mod2.name]
if not prev_id or not list[prev_id].enabled then
mod_ids[mod2.name] = id
end
end
end
@@ -494,14 +484,14 @@ function pkgmgr.enable_mod(this, toset)
core.log("warning", "Mod dependency \"" .. name ..
"\" not found!")
else
if mod_to_enable.enabled == false then
if not mod_to_enable.enabled then
mod_to_enable.enabled = true
toggled_mods[#toggled_mods+1] = mod_to_enable.name
end
-- Push the dependencies of the dependency onto the stack
local depends = pkgmgr.get_dependencies(mod_to_enable.path)
for i = 1, #depends do
if not enabled_mods[name] then
if not enabled_mods[depends[i]] then
sp = sp+1
to_enable[sp] = depends[i]
end
@@ -561,11 +551,10 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
local from = basefolder and basefolder.path or path
if targetpath then
core.delete_dir(targetpath)
core.create_dir(targetpath)
else
targetpath = core.get_texturepath() .. DIR_DELIM .. basename
end
if not core.copy_dir(from, targetpath) then
if not core.copy_dir(from, targetpath, false) then
return nil,
fgettext("Failed to install $1 to $2", basename, targetpath)
end
@@ -586,7 +575,6 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
-- Get destination name for modpack
if targetpath then
core.delete_dir(targetpath)
core.create_dir(targetpath)
else
local clean_path = nil
if basename ~= nil then
@@ -610,7 +598,6 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
if targetpath then
core.delete_dir(targetpath)
core.create_dir(targetpath)
else
local targetfolder = basename
if targetfolder == nil then
@@ -636,14 +623,13 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
if targetpath then
core.delete_dir(targetpath)
core.create_dir(targetpath)
else
targetpath = core.get_gamepath() .. DIR_DELIM .. basename
end
end
-- Copy it
if not core.copy_dir(basefolder.path, targetpath) then
if not core.copy_dir(basefolder.path, targetpath, false) then
return nil,
fgettext("Failed to install $1 to $2", basename, targetpath)
end
@@ -657,23 +643,6 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
return targetpath, nil
end
--------------------------------------------------------------------------------
function pkgmgr.install(type, modfilename, basename, dest)
local archive_info = pkgmgr.identify_filetype(modfilename)
local path = pkgmgr.extract(archive_info)
if path == nil then
return nil,
fgettext("Install: file: \"$1\"", archive_info.name) .. "\n" ..
fgettext("Install: Unsupported file type \"$1\" or broken archive",
archive_info.type)
end
local targetpath, msg = pkgmgr.install_dir(type, path, basename, dest)
core.delete_dir(path)
return targetpath, msg
end
--------------------------------------------------------------------------------
function pkgmgr.preparemodlist(data)
local retval = {}
@@ -682,11 +651,9 @@ function pkgmgr.preparemodlist(data)
local game_mods = {}
--read global mods
local modpath = core.get_modpath()
if modpath ~= nil and
modpath ~= "" then
get_mods(modpath,global_mods)
local modpaths = core.get_modpaths()
for _, modpath in ipairs(modpaths) do
get_mods(modpath, global_mods)
end
for i=1,#global_mods,1 do
@@ -819,45 +786,6 @@ function pkgmgr.refresh_globals()
pkgmgr.global_mods:set_sortmode("alphabetic")
end
--------------------------------------------------------------------------------
function pkgmgr.identify_filetype(name)
if name:sub(-3):lower() == "zip" then
return {
name = name,
type = "zip"
}
end
if name:sub(-6):lower() == "tar.gz" or
name:sub(-3):lower() == "tgz"then
return {
name = name,
type = "tgz"
}
end
if name:sub(-6):lower() == "tar.bz2" then
return {
name = name,
type = "tbz"
}
end
if name:sub(-2):lower() == "7z" then
return {
name = name,
type = "7z"
}
end
return {
name = name,
type = "ukn"
}
end
--------------------------------------------------------------------------------
function pkgmgr.find_by_gameid(gameid)
for i=1,#pkgmgr.games,1 do

View File

@@ -28,32 +28,35 @@ local core_developers = {
"Lars Hofhansl <larsh@apache.org>",
"Pierre-Yves Rollo <dev@pyrollo.com>",
"v-rob <robinsonvincent89@gmail.com>",
"hecks",
"Hugues Ross <hugues.ross@gmail.com>",
"Dmitry Kostenko (x2048) <codeforsmile@gmail.com>",
}
-- For updating active/previous contributors, see the script in ./util/gather_git_credits.py
local active_contributors = {
"Wuzzy [devtest game, visual corrections]",
"Zughy [Visual improvements, various fixes]",
"Maksim (MoNTE48) [Android]",
"Wuzzy [I18n for builtin, liquid features, fixes]",
"Zughy [Various features and fixes]",
"numzero [Graphics and rendering]",
"appgurueu [Various internal fixes]",
"Desour [Formspec and vector API changes]",
"HybridDog [Rendering fixes and documentation]",
"Hugues Ross [Graphics-related improvements]",
"ANAND (ClobberXD) [Mouse buttons rebinding]",
"luk3yx [Fixes]",
"hecks [Audiovisuals, Lua API]",
"LoneWolfHT [Object crosshair, documentation fixes]",
"Lejo [Server-related improvements]",
"EvidenceB [Compass HUD element]",
"Paul Ouellette (pauloue) [Lua API, documentation]",
"TheTermos [Collision detection, physics]",
"Desour [Internal fixes, Clipboard on X11]",
"Lars Müller [Various internal fixes]",
"JosiahWI [CMake, cleanups and fixes]",
"HybridDog [builtin, documentation]",
"Jude Melton-Houghton [Database implementation]",
"savilli [Fixes]",
"Liso [Shadow Mapping]",
"MoNTE48 [Build fix]",
"Jean-Patrick Guerrero (kilbith) [Fixes]",
"ROllerozxa [Code cleanups]",
"Lejo [bitop library integration]",
"LoneWolfHT [Build fixes]",
"NeroBurner [Joystick]",
"Elias Fleckenstein [Internal fixes]",
"David CARLIER [Unix & Haiku build fixes]",
"dcbrwn [Object shading]",
"Elias Fleckenstein [API features/fixes]",
"Jean-Patrick Guerrero (kilbith) [model element, visual fixes]",
"k.h.lai [Memory leak fixes, documentation]",
"pecksin [Clickable web links]",
"srfqi [Android & rendering fixes]",
"EvidenceB [Formspec]",
}
local previous_core_developers = {
@@ -70,6 +73,7 @@ local previous_core_developers = {
"Zeno",
"ShadowNinja <shadowninja@minetest.net>",
"Auke Kok (sofar) <sofar@foo-projects.org>",
"Aaron Suen <warr1024@gmail.com>",
}
local previous_contributors = {
@@ -80,10 +84,10 @@ local previous_contributors = {
"MirceaKitsune <mirceakitsune@gmail.com>",
"Constantin Wenger (SpeedProg)",
"Ciaran Gultnieks (CiaranG)",
"stujones11 [Android UX improvements]",
"Rogier <rogier777@gmail.com> [Fixes]",
"Gregory Currie (gregorycu) [optimisation]",
"srifqi [Fixes]",
"Paul Ouellette (pauloue)",
"stujones11",
"Rogier <rogier777@gmail.com>",
"Gregory Currie (gregorycu)",
"JacobF",
"Jeija <jeija@mesecons.net> [HTTP, particles]",
}
@@ -97,8 +101,8 @@ local function buildCreditList(source)
end
return {
name = "credits",
caption = fgettext("Credits"),
name = "about",
caption = fgettext("About"),
cbf_formspec = function(tabview, name, tabdata)
local logofile = defaulttexturedir .. "logo.png"
local version = core.get_version()
@@ -119,11 +123,16 @@ return {
buildCreditList(previous_contributors) .. "," ..
";1]"
-- Render information
fs = fs .. "label[0.75,4.9;" ..
fgettext("Active renderer:") .. "\n" ..
core.formspec_escape(core.get_screen_info().render_info) .. "]"
if PLATFORM ~= "Android" then
fs = fs .. "tooltip[userdata;" ..
fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" ..
"and texture packs in a file manager / explorer.") .. "]"
fs = fs .. "button[0,4.75;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]"
fs = fs .. "button[0,4;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]"
end
return fs

View File

@@ -145,11 +145,26 @@ local function get_formspec(tabview, name, tabdata)
return retval
end
--------------------------------------------------------------------------------
local function handle_doubleclick(pkg)
if pkg.type == "txp" then
if core.settings:get("texture_path") == pkg.path then
core.settings:set("texture_path", "")
else
core.settings:set("texture_path", pkg.path)
end
packages = nil
end
end
--------------------------------------------------------------------------------
local function handle_buttons(tabview, fields, tabname, tabdata)
if fields["pkglist"] ~= nil then
local event = core.explode_table_event(fields["pkglist"])
tabdata.selected_pkg = event.row
if event.type == "DCL" then
handle_doubleclick(packages:get_list()[tabdata.selected_pkg])
end
return true
end

View File

@@ -18,8 +18,14 @@
local enable_gamebar = PLATFORM ~= "Android"
local current_game, singleplayer_refresh_gamebar
local valid_disabled_settings = {
["enable_damage"]=true,
["creative_mode"]=true,
["enable_server"]=true,
}
if enable_gamebar then
-- Currently chosen game in gamebar for theming and filtering
function current_game()
local last_game_id = core.settings:get("menu_last_game")
local game = pkgmgr.find_by_gameid(last_game_id)
@@ -27,10 +33,30 @@ if enable_gamebar then
return game
end
-- Apply menu changes from given game
function apply_game(game)
core.set_topleft_text(game.name)
core.settings:set("menu_last_game", game.id)
menudata.worldlist:set_filtercriteria(game.id)
mm_game_theme.update("singleplayer", game) -- this refreshes the formspec
local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.settings:get("mainmenu_last_selected_world")))
if not index or index < 1 then
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil and selected < #menudata.worldlist:get_list() then
index = selected
else
index = #menudata.worldlist:get_list()
end
end
menu_worldmt_legacy(index)
end
function singleplayer_refresh_gamebar()
local old_bar = ui.find_by_name("game_button_bar")
if old_bar ~= nil then
old_bar:delete()
end
@@ -45,26 +71,10 @@ if enable_gamebar then
return true
end
for key,value in pairs(fields) do
for j=1,#pkgmgr.games,1 do
if ("game_btnbar_" .. pkgmgr.games[j].id == key) then
mm_texture.update("singleplayer", pkgmgr.games[j])
core.set_topleft_text(pkgmgr.games[j].name)
core.settings:set("menu_last_game",pkgmgr.games[j].id)
menudata.worldlist:set_filtercriteria(pkgmgr.games[j].id)
local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.settings:get("mainmenu_last_selected_world")))
if not index or index < 1 then
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil and selected < #menudata.worldlist:get_list() then
index = selected
else
index = #menudata.worldlist:get_list()
end
end
menu_worldmt_legacy(index)
return true
end
for _, game in ipairs(pkgmgr.games) do
if fields["game_btnbar_" .. game.id] then
apply_game(game)
return true
end
end
end
@@ -73,25 +83,22 @@ if enable_gamebar then
game_buttonbar_button_handler,
{x=-0.3,y=5.9}, "horizontal", {x=12.4,y=1.15})
for i=1,#pkgmgr.games,1 do
local btn_name = "game_btnbar_" .. pkgmgr.games[i].id
for _, game in ipairs(pkgmgr.games) do
local btn_name = "game_btnbar_" .. game.id
local image = nil
local text = nil
local tooltip = core.formspec_escape(pkgmgr.games[i].name)
local tooltip = core.formspec_escape(game.name)
if pkgmgr.games[i].menuicon_path ~= nil and
pkgmgr.games[i].menuicon_path ~= "" then
image = core.formspec_escape(pkgmgr.games[i].menuicon_path)
if (game.menuicon_path or "") ~= "" then
image = core.formspec_escape(game.menuicon_path)
else
local part1 = pkgmgr.games[i].id:sub(1,5)
local part2 = pkgmgr.games[i].id:sub(6,10)
local part3 = pkgmgr.games[i].id:sub(11)
local part1 = game.id:sub(1,5)
local part2 = game.id:sub(6,10)
local part3 = game.id:sub(11)
text = part1 .. "\n" .. part2
if part3 ~= nil and
part3 ~= "" then
if part3 ~= "" then
text = text .. "\n" .. part3
end
end
@@ -102,37 +109,91 @@ if enable_gamebar then
btnbar:add_button("game_open_cdb", "", plus_image, fgettext("Install games from ContentDB"))
end
else
-- Currently chosen game in gamebar: no gamebar -> no "current" game
function current_game()
return nil
end
end
local function get_disabled_settings(game)
if not game then
return {}
end
local gameconfig = Settings(game.path .. "/game.conf")
local disabled_settings = {}
if gameconfig then
local disabled_settings_str = (gameconfig:get("disabled_settings") or ""):split()
for _, value in pairs(disabled_settings_str) do
local state = false
value = value:trim()
if string.sub(value, 1, 1) == "!" then
state = true
value = string.sub(value, 2)
end
if valid_disabled_settings[value] then
disabled_settings[value] = state
else
core.log("error", "Invalid disabled setting in game.conf: "..tostring(value))
end
end
end
return disabled_settings
end
local function get_formspec(tabview, name, tabdata)
local retval = ""
local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.settings:get("mainmenu_last_selected_world"))
)
tonumber(core.settings:get("mainmenu_last_selected_world")))
local list = menudata.worldlist:get_list()
local world = list and index and list[index]
local game
if world then
game = pkgmgr.find_by_gameid(world.gameid)
else
game = current_game()
end
local disabled_settings = get_disabled_settings(game)
local creative, damage, host = "", "", ""
-- Y offsets for game settings checkboxes
local y = -0.2
local yo = 0.45
if disabled_settings["creative_mode"] == nil then
creative = "checkbox[0,"..y..";cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
dump(core.settings:get_bool("creative_mode")) .. "]"
y = y + yo
end
if disabled_settings["enable_damage"] == nil then
damage = "checkbox[0,"..y..";cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.settings:get_bool("enable_damage")) .. "]"
y = y + yo
end
if disabled_settings["enable_server"] == nil then
host = "checkbox[0,"..y..";cb_server;".. fgettext("Host Server") ..";" ..
dump(core.settings:get_bool("enable_server")) .. "]"
y = y + yo
end
retval = retval ..
"button[3.9,3.8;2.8,1;world_delete;".. fgettext("Delete") .. "]" ..
"button[6.55,3.8;2.8,1;world_configure;".. fgettext("Select Mods") .. "]" ..
"button[9.2,3.8;2.8,1;world_create;".. fgettext("New") .. "]" ..
"label[3.9,-0.05;".. fgettext("Select World:") .. "]"..
"checkbox[0,-0.20;cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
dump(core.settings:get_bool("creative_mode")) .. "]"..
"checkbox[0,0.25;cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.settings:get_bool("enable_damage")) .. "]"..
"checkbox[0,0.7;cb_server;".. fgettext("Host Server") ..";" ..
dump(core.settings:get_bool("enable_server")) .. "]" ..
creative ..
damage ..
host ..
"textlist[3.9,0.4;7.9,3.45;sp_worlds;" ..
menu_render_worldlist() ..
menu_render_worldlist(not enable_gamebar) ..
";" .. index .. "]"
if core.settings:get_bool("enable_server") then
if core.settings:get_bool("enable_server") and disabled_settings["enable_server"] == nil then
retval = retval ..
"button[7.9,4.75;4.1,1;play;".. fgettext("Host Game") .. "]" ..
"checkbox[0,1.15;cb_server_announce;" .. fgettext("Announce Server") .. ";" ..
"checkbox[0,"..y..";cb_server_announce;" .. fgettext("Announce Server") .. ";" ..
dump(core.settings:get_bool("server_announce")) .. "]" ..
"field[0.3,2.85;3.8,0.5;te_playername;" .. fgettext("Name") .. ";" ..
core.formspec_escape(core.settings:get("name")) .. "]" ..
@@ -227,9 +288,21 @@ local function main_button_handler(this, fields, name, tabdata)
-- Update last game
local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
local game_obj
if world then
local game = pkgmgr.find_by_gameid(world.gameid)
core.settings:set("menu_last_game", game.id)
game_obj = pkgmgr.find_by_gameid(world.gameid)
core.settings:set("menu_last_game", game_obj.id)
end
local disabled_settings = get_disabled_settings(game_obj)
for k, _ in pairs(valid_disabled_settings) do
local v = disabled_settings[k]
if v ~= nil then
if k == "enable_server" and v == true then
error("Setting 'enable_server' cannot be force-enabled! The game.conf needs to be fixed.")
end
core.settings:set_bool(k, disabled_settings[k])
end
end
if core.settings:get_bool("enable_server") then
@@ -251,11 +324,11 @@ local function main_button_handler(this, fields, name, tabdata)
end
if fields["world_create"] ~= nil then
local create_world_dlg = create_create_world_dlg(true)
local create_world_dlg = create_create_world_dlg(enable_gamebar)
create_world_dlg:set_parent(this)
this:hide()
create_world_dlg:show()
mm_texture.update("singleplayer", current_game())
mm_game_theme.update("singleplayer", current_game())
return true
end
@@ -272,7 +345,7 @@ local function main_button_handler(this, fields, name, tabdata)
delete_world_dlg:set_parent(this)
this:hide()
delete_world_dlg:show()
mm_texture.update("singleplayer",current_game())
mm_game_theme.update("singleplayer",current_game())
end
end
@@ -290,7 +363,7 @@ local function main_button_handler(this, fields, name, tabdata)
configdialog:set_parent(this)
this:hide()
configdialog:show()
mm_texture.update("singleplayer",current_game())
mm_game_theme.update("singleplayer",current_game())
end
end
@@ -303,11 +376,8 @@ if enable_gamebar then
function on_change(type, old_tab, new_tab)
if (type == "ENTER") then
local game = current_game()
if game then
menudata.worldlist:set_filtercriteria(game.id)
core.set_topleft_text(game.name)
mm_texture.update("singleplayer",game)
apply_game(game)
end
singleplayer_refresh_gamebar()
@@ -319,7 +389,7 @@ if enable_gamebar then
gamebar:hide()
end
core.set_topleft_text("")
mm_texture.update(new_tab,nil)
mm_game_theme.update(new_tab,nil)
end
end
end

View File

@@ -15,17 +15,50 @@
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
local function get_sorted_servers()
local servers = {
fav = {},
public = {},
incompatible = {}
}
local favs = serverlistmgr.get_favorites()
local taken_favs = {}
local result = menudata.search_result or serverlistmgr.servers
for _, server in ipairs(result) do
server.is_favorite = false
for index, fav in ipairs(favs) do
if server.address == fav.address and server.port == fav.port then
taken_favs[index] = true
server.is_favorite = true
break
end
end
server.is_compatible = is_server_protocol_compat(server.proto_min, server.proto_max)
if server.is_favorite then
table.insert(servers.fav, server)
elseif server.is_compatible then
table.insert(servers.public, server)
else
table.insert(servers.incompatible, server)
end
end
if not menudata.search_result then
for index, fav in ipairs(favs) do
if not taken_favs[index] then
table.insert(servers.fav, fav)
end
end
end
return servers
end
local function get_formspec(tabview, name, tabdata)
-- Update the cached supported proto info,
-- it may have changed after a change by the settings menu.
common_update_cached_supp_proto()
local selected
if menudata.search_result then
selected = menudata.search_result[tabdata.selected]
else
selected = serverlistmgr.servers[tabdata.selected]
end
if not tabdata.search_for then
tabdata.search_for = ""
@@ -33,128 +66,221 @@ local function get_formspec(tabview, name, tabdata)
local retval =
-- Search
"field[0.15,0.075;5.91,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" ..
"image_button[5.63,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" ..
"image_button[6.3,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" ..
"image_button[6.97,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png")
.. ";btn_mp_refresh;]" ..
"field[0.25,0.25;7,0.75;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" ..
"container[7.25,0.25]" ..
"image_button[0,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" ..
"image_button[0.75,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" ..
"image_button[1.5,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") .. ";btn_mp_refresh;]" ..
"tooltip[btn_mp_clear;" .. fgettext("Clear") .. "]" ..
"tooltip[btn_mp_search;" .. fgettext("Search") .. "]" ..
"tooltip[btn_mp_refresh;" .. fgettext("Refresh") .. "]" ..
"container_end[]" ..
"container[9.75,0]" ..
"box[0,0;5.75,7;#666666]" ..
-- Address / Port
"label[7.75,-0.25;" .. fgettext("Address / Port") .. "]" ..
"field[8,0.65;3.25,0.5;te_address;;" ..
"label[0.25,0.35;" .. fgettext("Address") .. "]" ..
"label[4.25,0.35;" .. fgettext("Port") .. "]" ..
"field[0.25,0.5;4,0.75;te_address;;" ..
core.formspec_escape(core.settings:get("address")) .. "]" ..
"field[11.1,0.65;1.4,0.5;te_port;;" ..
"field[4.25,0.5;1.25,0.75;te_port;;" ..
core.formspec_escape(core.settings:get("remote_port")) .. "]" ..
-- Name / Password
"label[7.75,0.95;" .. fgettext("Name / Password") .. "]" ..
"field[8,1.85;2.9,0.5;te_name;;" ..
"label[0.25,1.55;" .. fgettext("Name") .. "]" ..
"label[3,1.55;" .. fgettext("Password") .. "]" ..
"field[0.25,1.75;2.75,0.75;te_name;;" ..
core.formspec_escape(core.settings:get("name")) .. "]" ..
"pwdfield[10.73,1.85;1.77,0.5;te_pwd;]" ..
"pwdfield[3,1.75;2.5,0.75;te_pwd;]" ..
-- Description Background
"box[7.73,2.25;4.25,2.6;#999999]"..
"label[0.25,2.75;" .. fgettext("Server Description") .. "]" ..
"box[0.25,3;5.25,2.75;#999999]"..
-- Connect
"button[9.88,4.9;2.3,1;btn_mp_connect;" .. fgettext("Connect") .. "]"
"button[3,6;2.5,0.75;btn_mp_connect;" .. fgettext("Connect") .. "]"
if tabdata.selected and selected then
if tabdata.selected then
if gamedata.fav then
retval = retval .. "button[7.73,4.9;2.3,1;btn_delete_favorite;" ..
retval = retval .. "button[0.25,6;2.5,0.75;btn_delete_favorite;" ..
fgettext("Del. Favorite") .. "]"
end
if selected.description then
retval = retval .. "textarea[8.1,2.3;4.23,2.9;;;" ..
core.formspec_escape((gamedata.serverdescription or ""), true) .. "]"
if gamedata.serverdescription then
retval = retval .. "textarea[0.25,3;5.25,2.75;;;" ..
core.formspec_escape(gamedata.serverdescription) .. "]"
end
end
--favorites
retval = retval .. "container_end[]"
-- Table
retval = retval .. "tablecolumns[" ..
image_column(fgettext("Favorite"), "favorite") .. ";" ..
image_column(fgettext("Ping")) .. ",padding=0.25;" ..
"color,span=3;" ..
"text,align=right;" .. -- clients
"text,align=center,padding=0.25;" .. -- "/"
"text,align=right,padding=0.25;" .. -- clients_max
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
--~ PvP = Player versus Player
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
"image,tooltip=" .. fgettext("Ping") .. "," ..
"0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," ..
"1=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," ..
"2=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," ..
"3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," ..
"4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png") .. "," ..
"5=" .. core.formspec_escape(defaulttexturedir .. "server_favorite.png") .. "," ..
"6=" .. core.formspec_escape(defaulttexturedir .. "server_public.png") .. "," ..
"7=" .. core.formspec_escape(defaulttexturedir .. "server_incompatible.png") .. ";" ..
"color,span=1;" ..
"text,padding=1]" ..
"table[-0.15,0.6;7.75,5.15;favorites;"
"text,align=inline;"..
"color,span=1;" ..
"text,align=inline,width=4.25;" ..
"image,tooltip=" .. fgettext("Creative mode") .. "," ..
"0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," ..
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_creative.png") .. "," ..
"align=inline,padding=0.25,width=1.5;" ..
--~ PvP = Player versus Player
"image,tooltip=" .. fgettext("Damage / PvP") .. "," ..
"0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," ..
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_damage.png") .. "," ..
"2=" .. core.formspec_escape(defaulttexturedir .. "server_flags_pvp.png") .. "," ..
"align=inline,padding=0.25,width=1.5;" ..
"color,align=inline,span=1;" ..
"text,align=inline,padding=1]" ..
"table[0.25,1;9.25,5.75;servers;"
if menudata.search_result then
local favs = serverlistmgr.get_favorites()
for i = 1, #menudata.search_result do
local server = menudata.search_result[i]
for fav_id = 1, #favs do
if server.address == favs[fav_id].address and
server.port == favs[fav_id].port then
server.is_favorite = true
end
local servers = get_sorted_servers()
local dividers = {
fav = "5,#ffff00," .. fgettext("Favorites") .. ",,,0,0,,",
public = "6,#4bdd42," .. fgettext("Public Servers") .. ",,,0,0,,",
incompatible = "7,"..mt_color_grey.."," .. fgettext("Incompatible Servers") .. ",,,0,0,,"
}
local order = {"fav", "public", "incompatible"}
tabdata.lookup = {} -- maps row number to server
local rows = {}
for _, section in ipairs(order) do
local section_servers = servers[section]
if next(section_servers) ~= nil then
rows[#rows + 1] = dividers[section]
for _, server in ipairs(section_servers) do
tabdata.lookup[#rows + 1] = server
rows[#rows + 1] = render_serverlist_row(server)
end
if i ~= 1 then
retval = retval .. ","
end
retval = retval .. render_serverlist_row(server, server.is_favorite)
end
elseif #serverlistmgr.servers > 0 then
local favs = serverlistmgr.get_favorites()
if #favs > 0 then
for i = 1, #favs do
for j = 1, #serverlistmgr.servers do
if serverlistmgr.servers[j].address == favs[i].address and
serverlistmgr.servers[j].port == favs[i].port then
table.insert(serverlistmgr.servers, i, table.remove(serverlistmgr.servers, j))
end
end
if favs[i].address ~= serverlistmgr.servers[i].address then
table.insert(serverlistmgr.servers, i, favs[i])
end
end
end
retval = retval .. render_serverlist_row(serverlistmgr.servers[1], (#favs > 0))
for i = 2, #serverlistmgr.servers do
retval = retval .. "," .. render_serverlist_row(serverlistmgr.servers[i], (i <= #favs))
end
end
retval = retval .. table.concat(rows, ",")
if tabdata.selected then
retval = retval .. ";" .. tabdata.selected .. "]"
else
retval = retval .. ";0]"
end
return retval
return retval, "size[15.5,7,false]real_coordinates[true]"
end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
local serverlist = menudata.search_result or serverlistmgr.servers
local function search_server_list(input)
menudata.search_result = nil
if #serverlistmgr.servers < 2 then
return
end
-- setup the keyword list
local keywords = {}
for word in input:gmatch("%S+") do
word = word:gsub("(%W)", "%%%1")
table.insert(keywords, word)
end
if #keywords == 0 then
return
end
menudata.search_result = {}
-- Search the serverlist
local search_result = {}
for i = 1, #serverlistmgr.servers do
local server = serverlistmgr.servers[i]
local found = 0
for k = 1, #keywords do
local keyword = keywords[k]
if server.name then
local sername = server.name:lower()
local _, count = sername:gsub(keyword, keyword)
found = found + count * 4
end
if server.description then
local desc = server.description:lower()
local _, count = desc:gsub(keyword, keyword)
found = found + count * 2
end
end
if found > 0 then
local points = (#serverlistmgr.servers - i) / 5 + found
server.points = points
table.insert(search_result, server)
end
end
if #search_result == 0 then
return
end
table.sort(search_result, function(a, b)
return a.points > b.points
end)
menudata.search_result = search_result
end
local function set_selected_server(tabdata, idx, server)
-- reset selection
if idx == nil or server == nil then
tabdata.selected = nil
core.settings:set("address", "")
core.settings:set("remote_port", "30000")
return
end
local address = server.address
local port = server.port
gamedata.serverdescription = server.description
gamedata.fav = false
for _, fav in ipairs(serverlistmgr.get_favorites()) do
if address == fav.address and port == fav.port then
gamedata.fav = true
break
end
end
if address and port then
core.settings:set("address", address)
core.settings:set("remote_port", port)
end
tabdata.selected = idx
end
local function main_button_handler(tabview, fields, name, tabdata)
if fields.te_name then
gamedata.playername = fields.te_name
core.settings:set("name", fields.te_name)
end
if fields.favorites then
local event = core.explode_table_event(fields.favorites)
local fav = serverlist[event.row]
if fields.servers then
local event = core.explode_table_event(fields.servers)
local server = tabdata.lookup[event.row]
if event.type == "DCL" then
if event.row <= #serverlist then
if server then
if event.type == "DCL" then
if not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then
server.proto_min, server.proto_max) then
return true
end
gamedata.address = fav.address
gamedata.port = fav.port
gamedata.address = server.address
gamedata.port = server.port
gamedata.playername = fields.te_name
gamedata.selected_world = 0
@@ -162,84 +288,32 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.password = fields.te_pwd
end
gamedata.servername = fav.name
gamedata.serverdescription = fav.description
gamedata.servername = server.name
gamedata.serverdescription = server.description
if gamedata.address and gamedata.port then
core.settings:set("address", gamedata.address)
core.settings:set("remote_port", gamedata.port)
core.start()
end
return true
end
return true
end
if event.type == "CHG" then
if event.row <= #serverlist then
gamedata.fav = false
local favs = serverlistmgr.get_favorites()
local address = fav.address
local port = fav.port
gamedata.serverdescription = fav.description
for i = 1, #favs do
if fav.address == favs[i].address and
fav.port == favs[i].port then
gamedata.fav = true
end
end
if address and port then
core.settings:set("address", address)
core.settings:set("remote_port", port)
end
tabdata.selected = event.row
if event.type == "CHG" then
set_selected_server(tabdata, event.row, server)
return true
end
return true
end
end
if fields.key_up or fields.key_down then
local fav_idx = core.get_table_index("favorites")
local fav = serverlist[fav_idx]
if fav_idx then
if fields.key_up and fav_idx > 1 then
fav_idx = fav_idx - 1
elseif fields.key_down and fav_idx < #serverlistmgr.servers then
fav_idx = fav_idx + 1
end
else
fav_idx = 1
end
if not serverlistmgr.servers or not fav then
tabdata.selected = 0
return true
end
local address = fav.address
local port = fav.port
gamedata.serverdescription = fav.description
if address and port then
core.settings:set("address", address)
core.settings:set("remote_port", port)
end
tabdata.selected = fav_idx
return true
end
if fields.btn_delete_favorite then
local current_favorite = core.get_table_index("favorites")
if not current_favorite then return end
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(serverlistmgr.servers[current_favorite])
serverlistmgr.sync()
tabdata.selected = nil
core.settings:set("address", "")
core.settings:set("remote_port", "30000")
serverlistmgr.delete_favorite(server)
-- the server at [idx+1] will be at idx once list is refreshed
set_selected_server(tabdata, idx, tabdata.lookup[idx+1])
return true
end
@@ -250,63 +324,13 @@ local function main_button_handler(tabview, fields, name, tabdata)
end
if fields.btn_mp_search or fields.key_enter_field == "te_search" then
tabdata.selected = 1
local input = fields.te_search:lower()
tabdata.search_for = fields.te_search
if #serverlistmgr.servers < 2 then
return true
search_server_list(fields.te_search:lower())
if menudata.search_result then
-- first server in row 2 due to header
set_selected_server(tabdata, 2, menudata.search_result[1])
end
menudata.search_result = {}
-- setup the keyword list
local keywords = {}
for word in input:gmatch("%S+") do
word = word:gsub("(%W)", "%%%1")
table.insert(keywords, word)
end
if #keywords == 0 then
menudata.search_result = nil
return true
end
-- Search the serverlist
local search_result = {}
for i = 1, #serverlistmgr.servers do
local server = serverlistmgr.servers[i]
local found = 0
for k = 1, #keywords do
local keyword = keywords[k]
if server.name then
local sername = server.name:lower()
local _, count = sername:gsub(keyword, keyword)
found = found + count * 4
end
if server.description then
local desc = server.description:lower()
local _, count = desc:gsub(keyword, keyword)
found = found + count * 2
end
end
if found > 0 then
local points = (#serverlistmgr.servers - i) / 5 + found
server.points = points
table.insert(search_result, server)
end
end
if #search_result > 0 then
table.sort(search_result, function(a, b)
return a.points > b.points
end)
menudata.search_result = search_result
local first_server = search_result[1]
core.settings:set("address", first_server.address)
core.settings:set("remote_port", first_server.port)
gamedata.serverdescription = first_server.description
end
return true
end
@@ -322,20 +346,22 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.address = fields.te_address
gamedata.port = tonumber(fields.te_port)
gamedata.selected_world = 0
local fav_idx = core.get_table_index("favorites")
local fav = serverlist[fav_idx]
if fav_idx and fav_idx <= #serverlist and
fav.address == gamedata.address and
fav.port == gamedata.port then
local idx = core.get_table_index("servers")
local server = idx and tabdata.lookup[idx]
serverlistmgr.add_favorite(fav)
set_selected_server(tabdata)
gamedata.servername = fav.name
gamedata.serverdescription = fav.description
if server and server.address == gamedata.address and
server.port == gamedata.port then
serverlistmgr.add_favorite(server)
gamedata.servername = server.name
gamedata.serverdescription = server.description
if not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then
server.proto_min, server.proto_max) then
return true
end
else
@@ -354,6 +380,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
core.start()
return true
end
return false
end
@@ -362,7 +389,6 @@ local function on_change(type, old_tab, new_tab)
serverlistmgr.sync()
end
--------------------------------------------------------------------------------
return {
name = "online",
caption = fgettext("Join Game"),

View File

@@ -43,6 +43,14 @@ local labels = {
fgettext("2x"),
fgettext("4x"),
fgettext("8x")
},
shadow_levels = {
fgettext("Disabled"),
fgettext("Very Low"),
fgettext("Low"),
fgettext("Medium"),
fgettext("High"),
fgettext("Ultra High")
}
}
@@ -66,6 +74,10 @@ local dd_options = {
antialiasing = {
table.concat(labels.antialiasing, ","),
{"0", "2", "4", "8"}
},
shadow_levels = {
table.concat(labels.shadow_levels, ","),
{ "0", "1", "2", "3", "4", "5" }
}
}
@@ -110,6 +122,15 @@ local getSettingIndex = {
end
end
return 1
end,
ShadowMapping = function()
local shadow_setting = core.settings:get("shadow_levels")
for i = 1, #dd_options.shadow_levels[2] do
if shadow_setting == dd_options.shadow_levels[2][i] then
return i
end
end
return 1
end
}
@@ -198,6 +219,9 @@ local function formspec(tabview, name, tabdata)
.. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" ..
"checkbox[8.25,2;cb_waving_plants;" .. fgettext("Waving Plants") .. ";"
.. dump(core.settings:get_bool("enable_waving_plants")) .. "]"
--"label[8.25,3.0;" .. fgettext("Dynamic shadows: ") .. "]" ..
--"dropdown[8.25,3.5;3.5;dd_shadows;" .. dd_options.shadow_levels[1] .. ";"
-- .. getSettingIndex.ShadowMapping() .. "]"
else
tab_string = tab_string ..
"label[8.38,0.7;" .. core.colorize("#888888",
@@ -208,6 +232,8 @@ local function formspec(tabview, name, tabdata)
fgettext("Waving Leaves")) .. "]" ..
"label[8.38,2.2;" .. core.colorize("#888888",
fgettext("Waving Plants")) .. "]"
--"label[8.38,2.7;" .. core.colorize("#888888",
-- fgettext("Dynamic shadows")) .. "]"
end
return tab_string
@@ -221,7 +247,7 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
adv_settings_dlg:set_parent(this)
this:hide()
adv_settings_dlg:show()
--mm_texture.update("singleplayer", current_game())
--mm_game_theme.update("singleplayer", current_game())
return true
end
if fields["cb_smooth_lighting"] then
@@ -249,13 +275,7 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
return true
end
if fields["cb_shaders"] then
if (core.settings:get("video_driver") == "direct3d8" or
core.settings:get("video_driver") == "direct3d9") then
core.settings:set("enable_shaders", "false")
gamedata.errormessage = fgettext("To enable shaders the OpenGL driver needs to be used.")
else
core.settings:set("enable_shaders", fields["cb_shaders"])
end
core.settings:set("enable_shaders", fields["cb_shaders"])
return true
end
if fields["cb_tonemapping"] then
@@ -333,6 +353,34 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
ddhandled = true
end
for i = 1, #labels.shadow_levels do
if fields["dd_shadows"] == labels.shadow_levels[i] then
core.settings:set("shadow_levels", dd_options.shadow_levels[2][i])
ddhandled = true
end
end
if fields["dd_shadows"] == labels.shadow_levels[1] then
core.settings:set("enable_dynamic_shadows", "false")
else
local shadow_presets = {
[2] = { 80, 512, "true", 0, "false" },
[3] = { 120, 1024, "true", 1, "false" },
[4] = { 350, 2048, "true", 1, "false" },
[5] = { 350, 2048, "true", 2, "true" },
[6] = { 450, 4096, "true", 2, "true" },
}
local s = shadow_presets[table.indexof(labels.shadow_levels, fields["dd_shadows"])]
if s then
core.settings:set("enable_dynamic_shadows", "true")
core.settings:set("shadow_map_max_distance", s[1])
core.settings:set("shadow_map_texture_size", s[2])
core.settings:set("shadow_map_texture_32bit", s[3])
core.settings:set("shadow_filters", s[4])
core.settings:set("shadow_map_color", s[5])
end
end
return ddhandled
end

View File

@@ -2,6 +2,7 @@ _G.core = {}
_G.unpack = table.unpack
_G.serverlistmgr = {}
dofile("builtin/common/vector.lua")
dofile("builtin/common/misc_helpers.lua")
dofile("builtin/mainmenu/serverlistmgr.lua")

View File

@@ -15,6 +15,8 @@
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local S = core.get_translator("__builtin")
local function get_bool_default(name, default)
local val = core.settings:get_bool(name)
if val == nil then
@@ -40,9 +42,9 @@ function profiler.init_chatcommand()
instrumentation.init_chatcommand()
end
local param_usage = "print [filter] | dump [filter] | save [format [filter]] | reset"
local param_usage = S("print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset")
core.register_chatcommand("profiler", {
description = "handle the profiler and profiling data",
description = S("Handle the profiler and profiling data"),
params = param_usage,
privs = { server=true },
func = function(name, param)
@@ -51,21 +53,19 @@ function profiler.init_chatcommand()
if command == "dump" then
core.log("action", reporter.print(sampler.profile, arg0))
return true, "Statistics written to action log"
return true, S("Statistics written to action log.")
elseif command == "print" then
return true, reporter.print(sampler.profile, arg0)
elseif command == "save" then
return reporter.save(sampler.profile, args[1] or "txt", args[2])
elseif command == "reset" then
sampler.reset()
return true, "Statistics were reset"
return true, S("Statistics were reset.")
end
return false, string.format(
"Usage: %s\n" ..
"Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).",
param_usage
)
return false,
S("Usage: @1", param_usage) .. "\n" ..
S("Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).")
end
})

View File

@@ -102,8 +102,9 @@ local function instrument(def)
-- also called https://en.wikipedia.org/wiki/Continuation_passing_style
-- Compared to table creation and unpacking it won't lose `nil` returns
-- and is expected to be faster
-- `measure` will be executed after time() and func(...)
return measure(modname, instrument_name, time(), func(...))
-- `measure` will be executed after func(...)
local start = time()
return measure(modname, instrument_name, start, func(...))
end
end

View File

@@ -15,6 +15,10 @@
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local S = core.get_translator("__builtin")
-- Note: In this file, only messages are translated
-- but not the table itself, to keep it simple.
local DIR_DELIM, LINE_DELIM = DIR_DELIM, "\n"
local table, unpack, string, pairs, io, os = table, unpack, string, pairs, io, os
local rep, sprintf, tonumber = string.rep, string.format, tonumber
@@ -104,11 +108,11 @@ local TxtFormatter = Formatter:new {
end,
format = function(self, filter)
local profile = self.profile
self:print("Values below show absolute/relative times spend per server step by the instrumented function.")
self:print("A total of %d samples were taken", profile.stats_total.samples)
self:print(S("Values below show absolute/relative times spend per server step by the instrumented function."))
self:print(S("A total of @1 sample(s) were taken.", profile.stats_total.samples))
if filter then
self:print("The output is limited to '%s'", filter)
self:print(S("The output is limited to '@1'.", filter))
end
self:print()
@@ -259,19 +263,18 @@ function reporter.save(profile, format, filter)
local output, io_err = io.open(path, "w")
if not output then
return false, "Saving of profile failed with: " .. io_err
return false, S("Saving of profile failed: @1", io_err)
end
local content, err = serialize_profile(profile, format, filter)
if not content then
output:close()
return false, "Saving of profile failed with: " .. err
return false, S("Saving of profile failed: @1", err)
end
output:write(content)
output:close()
local logmessage = "Profile saved to " .. path
core.log("action", logmessage)
return true, logmessage
core.log("action", "Profile saved to " .. path)
return true, S("Profile saved to @1", path)
end
return reporter

View File

@@ -75,7 +75,7 @@ free_move (Flying) bool false
# If enabled, makes move directions relative to the player's pitch when flying or swimming.
pitch_move (Pitch move mode) bool false
# Fast movement (via the "special" key).
# Fast movement (via the "Aux1" key).
# This requires the "fast" privilege on the server.
fast_move (Fast movement) bool false
@@ -99,14 +99,14 @@ invert_mouse (Invert mouse) bool false
# Mouse sensitivity multiplier.
mouse_sensitivity (Mouse sensitivity) float 0.2
# If enabled, "special" key instead of "sneak" key is used for climbing down and
# If enabled, "Aux1" key instead of "Sneak" key is used for climbing down and
# descending.
aux1_descends (Special key for climbing/descending) bool false
aux1_descends (Aux1 key for climbing/descending) bool false
# Double-tapping the jump key toggles fly mode.
doubletap_jump (Double tap jump for fly) bool false
# If disabled, "special" key is used to fly fast if both fly and fast mode are
# If disabled, "Aux1" key is used to fly fast if both fly and fast mode are
# enabled.
always_fly_fast (Always fly and fast) bool true
@@ -135,9 +135,9 @@ touchscreen_threshold (Touch screen threshold) int 20 0 100
# If disabled, virtual joystick will center to first-touch's position.
fixed_virtual_joystick (Fixed virtual joystick) bool false
# (Android) Use virtual joystick to trigger "aux" button.
# If enabled, virtual joystick will also tap "aux" button when out of main circle.
virtual_joystick_triggers_aux (Virtual joystick triggers aux button) bool false
# (Android) Use virtual joystick to trigger "Aux1" button.
# If enabled, virtual joystick will also tap "Aux1" button when out of main circle.
virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool false
# Enable joysticks
enable_joysticks (Enable joysticks) bool false
@@ -146,17 +146,17 @@ enable_joysticks (Enable joysticks) bool false
joystick_id (Joystick ID) int 0
# The type of joystick
joystick_type (Joystick type) enum auto auto,generic,xbox
joystick_type (Joystick type) enum auto auto,generic,xbox,dragonrise_gamecube
# The time in seconds it takes between repeated events
# when holding down a joystick button combination.
repeat_joystick_button_time (Joystick button repetition interval) float 0.17 0.001
# The deadzone of the joystick
joystick_deadzone (Joystick deadzone) int 2048
# The dead zone of the joystick
joystick_deadzone (Joystick dead zone) int 2048
# The sensitivity of the joystick axes for moving the
# ingame view frustum around.
# in-game view frustum around.
joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170
# Key for moving the player forward.
@@ -199,7 +199,7 @@ keymap_inventory (Inventory key) key KEY_KEY_I
# Key for moving fast in fast mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_special1 (Special key) key KEY_KEY_E
keymap_aux1 (Aux1 key) key KEY_KEY_E
# Key for opening the chat window.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
@@ -451,9 +451,9 @@ keymap_decrease_viewing_range_min (View range decrease key) key -
[**Basic]
# Whether nametag backgrounds should be shown by default.
# Whether name tag backgrounds should be shown by default.
# Mods may still set a background.
show_nametag_backgrounds (Show nametag backgrounds by default) bool true
show_nametag_backgrounds (Show name tag backgrounds by default) bool true
# Enable vertex buffer objects.
# This should greatly improve graphics performance.
@@ -475,6 +475,10 @@ connected_glass (Connect glass) bool false
# Disable for speed or for different looks.
smooth_lighting (Smooth lighting) bool true
# Enables tradeoffs that reduce CPU load or increase rendering performance
# at the expense of minor visual glitches that do not impact game playability.
performance_tradeoffs (Tradeoffs for performance) bool false
# Clouds are a client side effect.
enable_clouds (Clouds) bool true
@@ -489,7 +493,7 @@ enable_particles (Digging particles) bool true
[**Filtering]
# Use mip mapping to scale textures. May slightly increase performance,
# Use mipmapping to scale textures. May slightly increase performance,
# especially when using a high resolution texture pack.
# Gamma correct downscaling is not supported.
mip_map (Mipmapping) bool false
@@ -504,18 +508,17 @@ bilinear_filter (Bilinear filtering) bool false
trilinear_filter (Trilinear filtering) bool false
# Filtered textures can blend RGB values with fully-transparent neighbors,
# which PNG optimizers usually discard, sometimes resulting in a dark or
# light edge to transparent textures. Apply this filter to clean that up
# at texture load time.
# which PNG optimizers usually discard, often resulting in dark or
# light edges to transparent textures. Apply a filter to clean that up
# at texture load time. This is automatically enabled if mipmapping is enabled.
texture_clean_transparent (Clean transparent textures) bool false
# When using bilinear/trilinear/anisotropic filters, low-resolution textures
# can be blurred, so automatically upscale them with nearest-neighbor
# interpolation to preserve crisp pixels. This sets the minimum texture size
# for the upscaled textures; higher values look sharper, but require more
# memory. Powers of 2 are recommended. Setting this higher than 1 may not
# have a visible effect unless bilinear/trilinear/anisotropic filtering is
# enabled.
# memory. Powers of 2 are recommended. This setting is ONLY applied if
# bilinear/trilinear/anisotropic filtering is enabled.
# This is also used as the base node texture size for world-aligned
# texture autoscaling.
texture_min_size (Minimum texture size) int 64
@@ -609,10 +612,10 @@ viewing_range (Viewing range) int 190 20 4000
# 0.1 = Default, 0.25 = Good value for weaker tablets.
near_plane (Near plane) float 0.1 0 0.25
# Width component of the initial window size.
# Width component of the initial window size. Ignored in fullscreen mode.
screen_w (Screen width) int 1024 1
# Height component of the initial window size.
# Height component of the initial window size. Ignored in fullscreen mode.
screen_h (Screen height) int 600 1
# Save window size automatically when modified.
@@ -621,9 +624,6 @@ autosave_screensize (Autosave screen size) bool true
# Fullscreen mode.
fullscreen (Full screen) bool false
# Bits per pixel (aka color depth) in fullscreen mode.
fullscreen_bpp (Full screen BPP) int 24
# Vertical screen synchronization.
vsync (VSync) bool false
@@ -662,12 +662,12 @@ lighting_boost_spread (Light curve boost spread) float 0.2 0.0 0.4
# Path to texture directory. All textures are first searched from here.
texture_path (Texture path) path
# The rendering back-end for Irrlicht.
# The rendering back-end.
# A restart is required after changing this.
# Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise.
# On other platforms, OpenGL is recommended.
# Shaders are supported by OpenGL (desktop only) and OGLES2 (experimental)
video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl,ogles1,ogles2
video_driver (Video driver) enum opengl opengl,ogles1,ogles2
# Radius of cloud area stated in number of 64 node cloud squares.
# Values larger than 26 will start to produce sharp cutoffs at cloud area corners.
@@ -728,7 +728,7 @@ selectionbox_width (Selection box width) int 2 1 5
crosshair_color (Crosshair color) string (255,255,255)
# Crosshair alpha (opaqueness, between 0 and 255).
# Also controls the object crosshair color
# This also applies to the object crosshair.
crosshair_alpha (Crosshair alpha) int 255 0 255
# Maximum number of recent chat messages to show
@@ -741,7 +741,7 @@ desynchronize_mapblock_texture_animation (Desynchronize block animation) bool tr
# Useful if there's something to be displayed right or left of hotbar.
hud_hotbar_max_width (Maximum hotbar width) float 1.0
# Modifies the size of the hudbar elements.
# Modifies the size of the HUD elements.
hud_scaling (HUD scale factor) float 1.0
# Enables caching of facedir rotated meshes.
@@ -834,10 +834,6 @@ tooltip_show_delay (Tooltip delay) int 400
# Append item name to tooltip.
tooltip_append_itemname (Append item name) bool false
# Whether FreeType fonts are used, requires FreeType support to be compiled in.
# If disabled, bitmap and XML vectors fonts are used instead.
freetype (FreeType fonts) bool true
font_bold (Font bold by default) bool false
font_italic (Font italic by default) bool false
@@ -848,44 +844,41 @@ font_shadow (Font shadow) int 1
# Opaqueness (alpha) of the shadow behind the default font, between 0 and 255.
font_shadow_alpha (Font shadow alpha) int 127 0 255
# Font size of the default font in point (pt).
# Font size of the default font where 1 unit = 1 pixel at 96 DPI
font_size (Font size) int 16 1
# Path to the default font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# For pixel-style fonts that do not scale well, this ensures that font sizes used
# with this font will always be divisible by this value, in pixels. For instance,
# a pixel font 16 pixels tall should have this set to 16, so it will only ever be
# sized 16, 32, 48, etc., so a mod requesting a size of 25 will get 32.
font_size_divisible_by (Font size divisible by) int 1 1
# Path to the default font. Must be a TrueType font.
# The fallback font will be used if the font cannot be loaded.
font_path (Regular font path) filepath fonts/Arimo-Regular.ttf
font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf
font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf
font_path_bolditalic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf
font_path_bold_italic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf
# Font size of the monospace font in point (pt).
mono_font_size (Monospace font size) int 15 1
# Font size of the monospace font where 1 unit = 1 pixel at 96 DPI
mono_font_size (Monospace font size) int 16 1
# Path to the monospace font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# For pixel-style fonts that do not scale well, this ensures that font sizes used
# with this font will always be divisible by this value, in pixels. For instance,
# a pixel font 16 pixels tall should have this set to 16, so it will only ever be
# sized 16, 32, 48, etc., so a mod requesting a size of 25 will get 32.
mono_font_size_divisible_by (Monospace font size divisible by) int 1 1
# Path to the monospace font. Must be a TrueType font.
# This font is used for e.g. the console and profiler screen.
mono_font_path (Monospace font path) filepath fonts/Cousine-Regular.ttf
mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf
mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf
mono_font_path_bolditalic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf
mono_font_path_bold_italic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf
# Font size of the fallback font in point (pt).
fallback_font_size (Fallback font size) int 15 1
# Shadow offset (in pixels) of the fallback font. If 0, then shadow will not be drawn.
fallback_font_shadow (Fallback font shadow) int 1
# Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255.
fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255
# Path of the fallback font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# Path of the fallback font. Must be a TrueType font.
# This font will be used for certain languages or if the default font is unavailable.
fallback_font_path (Fallback font path) filepath fonts/DroidSansFallbackFull.ttf
@@ -898,7 +891,7 @@ chat_font_size (Chat font size) int 0
screenshot_path (Screenshot folder) path screenshots
# Format of screenshots.
screenshot_format (Screenshot format) enum png png,jpg,bmp,pcx,ppm,tga
screenshot_format (Screenshot format) enum png png,jpg
# Screenshot quality. Only used for JPEG format.
# 1 means worst quality; 100 means best quality.
@@ -910,6 +903,9 @@ screenshot_quality (Screenshot quality) int 0 0 100
# Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens.
screen_dpi (DPI) int 72 1
# Adjust the detected display density, used for scaling UI elements.
display_density_factor (Display Density Scaling Factor) float 1
# Windows systems only: Start Minetest with the command line window in the background.
# Contains the same information as the file debug.txt (default name).
enable_console (Enable console window) bool false
@@ -934,6 +930,12 @@ mute_sound (Mute sound) bool false
[Client]
# Clickable weblinks (middle-click or Ctrl+left-click) enabled in chat console output.
clickable_chat_weblinks (Chat weblinks) bool false
# Optional override for chat weblink color.
chat_weblink_color (Weblink color) string
[*Network]
# Address to connect to.
@@ -946,9 +948,9 @@ address (Server address) string
remote_port (Remote port) int 30000 1 65535
# Prometheus listener address.
# If minetest is compiled with ENABLE_PROMETHEUS option enabled,
# If Minetest is compiled with ENABLE_PROMETHEUS option enabled,
# enable metrics listener for Prometheus on that address.
# Metrics can be fetch on http://127.0.0.1:30000/metrics
# Metrics can be fetched on http://127.0.0.1:30000/metrics
prometheus_listener_address (Prometheus listener address) string 127.0.0.1:30000
# Save the map received by the client on disk.
@@ -1055,11 +1057,10 @@ full_block_send_enable_min_time_from_building (Delay in sending blocks after bui
# client number.
max_packets_per_iteration (Max. packets per iteration) int 1024
# ZLib compression level to use when sending mapblocks to the client.
# -1 - Zlib's default compression level
# 0 - no compresson, fastest
# Compression level to use when sending mapblocks to the client.
# -1 - use default compression level
# 0 - least compression, fastest
# 9 - best compression, slowest
# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method)
map_compression_level_net (Map Compression Level for Network Transfer) int -1 -1 9
[*Game]
@@ -1122,7 +1123,7 @@ enable_mod_channels (Mod channels) bool false
# If this is set, players will always (re)spawn at the given position.
static_spawnpoint (Static spawnpoint) string
# If enabled, new players cannot join with an empty password.
# If enabled, players cannot join without a password or change theirs to an empty password.
disallow_empty_password (Disallow empty passwords) bool false
# If enabled, disable cheat prevention in multiplayer.
@@ -1136,6 +1137,10 @@ enable_rollback_recording (Rollback recording) bool false
# @name, @message, @timestamp (optional)
chat_message_format (Chat message format) string <@name> @message
# If the execution of a chat command takes longer than this specified time in
# seconds, add the time information to the chat command message
chatcommand_msg_time_threshold (Chat command time message threshold) float 0.1
# A message to be displayed to all clients when the server shuts down.
kick_msg_shutdown (Shutdown message) string Server shutting down.
@@ -1240,7 +1245,7 @@ movement_gravity (Gravity) float 9.81
deprecated_lua_api_handling (Deprecated Lua API handling) enum log none,log,error
# Number of extra blocks that can be loaded by /clearobjects at once.
# This is a trade-off between sqlite transaction overhead and
# This is a trade-off between SQLite transaction overhead and
# memory consumption (4096=100MB, as a rule of thumb).
max_clearobjects_extra_loaded_blocks (Max. clearobjects extra blocks) int 4096
@@ -1254,12 +1259,11 @@ max_objects_per_block (Maximum objects per block) int 64
# See https://www.sqlite.org/pragma.html#pragma_synchronous
sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2
# ZLib compression level to use when saving mapblocks to disk.
# -1 - Zlib's default compression level
# 0 - no compresson, fastest
# Compression level to use when saving mapblocks to disk.
# -1 - use default compression level
# 0 - least compression, fastest
# 9 - best compression, slowest
# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method)
map_compression_level_disk (Map Compression Level for Disk Storage) int 3 -1 9
map_compression_level_disk (Map Compression Level for Disk Storage) int -1 -1 9
# Length of a server tick and the interval at which objects are generally updated over
# network.
@@ -1364,8 +1368,8 @@ instrument.abm (Active Block Modifiers) bool true
# Instrument the action function of Loading Block Modifiers on registration.
instrument.lbm (Loading Block Modifiers) bool true
# Instrument chatcommands on registration.
instrument.chatcommand (Chatcommands) bool true
# Instrument chat commands on registration.
instrument.chatcommand (Chat commands) bool true
# Instrument global callback functions on registration.
# (anything you pass to a minetest.register_*() function)
@@ -1391,7 +1395,7 @@ name (Player name) string
# Set the language. Leave empty to use the system language.
# A restart is required after changing this.
language (Language) enum ,ar,ca,cs,da,de,dv,el,en,eo,es,et,eu,fil,fr,hu,id,it,ja,ja_KS,jbo,kk,kn,lo,lt,ms,my,nb,nl,nn,pl,pt,pt_BR,ro,ru,sl,sr_Cyrl,sv,sw,th,tr,uk,vi
language (Language) enum ,be,bg,ca,cs,da,de,el,en,eo,es,et,eu,fi,fr,gd,gl,hu,id,it,ja,jbo,kk,ko,lt,lv,ms,nb,nl,nn,pl,pt,pt_BR,ro,ru,sk,sl,sr_Cyrl,sr_Latn,sv,sw,tr,uk,vi,zh_CN,zh_TW
# Level of logging to be written to debug.txt:
# - <nothing> (no logging)
@@ -1418,9 +1422,8 @@ enable_ipv6 (IPv6) bool true
[*Advanced]
# Default timeout for cURL, stated in milliseconds.
# Only has an effect if compiled with cURL.
curl_timeout (cURL timeout) int 5000
# Maximum time an interactive request (e.g. server list fetch) may take, stated in milliseconds.
curl_timeout (cURL interactive timeout) int 20000
# Limits number of parallel HTTP requests. Affects:
# - Media fetch if server uses remote_media setting.
@@ -1429,12 +1432,9 @@ curl_timeout (cURL timeout) int 5000
# Only has an effect if compiled with cURL.
curl_parallel_limit (cURL parallel limit) int 8
# Maximum time in ms a file download (e.g. a mod download) may take.
# Maximum time a file download (e.g. a mod download) may take, stated in milliseconds.
curl_file_download_timeout (cURL file download timeout) int 300000
# Makes DirectX work with LuaJIT. Disable if it causes troubles.
high_precision_fpu (High-precision FPU) bool true
# Replaces the default main menu with a custom one.
main_menu_script (Main menu script) string
@@ -1459,11 +1459,11 @@ max_block_generate_distance (Max block generate distance) int 10
# Limit of map generation, in nodes, in all 6 directions from (0, 0, 0).
# Only mapchunks completely within the mapgen limit are generated.
# Value is stored per-world.
mapgen_limit (Map generation limit) int 31000 0 31000
mapgen_limit (Map generation limit) int 31007 0 31007
# Global map generation attributes.
# In Mapgen v6 the 'decorations' flag controls all decorations except trees
# and junglegrass, in all other mapgens this flag controls all decorations.
# and jungle grass, in all other mapgens this flag controls all decorations.
mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores,nocaves,nodungeons,nolight,nodecorations,nobiomes,noores
[*Biome API temperature and humidity noise parameters]
@@ -2173,15 +2173,15 @@ chunksize (Chunk size) int 5
enable_mapgen_debug_info (Mapgen debug) bool false
# Maximum number of blocks that can be queued for loading.
emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 1024
emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 1024 1 1000000
# Maximum number of blocks to be queued that are to be loaded from file.
# This limit is enforced per player.
emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 128
emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 128 1 1000000
# Maximum number of blocks to be queued that are to be generated.
# This limit is enforced per player.
emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 128
emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 128 1 1000000
# Number of emerge threads to use.
# Value 0:

View File

@@ -6,7 +6,7 @@ uniform sampler2D textureFlags;
#define rightImage normalTexture
#define maskImage textureFlags
varying mediump vec2 varTexCoord;
varying mediump vec4 varTexCoord;
void main(void)
{

View File

@@ -1,4 +1,4 @@
varying mediump vec2 varTexCoord;
varying mediump vec4 varTexCoord;
void main(void)
{

View File

@@ -3,5 +3,9 @@ varying lowp vec4 varColor;
void main(void)
{
gl_Position = mWorldViewProj * inVertexPosition;
#ifdef GL_ES
varColor = inVertexColor.bgra;
#else
varColor = inVertexColor;
#endif
}

View File

@@ -7,5 +7,9 @@ void main(void)
{
varTexCoord = inTexCoord0.st;
gl_Position = mWorldViewProj * inVertexPosition;
#ifdef GL_ES
varColor = inVertexColor.bgra;
#else
varColor = inVertexColor;
#endif
}

View File

@@ -1,5 +1,6 @@
uniform sampler2D baseTexture;
uniform vec3 dayLight;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
@@ -7,7 +8,22 @@ uniform vec3 eyePosition;
// The cameraOffset is the current center of the visible world.
uniform vec3 cameraOffset;
uniform float animationTimer;
#ifdef ENABLE_DYNAMIC_SHADOWS
// shadow texture
uniform sampler2D ShadowMapSampler;
// shadow uniforms
uniform vec3 v_LightDirection;
uniform float f_textureresolution;
uniform mat4 m_ShadowViewProj;
uniform float f_shadowfar;
varying float normalOffsetScale;
varying float adj_shadow_strength;
varying float cosLight;
varying float f_normal_length;
#endif
varying vec3 vNormal;
varying vec3 vPosition;
// World position in the visible world (i.e. relative to the cameraOffset.)
// This can be used for many shader effects without loss of precision.
@@ -22,10 +38,393 @@ varying mediump vec2 varTexCoord;
centroid varying vec2 varTexCoord;
#endif
varying vec3 eyeVec;
varying float nightRatio;
const float fogStart = FOG_START;
const float fogShadingParameter = 1.0 / ( 1.0 - fogStart);
#ifdef ENABLE_DYNAMIC_SHADOWS
const float bias0 = 0.9;
const float zPersFactor = 0.5;
const float bias1 = 1.0 - bias0 + 1e-6;
vec4 getPerspectiveFactor(in vec4 shadowPosition)
{
float pDistance = length(shadowPosition.xy);
float pFactor = pDistance * bias0 + bias1;
shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor);
return shadowPosition;
}
// assuming near is always 1.0
float getLinearDepth()
{
return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0));
}
vec3 getLightSpacePosition()
{
vec4 pLightSpace;
// some drawtypes have zero normals, so we need to handle it :(
#if DRAW_TYPE == NDT_PLANTLIKE
pLightSpace = m_ShadowViewProj * vec4(worldPosition, 1.0);
#else
float offsetScale = (0.0057 * getLinearDepth() + normalOffsetScale);
pLightSpace = m_ShadowViewProj * vec4(worldPosition + offsetScale * normalize(vNormal), 1.0);
#endif
pLightSpace = getPerspectiveFactor(pLightSpace);
return pLightSpace.xyz * 0.5 + 0.5;
}
// custom smoothstep implementation because it's not defined in glsl1.2
// https://docs.gl/sl4/smoothstep
float mtsmoothstep(in float edge0, in float edge1, in float x)
{
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
#ifdef COLORED_SHADOWS
// c_precision of 128 fits within 7 base-10 digits
const float c_precision = 128.0;
const float c_precisionp1 = c_precision + 1.0;
float packColor(vec3 color)
{
return floor(color.b * c_precision + 0.5)
+ floor(color.g * c_precision + 0.5) * c_precisionp1
+ floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
}
vec3 unpackColor(float value)
{
vec3 color;
color.b = mod(value, c_precisionp1) / c_precision;
color.g = mod(floor(value / c_precisionp1), c_precisionp1) / c_precision;
color.r = floor(value / (c_precisionp1 * c_precisionp1)) / c_precision;
return color;
}
vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
float visibility = step(0.0, realDistance - texDepth.r);
vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
if (visibility < 0.1) {
visibility = step(0.0, realDistance - texDepth.b);
result = vec4(visibility, unpackColor(texDepth.a));
}
return result;
}
#else
float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
float visibility = step(0.0, realDistance - texDepth);
return visibility;
}
#endif
#if SHADOW_FILTER == 2
#define PCFBOUND 3.5
#define PCFSAMPLES 64.0
#elif SHADOW_FILTER == 1
#define PCFBOUND 1.5
#if defined(POISSON_FILTER)
#define PCFSAMPLES 32.0
#else
#define PCFSAMPLES 16.0
#endif
#else
#define PCFBOUND 0.0
#if defined(POISSON_FILTER)
#define PCFSAMPLES 4.0
#else
#define PCFSAMPLES 1.0
#endif
#endif
#ifdef COLORED_SHADOWS
float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy);
float depth = max(realDistance - texDepth.r, realDistance - texDepth.b);
return depth;
}
#else
float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
float depth = realDistance - texDepth;
return depth;
}
#endif
float getBaseLength(vec2 smTexCoord)
{
float l = length(2.0 * smTexCoord.xy - 1.0); // length in texture coords
return bias1 / (1.0 / l - bias0); // return to undistorted coords
}
float getDeltaPerspectiveFactor(float l)
{
return 0.1 / (bias0 * l + bias1); // original distortion factor, divided by 10
}
float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier)
{
float baseLength = getBaseLength(smTexCoord);
float perspectiveFactor;
if (PCFBOUND == 0.0) return 0.0;
// Return fast if sharp shadows are requested
if (SOFTSHADOWRADIUS <= 1.0) {
perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
return max(2 * length(smTexCoord.xy) * 2048 / f_textureresolution / pow(perspectiveFactor, 3), SOFTSHADOWRADIUS);
}
vec2 clampedpos;
float texture_size = 1.0 / (2048 /*f_textureresolution*/ * 0.5);
float y, x;
float depth = 0.0;
float pointDepth;
float maxRadius = SOFTSHADOWRADIUS * 5.0 * multiplier;
float bound = clamp(PCFBOUND * (1 - baseLength), 0.0, PCFBOUND);
int n = 0;
for (y = -bound; y <= bound; y += 1.0)
for (x = -bound; x <= bound; x += 1.0) {
clampedpos = vec2(x,y);
perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * maxRadius);
clampedpos = clampedpos * texture_size * perspectiveFactor * maxRadius * perspectiveFactor + smTexCoord.xy;
pointDepth = getHardShadowDepth(shadowsampler, clampedpos.xy, realDistance);
if (pointDepth > -0.01) {
depth += pointDepth;
n += 1;
}
}
depth = depth / n;
depth = pow(clamp(depth, 0.0, 1000.0), 1.6) / 0.001;
perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
return max(length(smTexCoord.xy) * 2 * 2048 / f_textureresolution / pow(perspectiveFactor, 3), depth * maxRadius);
}
#ifdef POISSON_FILTER
const vec2[64] poissonDisk = vec2[64](
vec2(0.170019, -0.040254),
vec2(-0.299417, 0.791925),
vec2(0.645680, 0.493210),
vec2(-0.651784, 0.717887),
vec2(0.421003, 0.027070),
vec2(-0.817194, -0.271096),
vec2(-0.705374, -0.668203),
vec2(0.977050, -0.108615),
vec2(0.063326, 0.142369),
vec2(0.203528, 0.214331),
vec2(-0.667531, 0.326090),
vec2(-0.098422, -0.295755),
vec2(-0.885922, 0.215369),
vec2(0.566637, 0.605213),
vec2(0.039766, -0.396100),
vec2(0.751946, 0.453352),
vec2(0.078707, -0.715323),
vec2(-0.075838, -0.529344),
vec2(0.724479, -0.580798),
vec2(0.222999, -0.215125),
vec2(-0.467574, -0.405438),
vec2(-0.248268, -0.814753),
vec2(0.354411, -0.887570),
vec2(0.175817, 0.382366),
vec2(0.487472, -0.063082),
vec2(0.355476, 0.025357),
vec2(-0.084078, 0.898312),
vec2(0.488876, -0.783441),
vec2(0.470016, 0.217933),
vec2(-0.696890, -0.549791),
vec2(-0.149693, 0.605762),
vec2(0.034211, 0.979980),
vec2(0.503098, -0.308878),
vec2(-0.016205, -0.872921),
vec2(0.385784, -0.393902),
vec2(-0.146886, -0.859249),
vec2(0.643361, 0.164098),
vec2(0.634388, -0.049471),
vec2(-0.688894, 0.007843),
vec2(0.464034, -0.188818),
vec2(-0.440840, 0.137486),
vec2(0.364483, 0.511704),
vec2(0.034028, 0.325968),
vec2(0.099094, -0.308023),
vec2(0.693960, -0.366253),
vec2(0.678884, -0.204688),
vec2(0.001801, 0.780328),
vec2(0.145177, -0.898984),
vec2(0.062655, -0.611866),
vec2(0.315226, -0.604297),
vec2(-0.780145, 0.486251),
vec2(-0.371868, 0.882138),
vec2(0.200476, 0.494430),
vec2(-0.494552, -0.711051),
vec2(0.612476, 0.705252),
vec2(-0.578845, -0.768792),
vec2(-0.772454, -0.090976),
vec2(0.504440, 0.372295),
vec2(0.155736, 0.065157),
vec2(0.391522, 0.849605),
vec2(-0.620106, -0.328104),
vec2(0.789239, -0.419965),
vec2(-0.545396, 0.538133),
vec2(-0.178564, -0.596057)
);
#ifdef COLORED_SHADOWS
vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
vec4 visibility = vec4(0.0);
float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
if (radius < 0.1) {
// we are in the middle of even brightness, no need for filtering
return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
}
float baseLength = getBaseLength(smTexCoord);
float perspectiveFactor;
float texture_size = 1.0 / (f_textureresolution * 0.5);
int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
int end_offset = int(samples) + init_offset;
for (int x = init_offset; x < end_offset; x++) {
clampedpos = poissonDisk[x];
perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
}
return visibility / samples;
}
#else
float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
float visibility = 0.0;
float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
if (radius < 0.1) {
// we are in the middle of even brightness, no need for filtering
return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
}
float baseLength = getBaseLength(smTexCoord);
float perspectiveFactor;
float texture_size = 1.0 / (f_textureresolution * 0.5);
int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
int end_offset = int(samples) + init_offset;
for (int x = init_offset; x < end_offset; x++) {
clampedpos = poissonDisk[x];
perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
}
return visibility / samples;
}
#endif
#else
/* poisson filter disabled */
#ifdef COLORED_SHADOWS
vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
vec4 visibility = vec4(0.0);
float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
if (radius < 0.1) {
// we are in the middle of even brightness, no need for filtering
return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
}
float baseLength = getBaseLength(smTexCoord);
float perspectiveFactor;
float texture_size = 1.0 / (f_textureresolution * 0.5);
float y, x;
float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
int n = 0;
// basic PCF filter
for (y = -bound; y <= bound; y += 1.0)
for (x = -bound; x <= bound; x += 1.0) {
clampedpos = vec2(x,y); // screen offset
perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
n += 1;
}
return visibility / n;
}
#else
float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
float visibility = 0.0;
float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
if (radius < 0.1) {
// we are in the middle of even brightness, no need for filtering
return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
}
float baseLength = getBaseLength(smTexCoord);
float perspectiveFactor;
float texture_size = 1.0 / (f_textureresolution * 0.5);
float y, x;
float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
int n = 0;
// basic PCF filter
for (y = -bound; y <= bound; y += 1.0)
for (x = -bound; x <= bound; x += 1.0) {
clampedpos = vec2(x,y); // screen offset
perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
n += 1;
}
return visibility / n;
}
#endif
#endif
#endif
#if ENABLE_TONE_MAPPING
/* Hable's UC2 Tone mapping parameters
@@ -58,25 +457,79 @@ vec4 applyToneMapping(vec4 color)
}
#endif
void main(void)
{
vec3 color;
vec2 uv = varTexCoord.st;
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef USE_DISCARD
// If alpha is zero, we can just discard the pixel. This fixes transparency
// on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
// and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
if (base.a == 0.0) {
#ifdef USE_DISCARD
if (base.a == 0.0)
discard;
#endif
#ifdef USE_DISCARD_REF
if (base.a < 0.5)
discard;
}
#endif
color = base.rgb;
vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS
float shadow_int = 0.0;
vec3 shadow_color = vec3(0.0, 0.0, 0.0);
vec3 posLightSpace = getLightSpacePosition();
float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0));
float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0);
if (distance_rate > 1e-7) {
#ifdef COLORED_SHADOWS
vec4 visibility;
if (cosLight > 0.0)
visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
else
visibility = vec4(1.0, 0.0, 0.0, 0.0);
shadow_int = visibility.r;
shadow_color = visibility.gba;
#else
if (cosLight > 0.0)
shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
else
shadow_int = 1.0;
#endif
shadow_int *= distance_rate;
shadow_int = clamp(shadow_int, 0.0, 1.0);
}
// turns out that nightRatio falls off much faster than
// actual brightness of artificial light in relation to natual light.
// Power ratio was measured on torches in MTG (brightness = 14).
float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6);
if (f_normal_length != 0 && cosLight < 0.035) {
shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, 0.035)/0.035);
}
shadow_int *= f_adj_shadow_strength;
// calculate fragment color from components:
col.rgb =
adjusted_night_ratio * col.rgb + // artificial light
(1.0 - adjusted_night_ratio) * ( // natural light
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
// col.r = 0.5 * clamp(getPenumbraRadius(ShadowMapSampler, posLightSpace.xy, posLightSpace.z, 1.0) / SOFTSHADOWRADIUS, 0.0, 1.0) + 0.5 * col.r;
// col.r = adjusted_night_ratio; // debug night ratio adjustment
#endif
#if ENABLE_TONE_MAPPING
col = applyToneMapping(col);
#endif
@@ -94,6 +547,6 @@ void main(void)
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(skyBgColor, col, clarity);
col = vec4(col.rgb, base.a);
gl_FragColor = col;
}

View File

@@ -1,5 +1,4 @@
uniform mat4 mWorld;
// Color of the light emitted by the sun.
uniform vec3 dayLight;
uniform vec3 eyePosition;
@@ -8,6 +7,7 @@ uniform vec3 eyePosition;
uniform vec3 cameraOffset;
uniform float animationTimer;
varying vec3 vNormal;
varying vec3 vPosition;
// World position in the visible world (i.e. relative to the cameraOffset.)
// This can be used for many shader effects without loss of precision.
@@ -24,13 +24,38 @@ varying mediump vec2 varTexCoord;
#else
centroid varying vec2 varTexCoord;
#endif
varying vec3 eyeVec;
#ifdef ENABLE_DYNAMIC_SHADOWS
// shadow uniforms
uniform vec3 v_LightDirection;
uniform float f_textureresolution;
uniform mat4 m_ShadowViewProj;
uniform float f_shadowfar;
uniform float f_shadow_strength;
uniform float f_timeofday;
varying float cosLight;
varying float normalOffsetScale;
varying float adj_shadow_strength;
varying float f_normal_length;
#endif
varying vec3 eyeVec;
varying float nightRatio;
// Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
const float e = 2.718281828459;
const float BS = 10.0;
#ifdef ENABLE_DYNAMIC_SHADOWS
// custom smoothstep implementation because it's not defined in glsl1.2
// https://docs.gl/sl4/smoothstep
float mtsmoothstep(in float edge0, in float edge1, in float x)
{
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
#endif
float smoothCurve(float x)
{
@@ -86,6 +111,9 @@ float snoise(vec3 p)
#endif
void main(void)
{
varTexCoord = inTexCoord0.st;
@@ -136,20 +164,23 @@ void main(void)
gl_Position = mWorldViewProj * inVertexPosition;
#endif
vPosition = gl_Position.xyz;
eyeVec = -(mWorldView * inVertexPosition).xyz;
vNormal = inVertexNormal;
// Calculate color.
// Red, green and blue components are pre-multiplied with
// the brightness, so now we have to multiply these
// colors with the color of the incoming light.
// The pre-baked colors are halved to prevent overflow.
vec4 color;
#ifdef GL_ES
vec4 color = inVertexColor.bgra;
#else
vec4 color = inVertexColor;
#endif
// The alpha gives the ratio of sunlight in the incoming light.
float nightRatio = 1.0 - inVertexColor.a;
color.rgb = inVertexColor.rgb * (inVertexColor.a * dayLight.rgb +
nightRatio = 1.0 - color.a;
color.rgb = color.rgb * (color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2.0;
color.a = 1.0;
@@ -160,4 +191,26 @@ void main(void)
0.07 * brightness);
varColor = clamp(color, 0.0, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS
vec3 nNormal = normalize(vNormal);
cosLight = dot(nNormal, -v_LightDirection);
float texelSize = 767.0 / f_textureresolution;
float slopeScale = clamp(1.0 - abs(cosLight), 0.0, 1.0);
normalOffsetScale = texelSize * slopeScale;
if (f_timeofday < 0.2) {
adj_shadow_strength = f_shadow_strength * 0.5 *
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday));
} else if (f_timeofday >= 0.8) {
adj_shadow_strength = f_shadow_strength * 0.5 *
mtsmoothstep(0.8, 0.83, f_timeofday);
} else {
adj_shadow_strength = f_shadow_strength *
mtsmoothstep(0.20, 0.25, f_timeofday) *
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
}
f_normal_length = length(vNormal);
#endif
}

View File

@@ -23,8 +23,22 @@ const float BS = 10.0;
const float fogStart = FOG_START;
const float fogShadingParameter = 1.0 / (1.0 - fogStart);
#if ENABLE_TONE_MAPPING
#ifdef ENABLE_DYNAMIC_SHADOWS
// shadow texture
uniform sampler2D ShadowMapSampler;
// shadow uniforms
uniform vec3 v_LightDirection;
uniform float f_textureresolution;
uniform mat4 m_ShadowViewProj;
uniform float f_shadowfar;
uniform float f_timeofday;
varying float normalOffsetScale;
varying float adj_shadow_strength;
varying float cosLight;
varying float f_normal_length;
#endif
#if ENABLE_TONE_MAPPING
/* Hable's UC2 Tone mapping parameters
A = 0.22;
B = 0.30;
@@ -55,30 +69,310 @@ vec4 applyToneMapping(vec4 color)
}
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS
const float bias0 = 0.9;
const float zPersFactor = 0.5;
const float bias1 = 1.0 - bias0;
vec4 getPerspectiveFactor(in vec4 shadowPosition)
{
float pDistance = length(shadowPosition.xy);
float pFactor = pDistance * bias0 + bias1;
shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor);
return shadowPosition;
}
// assuming near is always 1.0
float getLinearDepth()
{
return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0));
}
vec3 getLightSpacePosition()
{
vec4 pLightSpace;
float normalBias = 0.0005 * getLinearDepth() * cosLight + normalOffsetScale;
pLightSpace = m_ShadowViewProj * vec4(worldPosition + normalBias * normalize(vNormal), 1.0);
pLightSpace = getPerspectiveFactor(pLightSpace);
return pLightSpace.xyz * 0.5 + 0.5;
}
#ifdef COLORED_SHADOWS
// c_precision of 128 fits within 7 base-10 digits
const float c_precision = 128.0;
const float c_precisionp1 = c_precision + 1.0;
float packColor(vec3 color)
{
return floor(color.b * c_precision + 0.5)
+ floor(color.g * c_precision + 0.5) * c_precisionp1
+ floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
}
vec3 unpackColor(float value)
{
vec3 color;
color.b = mod(value, c_precisionp1) / c_precision;
color.g = mod(floor(value / c_precisionp1), c_precisionp1) / c_precision;
color.r = floor(value / (c_precisionp1 * c_precisionp1)) / c_precision;
return color;
}
vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
float visibility = step(0.0, (realDistance-2e-5) - texDepth.r);
vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
if (visibility < 0.1) {
visibility = step(0.0, (realDistance-2e-5) - texDepth.r);
result = vec4(visibility, unpackColor(texDepth.a));
}
return result;
}
#else
float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
float visibility = step(0.0, (realDistance-2e-5) - texDepth);
return visibility;
}
#endif
#if SHADOW_FILTER == 2
#define PCFBOUND 3.5
#define PCFSAMPLES 64.0
#elif SHADOW_FILTER == 1
#define PCFBOUND 1.5
#if defined(POISSON_FILTER)
#define PCFSAMPLES 32.0
#else
#define PCFSAMPLES 16.0
#endif
#else
#define PCFBOUND 0.0
#if defined(POISSON_FILTER)
#define PCFSAMPLES 4.0
#else
#define PCFSAMPLES 1.0
#endif
#endif
#ifdef POISSON_FILTER
const vec2[64] poissonDisk = vec2[64](
vec2(0.170019, -0.040254),
vec2(-0.299417, 0.791925),
vec2(0.645680, 0.493210),
vec2(-0.651784, 0.717887),
vec2(0.421003, 0.027070),
vec2(-0.817194, -0.271096),
vec2(-0.705374, -0.668203),
vec2(0.977050, -0.108615),
vec2(0.063326, 0.142369),
vec2(0.203528, 0.214331),
vec2(-0.667531, 0.326090),
vec2(-0.098422, -0.295755),
vec2(-0.885922, 0.215369),
vec2(0.566637, 0.605213),
vec2(0.039766, -0.396100),
vec2(0.751946, 0.453352),
vec2(0.078707, -0.715323),
vec2(-0.075838, -0.529344),
vec2(0.724479, -0.580798),
vec2(0.222999, -0.215125),
vec2(-0.467574, -0.405438),
vec2(-0.248268, -0.814753),
vec2(0.354411, -0.887570),
vec2(0.175817, 0.382366),
vec2(0.487472, -0.063082),
vec2(0.355476, 0.025357),
vec2(-0.084078, 0.898312),
vec2(0.488876, -0.783441),
vec2(0.470016, 0.217933),
vec2(-0.696890, -0.549791),
vec2(-0.149693, 0.605762),
vec2(0.034211, 0.979980),
vec2(0.503098, -0.308878),
vec2(-0.016205, -0.872921),
vec2(0.385784, -0.393902),
vec2(-0.146886, -0.859249),
vec2(0.643361, 0.164098),
vec2(0.634388, -0.049471),
vec2(-0.688894, 0.007843),
vec2(0.464034, -0.188818),
vec2(-0.440840, 0.137486),
vec2(0.364483, 0.511704),
vec2(0.034028, 0.325968),
vec2(0.099094, -0.308023),
vec2(0.693960, -0.366253),
vec2(0.678884, -0.204688),
vec2(0.001801, 0.780328),
vec2(0.145177, -0.898984),
vec2(0.062655, -0.611866),
vec2(0.315226, -0.604297),
vec2(-0.780145, 0.486251),
vec2(-0.371868, 0.882138),
vec2(0.200476, 0.494430),
vec2(-0.494552, -0.711051),
vec2(0.612476, 0.705252),
vec2(-0.578845, -0.768792),
vec2(-0.772454, -0.090976),
vec2(0.504440, 0.372295),
vec2(0.155736, 0.065157),
vec2(0.391522, 0.849605),
vec2(-0.620106, -0.328104),
vec2(0.789239, -0.419965),
vec2(-0.545396, 0.538133),
vec2(-0.178564, -0.596057)
);
#ifdef COLORED_SHADOWS
vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
vec4 visibility = vec4(0.0);
float texture_size = 1.0 / (f_textureresolution * 0.5);
int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-PCFSAMPLES)));
int end_offset = int(PCFSAMPLES) + init_offset;
for (int x = init_offset; x < end_offset; x++) {
clampedpos = poissonDisk[x] * texture_size * SOFTSHADOWRADIUS + smTexCoord.xy;
visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
}
return visibility / PCFSAMPLES;
}
#else
float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
float visibility = 0.0;
float texture_size = 1.0 / (f_textureresolution * 0.5);
int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-PCFSAMPLES)));
int end_offset = int(PCFSAMPLES) + init_offset;
for (int x = init_offset; x < end_offset; x++) {
clampedpos = poissonDisk[x] * texture_size * SOFTSHADOWRADIUS + smTexCoord.xy;
visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
}
return visibility / PCFSAMPLES;
}
#endif
#else
/* poisson filter disabled */
#ifdef COLORED_SHADOWS
vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
vec4 visibility = vec4(0.0);
float sradius=0.0;
if( PCFBOUND>0)
sradius = SOFTSHADOWRADIUS / PCFBOUND;
float texture_size = 1.0 / (f_textureresolution * 0.5);
float y, x;
// basic PCF filter
for (y = -PCFBOUND; y <= PCFBOUND; y += 1.0)
for (x = -PCFBOUND; x <= PCFBOUND; x += 1.0) {
clampedpos = vec2(x,y) * texture_size* sradius + smTexCoord.xy;
visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
}
return visibility / PCFSAMPLES;
}
#else
float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{
vec2 clampedpos;
float visibility = 0.0;
float sradius=0.0;
if( PCFBOUND>0)
sradius = SOFTSHADOWRADIUS / PCFBOUND;
float texture_size = 1.0 / (f_textureresolution * 0.5);
float y, x;
// basic PCF filter
for (y = -PCFBOUND; y <= PCFBOUND; y += 1.0)
for (x = -PCFBOUND; x <= PCFBOUND; x += 1.0) {
clampedpos = vec2(x,y) * texture_size * sradius + smTexCoord.xy;
visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
}
return visibility / PCFSAMPLES;
}
#endif
#endif
#endif
void main(void)
{
vec3 color;
vec2 uv = varTexCoord.st;
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef USE_DISCARD
// If alpha is zero, we can just discard the pixel. This fixes transparency
// on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
// and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
if (base.a == 0.0) {
#ifdef USE_DISCARD
if (base.a == 0.0)
discard;
#endif
#ifdef USE_DISCARD_REF
if (base.a < 0.5)
discard;
}
#endif
color = base.rgb;
vec4 col = vec4(color.rgb, base.a);
col.rgb *= varColor.rgb;
col.rgb *= emissiveColor.rgb * vIDiff;
#ifdef ENABLE_DYNAMIC_SHADOWS
float shadow_int = 0.0;
vec3 shadow_color = vec3(0.0, 0.0, 0.0);
vec3 posLightSpace = getLightSpacePosition();
#ifdef COLORED_SHADOWS
vec4 visibility;
if (cosLight > 0.0)
visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
else
visibility = vec4(1.0, 0.0, 0.0, 0.0);
shadow_int = visibility.r;
shadow_color = visibility.gba;
#else
shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
#endif
if (f_normal_length != 0 && cosLight <= 0.001) {
shadow_int = clamp(shadow_int + 0.5 * abs(cosLight), 0.0, 1.0);
}
shadow_int = 1.0 - (shadow_int * adj_shadow_strength);
col.rgb = mix(shadow_color, col.rgb, shadow_int) * shadow_int;
#endif
#if ENABLE_TONE_MAPPING
col = applyToneMapping(col);
#endif

View File

@@ -13,12 +13,37 @@ varying mediump vec2 varTexCoord;
centroid varying vec2 varTexCoord;
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS
// shadow uniforms
uniform vec3 v_LightDirection;
uniform float f_textureresolution;
uniform mat4 m_ShadowViewProj;
uniform float f_shadowfar;
uniform float f_shadow_strength;
uniform float f_timeofday;
varying float cosLight;
varying float normalOffsetScale;
varying float adj_shadow_strength;
varying float f_normal_length;
#endif
varying vec3 eyeVec;
varying float vIDiff;
const float e = 2.718281828459;
const float BS = 10.0;
#ifdef ENABLE_DYNAMIC_SHADOWS
// custom smoothstep implementation because it's not defined in glsl1.2
// https://docs.gl/sl4/smoothstep
float mtsmoothstep(in float edge0, in float edge1, in float x)
{
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
#endif
float directional_ambient(vec3 normal)
{
vec3 v = normal * normal;
@@ -49,5 +74,30 @@ void main(void)
: directional_ambient(normalize(inVertexNormal));
#endif
#ifdef GL_ES
varColor = inVertexColor.bgra;
#else
varColor = inVertexColor;
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS
cosLight = max(0.0, dot(vNormal, -v_LightDirection));
float texelSize = 0.51;
float slopeScale = clamp(1.0 - cosLight, 0.0, 1.0);
normalOffsetScale = texelSize * slopeScale;
if (f_timeofday < 0.2) {
adj_shadow_strength = f_shadow_strength * 0.5 *
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday));
} else if (f_timeofday >= 0.8) {
adj_shadow_strength = f_shadow_strength * 0.5 *
mtsmoothstep(0.8, 0.83, f_timeofday);
} else {
adj_shadow_strength = f_shadow_strength *
mtsmoothstep(0.20, 0.25, f_timeofday) *
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
}
f_normal_length = length(vNormal);
#endif
}

View File

@@ -6,5 +6,9 @@ void main(void)
varTexCoord = inTexCoord0.st;
gl_Position = mWorldViewProj * inVertexPosition;
#ifdef GL_ES
varColor = inVertexColor.bgra;
#else
varColor = inVertexColor;
#endif
}

View File

@@ -0,0 +1,13 @@
uniform sampler2D ColorMapSampler;
varying vec4 tPos;
void main()
{
vec4 col = texture2D(ColorMapSampler, gl_TexCoord[0].st);
if (col.a < 0.70)
discard;
float depth = 0.5 + tPos.z * 0.5;
gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);
}

View File

@@ -0,0 +1,42 @@
uniform sampler2D ColorMapSampler;
varying vec4 tPos;
#ifdef COLORED_SHADOWS
varying vec3 varColor;
// c_precision of 128 fits within 7 base-10 digits
const float c_precision = 128.0;
const float c_precisionp1 = c_precision + 1.0;
float packColor(vec3 color)
{
return floor(color.b * c_precision + 0.5)
+ floor(color.g * c_precision + 0.5) * c_precisionp1
+ floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
}
const vec3 black = vec3(0.0);
#endif
void main()
{
vec4 col = texture2D(ColorMapSampler, gl_TexCoord[0].st);
#ifndef COLORED_SHADOWS
if (col.a < 0.5)
discard;
#endif
float depth = 0.5 + tPos.z * 0.5;
// ToDo: Liso: Apply movement on waving plants
// depth in [0, 1] for texture
//col.rgb = col.a == 1.0 ? vec3(1.0) : col.rgb;
#ifdef COLORED_SHADOWS
col.rgb *= varColor.rgb;
// premultiply color alpha (see-through side)
float packedColor = packColor(col.rgb * (1.0 - col.a));
gl_FragColor = vec4(depth, packedColor, 0.0,1.0);
#else
gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);
#endif
}

View File

@@ -0,0 +1,33 @@
uniform mat4 LightMVP; // world matrix
varying vec4 tPos;
#ifdef COLORED_SHADOWS
varying vec3 varColor;
#endif
const float bias0 = 0.9;
const float zPersFactor = 0.5;
const float bias1 = 1.0 - bias0 + 1e-6;
vec4 getPerspectiveFactor(in vec4 shadowPosition)
{
float pDistance = length(shadowPosition.xy);
float pFactor = pDistance * bias0 + bias1;
shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor);
return shadowPosition;
}
void main()
{
vec4 pos = LightMVP * gl_Vertex;
tPos = getPerspectiveFactor(LightMVP * gl_Vertex);
gl_Position = vec4(tPos.xyz, 1.0);
gl_TexCoord[0].st = gl_MultiTexCoord0.st;
#ifdef COLORED_SHADOWS
varColor = gl_Color.rgb;
#endif
}

View File

@@ -0,0 +1,26 @@
uniform mat4 LightMVP; // world matrix
varying vec4 tPos;
const float bias0 = 0.9;
const float zPersFactor = 0.5;
const float bias1 = 1.0 - bias0 + 1e-6;
vec4 getPerspectiveFactor(in vec4 shadowPosition)
{
float pDistance = length(shadowPosition.xy);
float pFactor = pDistance * bias0 + bias1;
shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor);
return shadowPosition;
}
void main()
{
vec4 pos = LightMVP * gl_Vertex;
tPos = getPerspectiveFactor(pos);
gl_Position = vec4(tPos.xyz, 1.0);
gl_TexCoord[0].st = gl_MultiTexCoord0.st;
}

View File

@@ -0,0 +1,23 @@
uniform sampler2D ShadowMapClientMap;
#ifdef COLORED_SHADOWS
uniform sampler2D ShadowMapClientMapTraslucent;
#endif
uniform sampler2D ShadowMapSamplerdynamic;
void main() {
#ifdef COLORED_SHADOWS
vec2 first_depth = texture2D(ShadowMapClientMap, gl_TexCoord[0].st).rg;
vec2 depth_splitdynamics = vec2(texture2D(ShadowMapSamplerdynamic, gl_TexCoord[2].st).r, 0.0);
if (first_depth.r > depth_splitdynamics.r)
first_depth = depth_splitdynamics;
vec2 depth_color = texture2D(ShadowMapClientMapTraslucent, gl_TexCoord[1].st).rg;
gl_FragColor = vec4(first_depth.r, first_depth.g, depth_color.r, depth_color.g);
#else
float first_depth = texture2D(ShadowMapClientMap, gl_TexCoord[0].st).r;
float depth_splitdynamics = texture2D(ShadowMapSamplerdynamic, gl_TexCoord[2].st).r;
first_depth = min(first_depth, depth_splitdynamics);
gl_FragColor = vec4(first_depth, 0.0, 0.0, 1.0);
#endif
}

View File

@@ -0,0 +1,9 @@
void main()
{
vec4 uv = vec4(gl_Vertex.xyz, 1.0) * 0.5 + 0.5;
gl_TexCoord[0] = uv;
gl_TexCoord[1] = uv;
gl_TexCoord[2] = uv;
gl_Position = vec4(gl_Vertex.xyz, 1.0);
}

View File

@@ -0,0 +1 @@
name = preview

View File

@@ -12,8 +12,6 @@ if(ENABLE_SYSTEM_GMP)
else()
message (STATUS "Detecting GMP from system failed.")
endif()
else()
message (STATUS "Detecting GMP from system disabled! (ENABLE_SYSTEM_GMP=0)")
endif()
if(NOT USE_SYSTEM_GMP)

View File

@@ -42,15 +42,6 @@ if(WIN32)
NAMES ${GETTEXT_LIB_NAMES}
PATHS "${CUSTOM_GETTEXT_PATH}/lib"
DOC "GetText library")
find_file(GETTEXT_DLL
NAMES libintl.dll intl.dll libintl3.dll intl3.dll
PATHS "${CUSTOM_GETTEXT_PATH}/bin" "${CUSTOM_GETTEXT_PATH}/lib"
DOC "gettext *intl*.dll")
find_file(GETTEXT_ICONV_DLL
NAMES libiconv2.dll
PATHS "${CUSTOM_GETTEXT_PATH}/bin" "${CUSTOM_GETTEXT_PATH}/lib"
DOC "gettext *iconv*.lib")
set(GETTEXT_REQUIRED_VARS ${GETTEXT_REQUIRED_VARS} GETTEXT_DLL GETTEXT_ICONV_DLL)
endif(WIN32)

View File

@@ -1,77 +0,0 @@
mark_as_advanced(IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR IRRLICHT_DLL)
set(IRRLICHT_SOURCE_DIR "" CACHE PATH "Path to irrlicht source directory (optional)")
# Find include directory
if(NOT IRRLICHT_SOURCE_DIR STREQUAL "")
set(IRRLICHT_SOURCE_DIR_INCLUDE
"${IRRLICHT_SOURCE_DIR}/include"
)
set(IRRLICHT_LIBRARY_NAMES libIrrlicht.a Irrlicht Irrlicht.lib)
if(WIN32)
if(MSVC)
set(IRRLICHT_SOURCE_DIR_LIBS "${IRRLICHT_SOURCE_DIR}/lib/Win32-visualstudio")
set(IRRLICHT_LIBRARY_NAMES Irrlicht.lib)
else()
set(IRRLICHT_SOURCE_DIR_LIBS "${IRRLICHT_SOURCE_DIR}/lib/Win32-gcc")
set(IRRLICHT_LIBRARY_NAMES libIrrlicht.a libIrrlicht.dll.a)
endif()
else()
set(IRRLICHT_SOURCE_DIR_LIBS "${IRRLICHT_SOURCE_DIR}/lib/Linux")
set(IRRLICHT_LIBRARY_NAMES libIrrlicht.a)
endif()
find_path(IRRLICHT_INCLUDE_DIR NAMES irrlicht.h
PATHS
${IRRLICHT_SOURCE_DIR_INCLUDE}
NO_DEFAULT_PATH
)
find_library(IRRLICHT_LIBRARY NAMES ${IRRLICHT_LIBRARY_NAMES}
PATHS
${IRRLICHT_SOURCE_DIR_LIBS}
NO_DEFAULT_PATH
)
else()
find_path(IRRLICHT_INCLUDE_DIR NAMES irrlicht.h
PATHS
/usr/local/include/irrlicht
/usr/include/irrlicht
/system/develop/headers/irrlicht #Haiku
PATH_SUFFIXES "include/irrlicht"
)
find_library(IRRLICHT_LIBRARY NAMES libIrrlicht.so libIrrlicht.a Irrlicht
PATHS
/usr/local/lib
/usr/lib
/system/develop/lib # Haiku
)
endif()
# On Windows, find the DLL for installation
if(WIN32)
# If VCPKG_APPLOCAL_DEPS is ON, dll's are automatically handled by VCPKG
if(NOT VCPKG_APPLOCAL_DEPS)
if(MSVC)
set(IRRLICHT_COMPILER "VisualStudio")
else()
set(IRRLICHT_COMPILER "gcc")
endif()
find_file(IRRLICHT_DLL NAMES Irrlicht.dll
PATHS
"${IRRLICHT_SOURCE_DIR}/bin/Win32-${IRRLICHT_COMPILER}"
DOC "Path of the Irrlicht dll (for installation)"
)
endif()
endif(WIN32)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Irrlicht DEFAULT_MSG IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR)

View File

@@ -1,26 +1,25 @@
# Look for JSONCPP if asked to.
# We use a bundled version by default because some distros ship versions of
# JSONCPP that cause segfaults and other memory errors when we link with them.
# See https://github.com/minetest/minetest/issues/1793
# Look for JsonCpp, with fallback to bundeled version
mark_as_advanced(JSON_LIBRARY JSON_INCLUDE_DIR)
option(ENABLE_SYSTEM_JSONCPP "Enable using a system-wide JSONCPP. May cause segfaults and other memory errors!" FALSE)
option(ENABLE_SYSTEM_JSONCPP "Enable using a system-wide JsonCpp" TRUE)
set(USE_SYSTEM_JSONCPP FALSE)
if(ENABLE_SYSTEM_JSONCPP)
find_library(JSON_LIBRARY NAMES jsoncpp)
find_path(JSON_INCLUDE_DIR json/allocator.h PATH_SUFFIXES jsoncpp)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Json DEFAULT_MSG JSON_LIBRARY JSON_INCLUDE_DIR)
if(JSON_FOUND)
message(STATUS "Using system JSONCPP library.")
if(JSON_LIBRARY AND JSON_INCLUDE_DIR)
message(STATUS "Using JsonCpp provided by system.")
set(USE_SYSTEM_JSONCPP TRUE)
endif()
endif()
if(NOT JSON_FOUND)
message(STATUS "Using bundled JSONCPP library.")
if(NOT USE_SYSTEM_JSONCPP)
message(STATUS "Using bundled JsonCpp library.")
set(JSON_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/jsoncpp)
set(JSON_LIBRARY jsoncpp)
add_subdirectory(lib/jsoncpp)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Json DEFAULT_MSG JSON_LIBRARY JSON_INCLUDE_DIR)

View File

@@ -1,8 +1,8 @@
# Locate LuaJIT library
# This module defines
# LUAJIT_FOUND, if false, do not try to link to Lua
# LUA_LIBRARY, where to find the lua library
# LUA_INCLUDE_DIR, where to find lua.h
# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
#
# This module is similar to FindLua51.cmake except that it finds LuaJit instead.
@@ -44,19 +44,10 @@ else()
)
endif()
IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h")
FILE(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT .+\"")
STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
UNSET(lua_version_str)
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
# all listed variables are TRUE
# all listed variables exist
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT
REQUIRED_VARS LUA_LIBRARY LUA_INCLUDE_DIR
VERSION_VAR LUA_VERSION_STRING)
REQUIRED_VARS LUA_LIBRARY LUA_INCLUDE_DIR)
MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY)
MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARY)

View File

@@ -42,7 +42,7 @@ else()
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OPENGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)
find_package_handle_standard_args(OpenGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)
find_path(EGL_INCLUDE_DIR EGL/egl.h
PATHS /usr/openwin/share/include
@@ -59,7 +59,6 @@ else()
/usr/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR)
endif()

View File

@@ -0,0 +1,25 @@
mark_as_advanced(ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
find_path(ZSTD_INCLUDE_DIR NAMES zstd.h)
find_library(ZSTD_LIBRARY NAMES zstd)
if(ZSTD_INCLUDE_DIR AND ZSTD_LIBRARY)
# Check that the API we use exists
include(CheckSymbolExists)
unset(HAVE_ZSTD_INITCSTREAM CACHE)
set(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY})
check_symbol_exists(ZSTD_initCStream zstd.h HAVE_ZSTD_INITCSTREAM)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
if(NOT HAVE_ZSTD_INITCSTREAM)
unset(ZSTD_INCLUDE_DIR CACHE)
unset(ZSTD_LIBRARY CACHE)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zstd DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)

View File

@@ -0,0 +1,26 @@
# Locate Irrlicht or IrrlichtMt headers on system.
foreach(libname IN ITEMS IrrlichtMt Irrlicht)
string(TOLOWER "${libname}" libname2)
find_path(IRRLICHT_INCLUDE_DIR NAMES irrlicht.h
DOC "Path to the directory with IrrlichtMt includes"
PATHS
/usr/local/include/${libname2}
/usr/include/${libname2}
/system/develop/headers/${libname2} #Haiku
PATH_SUFFIXES "include/${libname2}"
)
if(IRRLICHT_INCLUDE_DIR)
break()
endif()
endforeach()
# Handholding for users
if(IRRLICHT_INCLUDE_DIR AND (NOT IS_DIRECTORY "${IRRLICHT_INCLUDE_DIR}" OR
NOT EXISTS "${IRRLICHT_INCLUDE_DIR}/irrlicht.h"))
message(WARNING "IRRLICHT_INCLUDE_DIR was set to ${IRRLICHT_INCLUDE_DIR} "
"but irrlicht.h does not exist inside. The path will not be used.")
unset(IRRLICHT_INCLUDE_DIR CACHE)
endif()

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