Compare commits

..

512 Commits
0.4.7 ... 0.4.9

Author SHA1 Message Date
kwolekr
1ad81c1ce3 Bump version to 0.4.9 2014-01-01 16:54:28 -05:00
kwolekr
25b1cca415 Fix exception caused by destroying sockets on Server shutdown 2013-12-31 15:00:49 -05:00
kaeza
767b2e7b17 Fix enum element name in Lua HUD code (position vs. pos) 2013-12-31 06:13:54 +01:00
ShadowNinja
2902a29c2d Initialize world before creating BanManager and RollbackManager 2013-12-30 14:29:33 -05:00
ShadowNinja
829426c714 Fix InventoryList reading order
Lua does not guarantee that the indexes of a table will be in numerical order.
2013-12-30 14:00:05 -05:00
Novatux
8e1d78e9de Revert "Fix minetest.facedir_to_dir when param2 is 5 or 7."
This reverts commit 4e5760a541.
2013-12-30 18:45:34 +01:00
PilzAdam
4b31a38ae9 Remove FPS from window title
This doubles performance on some window managers (WTF?!)
2013-12-25 03:52:44 +01:00
Kahrl
bf9f50bc0e Make SHA1::addBytes(..., 0) a no-op instead of an assertion failure 2013-12-25 00:29:00 +01:00
Kahrl
3aa28bc7a2 Use sleep_ms instead of select in httpfetch when max_fd == -1, fixes WSAEINVAL 2013-12-24 19:28:09 +01:00
Kahrl
a5377251e2 Fix particle code ignoring return value of std::vector::erase(). Wat. 2013-12-23 15:11:53 +01:00
RealBadAngel
a58b47d0f6 Fix wrong names for parallax settings in config example. 2013-12-22 00:30:17 +01:00
RealBadAngel
7ae0b90ff7 Bugfix to get_all_craft_recipes.
Indexes for empty slots shall not be skipped.
2013-12-21 23:03:51 +01:00
Kahrl
a50db0e824 Check for denied access in itemdef/nodedef/media fetch loop 2013-12-19 21:47:08 +01:00
ShadowNinja
e1f9ba435f Don't throw a error when writing JSON fails 2013-12-18 18:18:43 -05:00
Kahrl
ba8fa0bd42 Log guilty node name when allow_metadata_inventory_move/put/take fails 2013-12-18 23:04:13 +01:00
ShadowNinja
1ed90c90c3 Add 'minetest.write_json' 2013-12-18 16:46:53 -05:00
ShadowNinja
49cec3f782 Handle LuaErrors in Lua -> C++ calls on LuaJIT 2013-12-18 16:35:55 -05:00
BlockMen
38d112033b Fix formspec field labels 2013-12-17 01:13:16 +01:00
sapier
54dbd78f90 Fix broken httpfetch due to SimpleThread removal 2013-12-16 23:31:56 +01:00
BlockMen
c9ac9992c7 Fix MSVC compiling issue 2013-12-16 01:13:08 +01:00
sapier
3946d2a504 Reduce cloud coloring for colored fog and cloud mode 2013-12-16 00:16:06 +01:00
PilzAdam
5fd92d67d5 Remove an unused function and include from client.cpp 2013-12-15 19:57:08 +01:00
sapier
c120ea57c9 Add setting to disable direction dependent fog and sky colors 2013-12-15 15:30:02 +01:00
MirceaKitsune
848f80b2e5 Directional fog + horizon colors, based on sun & moon positions at sunrise / sunset 2013-12-15 14:28:50 +01:00
sapier
e9e9fd7c3f Replace SimpleThread by JThread now implementing same features 2013-12-15 13:39:42 +01:00
BlockMen
9772322613 Add alpha setting to font shadow 2013-12-14 21:11:38 +01:00
kwolekr
7a4c1e7327 Update mapgen params in ServerMap after Mapgen init 2013-12-14 10:49:20 -05:00
kwolekr
15c316765d Handle Lua errors in on_generate callbacks instead of throwing SIGABRT 2013-12-14 01:59:16 -05:00
kwolekr
c3708b456e Add map feature generation notify Lua API 2013-12-14 01:52:24 -05:00
ShadowNinja
83853ccd41 Remove support for optdepends.txt 2013-12-13 13:10:24 -05:00
Kahrl
e275b7099a Don't call curl_global_init twice 2013-12-13 18:08:53 +01:00
sapier
0d990bd189 Replace any direct curl usage by httpfetch 2013-12-13 18:05:46 +01:00
Kahrl
b03135548b Use httpfetch_async in serverlist announce code 2013-12-13 18:05:39 +01:00
Kahrl
0a903e69fb Implement urlencode and urldecode 2013-12-13 18:05:35 +01:00
Kahrl
0404bbf671 Rewrite client media download and support hash-based remote download
Move most of the media-related code in client.cpp into a new class
ClientMediaDownloader (clientmedia.cpp, clientmedia.h). Among other
things, this class does the following things:

- Download [remote_server][sha1] instead of [remote_server][name]. This
is to support servers that provide the same file name with different
contents.
- Initially fetch [remote_server]index.mth. This file should follow the
Minetest Hashset format (currently version 1) and contain a list of SHA1
hashes that exist on the server.
- The list of needed SHA1s is uploaded (via HTTP POST) when index.mth is
requested, so servers can optionally narrow down the list to the needs
of the client.
- If index.mth is missing (HTTP response code 404), we enter compat mode,
fetching [remote_server][name] as before this commit.
- remote_server can now contain multiple servers, separated by commas.
The downloader code attempts to split requests between the different
servers, as permitted by each server's index.mth. If one server claims
to have a file but actually doesn't (or something fails), we ask a
different server that also claims to have it.
- As before, when none of the remote servers provide a particular
file, we download it via the conventional method, i.e. using
the minetest protocol: TOSERVER_REQUEST_MEDIA / TOCLIENT_MEDIA.
- Bugfix: Every downloaded file's SHA1 is now verified against the SHA1
announced by the minetest server (before loading it and inserting it
into the file cache).
- Bugfix: Only send TOSERVER_RECEIVED_MEDIA when we actually have all
media. This should fix #863.
2013-12-13 18:05:20 +01:00
Kahrl
0ea3e6dbe2 Implement httpfetch module and initialize it from main()
Add curl_parallel_limit setting that will replace media_fetch_threads in
a later commit.

Fix a typo in MutexedQueue::pop_back() that made it impossible to compile
code that used this function. (Noticed this while implementing httpfetch.)
2013-12-13 18:05:10 +01:00
Ilya Zhuravlev
67bf7130ce Fix a bug in GenericCAO GENERIC_CMD_UPDATE_POSITION parsing. 2013-12-13 13:18:00 +04:00
stujones11
d9ef072305 Make line_of_sight return blocking node position 2013-12-12 16:11:00 -05:00
kaeza
33de69a173 Add 'on_prejoinplayer' callback 2013-12-12 13:42:14 -05:00
Ilya Zhuravlev
76036abdb0 Add configurable font shadow. 2013-12-12 21:47:54 +04:00
sapier
4ccaa6d0af Implement search tab and version picker 2013-12-11 23:07:38 +01:00
Ilya Zhuravlev
dfd1f87762 Add Lithuanian translation. 2013-12-11 22:10:56 +04:00
PilzAdam
6c4a8766ab Check if width, height or start index of a list[] is negative 2013-12-09 22:39:24 +01:00
RealBadAngel
dae03382bf Optimize shaders code. Add settings at compile time. 2013-12-09 13:28:50 +01:00
kwolekr
50b0e9f7a4 Mapgen Indev: Fix segfault in cave generation due to uninitialized variable 2013-12-08 22:13:05 -05:00
Novatux
206565d965 Fix shaders on some GPUs 2013-12-08 08:01:20 +01:00
kwolekr
3cc45fd8ad Fix leak and possible segfault in minetest.set_mapgen_params 2013-12-08 01:37:41 -05:00
kwolekr
83cc882335 EmergeManager: Fix Lua mapgen override param handling 2013-12-08 01:31:06 -05:00
kwolekr
bbae8eb751 Dungeongen: Create dungeon gen tuneables; add desert temples for Mapgen V6 2013-12-07 22:45:26 -05:00
ShadowNinja
a0dce51af6 Move script_run_callbacks to Lua 2013-12-07 22:03:07 -05:00
ShadowNinja
96f753a108 Fix paralax occlusion setting 2013-12-06 22:42:09 -05:00
sfan5
e15681080e Fix small mistake in Lua API docs 2013-12-06 18:37:32 +01:00
sapier
35f88ac67c Fix win32 jthread implementation 2013-12-06 17:49:10 +01:00
sweetbomber
22dbbf0a6f Improve (re)spawn, add cache_block_before_spawn and max_spawn_height settings 2013-12-05 16:09:02 -05:00
ShadowNinja
000da6b25d Only create one alias metatable 2013-12-04 14:31:55 -05:00
PilzAdam
e51ad5337f Use a table in set_physics_override() 2013-12-03 23:20:00 +01:00
PilzAdam
15be2659ea Add sneak and sneak_glitch to set_physics_override() 2013-12-03 23:20:00 +01:00
Sfan5
d9de9f23d9 Fix LevelDB maps 2013-12-03 20:03:20 +01:00
RealBadAngel
2330267d22 Shaders rework. 2013-12-03 18:55:25 +01:00
PilzAdam
60113bde74 Dont move item back when not clicking on a slot 2013-12-03 18:05:36 +01:00
proller
1309e52198 Rename names -> can_see_far_names in announce 2013-12-03 20:14:06 +04:00
sapier
5004f31575 Fix broken async locking in release build 2013-12-03 17:50:00 +02:00
proller
6cbd1b8bf7 Remove link to #, add unlimited_player_transfer_distance to announce 2013-12-03 19:48:43 +04:00
Sfan5
6fa3892a71 Fix MinGW build 2013-12-01 20:58:46 +01:00
sapier
04e9a9d541 Cleanup jthread and fix win32 build 2013-12-01 16:25:46 +01:00
kwolekr
f3439c40d8 Cavegen: Fix possible out-of-bounds heightmap access 2013-12-01 08:57:35 -05:00
kwolekr
20e3d550fa Decoration: Add schematic Y-slice probability support 2013-12-01 01:24:59 -05:00
sapier
de0cdbc01c Fix log threadname lookup handling not beeing threadsafe 2013-11-30 21:22:15 +01:00
0gb.us
e605d70256 Assume a selection box for fences
Similar to assuming a selection box for the nodebox drawtype, minetest.register_item() now assumes a selection box for the fencelike drawtype.
2013-11-30 13:22:50 -05:00
ShadowNinja
4696c59a5f Add error handler to async step 2013-11-30 13:05:13 -05:00
ShadowNinja
4594ba6522 Optimize table creation 2013-11-30 13:05:13 -05:00
Novatux
06baf05c64 Add documentation for minetest.swap_node 2013-11-30 18:57:56 +01:00
Novatux
d879a539cd Add minetest.swap_node 2013-11-30 18:37:56 +01:00
Ilya Zhuravlev
752e11e114 Fix MSVC build. 2013-11-30 21:00:18 +04:00
kwolekr
9a927476ca Change default value of is_ground_content to true
Most modders would otherwise forget to explicitly define this, and generated nodes aliased from mods would wall-off caves
2013-11-30 02:37:10 -05:00
kwolekr
ff7d7080e3 LuaVoxelManip: Add area parameters back to calc_lighting and set_lighting, made optional this time; also fixed a slight bug with night values being ignored 2013-11-30 00:27:39 -05:00
kwolekr
769b2d7c05 LuaVoxelManip: Add get_light_data() and set_light_data() 2013-11-30 00:01:43 -05:00
MetaDucky
5be786c804 Fixed potential NULL pointer and leak when setting node metadata 2013-11-29 23:35:16 -05:00
kwolekr
747bc40840 Cavegen: Respect is_ground_content MapNode setting; fix some code formatting issues 2013-11-29 20:54:04 -05:00
sapier
d19a69cd0d Fix broken thread stop handling 2013-11-30 02:15:31 +01:00
sapier
d02ce1cf4d Fix old gcc build 2013-11-29 23:36:18 +01:00
sapier
2e66aca357 Fix modstore/favourites hang by adding asynchronous lua job support 2013-11-29 22:09:14 +01:00
sapier
b08d7558de Split server/client port setting to avoid port number clashes in mainmenu 2013-11-28 21:43:06 +01:00
ShadowNinja
ff25218374 Don't use variable length arrays 2013-11-28 11:22:41 -05:00
ShadowNinja
7433d65d3e Rollback fixes and get_node_actions 2013-11-27 18:13:06 -05:00
Mario Barrera
1fd9a11e30 SQLite rollback 2013-11-27 18:13:06 -05:00
sapier
4f246f0e22 Fix line_of_sight (AGAIN) 2013-11-25 00:04:05 +01:00
PilzAdam
f87c1c2410 Reenable -dev suffix 2013-11-24 19:01:25 +01:00
kwolekr
122875c30c Bump version to 0.4.8 2013-11-24 02:23:49 -05:00
kwolekr
068dd796f5 Don't continue trying to deserialize blank block data 2013-11-24 02:10:15 -05:00
sapier
16bd368374 Temporary disable local install button due to irrlicht dialog breaking localization 2013-11-24 02:15:25 +01:00
Novatux
83f1d9ae6b Fix my name (doesn't display correctly because of utf8 characters) 2013-11-23 20:05:07 +01:00
Sfan5
374e68d205 Fix rename modpack button not working, fixes #1019 2013-11-23 19:06:35 +01:00
PilzAdam
fb150e0504 Run updatepo.sh 2013-11-23 17:38:01 +01:00
Pablo Lezaeta
c439bdd4e5 Translated using Weblate (Spanish) 2013-11-23 17:33:15 +01:00
Anton Tsyganenko
d661cb320d Translated using Weblate (Russian) 2013-11-23 17:33:15 +01:00
Maciej Kasatkin
78f1fcf450 Translated using Weblate (Polish) 2013-11-23 17:33:15 +01:00
Jakub Vaněk
28c21ed566 Translated using Weblate (Czech)
Myslím, že se jedná o IME Convert klávesu: http://msdn.microsoft.com/en-us/library/system.windows.input.key.aspx
2013-11-23 17:33:15 +01:00
King Artur
d7b0fcb2f0 Translated using Weblate (Romanian) 2013-11-23 17:33:15 +01:00
Jakub Vaněk
e5b1447d72 Translated using Weblate (Czech)
Myslím, že se jedná o IME NonConvert klávesu: http://msdn.microsoft.com/en-us/library/system.windows.input.key.aspx
2013-11-23 17:33:15 +01:00
Frantisek Simorda
dfc268d88b Translated using Weblate (Czech) 2013-11-23 17:33:15 +01:00
Pablo Lezaeta
8c3cf606a6 Translated using Weblate (Spanish) 2013-11-23 17:33:15 +01:00
Heisenberg CZE
c28810f6df Translated using Weblate (Czech) 2013-11-23 17:33:15 +01:00
Pablo Lezaeta
012551f16f Translated using Weblate (Spanish) 2013-11-23 17:33:15 +01:00
Petr Hála
4d165f5ea5 Translated using Weblate (Czech) 2013-11-23 17:33:15 +01:00
Heisenberg CZE
71cc575ea0 Translated using Weblate (Czech) 2013-11-23 17:33:14 +01:00
Heisenberg CZE
e023e7228e Translated using Weblate (Czech) 2013-11-23 17:33:14 +01:00
Petr Hála
80981f80f3 Translated using Weblate (Czech) 2013-11-23 17:33:14 +01:00
Kahrl
ab601e8710 Fix invalid escape sequence in database migration code 2013-11-23 16:09:38 +01:00
Sfan5
ee0b8da844 Prevent enabling Shaders if Direct3D is used 2013-11-23 15:41:47 +01:00
Kahrl
6f851c9692 Fix crash when pressing Enter key in formspec menu 2013-11-23 00:37:32 +01:00
ShadowNinja
e52d811110 Fix usage of 'minetest' where 'engine' was intended 2013-11-21 21:24:04 -05:00
kwolekr
5323d800cc Fix possible implicit conversion of NULL to std::string 2013-11-21 00:49:32 -05:00
kwolekr
98e4e2b373 LuaVoxelManip: Update parameter index of set_lighting() 2013-11-21 00:45:17 -05:00
kwolekr
b38afc9311 Mapgen V6: Respect water_level setting 2013-11-21 00:43:27 -05:00
BlockMen
0c8bf7cf94 Fix modmanager screenshot path 2013-11-19 15:39:40 +01:00
MetaDucky
0930911efa fix gettext compile issues under win32 2013-11-18 21:11:52 -05:00
kwolekr
86ef7147b6 Fix issue #1009 (minetest.get_connected_players() returns non-existing players) 2013-11-17 15:15:59 -05:00
PilzAdam
a55c073ce9 Increase liquid_loop_max to 10000 again 2013-11-17 21:05:14 +01:00
Perttu Ahola
21789ccc5f Revert patch 58f036ad1 that causes object duplication (which tried to fix objects getting hidden from client) and fix the original problem correctly. This fixes the second distinct object duplication bug. 2013-11-17 14:46:01 -05:00
sapier
b2d9205796 Fix Result of processed Request was written to invalid (non existent) ResultQueue if requesting thread timed out before 2013-11-17 12:46:54 -05:00
sapier
eadc943159 Add missing RequestQueue doc 2013-11-17 12:46:43 -05:00
sapier
dc407e219f Fix multicaller support in RequestQueue 2013-11-17 12:45:58 -05:00
kwolekr
d419e4cbb6 Do the same for LevelDB interface 2013-11-17 11:26:34 -05:00
kwolekr
aa172bdda4 Handle blank blocks in database
Fix screwed-up indentation
2013-11-17 10:57:45 -05:00
kwolekr
a439aea9ba Revert "Don't use msvc libs for mingw build"
This reverts commit 3985c01ad7.
2013-11-17 10:33:58 -05:00
PilzAdam
367b5382a3 Replace print()s with minetest.log() in builtin 2013-11-17 12:11:44 +01:00
kwolekr
a92fc3563c Prevent shaders from being created when disabled 2013-11-17 02:46:05 -05:00
sapier
533785ec9a Add CURL_DLL search to show up CURL_DLL in cmake gui and don't silently ignore missing CURL_DLL 2013-11-17 02:28:39 -05:00
sapier
3985c01ad7 Don't use msvc libs for mingw build 2013-11-17 02:27:00 -05:00
kwolekr
cca4f09ba1 Decoration: Stop DecoSimple::resolveNodeNames from complaining about no node name if decolist is used
Fix warning message for spawnby nodes

Prevent type-punning warning caused by casting enum to int
2013-11-17 02:22:24 -05:00
kwolekr
e396fb2984 Actually fix weather
The real problem was that MapBlocks were not activated before getting sent to the client
2013-11-17 01:59:04 -05:00
sapier
90e7832408 Fix invalid listname and listsize not handled correctly in set_size 2013-11-16 15:52:41 +01:00
MetaDucky
35606cfb67 fixed array limit check when reading Lua specialtiles table 2013-11-16 15:31:17 +01:00
ShadowNinja
371b39a09a Pass a errfunc to lua_pcall to get a traceback 2013-11-15 14:13:31 -05:00
BlockMen
3f519eb729 Fix formspec background padding when clipped 2013-11-14 19:03:55 +01:00
proller
9a750450ed Improved default settings for floatland perlin noise 1. Larger, more detailed floatlands. 2013-11-14 15:38:32 +04:00
Sfan5
5094a39f05 Fix compiling with 32bit MinGW 2013-11-12 15:18:20 +01:00
sapier
a935d81053 Fix invalid usage of temporary object in mainmenu json conversion 2013-11-11 23:23:58 +01:00
sapier
bb54e2cf1d Disable localization workaround in server 2013-11-11 19:56:49 +01:00
sapier
22a59b3912 Fix win32/msvc i18n (quite UGLY version, blame Microsoft) 2013-11-11 19:56:49 +01:00
sapier
0f9440fa61 Fix "TODO read modinfo" in modmanager to improve ui usability 2013-11-10 19:37:45 +01:00
proller
d75b1718f8 Fix spaces float islands code 2013-11-10 18:46:57 +04:00
0gb.us
a92e90f684 FIxed floating isle generation at chunk boundaries
A mapgen fix authored by paramat, as mentioned here: https://github.com/minetest/minetest/issues/989
2013-11-10 18:45:14 +04:00
kwolekr
b401e58c0d Weather: Fix uninitialized weather_update_time (sorry proller) 2013-11-09 15:29:22 -05:00
PilzAdam
0aeecf3f7f Add BlockMen to core dev list 2013-11-09 14:28:00 +01:00
sapier
b6bb3ffec4 Fix game buttons not beeing 48x48 2013-11-09 13:58:57 +01:00
sapier
7bd30b59ee Fix crash updating gametype without game 2013-11-09 13:30:44 +01:00
PilzAdam
1afd359550 Fix typo in lua_api.txt 2013-11-08 18:16:08 +01:00
4Evergreen4
1d856b734b Add wrapper for minetest.rotate_and_place. 2013-11-07 20:14:26 -05:00
Cy
3d63492f50 Don't assert scalars must be vectors. 2013-11-06 23:16:49 -05:00
Vanessa Ezekowitz
8ad052881c Fix orient_flags to be optional. 2013-11-06 22:23:00 -05:00
Vanessa Ezekowitz
d886f34003 Add 6d facedir rotation prediction routine 2013-11-06 21:08:36 -05:00
proller
8903c68460 Correct useragent in http queries
Net struct init
2013-11-06 00:50:32 +04:00
proller
6f44492238 Masterserver uptime fix 2013-11-05 21:18:37 +04:00
kwolekr
2e89209cf1 Add seed entry to world creation dialog 2013-11-05 00:00:01 -05:00
kwolekr
e46c527733 Accept hexadecimal and string values for seeds 2013-11-04 23:59:26 -05:00
sapier
1a96987d0f Fix invalid use of pointer to temporary object in json2lua conversion 2013-11-04 19:11:11 +01:00
Ilya Zhuravlev
7be18657b1 Fix masterserver README.md 2013-11-04 21:54:25 +04:00
proller
cf0786dc9d Masterserver fixes 2013-11-04 13:02:42 +04:00
proller
4a8a50a2a2 Masterserver show privs and js autoload 2013-11-04 04:56:39 +04:00
ShadowNinja
0fd29b7e09 Add a "More..." link when the serverlist is filtered 2013-11-03 18:21:53 -05:00
ShadowNinja
4c2687775f Only show servers with at least master.min_clients clients 2013-11-03 18:02:07 -05:00
ShadowNinja
50ea8601d5 Use a doT.js template for the serverlist 2013-11-03 17:47:16 -05:00
sapier
68bbdf1b2c Fix invalid usage of texture->getSize() where actually texture->getOriginalSize() was meant 2013-11-03 23:00:54 +01:00
BlockMen
5fbc39a76c Fix typo 2013-11-03 22:33:06 +01:00
BlockMen
25edae00ea Reworked formspecs and kahrl's hexcolor parser 2013-11-03 22:14:37 +01:00
Novatux
0b78889289 Send a on_receive_fields event when formspec is closed, with fields.quit = "true" 2013-11-03 11:53:59 +01:00
ShadowNinja
06a5eceb81 Add basic protection support to builtin 2013-11-02 14:01:10 -04:00
Aaron Suen
2636c92075 Portability fixes for OpenBSD (and possibly NetBSD and others). 2013-11-02 13:41:26 -04:00
Novatux
d11c76b9f2 Fix possible crash with grass ABM. 2013-11-02 16:22:26 +01:00
PilzAdam
0d35350b69 Fix liquid_range
* Prevent graphical glitches on old servers
* Fix flowing of liquids with viscosity != 1 and range != 8
* Fix range = 0, no flowing nodes will appear
2013-11-02 15:47:44 +01:00
Novatux
2bf9abade2 Fix grass adding/removing ABM. 2013-11-02 13:49:22 +01:00
Novatux
69a59f1e41 Move the sapling growing and grass adding/removing ABMs to Lua 2013-11-02 10:50:11 +01:00
ShadowNinja
b1c82f332c Add my email address to the main menu credits 2013-11-01 16:30:30 -04:00
ShadowNinja
fba2650e39 Add more checks to vector functions 2013-11-01 13:16:07 -04:00
BlockMen
1cbba877ff Don't remove background of games in submenus 2013-11-01 16:46:25 +01:00
0gb.us
53ab2f8def Fixed ignoring of "diggable" property of nodes. 2013-11-01 10:58:41 -04:00
Novatux
bd6d4666ab Add a callback: minetest.register_on_craft(itemstack, player,
old_craft_grid, craft_inv) and
minetest.register_craft_predict(itemstack, player, old_craft_grid,
craft_inv)
2013-11-01 15:55:34 +01:00
ShadowNinja
2f10cfb226 Made unknown nodes stop falling nodes properly and shorten lines 2013-11-01 10:33:29 -04:00
ShadowNinja
8bc68645cb Raise the maximum node limit to 0x7fff
As agreed to by kahrl
2013-11-01 10:27:23 -04:00
Novatux
6e17503208 Move new core devs to the "Core Developpers" section of mainmenu. 2013-11-01 12:27:50 +01:00
proller
382357d61c Masterserver totals fix 2013-10-18 23:57:22 +04:00
proller
a924409bd1 Masterserver update 2013-10-18 01:32:49 +04:00
ShadowNinja
e232f7311f Add sanity checks to vector functions 2013-10-17 09:42:57 +03:00
ShadowNinja
12504a18ec Remove vector metatable setting
This not only makes the vector functions faster, but also makes them more
consistent with other functions.
2013-10-17 09:41:01 +03:00
Perttu Ahola
b3591019ad Fix object duplication bug (at least in the most reproducible UFO case) 2013-10-17 00:10:16 +03:00
Novatux
34e0a0ca0f Add tool callback 2013-10-16 21:58:29 +04:00
Novatux
4e5760a541 Fix minetest.facedir_to_dir when param2 is 5 or 7. 2013-10-16 21:55:01 +04:00
Sokomine
19742d8d98 Add support for parameter 'visual_scale' for drawtypes 'signlike' and 'torchlike' like used for drawtype 'plantlike' 2013-10-14 21:38:56 +03:00
William Strealy
f86cdf0960 Translated using Weblate (Spanish) 2013-10-08 06:24:36 +02:00
Frederico Guimarães
ee9f4f11a3 Translated using Weblate (Portuguese (Brazil)) 2013-10-08 06:24:36 +02:00
Rutger NL
919ffd9d36 Translated using Weblate (Dutch) 2013-10-08 06:24:36 +02:00
Frederico Guimarães
406bed1164 Translated using Weblate (Portuguese (Brazil)) 2013-10-08 06:24:36 +02:00
Shen Zheyu
d0ddcecbe5 Translated using Weblate (Chinese (China)) 2013-10-08 06:24:36 +02:00
Rutger NL
25304b53a1 Translated using Weblate (Dutch) 2013-10-08 06:24:36 +02:00
we prefer instagib metl3
14e562e92b Translated using Weblate (French) 2013-10-08 06:24:36 +02:00
Pilz Adam
b3ad0f1ed4 Translated using Weblate (German) 2013-10-08 06:24:36 +02:00
Kahrl
5f3806c93c Add Czech language 2013-10-08 00:23:35 +02:00
RealBadAngel
5598f3c81b FIx wrong error message on invalid use of the formspec element image_button 2013-10-07 22:50:26 +02:00
0gb.us
afb27329fc Remove mapgen_air alias (#935) 2013-10-05 18:42:31 +02:00
fairiestoy
2170c9958a Optimized minetest.get_connected_players()
Instead of collecting all objects within a huge radius (which could be
a big value), just register each player that connects and give back the
current hold list.
2013-10-01 15:03:03 +02:00
Kahrl
2134316c80 Pass VERSION_EXTRA to GenerateVersion.cmake 2013-09-29 16:05:09 +02:00
PilzAdam
a9c0961e0c Add set_name(), set_count(), set_wear() and set_metadata() to Lua ItemStack 2013-09-28 23:46:48 +02:00
PilzAdam
731392866f Allow to manually specify param2 in minetest.item_place() and return success 2013-09-28 23:46:48 +02:00
Kahrl
5dce44ec5e Add --version option 2013-09-28 21:30:17 +02:00
Kahrl
f0edd88dff Remove doc/gpl-2.0.txt, add doc/lgpl-2.1.txt 2013-09-28 21:30:17 +02:00
Kahrl
8bc7ea61b9 Show git hash in version string at top left corner of window 2013-09-28 21:30:17 +02:00
ShadowNinja
372d638ec1 Lower the default max_users from 100 to 15 2013-09-28 21:09:52 +02:00
PilzAdam
4ea0e4f606 Add curl, freetype and luaJIT to CMAKE_BUILD_INFO 2013-09-28 15:41:37 +02:00
kwolekr
fb6a789991 Re-fix hud_change stat argument retrieval
Conflicts:
	src/script/lua_api/l_object.cpp
2013-09-26 04:39:10 +02:00
BlockMen
9e6bdc377f Fix compiling issue of MSVC 2013-09-23 11:51:14 +02:00
BlockMen
27947d85f7 Add option to scale image to percentage values 2013-09-20 20:03:58 +02:00
proller
f7ee5da4c1 Fix null dereference in weather update functions 2013-09-18 01:37:47 +04:00
kwolekr
c0398224ef Fix some warnings and other minor details 2013-09-16 23:52:42 -04:00
kwolekr
9bccd75e34 Weather: Clean up getHeat/getHumidity somewhat 2013-09-16 23:33:53 -04:00
ShadowNinja
c9eb17aba3 Fix comments about length of server step
6b927229f5 Changed the default server step
from 0.05s to 0.1s
2013-09-17 01:47:45 +02:00
proller
cfe6eaa66b Use cached "weather" setting 2013-09-17 02:57:36 +04:00
proller
62bc5331aa Fog depend on humidity 2013-09-17 02:43:24 +04:00
proller
4c704fe306 Add configurable PRAGMA synchronous = 2013-09-17 02:11:30 +04:00
kwolekr
d308352dbd Always use builtin JThread library 2013-09-15 23:00:01 -04:00
Kahrl
3c4734d69a Change mainmenu texture handling + small misc changes
Texture names must now be escaped in formspec elements image[],
background[], image_button[], image_button_exit[].

Instead of special-case handling of texture loading (and unloading
which was missing) in guiFormSpecMenu.cpp, use the newly created
ISimpleTextureSource interface which is a minimal subset of
ITextureSource. There is an implementation of this interface
used by GUIEngine (MenuTextureSource).

Fix an off-by-one bug in unescape_string; it caused requests for a
texture called "\0".
2013-09-11 00:08:56 +02:00
BlockMen
da9fe64851 Fix hotbar padding at bottom 2013-09-10 23:39:38 +02:00
PilzAdam
4feea0ac68 Add offset to automatic_face_movement_dir 2013-09-10 23:31:44 +02:00
sapier
681e136d5f Fix bug: texture pack not overriding default menu textures 2013-09-10 22:51:27 +02:00
PilzAdam
e0f9f15d1d Use engine.is_yes() in mainmenu 2013-09-10 21:38:50 +02:00
PilzAdam
214da7bef9 Use the Settings Lua interface to read world.mt 2013-09-10 21:38:49 +02:00
PilzAdam
dd5c451e03 Allow non-string arguments for minetest.is_yes() 2013-09-10 21:38:44 +02:00
PilzAdam
d820a6bfd8 Add Settings interface for Lua 2013-09-10 18:31:38 +02:00
Kahrl
10a38a3005 Handle --migrate even when compiled without leveldb support 2013-09-10 18:29:51 +02:00
Kahrl
c6e3797c1a Remove assert warning in leveldb wonderland 2013-09-10 18:28:26 +02:00
Kahrl
168fa2ffe0 Fix loading leveldb worlds 2013-09-10 18:16:36 +02:00
Kahrl
6fb4a78d71 Fix broken build due to missing mapsector.h include 2013-09-10 17:49:53 +02:00
Kahrl
217b66e5d2 Add --migrate to manpages and update manpage dates 2013-09-10 16:44:11 +02:00
Kahrl
95e4a93b1b Add license headers and remove useless includes 2013-09-10 16:09:30 +02:00
Sfan5
3725179736 Use system-wide LevelDB instead of bundled one 2013-09-09 22:50:51 +02:00
Sfan5
1f3402e7a1 Prevent ModMgr from deleting backend setting in world.mt 2013-09-09 22:50:51 +02:00
Sfan5
49a75b1894 Make --migrate update world.mt too 2013-09-09 22:50:51 +02:00
Sfan5
321ac66558 Add note about --migrate only working with minetestserver or --server 2013-09-09 22:50:51 +02:00
Sfan5
d423a8fc20 Fix 'Unknown map backend' error when using Configure menu right after creating world 2013-09-09 22:50:51 +02:00
Sfan5
f1e4a671dc Use STL containers instead of irr::core::list 2013-09-09 22:50:51 +02:00
Sfan5
1cc1c56234 Add message that LevelDB is not supported on Windows 2013-09-09 22:50:51 +02:00
Sfan5
7e44c2ace1 Make it compile 2013-09-09 22:50:50 +02:00
Ilya Zhuravlev
58841ef12f Add dummy and LevelDB database backends 2013-09-09 22:50:50 +02:00
Ilya Zhuravlev
71a8769bb5 Run updatepo.sh 2013-09-08 15:16:19 +04:00
Ilya Zhuravlev
6de16bb438 Add fallback font support for some languages. 2013-09-08 15:16:19 +04:00
Novatux
6291fd1cbb Add minetest.get_gametime() API function, that returns the number of seconds since the world was created. 2013-09-08 11:09:50 +02:00
Leonardo Costa
4a2203413f Translated using Weblate (Portuguese) 2013-09-07 19:55:22 +02:00
Block Men
0be633a61d Translated using Weblate (German)
Fix typo
2013-09-07 19:55:22 +02:00
Shen Zheyu
2963f631e3 Translated using Weblate (Chinese (China)) 2013-09-07 19:55:22 +02:00
Sfan5
df3a5a2abf Add mapgen_stair_cobble alias to minimal 2013-09-06 21:46:22 +02:00
0gb.us
211b372e26 Standardized method of getting node info in dungeon mapgen. 2013-09-06 21:42:01 +02:00
sapier
8489980039 Add sanity check to sort function 2013-09-05 01:45:39 +02:00
sapier
7935044820 Fix selectionbox not honoring anaglyph mode 3d distortion 2013-09-05 00:57:09 +02:00
sapier
e8b9467905 Fix crash on lua exception 2013-09-05 00:45:00 +02:00
PilzAdam
7860097eda Use player:set_hotbar_image() instead of hardcoded hotbar.png 2013-09-05 00:21:16 +02:00
sapier
5b518ed2fe Add backtrace to error function 2013-09-04 12:19:26 +02:00
Kahrl
af490330e7 Fix remnants of s32 enable_shaders 2013-09-04 00:16:33 +02:00
Kahrl
1ad9365d34 Fix enable_fog = false not having any effect when shaders are enabled 2013-09-03 13:23:30 +02:00
Ilya
e61b1773c9 Server::ProcessData(): call getBanName once instead of twice (#639) 2013-09-03 07:34:43 +02:00
Kahrl
1ecf51a13f Add minetest.parse_json, engine.parse_json 2013-09-02 02:20:08 +02:00
PilzAdam
71a6ffa762 Use wstring for vertlabels 2013-08-31 21:07:53 +02:00
sapier
5d0f19fd7d Fix bug in pathfinder causing endless loop in some situations 2013-08-31 21:26:51 +04:00
Diego Martínez
a0ef75d32d Translated using Weblate (Spanish) 2013-08-30 23:15:56 +02:00
Ilya Zhuravlev
fd6e7cef92 Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Anton Tsyganenko
d01d9217dd Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Ilya Zhuravlev
1751fdf937 Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Anton Tsyganenko
7766420cf4 Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Anton Tsyganenko
e69764a6f3 Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Anton Tsyganenko
525483c500 Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Anton Tsyganenko
18bf767014 Translated using Weblate (Russian) 2013-08-30 23:15:56 +02:00
Pilz Adam
cfaa9b3be5 Translated using Weblate (German) 2013-08-30 23:15:56 +02:00
proller
902d5927f0 Normalized heat and adjusted humidity 2013-08-30 00:42:53 +04:00
Ilya Zhuravlev
82e1ab7b2b Add escaping to world list in main menu (fixes #896). 2013-08-29 16:12:16 +04:00
Ilya Zhuravlev
d470842e8e Remove "po/du". "du" is invalid language code (fixes #881). 2013-08-26 14:30:17 +04:00
BlockMen
439079cad8 Add support for using textures in hotbar 2013-08-25 18:49:10 +02:00
Kahrl
fead7a27ca Fix aliases not working in shapeless crafting recipes 2013-08-25 18:14:26 +02:00
PilzAdam
4679455c3f Run util/updatepo.sh 2013-08-25 16:54:50 +02:00
Ilya Zhuravlev
d05b15df77 Add a setting for HighPrecisionFPU (fixes #763). 2013-08-25 18:25:01 +04:00
Ilya Zhuravlev
151617c552 Fix *.po errors caused by rebase. 2013-08-25 16:59:53 +04:00
Vladimir a
5a0cadab0c Translated using Weblate (Ukrainian) 2013-08-25 13:05:13 +04:00
Anton Tsyganenko
c9449c6fb7 Translated using Weblate (Russian) 2013-08-25 13:02:30 +04:00
sfan5
833183ddb4 Translated using Weblate (Norwegian Bokmål) 2013-08-25 13:02:11 +04:00
sfan5
f4ef91debf Translated using Weblate (Estonian) 2013-08-25 13:01:41 +04:00
Sasikaa Lacikaa
e74dfaf868 Translated using Weblate (Dutch) 2013-08-25 13:01:17 +04:00
Sasikaa Lacikaa
4260b99df2 Translated using Weblate (Hungarian) 2013-08-25 13:01:17 +04:00
sfan5
9ebed5e497 Translated using Weblate (Dutch) 2013-08-25 12:59:48 +04:00
Vladimir a
342629a3bf Translated using Weblate (Russian) 2013-08-25 12:59:02 +04:00
Nicola Spanti
ca58c2464a Translated using Weblate (French) 2013-08-25 12:57:33 +04:00
we prefer instagib metl3
9f2b08ddf0 Translated using Weblate (French) 2013-08-25 12:57:32 +04:00
sfan5
ba335958d6 Translated using Weblate (Ukrainian) 2013-08-25 12:57:15 +04:00
BlockMen
78ea818aaf Fix umlauts/special character issue in lua gettext 2013-08-19 22:23:41 +02:00
BlockMen
deaa8dc287 Fix gettext for tabs (windows) 2013-08-19 15:59:09 +02:00
Kahrl
ade70fe4b9 Allow SIGINT to kill mainmenu again 2013-08-19 15:49:36 +02:00
Kahrl
4242782dc2 World config dialog: Use engine determined path for game mods 2013-08-19 15:49:36 +02:00
Kahrl
8548bb75b6 GUIFormSpecMenu focus fixes 2013-08-19 15:49:36 +02:00
BlockMen
72b9b0fe3a Reenable image scaling in formspecs 2013-08-18 15:52:04 +02:00
Kahrl
392689e7ba Fix trailing nils being dropped by deprecated minetest.env handler 2013-08-18 15:15:33 +02:00
sapier
09a50d0458 Add translation for main menu
Add engine.gettext() and remove gettext() calls in guiFormspecMenu.cpp
2013-08-17 16:01:43 +02:00
PilzAdam
787b43b218 Send player damage to all clients and apply [brighten 2013-08-17 01:23:25 +02:00
Kahrl
3ee8098708 Diagonal liquid animation 2013-08-17 01:00:36 +02:00
Novatux
4095e8f383 Fix modstore pagecount 2013-08-16 17:54:19 +02:00
Novatux
a2380bf76f Use get_texturepath() instead of get_gamepath()/../textures 2013-08-16 17:44:39 +02:00
PilzAdam
75a139e62c Use errorstream instead of std::cout in pathfinder.cpp 2013-08-16 17:42:12 +02:00
PilzAdam
1e4e64f831 Remove debug output 2013-08-16 02:48:50 +02:00
PilzAdam
b94f18298d Sort modlist alphabetically 2013-08-16 02:09:45 +02:00
PilzAdam
d52185c43e Add ability to activate mods with doubleclick (remove old_style_mod_selection) 2013-08-16 01:04:37 +02:00
Kahrl
5e312dc40d Don't automatically scroll listbox when selecting an item in the middle 2013-08-16 00:58:03 +02:00
Kahrl
d8337034b5 Formspec textlist: Black Irrlicht magic to detect fake doubleclicks 2013-08-16 00:08:19 +02:00
Novatux
7921fe2cd1 Fix formspec escaping, add escaping to info.txt for texture packs. 2013-08-15 22:12:51 +02:00
Sfan5
a97c085e9e Fix documentation about colors in formspec 2013-08-15 19:38:54 +02:00
Kahrl
58beca005c Add virtual destructor to IBackgroundBlockEmerger to silence warning 2013-08-15 01:16:34 +02:00
Kahrl
4e1f50035e Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu 2013-08-14 21:03:33 +02:00
Ilya Zhuravlev
6228d634fb Fix my name. 2013-08-14 20:35:38 +04:00
PilzAdam
fc72d7fbb6 Fix typos 2013-08-14 00:50:03 +02:00
sapier
fc571ad46d Add support for entities to automatic face movement direction 2013-08-13 23:48:47 +02:00
PilzAdam
d718b0b34e Dont write directly to files but rather write and copy a tmp file 2013-08-13 22:05:45 +02:00
Kahrl
c8930850e3 Remove farmesh 2013-08-13 09:25:13 +02:00
kwolekr
c06caa14c3 Decoration: Fix schematic probability mess with new MTS file version 2013-08-11 15:34:49 -04:00
PilzAdam
56b9377c1c Dont crash if facedir > 23 2013-08-10 16:26:02 +02:00
PilzAdam
0d60bc55e4 Dont download modstore info if its isnt needed 2013-08-10 13:35:38 +02:00
Perttu Ahola
35c5ccfad3 Don't freak out when a client sends multiple TOSERVER_INIT packets; also log one thing more. 2013-08-08 06:11:43 +03:00
Kahrl
2ed3067bbe Fix various memory access problems detected by valgrind 2013-08-07 19:48:31 +02:00
PilzAdam
218f82f798 Fix path of mono font in defaultsettings.cpp 2013-08-07 13:41:00 +02:00
Sfan5
8b9bf47166 Fix stored XSS vulnerability in the serverlist 2013-08-07 09:24:32 +02:00
Kahrl
7294f28c3a Fix uninitialized irr::SEvent fields in guiFormSpecMenu.cpp 2013-08-07 01:36:19 +02:00
Novatux
779165144e Simplify code of mainmenu world sort 2013-08-06 18:33:23 +02:00
Kahrl
7fbc8152bf Fix full crack texture being shown when releasing dig button 2013-08-06 18:15:40 +02:00
BlockMen
7b13d119ed Add support for different drowning damage and allow drowning in other nodetypes 2013-08-06 17:49:39 +02:00
PilzAdam
ba65e2ae6c Fix worldlist in servertab being filtered by selected game 2013-08-06 17:28:51 +02:00
Perttu Ahola
53bf62bb83 Rename LagPool's member variables to avoid MSVC freaking up due to it's #define max 2013-08-06 18:17:58 +03:00
Perttu Ahola
61f240946a Clean up server's log messages and give a better error to client when its player is in use 2013-08-06 18:13:11 +03:00
Novatux
14eab22d81 Add minetest.registered_biomes 2013-08-06 13:24:54 +02:00
Kahrl
96c34d369e Fix crack overlay for animated textures 2013-08-05 01:52:09 +02:00
proller
2336d21efd Master server script improvement 2013-08-05 01:50:34 +04:00
PilzAdam
314e4dd4a6 Fix installation of textures/texture_packs_here.txt 2013-08-04 22:44:31 +02:00
Zeg9
44eb01695a Fix texture bumpmapping on some GPUs 2013-08-04 21:49:48 +02:00
proller
0b0919e81c Masterserver bugfix 2013-08-04 23:46:03 +04:00
proller
714a8cef38 Freeze-melt adjust 2013-08-04 23:31:01 +04:00
BlockMen
be4670fecf Fix formspec label issues in win builds (MSVC) 2013-08-04 20:49:23 +02:00
PilzAdam
2af5864534 Make freetype usage configureable by a setting 2013-08-04 20:35:14 +02:00
PilzAdam
3fd84edb61 Dont show gamefilter in TP tab 2013-08-04 18:37:19 +02:00
Novatux
383153419b Add texture pack selection to main menu 2013-08-04 16:52:30 +02:00
Novatux
fe1fe1b1e4 Change large amount of objects to be configurable via a setting in minetest.conf (max_objects_per_block). 2013-08-04 15:28:01 +03:00
Perttu Ahola
e6687be493 Fix server getting completely choked up on even a little of DoS
* If client count is unbearable, immediately delete denied clients
* Re-prioritize the checking order of things about incoming clients
* Remove a huge CPU-wasting exception in ReliablePacketBuffer
2013-08-04 10:44:37 +03:00
Perttu Ahola
8831669505 Allow mods to listen to cheat detections using minetest.register_on_cheat() 2013-08-04 00:45:49 +03:00
Perttu Ahola
742614180c Fix anticheat 2013-08-03 23:16:37 +03:00
Perttu Ahola
bc5db9b027 Lessen the sky color glitch when quickly turning to look up after looking at ground that contains caves 2013-08-03 19:04:16 +03:00
Perttu Ahola
c50c9a10f1 Fix and improve view range tuner 2013-08-03 18:46:18 +03:00
PilzAdam
45589fae58 Add replacements to schematics 2013-08-03 03:22:14 +02:00
proller
5e433fa913 More info in serverlist 2013-08-03 03:02:59 +04:00
PilzAdam
0b77588e87 Allow multiple 'wherein' nodes in oredef 2013-08-02 00:55:16 +02:00
proller
06cdce1e12 Weather backward compatibility 2013-08-02 00:51:36 +04:00
proller
0e89bca173 Leveled nodebox backward compatibility 2013-08-02 00:50:58 +04:00
Esteban I. Ruiz Moreno
c6cb97e693 Make bumpmapping compatible with irrlicht 1.8 2013-07-31 19:35:28 +02:00
sapier
251e3e01c7 Add support for setting stepheight for entities 2013-07-30 19:48:02 +02:00
PilzAdam
ff7c380d0e Fix warnings in mapblock.cpp 2013-07-28 23:34:58 +02:00
PilzAdam
4fb4efd8ed Play sounds/main_menu.ogg in menu 2013-07-28 23:29:03 +02:00
proller
174285f298 Warnings fix 2013-07-29 00:11:33 +04:00
proller
037e84d377 Better snow fall, finite liquid transform, leveled nodes api 2013-07-28 17:14:31 +04:00
proller
3aedfac968 Weather support 2013-07-27 23:21:48 +04:00
proller
e65d8ad655 Dont announce server in singleplayer 2013-07-27 17:51:34 +04:00
sapier
215e37aac3 Show portnumber for ip adresses only 2013-07-25 12:58:14 +02:00
BlockMen
a59f85c1a0 Add support of pressed_texture of image_button
Fix params number

Add pressed texture name

Fix string def

Fix syntax error
2013-07-24 01:02:43 +02:00
BlockMen
8e2467c393 Add gettext translation for image_button 2013-07-24 01:01:56 +02:00
proller
3629a90c2e Cosmetic player info changes 2013-07-24 02:41:03 +04:00
hdastwb
a0f5b70568 added (optional) support for 6d facedir in dir_to_facedir and added facedir_to_dir 2013-07-24 00:31:32 +02:00
PilzAdam
0b4b9e7f3a Fix modstore URLs 2013-07-22 22:26:48 +02:00
PilzAdam
a38f8d9900 Disable gamemanager by default 2013-07-22 18:16:36 +02:00
sapier
4f3bc05a5b Fix enable mod/enable button not shown on entering world config dialog 2013-07-22 18:10:00 +02:00
sapier
b3db44f801 Fix bug in world creation
Add old style mod selection in worldconfig dialog
2013-07-22 18:10:00 +02:00
sapier
4e2b394ae8 Add missing header/footer for singleplayer tab 2013-07-22 18:10:00 +02:00
sapier
e7ba4777fe Remove debug output 2013-07-22 18:10:00 +02:00
sapier
60225be7fa Fix Bug in modname guessing resulting in undefined modname 2013-07-22 18:10:00 +02:00
sapier
07fb257c04 Use user folder for gamemanager too 2013-07-22 18:10:00 +02:00
sapier
8beb0f19d1 Enable mod and gamemanager by default 2013-07-22 18:10:00 +02:00
sapier
32001d1e2b merge mainmenu_helper.lua to misc_helpers.lua 2013-07-22 18:10:00 +02:00
sapier
e3827fbc23 Fix background/overlay/footer/header handling
Add missing file headers
2013-07-22 18:10:00 +02:00
sapier
5160be91ae Add configurable curl timeout 2013-07-22 18:09:59 +02:00
sapier
d6c052038f Add playernumber to favorites list 2013-07-22 18:09:59 +02:00
sapier
8a1658ec3e filterlist api cleanup 2013-07-22 18:09:59 +02:00
sapier
baf5614880 Add port to favorites if not 30000
Major modmgr overhaul
Add missing formspec checkbox doc
2013-07-22 18:09:59 +02:00
sapier
868f35e27a Replace worldlist by generic filterlist implementation 2013-07-22 18:09:59 +02:00
sapier
5c7ecdb7c5 Add support for modstore screenshots
Add error output on invalid mmdb entries
2013-07-22 18:09:59 +02:00
sapier
80a2acaa86 Swap name/password <-> server description 2013-07-22 18:09:59 +02:00
sapier
47a0a5c746 Revert "Fix serverdescription and name not beeing saved to local serverlist"
This reverts commit 7dbbbfc665.
(was added twice)
2013-07-22 18:09:59 +02:00
sapier
7a9f365ba4 Remove unused required by list in worldconfig 2013-07-22 18:09:59 +02:00
RealBadAngel
0850d3fcf8 Fix light issue in 6d facedir. 2013-07-21 14:06:18 +02:00
PilzAdam
46d1d70e4c Bump protocol version 2013-07-20 21:25:21 +02:00
PilzAdam
8cae659786 Add an option to disable object <-> object collision for Lua entities 2013-07-20 20:43:11 +02:00
PilzAdam
413f0d0353 Add liquid_range to nodedef 2013-07-20 20:41:17 +02:00
PilzAdam
cba90d4441 Make range of tools configureable 2013-07-20 20:37:59 +02:00
RealBadAngel
d19c8b815d Add set_breath and get_breath to lua API. 2013-07-20 20:34:11 +02:00
PilzAdam
ab145c8827 Randomly choose singleplayer port 2013-07-16 02:02:56 +02:00
PilzAdam
ecb024af64 Fix lighting bug caused by disappearing lava 2013-07-16 01:51:04 +02:00
PilzAdam
4e5a45952a Remove support for common mods 2013-07-16 01:46:59 +02:00
Kahrl
112dbba7c4 Change ContentFeatures array to a vector 2013-07-14 23:06:31 +02:00
proller
9733dd5b5e Leveled nodebox 2013-07-13 22:13:24 +04:00
proller
a70993d6d2 Masterserver mods fix 2013-07-13 04:11:26 +04:00
proller
0a2de78da4 Better masterserver html 2013-07-13 01:41:49 +04:00
sapier
288948edf7 Don't show flags in local favorites 2013-07-12 22:55:34 +02:00
sapier
a0771d0940 Fix bug server name set to address field when using up/down keys
Show server description above connect button instead of in favorites list
2013-07-12 22:46:28 +02:00
sapier
38bc38cd88 Add missing server flags in public serverlist 2013-07-12 22:46:27 +02:00
sapier
494fa0c81a Remove lots of debug output from modmgr
Fix RUN_IN_PLACE=0 mod install (now mods are saved in user folder in that case)
Fix text of field element not unescaped correctly
2013-07-12 22:46:27 +02:00
sapier
7dbbbfc665 Fix serverdescription and name not beeing saved to local serverlist 2013-07-12 22:46:27 +02:00
proller
ac7a44792c Masterserver mods announse, ipv6, better curl errors 2013-07-13 00:19:05 +04:00
kwolekr
fc6725f14e Clean up bumpmap code a bit 2013-07-12 00:11:46 -04:00
PilzAdam
320a00e7c6 Disallow the name 'singleplayer' in a multiplayer server 2013-07-12 02:15:09 +02:00
Kahrl
6027c8d259 Add VoxelArea:position, VoxelArea:iter and VoxelArea:iterp 2013-07-11 22:57:26 +02:00
sapier
52beafff53 Worldlist fixes
Add alphabeticaly sorted worldlists
Select world after creation
Move worldlist handling to separate file
Merge world selection of singleplayer/server tab
Remove some useless code
2013-07-11 22:20:50 +02:00
stujones11
e8f201cefa Fix multiple texture support for animated meshnodes 2013-07-10 00:22:21 +02:00
sapier
1c7c5d571d Fix serverlist 2013-07-09 22:55:39 +02:00
proller
e3b7c8e0cc Public server checkbox 2013-07-10 00:17:47 +04:00
PilzAdam
c8bd2ae11c Dont play digging sound if not digging 2013-07-09 02:42:05 +02:00
kwolekr
e1a13608d8 Revert "Fix serverlist not beeing escaped correctly"
This reverts commit 39d03148e5.
2013-07-08 20:21:09 -04:00
sapier
eedb29346e Fix header not beeing shown except on singleplayer tab 2013-07-08 19:58:28 -04:00
sapier
39d03148e5 Fix serverlist not beeing escaped correctly
Always use address for server
Fix first (empty) element beeing selected after deleting last world
2013-07-08 19:58:17 -04:00
sapier
f419f66546 fix crash on play/start with empty world list
make enter button work in create world dialog
2013-07-08 19:58:03 -04:00
kwolekr
fca4610f11 Fix wallmounted rotations along Y axis for 90 and 270 degree cases 2013-07-08 18:50:29 -04:00
kwolekr
ce955f37ba Decoration: Handle facedir and wallmounted param2types with schematic rotation 2013-07-08 15:19:48 -04:00
PilzAdam
c813a3cc53 Remove note in lua-api.txt that there are no vector helper functions 2013-07-08 13:41:46 +02:00
PilzAdam
0b5f18754c Make sure that coordinates passed to /teleport are actual numbers 2013-07-08 13:33:14 +02:00
ShadowNinja
a75afb85ca Move math.hypot() to misc_helpers.lua and fix zero-division error 2013-07-07 21:47:38 -04:00
kwolekr
9dcd21911a Lua main menu: Fix world creation dialog 2013-07-07 20:37:00 -04:00
PilzAdam
9bd5f612f7 Set numeric locale in Lua in main menu 2013-07-08 02:28:36 +02:00
PilzAdam
6bc3a43d52 Settings: everything != 0 equals true; remove .asm shaders 2013-07-08 01:58:49 +02:00
sapier
88d43af276 Fix many formspec menu bugs 2013-07-07 19:49:52 -04:00
Sfan5
7e73b7cae9 Fix parseColor, change remaining colorkeys to new format, fix Contributor list 2013-07-07 19:59:18 +02:00
Kahrl
b3001bcd6e When server sends late media, log to errorstream instead of crashing.
Do a check for valid num_files before doing
assert(!m_mesh_update_thread.IsRunning());

In particular, don't execute the assertion if all media has already
been received.
2013-07-07 08:35:25 +02:00
ShadowNinja
07715b1b6a Handle 0 vectors in vector.normalize() 2013-07-07 02:29:09 -04:00
Vincent Heuken
39ab22070e include mathconstants.h in numerics.cpp 2013-07-07 01:52:43 -04:00
ShadowNinja
ae8ff4b8e2 Add vector helpers 2013-07-07 01:49:11 -04:00
kwolekr
d22baa88ed BiomeDefManager: Fully initialize default biome 2013-07-06 15:28:59 -04:00
kwolekr
65874c25db Mapgen V7: Fix out-of-bounds array access 2013-07-06 15:22:51 -04:00
kwolekr
06266abd6e LuaVoxelManip: Allow liquid updates in non-mapgen VoxelManip objects 2013-07-06 15:12:40 -04:00
kwolekr
55ecde665d Decoration: Remove usage of multi-character constants 2013-07-06 15:03:54 -04:00
Sfan5
307c57dcc4 Use hexadecimal RRGGBB instead of colorkeys, rename getColor to parseColor 2013-07-06 10:32:58 +02:00
kwolekr
18d7bc7fa1 Mapgen V7: Huge rewrite, also tweaks to cavegen et al. 2013-07-06 02:21:54 -04:00
Kahrl
3607fae75a Fix possible NULL dereference in createExtrudedMesh 2013-07-06 06:16:51 +02:00
Kahrl
922a30ee47 Don't rebuild the dummy shader (less SourceShaderCache warning spam)
Also write something about rebuilding shaders to infostream in
Client::afterContentReceived()
2013-07-05 04:24:05 +02:00
proller
92833a07d1 Improve finite liquid distribution, fix small bug 2013-07-05 00:11:11 +04:00
Kahrl
a013f762c4 Throw exception instead of assert on nested reliable packets
Fixes a denial of service vulnerability, issue #784
2013-07-04 06:18:50 +02:00
RealBadAngel
3f6f327cb9 Add texture bumpmapping feature. 2013-07-04 02:36:32 +02:00
Kahrl
b850f0f038 Whoever called a function parameter m_device is fired without notice. 2013-07-03 20:33:54 +02:00
kwolekr
a225efaec5 Lua main menu: Fix crash on init lua error, mapgen dropdown index, and new worlds not saving index 2013-07-03 01:25:26 -04:00
kwolekr
ad4c065344 Change debug optimization level back to -O1 2013-07-02 21:48:18 -04:00
BlockMen
89533f0811 Update wiki url 2013-07-03 03:37:00 +02:00
Kahrl
8f1d5d34a6 Move generateTextureFromMesh to TextureSource to fix a texture leak
TextureSource has a list of textures to delete (m_texture_trash) so this
provides a proper, non-hacky way to delete RTT textures. Also, the prior,
hacky way of deleting them seems to be broken (see pull request #803).

To avoid header file clutter by repeating the same long list of
arguments over and over again, store the arguments of
generateTextureFromMesh in a struct called TextureFromMeshParams.

Also fix issue #782 (Only use bilinear (and others) on item textures
when settings allow it).
2013-07-03 03:24:28 +02:00
sapier
b1ef850877 Fix possible 0 pointer access 2013-07-02 20:01:48 -04:00
sapier
967121a34b Replace C++ mainmenu by formspec powered one 2013-07-02 19:58:20 -04:00
kwolekr
fe4ce03d52 Cavegen: Prevent caves from occuring above ground level, and superfluous mixing of lava and water in caves 2013-07-01 21:20:03 -04:00
Kahrl
8161ab573f Remove texture atlas / AtlasPointer, rename getTextureRaw to getTexture 2013-07-02 03:03:10 +02:00
PilzAdam
caf0b67e47 Remove unnecessary debug output in node_dig() 2013-07-02 00:34:59 +00:00
Lord89James
90b095aa54 Infinite tools in creative mode 2013-07-02 00:33:31 +00:00
arsdragonfly
4bbb78a99b Fix i18n of some strings. 2013-07-02 00:13:50 +00:00
kwolekr
dd6d1afd8e Decoration: Add schematic rotation support 2013-07-01 18:04:51 -04:00
proller
131eb56f52 Disable collision fix, its broke unit tests 2013-07-01 00:26:54 +04:00
proller
37ca8854f7 Fix sand, gravel falling stuck 2013-06-30 22:48:51 +04:00
kwolekr
067888d549 LuaVoxelManip: Fix minor bug with set_lighting, remove coordinate params for light and liquid updates 2013-06-29 22:23:00 -04:00
proller
848c3fe51a Optimize liquid queue on generate map for liquid_finite 2013-06-30 01:29:21 +04:00
kwolekr
21a4adcd27 Update documentation for get_mapgen_object 2013-06-29 16:24:32 -04:00
kwolekr
0003fc8215 Add Lua VoxelArea methods: contains, containsp, containsi 2013-06-28 22:52:13 -04:00
kwolekr
9126823c7e Make generated water a shade darker to match up with older versions 2013-06-28 22:22:44 -04:00
kwolekr
3f13dc790c Add voxelarea.lua helper to builtin 2013-06-28 11:07:45 -04:00
PilzAdam
280946ba83 Dont write player files all the time 2013-06-28 14:15:48 +00:00
kwolekr
9e100bc42b Apply various fixes to several things 2013-06-27 22:35:35 -04:00
kwolekr
6b3169e4d0 LuaVoxelManip: Separate VoxelManip data get/set from emerging/blitting data back to map 2013-06-27 22:35:35 -04:00
kwolekr
2e292b67a0 Add Lua on_mapgen_init callback, and minetest.set_mapgen_params API 2013-06-27 22:35:35 -04:00
kwolekr
18882a4d26 Add Lua PerlinNoiseMap:get#dMap_flat API 2013-06-27 22:35:35 -04:00
kwolekr
8aa930f28e Add minetest.get_mapgen_object to API 2013-06-27 22:35:35 -04:00
kwolekr
2c0b51795e Fix issue of VManip occasionally not blitting back blocks, and pitch black lighting bug 2013-06-27 22:35:35 -04:00
kwolekr
d6ac3d8d9a Add LuaVoxelManip 2013-06-27 22:35:35 -04:00
proller
e47f6fdfe9 Fix ipv6 on windows 2013-06-24 20:13:56 +04:00
kwolekr
30d6d4c733 Cavegen: fix division by 0 with abnormal max tunnel diameter sizes 2013-06-23 15:16:52 -04:00
proller
f764297be2 Math mapgen fix, ip show on connect, pathfinder segfault fix 2013-06-23 20:35:16 +04:00
proller
75b8c13b00 New math mapgen with fractal based worlds 2013-06-23 18:07:10 +04:00
proller
f960c3be31 Add support for IPv6
Two new configuration options are added:
     - "enable_ipv6" to enable/disable the overall use of IPv6
     - "ipv6_server" to enable/disable the use of IPv6 sockets when running
       a server (when "enable_ipv6" is enabled)
2013-06-23 11:31:22 +04:00
kwolekr
309c5f3641 Decoration: Add support for zero probability, fix breakage from last commit 2013-06-22 20:49:01 -04:00
PilzAdam
130464c268 Print playername when failing to read playerfile and ignore files starting with . 2013-06-22 21:39:47 +00:00
kwolekr
4d77781ce7 A handful of minor fixes to various things 2013-06-22 17:27:48 -04:00
kwolekr
c1b829077a Decoration: Add Schematic decoration type 2013-06-22 01:11:52 -04:00
Ilya Zhuravlev
b1a74df26d Add Hungarian language. 2013-06-21 12:26:07 +04:00
Weblate
3af90db5b5 Merge remote-tracking branch 'origin/master' 2013-06-21 10:24:16 +02:00
Chyngyz Dzhumaliev
58f3cd3eb5 Translated using Weblate (Kirghiz) 2013-06-21 10:24:06 +02:00
PilzAdam
b1ebd9f79c Add a setting for max loop count per step in liquid update 2013-06-20 22:31:46 +00:00
Kahrl
c2cdaceed0 Make minetest.debug accept multiple parameters; convert them to string 2013-06-21 00:04:18 +02:00
Kahrl
469d0b120e Remove deprecated functions that don't work anymore from lua_api.txt 2013-06-20 07:52:04 +02:00
PilzAdam
81c8b404e7 Play placing sound only if place prediction was successful 2013-06-19 21:42:12 +00:00
PilzAdam
9b6f1d647c Dont dig or place nodes if interact priv is missing (clientside) 2013-06-19 21:42:12 +00:00
PilzAdam
53066024f6 Add drowning 2013-06-19 15:47:00 +00:00
Diego Martínez
e65ac4d626 Restore old output format of dump() 2013-06-18 19:55:53 +00:00
David Gumberg
26165453d2 Compress textures 2013-06-18 19:48:04 +00:00
kwolekr
f18b4872ea Decoration: Place decorations in mgv6, check if air or cignore before placement 2013-06-17 21:59:57 -04:00
Kahrl
261f559339 Show number of objects in client environment in profiler (F6) 2013-06-18 01:49:06 +02:00
Kahrl
d74c377337 Formspec: Don't perform black magic if selected item fits the guess 2013-06-18 01:32:11 +02:00
Kahrl
c8ed61b281 Fix calculation of selected item (for not drawing it) in formspec
The previous code did not work when the list did not start at index 0
of the inventory list (issue #779).
2013-06-18 01:18:54 +02:00
Esteban I. Ruiz Moreno
816ffa99ba Remove useless recalculation of bounding box (mapblock_mesh) 2013-06-18 01:11:46 +02:00
kwolekr
0b20768a24 Decoration, Ore: Resolve node names on Mapgen init 2013-06-17 18:51:29 -04:00
kwolekr
56093b6614 Decoration: Change divlen to sidelen 2013-06-17 18:23:31 -04:00
kwolekr
0a8519a26f Add initial Decoration support, many misc. improvements & modifications 2013-06-17 03:21:36 -04:00
Kahrl
eccd1fdbed Extend a delay in TestConnection from 50 to 100 milliseconds.
The 50 ms delay causes frequent test failures on certain systems with
slow network stacks, these failures go away with the 100 ms variant.
2013-06-17 02:09:50 +02:00
Kahrl
b5918760fb Tweak IDropAction restriction handling in server.cpp 2013-06-16 17:01:21 +02:00
Kahrl
4405310184 Lazy sunday typo fixing. s/unban_player_of_ip/unban_player_or_ip/g 2013-06-16 14:07:12 +02:00
sweetbomber
0413f8ad9d Removed a redundant step which degraded performance 2013-06-15 21:41:30 +04:00
Esteban I. Ruiz Moreno
93dfc3ec70 Add basic unicode support to the console (linux workaround) 2013-06-15 15:09:11 +00:00
khonkhortisan
3e4f1462bc Fix crash in dump() when index is a table 2013-06-15 00:10:16 +00:00
MetaDucky
40b2f36eb8 Fixes cmake-gui causing RUN_IN_PLACE to be always off 2013-06-13 16:45:52 +02:00
PilzAdam
7a58c1d4ca Reset dig_time when switching to a tool that cant dig the current node 2013-06-13 13:34:48 +00:00
Kahrl
21d6b39fd7 Enable word wrapping in profiler IGUIStaticText (freetype needs this) 2013-06-13 14:32:53 +02:00
PilzAdam
2cdf0ff4ab Play player_damage.ogg when recieving damage and additionally play player_falling_damage.ogg when recieving falling damage 2013-06-12 20:27:06 +00:00
Kahrl
773471750d Fix class/struct forward declaration inconsistencies (good on ya, MSVC) 2013-06-06 22:57:38 +02:00
Dany Cuartiella
29e9d09c68 Translated using Weblate (French) 2013-06-02 01:56:06 +02:00
492 changed files with 45916 additions and 20242 deletions

1
.gitignore vendored
View File

@@ -31,6 +31,7 @@ CMakeFiles/*
src/CMakeFiles/*
src/Makefile
src/cmake_config.h
src/cmake_config_githash.h
src/cmake_install.cmake
src/script/CMakeFiles/*
src/script/common/CMakeFiles/*

View File

@@ -12,9 +12,12 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
set(VERSION_MAJOR 0)
set(VERSION_MINOR 4)
set(VERSION_PATCH 7)
set(VERSION_PATCH 9)
if(VERSION_EXTRA)
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
else()
# Comment the following line during release
#set(VERSION_PATCH ${VERSION_PATCH}-dev)
endif()
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
@@ -28,6 +31,13 @@ else()
set(RUN_IN_PLACE 0 CACHE BOOL "Run directly in source directory structure")
endif()
# RUN_IN_PLACE is exported as a #define value, ensure it's 1/0 instead of ON/OFF
if(RUN_IN_PLACE)
set(RUN_IN_PLACE 1)
else()
set(RUN_IN_PLACE 0)
endif()
set(BUILD_CLIENT 1 CACHE BOOL "Build client")
if(WIN32)
set(BUILD_SERVER 0 CACHE BOOL "Build server")
@@ -146,7 +156,7 @@ if(BUILD_CLIENT)
endif()
if(RUN_IN_PLACE)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/mods/mods_here.txt" DESTINATION "${SHAREDIR}/mods")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/all/textures_here.txt" DESTINATION "${SHAREDIR}/textures/all")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/texture_packs_here.txt" DESTINATION "${SHAREDIR}/textures")
endif()
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}")

View File

@@ -16,7 +16,7 @@ See the README.txt in it.
Further documentation
----------------------
- Website: http://minetest.net/
- Wiki: http://wiki.minetest.com/
- Wiki: http://wiki.minetest.net/
- Developer wiki: http://dev.minetest.net/
- Forum: http://forum.minetest.net/
- Github: https://github.com/minetest/minetest/
@@ -382,17 +382,31 @@ DejaVu Sans Mono:
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
Bitstream Vera Fonts Copyright:
Bitstream Vera Fonts Copyright:
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.
Arev Fonts Copyright:
Arev Fonts Copyright:
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
Liberation Fonts Copyright:
Liberation Fonts Copyright:
Copyright (c) 2007 Red Hat, Inc. All rights reserved. LIBERATION is a trademark of Red Hat, Inc.
DroidSansFallback:
Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

19
builtin/async_env.lua Normal file
View File

@@ -0,0 +1,19 @@
engine.log("info","Initializing Asynchronous environment")
dofile(SCRIPTDIR .. DIR_DELIM .. "misc_helpers.lua")
function engine.job_processor(serialized_function, serialized_data)
local fct = marshal.decode(serialized_function)
local params = marshal.decode(serialized_data)
local retval = marshal.encode(nil)
if fct ~= nil and type(fct) == "function" then
local result = fct(params)
retval = marshal.encode(result)
else
engine.log("error","ASYNC WORKER: unable to deserialize function")
end
return retval,retval:len()
end

59
builtin/async_event.lua Normal file
View File

@@ -0,0 +1,59 @@
local tbl = engine or minetest
tbl.async_jobs = {}
if engine ~= nil then
function tbl.async_event_handler(jobid, serialized_retval)
local retval = nil
if serialized_retval ~= "ERROR" then
retval= marshal.decode(serialized_retval)
else
tbl.log("error","Error fetching async result")
end
assert(type(tbl.async_jobs[jobid]) == "function")
tbl.async_jobs[jobid](retval)
tbl.async_jobs[jobid] = nil
end
else
minetest.register_globalstep(
function(dtime)
local list = tbl.get_finished_jobs()
for i=1,#list,1 do
local retval = marshal.decode(list[i].retval)
assert(type(tbl.async_jobs[jobid]) == "function")
tbl.async_jobs[list[i].jobid](retval)
tbl.async_jobs[list[i].jobid] = nil
end
end)
end
function tbl.handle_async(fct, parameters, callback)
--serialize fct
local serialized_fct = marshal.encode(fct)
assert(marshal.decode(serialized_fct) ~= nil)
--serialize parameters
local serialized_params = marshal.encode(parameters)
if serialized_fct == nil or
serialized_params == nil or
serialized_fct:len() == 0 or
serialized_params:len() == 0 then
return false
end
local jobid = tbl.do_async_callback( serialized_fct,
serialized_fct:len(),
serialized_params,
serialized_params:len())
tbl.async_jobs[jobid] = callback
return true
end

View File

@@ -10,19 +10,27 @@ print = minetest.debug
math.randomseed(os.time())
os.setlocale("C", "numeric")
-- Load other files
dofile(minetest.get_modpath("__builtin").."/serialize.lua")
dofile(minetest.get_modpath("__builtin").."/misc_helpers.lua")
dofile(minetest.get_modpath("__builtin").."/item.lua")
dofile(minetest.get_modpath("__builtin").."/misc_register.lua")
dofile(minetest.get_modpath("__builtin").."/item_entity.lua")
dofile(minetest.get_modpath("__builtin").."/deprecated.lua")
dofile(minetest.get_modpath("__builtin").."/misc.lua")
dofile(minetest.get_modpath("__builtin").."/privileges.lua")
dofile(minetest.get_modpath("__builtin").."/auth.lua")
dofile(minetest.get_modpath("__builtin").."/chatcommands.lua")
dofile(minetest.get_modpath("__builtin").."/static_spawn.lua")
dofile(minetest.get_modpath("__builtin").."/detached_inventory.lua")
dofile(minetest.get_modpath("__builtin").."/falling.lua")
dofile(minetest.get_modpath("__builtin").."/features.lua")
local errorfct = error
error = function(text)
print(debug.traceback(""))
errorfct(text)
end
-- Load other files
local modpath = minetest.get_modpath("__builtin")
dofile(modpath.."/serialize.lua")
dofile(modpath.."/misc_helpers.lua")
dofile(modpath.."/item.lua")
dofile(modpath.."/misc_register.lua")
dofile(modpath.."/item_entity.lua")
dofile(modpath.."/deprecated.lua")
dofile(modpath.."/misc.lua")
dofile(modpath.."/privileges.lua")
dofile(modpath.."/auth.lua")
dofile(modpath.."/chatcommands.lua")
dofile(modpath.."/static_spawn.lua")
dofile(modpath.."/detached_inventory.lua")
dofile(modpath.."/falling.lua")
dofile(modpath.."/features.lua")
dofile(modpath.."/voxelarea.lua")
dofile(modpath.."/vector.lua")

View File

@@ -272,6 +272,9 @@ minetest.register_chatcommand("teleport", {
local teleportee = nil
local p = {}
p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
p.x = tonumber(p.x)
p.y = tonumber(p.y)
p.z = tonumber(p.z)
teleportee = minetest.get_player_by_name(name)
if teleportee and p.x and p.y and p.z then
minetest.chat_send_player(name, "Teleporting to ("..p.x..", "..p.y..", "..p.z..")")
@@ -302,6 +305,9 @@ minetest.register_chatcommand("teleport", {
local p = {}
local teleportee_name = nil
teleportee_name, p.x, p.y, p.z = string.match(param, "^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
p.x = tonumber(p.x)
p.y = tonumber(p.y)
p.z = tonumber(p.z)
if teleportee_name then
teleportee = minetest.get_player_by_name(teleportee_name)
end
@@ -465,10 +471,10 @@ minetest.register_chatcommand("spawnentity", {
minetest.chat_send_player(name, "entityname required")
return
end
print('/spawnentity invoked, entityname="'..entityname..'"')
minetest.log("action", '/spawnentity invoked, entityname="'..entityname..'"')
local player = minetest.get_player_by_name(name)
if player == nil then
print("Unable to spawn entity, player is nil")
minetest.log("error", "Unable to spawn entity, player is nil")
return true -- Handled chat message
end
local p = player:getpos()
@@ -485,7 +491,7 @@ minetest.register_chatcommand("pulverize", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
if player == nil then
print("Unable to pulverize, player is nil")
minetest.log("error", "Unable to pulverize, player is nil")
return true -- Handled chat message
end
if player:get_wielded_item():is_empty() then
@@ -509,34 +515,45 @@ minetest.register_on_punchnode(function(pos, node, puncher)
end)
minetest.register_chatcommand("rollback_check", {
params = "[<range>] [<seconds>]",
params = "[<range>] [<seconds>] [limit]",
description = "check who has last touched a node or near it, "..
"max. <seconds> ago (default range=0, seconds=86400=24h)",
"max. <seconds> ago (default range=0, seconds=86400=24h, limit=5)",
privs = {rollback=true},
func = function(name, param)
local range, seconds = string.match(param, "(%d+) *(%d*)")
local range, seconds, limit =
param:match("(%d+) *(%d*) *(%d*)")
range = tonumber(range) or 0
seconds = tonumber(seconds) or 86400
minetest.chat_send_player(name, "Punch a node (limits set: range="..
dump(range).." seconds="..dump(seconds).."s)")
limit = tonumber(limit) or 5
if limit > 100 then
minetest.chat_send_player(name, "That limit is too high!")
return
end
minetest.chat_send_player(name, "Punch a node (range="..
range..", seconds="..seconds.."s, limit="..limit..")")
minetest.rollback_punch_callbacks[name] = function(pos, node, puncher)
local name = puncher:get_player_name()
minetest.chat_send_player(name, "Checking...")
local actor, act_p, act_seconds =
minetest.rollback_get_last_node_actor(pos, range, seconds)
if actor == "" then
minetest.chat_send_player(name, "Checking "..minetest.pos_to_string(pos).."...")
local actions = minetest.rollback_get_node_actions(pos, range, seconds, limit)
local num_actions = #actions
if num_actions == 0 then
minetest.chat_send_player(name, "Nobody has touched the "..
"specified location in "..dump(seconds).." seconds")
"specified location in "..seconds.." seconds")
return
end
local nodedesc = "this node"
if act_p.x ~= pos.x or act_p.y ~= pos.y or act_p.z ~= pos.z then
nodedesc = minetest.pos_to_string(act_p)
local time = os.time()
for i = num_actions, 1, -1 do
local action = actions[i]
minetest.chat_send_player(name,
("%s %s %s -> %s %d seconds ago.")
:format(
minetest.pos_to_string(action.pos),
action.actor,
action.oldnode.name,
action.newnode.name,
time - action.time))
end
local nodename = minetest.get_node(act_p).name
minetest.chat_send_player(name, "Last actor on "..nodedesc..
" was "..actor..", "..dump(act_seconds)..
"s ago (node is now "..nodename..")")
end
end,
})
@@ -548,7 +565,7 @@ minetest.register_chatcommand("rollback", {
func = function(name, param)
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
if not target_name then
local player_name = nil;
local player_name = nil
player_name, seconds = string.match(param, "([^ ]+) *(%d*)")
if not player_name then
minetest.chat_send_player(name, "Invalid parameters. See /help rollback and /help rollback_check")
@@ -558,13 +575,13 @@ minetest.register_chatcommand("rollback", {
end
seconds = tonumber(seconds) or 60
minetest.chat_send_player(name, "Reverting actions of "..
dump(target_name).." since "..dump(seconds).." seconds.")
target_name.." since "..seconds.." seconds.")
local success, log = minetest.rollback_revert_actions_by(
target_name, seconds)
if #log > 10 then
if #log > 100 then
minetest.chat_send_player(name, "(log is too long to show)")
else
for _,line in ipairs(log) do
for _, line in pairs(log) do
minetest.chat_send_player(name, line)
end
end

View File

@@ -38,7 +38,7 @@ setmetatable(minetest.env, {
local func = minetest[key]
if type(func) == "function" then
rawset(table, key, function(self, ...)
return func(unpack({...}))
return func(...)
end)
else
rawset(table, key, nil)
@@ -46,3 +46,8 @@ setmetatable(minetest.env, {
return rawget(table, key)
end
})
function minetest.rollback_get_last_node_actor(pos, range, seconds)
return minetest.rollback_get_node_actions(pos, range, seconds, 1)[1]
end

View File

@@ -7,17 +7,18 @@
minetest.register_entity("__builtin:falling_node", {
initial_properties = {
physical = true,
collide_with_objects = false,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "wielditem",
textures = {},
visual_size = {x=0.667, y=0.667},
},
nodename = "",
node = {},
set_node = function(self, nodename)
self.nodename = nodename
local stack = ItemStack(nodename)
set_node = function(self, node)
self.node = node
local stack = ItemStack(node.name)
local itemtable = stack:to_table()
local itemname = nil
if itemtable then
@@ -31,20 +32,19 @@ minetest.register_entity("__builtin:falling_node", {
end
prop = {
is_visible = true,
textures = {nodename},
textures = {node.name},
}
self.object:set_properties(prop)
end,
get_staticdata = function(self)
return self.nodename
return self.node.name
end,
on_activate = function(self, staticdata)
self.nodename = staticdata
self.object:set_armor_groups({immortal=1})
--self.object:setacceleration({x=0, y=-10, z=0})
self:set_node(self.nodename)
self:set_node({name=staticdata})
end,
on_step = function(self, dtime)
@@ -54,10 +54,25 @@ minetest.register_entity("__builtin:falling_node", {
local pos = self.object:getpos()
local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point
local bcn = minetest.get_node(bcp)
local bcd = minetest.registered_nodes[bcn.name]
-- Note: walkable is in the node definition, not in item groups
if minetest.registered_nodes[bcn.name] and
minetest.registered_nodes[bcn.name].walkable then
if minetest.registered_nodes[bcn.name].buildable_to then
if not bcd or
(bcd.walkable or
(minetest.get_node_group(self.node.name, "float") ~= 0 and
bcd.liquidtype ~= "none")) then
if bcd and bcd.leveled and
bcn.name == self.node.name then
local addlevel = self.node.level
if addlevel == nil or addlevel <= 0 then
addlevel = bcd.leveled
end
if minetest.add_node_level(bcp, addlevel) == 0 then
self.object:remove()
return
end
elseif bcd and bcd.buildable_to and
(minetest.get_node_group(self.node.name, "float") == 0 or
bcd.liquidtype == "none") then
minetest.remove_node(bcp)
return
end
@@ -82,7 +97,7 @@ minetest.register_entity("__builtin:falling_node", {
end
end
-- Create node and remove entity
minetest.add_node(np, {name=self.nodename})
minetest.add_node(np, self.node)
self.object:remove()
nodeupdate(np)
else
@@ -91,9 +106,9 @@ minetest.register_entity("__builtin:falling_node", {
end
})
function spawn_falling_node(p, nodename)
function spawn_falling_node(p, node)
obj = minetest.add_entity(p, "__builtin:falling_node")
obj:get_luaentity():set_node(nodename)
obj:get_luaentity():set_node(node)
end
function drop_attached_node(p)
@@ -149,13 +164,16 @@ function nodeupdate_single(p, delay)
n_bottom = minetest.get_node(p_bottom)
-- Note: walkable is in the node definition, not in item groups
if minetest.registered_nodes[n_bottom.name] and
(minetest.get_node_group(n.name, "float") == 0 or minetest.registered_nodes[n_bottom.name].liquidtype == "none") and
(n.name ~= n_bottom.name or (minetest.registered_nodes[n_bottom.name].leveled and minetest.env:get_node_level(p_bottom) < minetest.env:get_node_max_level(p_bottom))) and
(not minetest.registered_nodes[n_bottom.name].walkable or
minetest.registered_nodes[n_bottom.name].buildable_to) then
if delay then
minetest.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
else
n.level = minetest.env:get_node_level(p)
minetest.remove_node(p)
spawn_falling_node(p, n.name)
spawn_falling_node(p, n)
nodeupdate(p)
end
end
@@ -169,7 +187,7 @@ function nodeupdate_single(p, delay)
end
end
function nodeupdate(p)
function nodeupdate(p, delay)
-- Round p to prevent falling entities to get stuck
p.x = math.floor(p.x+0.5)
p.y = math.floor(p.y+0.5)
@@ -178,7 +196,7 @@ function nodeupdate(p)
for x = -1,1 do
for y = -1,1 do
for z = -1,1 do
nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, not (x==0 and y==0 and z==0))
nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, delay or not (x==0 and y==0 and z==0))
end
end
end

View File

@@ -6,6 +6,7 @@ minetest.features = {
chat_send_player_param3 = true,
get_all_craft_recipes_works = true,
use_texture_alpha = true,
no_legacy_abms = true,
}
function minetest.has_feature(arg)

301
builtin/filterlist.lua Normal file
View File

@@ -0,0 +1,301 @@
--Minetest
--Copyright (C) 2013 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--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.
--------------------------------------------------------------------------------
-- Generic implementation of a filter/sortable list --
-- Usage: --
-- Filterlist needs to be initialized on creation. To achieve this you need to --
-- pass following functions: --
-- raw_fct() (mandatory): --
-- function returning a table containing the elements to be filtered --
-- compare_fct(element1,element2) (mandatory): --
-- function returning true/false if element1 is same element as element2 --
-- uid_match_fct(element1,uid) (optional) --
-- function telling if uid is attached to element1 --
-- filter_fct(element,filtercriteria) (optional) --
-- function returning true/false if filtercriteria met to element --
-- fetch_param (optional) --
-- parameter passed to raw_fct to aquire correct raw data --
-- --
--------------------------------------------------------------------------------
filterlist = {}
--------------------------------------------------------------------------------
function filterlist.refresh(this)
this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
filterlist.process(this)
end
--------------------------------------------------------------------------------
function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
local this = {}
this.m_raw_list_fct = raw_fct
this.m_compare_fct = compare_fct
this.m_filter_fct = filter_fct
this.m_uid_match_fct = uid_match_fct
this.m_filtercriteria = nil
this.m_fetch_param = fetch_param
this.m_sortmode = "none"
this.m_sort_list = {}
this.m_processed_list = nil
this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
filterlist.process(this)
return this
end
--------------------------------------------------------------------------------
function filterlist.add_sort_mechanism(this,name,fct)
this.m_sort_list[name] = fct
end
--------------------------------------------------------------------------------
function filterlist.set_filtercriteria(this,criteria)
if criteria == this.m_filtercriteria and
type(criteria) ~= "table" then
return
end
this.m_filtercriteria = criteria
filterlist.process(this)
end
--------------------------------------------------------------------------------
function filterlist.get_filtercriteria(this)
return this.m_filtercriteria
end
--------------------------------------------------------------------------------
--supported sort mode "alphabetic|none"
function filterlist.set_sortmode(this,mode)
if (mode == this.m_sortmode) then
return
end
this.m_sortmode = mode
filterlist.process(this)
end
--------------------------------------------------------------------------------
function filterlist.get_list(this)
return this.m_processed_list
end
--------------------------------------------------------------------------------
function filterlist.get_raw_list(this)
return this.m_raw_list
end
--------------------------------------------------------------------------------
function filterlist.get_raw_element(this,idx)
if type(idx) ~= "number" then
idx = tonumber(idx)
end
if idx ~= nil and idx > 0 and idx < #this.m_raw_list then
return this.m_raw_list[idx]
end
return nil
end
--------------------------------------------------------------------------------
function filterlist.get_raw_index(this,listindex)
assert(this.m_processed_list ~= nil)
if listindex ~= nil and listindex > 0 and
listindex <= #this.m_processed_list then
local entry = this.m_processed_list[listindex]
for i,v in ipairs(this.m_raw_list) do
if this.m_compare_fct(v,entry) then
return i
end
end
end
return 0
end
--------------------------------------------------------------------------------
function filterlist.get_current_index(this,listindex)
assert(this.m_processed_list ~= nil)
if listindex ~= nil and listindex > 0 and
listindex <= #this.m_raw_list then
local entry = this.m_raw_list[listindex]
for i,v in ipairs(this.m_processed_list) do
if this.m_compare_fct(v,entry) then
return i
end
end
end
return 0
end
--------------------------------------------------------------------------------
function filterlist.process(this)
assert(this.m_raw_list ~= nil)
if this.m_sortmode == "none" and
this.m_filtercriteria == nil then
this.m_processed_list = this.m_raw_list
return
end
this.m_processed_list = {}
for k,v in pairs(this.m_raw_list) do
if this.m_filtercriteria == nil or
this.m_filter_fct(v,this.m_filtercriteria) then
table.insert(this.m_processed_list,v)
end
end
if this.m_sortmode == "none" then
return
end
if this.m_sort_list[this.m_sortmode] ~= nil and
type(this.m_sort_list[this.m_sortmode]) == "function" then
this.m_sort_list[this.m_sortmode](this)
end
end
--------------------------------------------------------------------------------
function filterlist.size(this)
if this.m_processed_list == nil then
return 0
end
return #this.m_processed_list
end
--------------------------------------------------------------------------------
function filterlist.uid_exists_raw(this,uid)
for i,v in ipairs(this.m_raw_list) do
if this.m_uid_match_fct(v,uid) then
return true
end
end
return false
end
--------------------------------------------------------------------------------
function filterlist.raw_index_by_uid(this, uid)
local elementcount = 0
local elementidx = 0
for i,v in ipairs(this.m_raw_list) do
if this.m_uid_match_fct(v,uid) then
elementcount = elementcount +1
elementidx = i
end
end
-- If there are more elements than one with same name uid can't decide which
-- one is meant. This shouldn't be possible but just for sure.
if elementcount > 1 then
elementidx=0
end
return elementidx
end
--------------------------------------------------------------------------------
-- COMMON helper functions --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function compare_worlds(world1,world2)
if world1.path ~= world2.path then
return false
end
if world1.name ~= world2.name then
return false
end
if world1.gameid ~= world2.gameid then
return false
end
return true
end
--------------------------------------------------------------------------------
function sort_worlds_alphabetic(this)
table.sort(this.m_processed_list, function(a, b)
--fixes issue #857 (crash due to sorting nil in worldlist)
if a == nil or b == nil then
if a == nil and b ~= nil then return false end
if b == nil and a ~= nil then return true end
return false
end
if a.name:lower() == b.name:lower() then
return a.name < b.name
end
return a.name:lower() < b.name:lower()
end)
end
--------------------------------------------------------------------------------
function sort_mod_list(this)
table.sort(this.m_processed_list, function(a, b)
-- Show game mods at bottom
if a.typ ~= b.typ then
return b.typ == "game_mod"
end
-- If in same or no modpack, sort by name
if a.modpack == b.modpack then
if a.name:lower() == b.name:lower() then
return a.name < b.name
end
return a.name:lower() < b.name:lower()
-- Else compare name to modpack name
else
-- Always show modpack pseudo-mod on top of modpack mod list
if a.name == b.modpack then
return true
elseif b.name == a.modpack then
return false
end
local name_a = a.modpack or a.name
local name_b = b.modpack or b.name
if name_a:lower() == name_b:lower() then
return name_a < name_b
end
return name_a:lower() < name_b:lower()
end
end)
end

322
builtin/gamemgr.lua Normal file
View File

@@ -0,0 +1,322 @@
--Minetest
--Copyright (C) 2013 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--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.
gamemgr = {}
--------------------------------------------------------------------------------
function gamemgr.dialog_new_game()
local retval =
"label[2,2;" .. fgettext("Game Name") .. "]"..
"field[4.5,2.4;6,0.5;te_game_name;;]" ..
"button[5,4.2;2.6,0.5;new_game_confirm;" .. fgettext("Create") .. "]" ..
"button[7.5,4.2;2.8,0.5;new_game_cancel;" .. fgettext("Cancel") .. "]"
return retval
end
--------------------------------------------------------------------------------
function gamemgr.handle_games_buttons(fields)
if fields["gamelist"] ~= nil then
local event = explode_textlist_event(fields["gamelist"])
gamemgr.selected_game = event.index
end
if fields["btn_game_mgr_edit_game"] ~= nil then
return {
is_dialog = true,
show_buttons = false,
current_tab = "dialog_edit_game"
}
end
if fields["btn_game_mgr_new_game"] ~= nil then
return {
is_dialog = true,
show_buttons = false,
current_tab = "dialog_new_game"
}
end
return nil
end
--------------------------------------------------------------------------------
function gamemgr.handle_new_game_buttons(fields)
if fields["new_game_confirm"] and
fields["te_game_name"] ~= nil and
fields["te_game_name"] ~= "" then
local gamepath = engine.get_gamepath()
if gamepath ~= nil and
gamepath ~= "" then
local gamefolder = cleanup_path(fields["te_game_name"])
--TODO check for already existing first
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder)
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "mods")
engine.create_dir(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "menu")
local gameconf =
io.open(gamepath .. DIR_DELIM .. gamefolder .. DIR_DELIM .. "game.conf","w")
if gameconf then
gameconf:write("name = " .. fields["te_game_name"])
gameconf:close()
end
end
end
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
--------------------------------------------------------------------------------
function gamemgr.handle_edit_game_buttons(fields)
local current_game = gamemgr.get_game(gamemgr.selected_game)
if fields["btn_close_edit_game"] ~= nil or
current_game == nil then
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
if fields["btn_remove_mod_from_game"] ~= nil then
gamemgr.delete_mod(current_game,engine.get_textlist_index("mods_current"))
end
if fields["btn_add_mod_to_game"] ~= nil then
local modindex = engine.get_textlist_index("mods_available")
local mod = modmgr.get_global_mod(modindex)
if mod ~= nil then
local sourcepath = mod.path
if not gamemgr.add_mod(current_game,sourcepath) then
gamedata.errormessage =
fgettext("Gamemgr: Unable to copy mod \"$1\" to game \"$2\"", mod.name, current_game.id)
end
end
end
return nil
end
--------------------------------------------------------------------------------
function gamemgr.add_mod(gamespec,sourcepath)
if gamespec.gamemods_path ~= nil and
gamespec.gamemods_path ~= "" then
local modname = get_last_folder(sourcepath)
return engine.copy_dir(sourcepath,gamespec.gamemods_path .. DIR_DELIM .. modname);
end
return false
end
--------------------------------------------------------------------------------
function gamemgr.delete_mod(gamespec,modindex)
if gamespec.gamemods_path ~= nil and
gamespec.gamemods_path ~= "" then
local game_mods = {}
get_mods(gamespec.gamemods_path,game_mods)
if modindex > 0 and
#game_mods >= modindex then
if game_mods[modindex].path:sub(0,gamespec.gamemods_path:len())
== gamespec.gamemods_path then
engine.delete_dir(game_mods[modindex].path)
end
end
end
end
--------------------------------------------------------------------------------
function gamemgr.find_by_gameid(gameid)
for i=1,#gamemgr.games,1 do
if gamemgr.games[i].id == gameid then
return gamemgr.games[i], i
end
end
return nil, nil
end
--------------------------------------------------------------------------------
function gamemgr.get_game_mods(gamespec, retval)
if gamespec ~= nil and
gamespec.gamemods_path ~= nil and
gamespec.gamemods_path ~= "" then
get_mods(gamespec.gamemods_path, retval)
end
end
--------------------------------------------------------------------------------
function gamemgr.get_game_modlist(gamespec)
local retval = ""
local game_mods = {}
gamemgr.get_game_mods(gamespec, game_mods)
for i=1,#game_mods,1 do
if retval ~= "" then
retval = retval..","
end
retval = retval .. game_mods[i].name
end
return retval
end
--------------------------------------------------------------------------------
function gamemgr.gettab(name)
local retval = ""
if name == "dialog_edit_game" then
retval = retval .. gamemgr.dialog_edit_game()
end
if name == "dialog_new_game" then
retval = retval .. gamemgr.dialog_new_game()
end
if name == "game_mgr" then
retval = retval .. gamemgr.tab()
end
return retval
end
--------------------------------------------------------------------------------
function gamemgr.tab()
if gamemgr.selected_game == nil then
gamemgr.selected_game = 1
end
local retval =
"vertlabel[0,-0.25;" .. fgettext("GAMES") .. "]" ..
"label[1,-0.25;" .. fgettext("Games") .. ":]" ..
"textlist[1,0.25;4.5,4.4;gamelist;" ..
gamemgr.gamelist() ..
";" .. gamemgr.selected_game .. "]"
local current_game = gamemgr.get_game(gamemgr.selected_game)
if current_game ~= nil then
if current_game.menuicon_path ~= nil and
current_game.menuicon_path ~= "" then
retval = retval ..
"image[5.8,-0.25;2,2;" ..
engine.formspec_escape(current_game.menuicon_path) .. "]"
end
retval = retval ..
"field[8,-0.25;6,2;;" .. current_game.name .. ";]"..
"label[6,1.4;" .. fgettext("Mods:") .."]" ..
"button[9.7,1.5;2,0.2;btn_game_mgr_edit_game;" .. fgettext("edit game") .. "]" ..
"textlist[6,2;5.5,3.3;game_mgr_modlist;"
.. gamemgr.get_game_modlist(current_game) ..";0]" ..
"button[1,4.75;3.2,0.5;btn_game_mgr_new_game;" .. fgettext("new game") .. "]"
end
return retval
end
--------------------------------------------------------------------------------
function gamemgr.dialog_edit_game()
local current_game = gamemgr.get_game(gamemgr.selected_game)
if current_game ~= nil then
local retval =
"vertlabel[0,-0.25;" .. fgettext("EDIT GAME") .."]" ..
"label[0,-0.25;" .. current_game.name .. "]" ..
"button[11.55,-0.2;0.75,0.5;btn_close_edit_game;x]"
if current_game.menuicon_path ~= nil and
current_game.menuicon_path ~= "" then
retval = retval ..
"image[5.25,0;2,2;" ..
engine.formspec_escape(current_game.menuicon_path) .. "]"
end
retval = retval ..
"textlist[0.5,0.5;4.5,4.3;mods_current;"
.. gamemgr.get_game_modlist(current_game) ..";0]"
retval = retval ..
"textlist[7,0.5;4.5,4.3;mods_available;"
.. modmgr.render_modlist() .. ";0]"
retval = retval ..
"button[0.55,4.95;4.7,0.5;btn_remove_mod_from_game;" .. fgettext("Remove selected mod") .."]"
retval = retval ..
"button[7.05,4.95;4.7,0.5;btn_add_mod_to_game;" .. fgettext("<<-- Add mod") .."]"
return retval
end
end
--------------------------------------------------------------------------------
function gamemgr.handle_buttons(tab,fields)
local retval = nil
if tab == "dialog_edit_game" then
retval = gamemgr.handle_edit_game_buttons(fields)
end
if tab == "dialog_new_game" then
retval = gamemgr.handle_new_game_buttons(fields)
end
if tab == "game_mgr" then
retval = gamemgr.handle_games_buttons(fields)
end
return retval
end
--------------------------------------------------------------------------------
function gamemgr.get_game(index)
if index > 0 and index <= #gamemgr.games then
return gamemgr.games[index]
end
return nil
end
--------------------------------------------------------------------------------
function gamemgr.update_gamelist()
gamemgr.games = engine.get_games()
end
--------------------------------------------------------------------------------
function gamemgr.gamelist()
local retval = ""
if #gamemgr.games > 0 then
retval = retval .. gamemgr.games[1].id
for i=2,#gamemgr.games,1 do
retval = retval .. "," .. gamemgr.games[i].name
end
end
return retval
end

View File

@@ -34,8 +34,45 @@ function minetest.get_pointed_thing_position(pointed_thing, above)
end
end
function minetest.dir_to_facedir(dir)
if math.abs(dir.x) > math.abs(dir.z) then
function minetest.dir_to_facedir(dir, is6d)
--account for y if requested
if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then
--from above
if dir.y < 0 then
if math.abs(dir.x) > math.abs(dir.z) then
if dir.x < 0 then
return 19
else
return 13
end
else
if dir.z < 0 then
return 10
else
return 4
end
end
--from below
else
if math.abs(dir.x) > math.abs(dir.z) then
if dir.x < 0 then
return 15
else
return 17
end
else
if dir.z < 0 then
return 6
else
return 8
end
end
end
--otherwise, place horizontally
elseif math.abs(dir.x) > math.abs(dir.z) then
if dir.x < 0 then
return 3
else
@@ -50,6 +87,27 @@ function minetest.dir_to_facedir(dir)
end
end
function minetest.facedir_to_dir(facedir)
--a table of possible dirs
return ({{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}})
--indexed into by a table of correlating facedirs
[({[0]=1, 2, 3, 4,
5, 2, 6, 4,
6, 2, 5, 4,
1, 5, 3, 6,
1, 6, 3, 5,
1, 4, 3, 2})
--indexed into by the facedir in question
[facedir]]
end
function minetest.dir_to_wallmounted(dir)
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
if dir.y < 0 then
@@ -121,11 +179,11 @@ function minetest.get_node_drops(nodename, toolname)
return got_items
end
function minetest.item_place_node(itemstack, placer, pointed_thing)
function minetest.item_place_node(itemstack, placer, pointed_thing, param2)
local item = itemstack:peek_item()
local def = itemstack:get_definition()
if def.type ~= "node" or pointed_thing.type ~= "node" then
return itemstack
return itemstack, false
end
local under = pointed_thing.under
@@ -136,7 +194,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
if not oldnode_under or not oldnode_above then
minetest.log("info", placer:get_player_name() .. " tried to place"
.. " node in unloaded position " .. minetest.pos_to_string(above))
return itemstack
return itemstack, false
end
local olddef_under = ItemStack({name=oldnode_under.name}):get_definition()
@@ -148,7 +206,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
minetest.log("info", placer:get_player_name() .. " tried to place"
.. " node in invalid position " .. minetest.pos_to_string(above)
.. ", replacing " .. oldnode_above.name)
return itemstack
return itemstack, false
end
-- Place above pointed node
@@ -160,14 +218,23 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
place_to = {x = under.x, y = under.y, z = under.z}
end
if minetest.is_protected(place_to, placer:get_player_name()) then
minetest.log("action", placer:get_player_name()
.. " tried to place " .. def.name
.. " at protected position "
.. minetest.pos_to_string(place_to))
minetest.record_protection_violation(place_to, placer:get_player_name())
return itemstack
end
minetest.log("action", placer:get_player_name() .. " places node "
.. def.name .. " at " .. minetest.pos_to_string(place_to))
local oldnode = minetest.get_node(place_to)
local newnode = {name = def.name, param1 = 0, param2 = 0}
local newnode = {name = def.name, param1 = 0, param2 = param2}
-- Calculate direction for wall mounted stuff like torches and signs
if def.paramtype2 == 'wallmounted' then
if def.paramtype2 == 'wallmounted' and not param2 then
local dir = {
x = under.x - above.x,
y = under.y - above.y,
@@ -175,7 +242,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
}
newnode.param2 = minetest.dir_to_wallmounted(dir)
-- Calculate the direction for furnaces and chests and stuff
elseif def.paramtype2 == 'facedir' then
elseif def.paramtype2 == 'facedir' and not param2 then
local placer_pos = placer:getpos()
if placer_pos then
local dir = {
@@ -193,7 +260,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
not check_attached_node(place_to, newnode) then
minetest.log("action", "attached node " .. def.name ..
" can not be placed at " .. minetest.pos_to_string(place_to))
return itemstack
return itemstack, false
end
-- Add node and update
@@ -225,7 +292,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
if take_item then
itemstack:take_item()
end
return itemstack
return itemstack, true
end
function minetest.item_place_object(itemstack, placer, pointed_thing)
@@ -237,19 +304,19 @@ function minetest.item_place_object(itemstack, placer, pointed_thing)
return itemstack
end
function minetest.item_place(itemstack, placer, pointed_thing)
function minetest.item_place(itemstack, placer, pointed_thing, param2)
-- Call on_rightclick if the pointed node defines it
if pointed_thing.type == "node" and placer and
not placer:get_player_control().sneak then
local n = minetest.get_node(pointed_thing.under)
local nn = n.name
if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then
return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, placer, itemstack) or itemstack
return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, placer, itemstack) or itemstack, false
end
end
if itemstack:get_definition().type == "node" then
return minetest.item_place_node(itemstack, placer, pointed_thing)
return minetest.item_place_node(itemstack, placer, pointed_thing, param2)
end
return itemstack
end
@@ -311,28 +378,40 @@ function minetest.handle_node_drops(pos, drops, digger)
end
function minetest.node_dig(pos, node, digger)
minetest.debug("node_dig")
local def = ItemStack({name=node.name}):get_definition()
-- Check if def ~= 0 because we always want to be able to remove unknown nodes
if #def ~= 0 and not def.diggable or (def.can_dig and not def.can_dig(pos,digger)) then
minetest.debug("not diggable")
if not def.diggable or (def.can_dig and not def.can_dig(pos,digger)) then
minetest.log("info", digger:get_player_name() .. " tried to dig "
.. node.name .. " which is not diggable "
.. minetest.pos_to_string(pos))
return
end
if minetest.is_protected(pos, digger:get_player_name()) then
minetest.log("action", digger:get_player_name()
.. " tried to dig " .. node.name
.. " at protected position "
.. minetest.pos_to_string(pos))
minetest.record_protection_violation(pos, digger:get_player_name())
return
end
minetest.log('action', digger:get_player_name() .. " digs "
.. node.name .. " at " .. minetest.pos_to_string(pos))
local wielded = digger:get_wielded_item()
local drops = minetest.get_node_drops(node.name, wielded:get_name())
-- Wear out tool
local wdef = wielded:get_definition()
local tp = wielded:get_tool_capabilities()
local dp = minetest.get_dig_params(def.groups, tp)
wielded:add_wear(dp.wear)
if wdef and wdef.after_use then
wielded = wdef.after_use(wielded, digger, node, dp) or wielded
else
-- Wear out tool
if not minetest.setting_getbool("creative_mode") then
wielded:add_wear(dp.wear)
end
end
digger:set_wielded_item(wielded)
-- Handle drops
@@ -422,7 +501,7 @@ minetest.nodedef_default = {
post_effect_color = {a=0, r=0, g=0, b=0},
paramtype = "none",
paramtype2 = "none",
is_ground_content = false,
is_ground_content = true,
sunlight_propagates = false,
walkable = true,
pointable = true,
@@ -433,6 +512,7 @@ minetest.nodedef_default = {
liquid_alternative_flowing = "",
liquid_alternative_source = "",
liquid_viscosity = 0,
drowning = 0,
light_source = 0,
damage_per_second = 0,
selection_box = {type="regular"},

View File

@@ -12,6 +12,7 @@ minetest.register_entity("__builtin:item", {
initial_properties = {
hp_max = 1,
physical = true,
collide_with_objects = false,
collisionbox = {-0.17,-0.17,-0.17, 0.17,0.17,0.17},
visual = "sprite",
visual_size = {x=0.5, y=0.5},

1328
builtin/mainmenu.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -40,15 +40,24 @@ function minetest.check_player_privs(name, privs)
return true, ""
end
local player_list = {}
minetest.register_on_joinplayer(function(player)
player_list[player:get_player_name()] = player
end)
minetest.register_on_leaveplayer(function(player)
player_list[player:get_player_name()] = nil
end)
function minetest.get_connected_players()
-- This could be optimized a bit, but leave that for later
local list = {}
for _, obj in pairs(minetest.get_objects_inside_radius({x=0,y=0,z=0}, 1000000)) do
if obj:is_player() then
table.insert(list, obj)
local temp_table = {}
for index, value in pairs(player_list) do
if value:is_player_connected() then
table.insert(temp_table, value)
end
end
return list
return temp_table
end
function minetest.hash_node_position(pos)
@@ -99,10 +108,14 @@ function minetest.setting_get_pos(name)
return minetest.string_to_pos(value)
end
function minetest.formspec_escape(str)
str = string.gsub(str, "\\", "\\\\")
str = string.gsub(str, "%[", "\\[")
str = string.gsub(str, "%]", "\\]")
return str
-- To be overriden by protection mods
function minetest.is_protected(pos, name)
return false
end
function minetest.record_protection_violation(pos, name)
for _, func in pairs(minetest.registered_on_protection_violation) do
func(pos, name)
end
end

View File

@@ -1,5 +1,6 @@
-- Minetest: builtin/misc_helpers.lua
--------------------------------------------------------------------------------
function basic_dump2(o)
if type(o) == "number" then
return tostring(o)
@@ -19,6 +20,7 @@ function basic_dump2(o)
end
end
--------------------------------------------------------------------------------
function dump2(o, name, dumped)
name = name or "_"
dumped = dumped or {}
@@ -44,6 +46,7 @@ function dump2(o, name, dumped)
end
end
--------------------------------------------------------------------------------
function dump(o, dumped)
dumped = dumped or {}
if type(o) == "number" then
@@ -57,7 +60,7 @@ function dump(o, dumped)
dumped[o] = true
local t = {}
for k,v in pairs(o) do
t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
t[#t+1] = "[" .. dump(k, dumped) .. "] = " .. dump(v, dumped)
end
return "{" .. table.concat(t, ", ") .. "}"
elseif type(o) == "boolean" then
@@ -74,6 +77,7 @@ function dump(o, dumped)
end
end
--------------------------------------------------------------------------------
function string:split(sep)
local sep, fields = sep or ",", {}
local pattern = string.format("([^%s]+)", sep)
@@ -81,14 +85,319 @@ function string:split(sep)
return fields
end
--------------------------------------------------------------------------------
function file_exists(filename)
local f = io.open(filename, "r")
if f==nil then
return false
else
f:close()
return true
end
end
--------------------------------------------------------------------------------
function string:trim()
return (self:gsub("^%s*(.-)%s*$", "%1"))
end
assert(string.trim("\n \t\tfoo bar\t ") == "foo bar")
function minetest.pos_to_string(pos)
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
--------------------------------------------------------------------------------
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)
end
--------------------------------------------------------------------------------
function explode_textlist_event(text)
local retval = {}
retval.typ = "INV"
local parts = text:split(":")
if #parts == 2 then
retval.typ = parts[1]:trim()
retval.index= tonumber(parts[2]:trim())
if type(retval.index) ~= "number" then
retval.typ = "INV"
end
end
return retval
end
--------------------------------------------------------------------------------
function get_last_folder(text,count)
local parts = text:split(DIR_DELIM)
if count == nil then
return parts[#parts]
end
local retval = ""
for i=1,count,1 do
retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
end
return retval
end
--------------------------------------------------------------------------------
function cleanup_path(temppath)
local parts = temppath:split("-")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. "_"
end
temppath = temppath .. parts[i]
end
parts = temppath:split(".")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. "_"
end
temppath = temppath .. parts[i]
end
parts = temppath:split("'")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. ""
end
temppath = temppath .. parts[i]
end
parts = temppath:split(" ")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath
end
temppath = temppath .. parts[i]
end
return temppath
end
local tbl = engine or minetest
function tbl.formspec_escape(text)
if text ~= nil then
text = string.gsub(text,"\\","\\\\")
text = string.gsub(text,"%]","\\]")
text = string.gsub(text,"%[","\\[")
text = string.gsub(text,";","\\;")
text = string.gsub(text,",","\\,")
end
return text
end
function tbl.splittext(text,charlimit)
local retval = {}
local current_idx = 1
local start,stop = string.find(text," ",current_idx)
local nl_start,nl_stop = string.find(text,"\n",current_idx)
local gotnewline = false
if nl_start ~= nil and (start == nil or nl_start < start) then
start = nl_start
stop = nl_stop
gotnewline = true
end
local last_line = ""
while start ~= nil do
if string.len(last_line) + (stop-start) > charlimit then
table.insert(retval,last_line)
last_line = ""
end
if last_line ~= "" then
last_line = last_line .. " "
end
last_line = last_line .. string.sub(text,current_idx,stop -1)
if gotnewline then
table.insert(retval,last_line)
last_line = ""
gotnewline = false
end
current_idx = stop+1
start,stop = string.find(text," ",current_idx)
nl_start,nl_stop = string.find(text,"\n",current_idx)
if nl_start ~= nil and (start == nil or nl_start < start) then
start = nl_start
stop = nl_stop
gotnewline = true
end
end
--add last part of text
if string.len(last_line) + (string.len(text) - current_idx) > charlimit then
table.insert(retval,last_line)
table.insert(retval,string.sub(text,current_idx))
else
last_line = last_line .. " " .. string.sub(text,current_idx)
table.insert(retval,last_line)
end
return retval
end
--------------------------------------------------------------------------------
if minetest then
local dirs1 = { 9, 18, 7, 12 }
local dirs2 = { 20, 23, 22, 21 }
function minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags)
orient_flags = orient_flags or {}
local node = minetest.get_node(pointed_thing.under)
if not minetest.registered_nodes[node.name]
or not minetest.registered_nodes[node.name].on_rightclick then
local above = pointed_thing.above
local under = pointed_thing.under
local pitch = placer:get_look_pitch()
local pname = minetest.get_node(under).name
local node = minetest.get_node(above)
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
local wield_name = itemstack:get_name()
local reg_node = minetest.registered_nodes[pname]
if not reg_node or not reg_node.on_rightclick then
local iswall = (above.x ~= under.x) or (above.z ~= under.z)
local isceiling = (above.x == under.x) and (above.z == under.z)
and (pitch > 0)
local pos1 = above
if reg_node and reg_node.buildable_to then
pos1 = under
iswall = false
end
reg_node = minetest.registered_nodes[minetest.get_node(pos1).name]
if not reg_node or not reg_node.buildable_to then
return
end
if orient_flags.force_floor then
iswall = false
isceiling = false
elseif orient_flags.force_ceiling then
iswall = false
isceiling = true
elseif orient_flags.force_wall then
iswall = true
isceiling = false
elseif orient_flags.invert_wall then
iswall = not iswall
end
if iswall then
minetest.add_node(pos1, {name = wield_name, param2 = dirs1[fdir+1] })
elseif isceiling then
if orient_flags.force_facedir then
minetest.add_node(pos1, {name = wield_name, param2 = 20 })
else
minetest.add_node(pos1, {name = wield_name, param2 = dirs2[fdir+1] })
end
else -- place right side up
if orient_flags.force_facedir then
minetest.add_node(pos1, {name = wield_name, param2 = 0 })
else
minetest.add_node(pos1, {name = wield_name, param2 = fdir })
end
end
if not infinitestacks then
itemstack:take_item()
return itemstack
end
end
else
minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack)
end
end
--------------------------------------------------------------------------------
--Wrapper for rotate_and_place() to check for sneak and assume Creative mode
--implies infinite stacks when performing a 6d rotation.
--------------------------------------------------------------------------------
minetest.rotate_node = function(itemstack, placer, pointed_thing)
minetest.rotate_and_place(itemstack, placer, pointed_thing,
minetest.setting_getbool("creative_mode"),
{invert_wall = placer:get_player_control().sneak})
return itemstack
end
end
--------------------------------------------------------------------------------
-- mainmenu only functions
--------------------------------------------------------------------------------
if engine ~= nil then
engine.get_game = function(index)
local games = game.get_games()
if index > 0 and index <= #games then
return games[index]
end
return nil
end
function fgettext(text, ...)
text = engine.gettext(text)
local arg = {n=select('#', ...), ...}
if arg.n >= 1 then
-- Insert positional parameters ($1, $2, ...)
result = ''
pos = 1
while pos <= text:len() do
newpos = text:find('[$]', pos)
if newpos == nil then
result = result .. text:sub(pos)
pos = text:len() + 1
else
paramindex = tonumber(text:sub(newpos+1, newpos+1))
result = result .. text:sub(pos, newpos-1) .. tostring(arg[paramindex])
pos = newpos + 2
end
end
text = result
end
return engine.formspec_escape(text)
end
end
--------------------------------------------------------------------------------
-- core only fct
--------------------------------------------------------------------------------
if minetest ~= nil then
--------------------------------------------------------------------------------
function minetest.pos_to_string(pos)
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
end
end

View File

@@ -24,17 +24,15 @@ minetest.registered_aliases = {}
-- For tables that are indexed by item name:
-- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
local function set_alias_metatable(table)
setmetatable(table, {
__index = function(name)
return rawget(table, minetest.registered_aliases[name])
end
})
end
set_alias_metatable(minetest.registered_items)
set_alias_metatable(minetest.registered_nodes)
set_alias_metatable(minetest.registered_craftitems)
set_alias_metatable(minetest.registered_tools)
local alias_metatable = {
__index = function(t, name)
return rawget(t, minetest.registered_aliases[name])
end
}
setmetatable(minetest.registered_items, alias_metatable)
setmetatable(minetest.registered_nodes, alias_metatable)
setmetatable(minetest.registered_craftitems, alias_metatable)
setmetatable(minetest.registered_tools, alias_metatable)
-- These item names may not be used because they would interfere
-- with legacy itemstrings
@@ -106,6 +104,11 @@ function minetest.register_item(name, itemdef)
-- Use the nodebox as selection box if it's not set manually
if itemdef.drawtype == "nodebox" and not itemdef.selection_box then
itemdef.selection_box = itemdef.node_box
elseif itemdef.drawtype == "fencelike" and not itemdef.selection_box then
itemdef.selection_box = {
type = "fixed",
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
}
end
setmetatable(itemdef, {__index = minetest.nodedef_default})
minetest.registered_nodes[itemdef.name] = itemdef
@@ -223,6 +226,27 @@ function minetest.register_alias(name, convert_to)
end
end
local register_biome_raw = minetest.register_biome
minetest.registered_biomes = {}
function minetest.register_biome(biome)
minetest.registered_biomes[biome.name] = biome
register_biome_raw(biome)
end
function minetest.on_craft(itemstack, player, old_craft_list, craft_inv)
for _, func in ipairs(minetest.registered_on_crafts) do
itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack
end
return itemstack
end
function minetest.craft_predict(itemstack, player, old_craft_list, craft_inv)
for _, func in ipairs(minetest.registered_craft_predicts) do
itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack
end
return itemstack
end
-- Alias the forbidden item names to "" so they can't be
-- created via itemstrings (e.g. /give)
local name
@@ -249,6 +273,7 @@ minetest.register_item(":unknown", {
on_place = minetest.item_place,
on_drop = minetest.item_drop,
groups = {not_in_creative_inventory=1},
diggable = true,
})
minetest.register_node(":air", {
@@ -289,6 +314,45 @@ minetest.register_item(":", {
groups = {not_in_creative_inventory=1},
})
function minetest.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table")
local cb_len = #callbacks
if cb_len == 0 then
if mode == 2 or mode == 3 then
return true
elseif mode == 4 or mode == 5 then
return false
end
end
local ret = nil
for i = 1, cb_len do
local cb_ret = callbacks[i](...)
if mode == 0 and i == 1 then
ret = cb_ret
elseif mode == 1 and i == cb_len then
ret = cb_ret
elseif mode == 2 then
if not cb_ret or i == 1 then
ret = cb_ret
end
elseif mode == 3 then
if cb_ret then
return cb_ret
end
ret = cb_ret
elseif mode == 4 then
if (cb_ret and not ret) or i == 1 then
ret = cb_ret
end
elseif mode == 5 and cb_ret then
return cb_ret
end
end
return ret
end
--
-- Callback registration
--
@@ -307,6 +371,7 @@ end
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
minetest.registered_on_mapgen_inits, minetest.register_on_mapgen_init = make_registration()
minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration()
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
@@ -315,7 +380,12 @@ minetest.registered_on_generateds, minetest.register_on_generated = make_registr
minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
minetest.registered_on_prejoinplayers, minetest.register_on_prejoinplayer = make_registration()
minetest.registered_on_joinplayers, minetest.register_on_joinplayer = make_registration()
minetest.registered_on_leaveplayers, minetest.register_on_leaveplayer = make_registration()
minetest.registered_on_player_receive_fields, minetest.register_on_player_receive_fields = make_registration_reverse()
minetest.registered_on_cheats, minetest.register_on_cheat = make_registration()
minetest.registered_on_crafts, minetest.register_on_craft = make_registration()
minetest.registered_craft_predicts, minetest.register_craft_predict = make_registration()
minetest.registered_on_protection_violation, minetest.register_on_protection_violation = make_registration()

80
builtin/mm_menubar.lua Normal file
View File

@@ -0,0 +1,80 @@
--Minetest
--Copyright (C) 2013 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--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.
menubar = {}
--------------------------------------------------------------------------------
function menubar.handle_buttons(fields)
for i=1,#menubar.buttons,1 do
if fields[menubar.buttons[i].btn_name] ~= nil then
menu.last_game = menubar.buttons[i].index
engine.setting_set("main_menu_last_game_idx",menu.last_game)
menu.update_gametype()
end
end
end
--------------------------------------------------------------------------------
function menubar.refresh()
menubar.formspec = "box[-0.3,5.625;12.4,1.2;#000000]" ..
"box[-0.3,5.6;12.4,0.05;#FFFFFF]"
menubar.buttons = {}
local button_base = -0.08
local maxbuttons = #gamemgr.games
if maxbuttons > 11 then
maxbuttons = 11
end
for i=1,maxbuttons,1 do
local btn_name = "menubar_btn_" .. gamemgr.games[i].id
local buttonpos = button_base + (i-1) * 1.1
if gamemgr.games[i].menuicon_path ~= nil and
gamemgr.games[i].menuicon_path ~= "" then
menubar.formspec = menubar.formspec ..
"image_button[" .. buttonpos .. ",5.72;1.165,1.175;" ..
engine.formspec_escape(gamemgr.games[i].menuicon_path) .. ";" ..
btn_name .. ";;true;false]"
else
local part1 = gamemgr.games[i].id:sub(1,5)
local part2 = gamemgr.games[i].id:sub(6,10)
local part3 = gamemgr.games[i].id:sub(11)
local text = part1 .. "\n" .. part2
if part3 ~= nil and
part3 ~= "" then
text = text .. "\n" .. part3
end
menubar.formspec = menubar.formspec ..
"image_button[" .. buttonpos .. ",5.72;1.165,1.175;;" ..btn_name ..
";" .. text .. ";true;true]"
end
local toadd = {
btn_name = btn_name,
index = i,
}
table.insert(menubar.buttons,toadd)
end
end

146
builtin/mm_textures.lua Normal file
View File

@@ -0,0 +1,146 @@
--Minetest
--Copyright (C) 2013 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--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.
mm_texture = {}
--------------------------------------------------------------------------------
function mm_texture.init()
mm_texture.defaulttexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM
mm_texture.basetexturedir = mm_texture.defaulttexturedir
mm_texture.texturepack = engine.setting_get("texture_path")
mm_texture.gameid = nil
end
--------------------------------------------------------------------------------
function mm_texture.update(tab,gamedetails)
if tab ~= "singleplayer" then
mm_texture.reset()
return
end
if gamedetails == nil then
return
end
mm_texture.update_game(gamedetails)
end
--------------------------------------------------------------------------------
function mm_texture.reset()
mm_texture.gameid = nil
local have_bg = false
local have_overlay = mm_texture.set_generic("overlay")
if not have_overlay then
have_bg = mm_texture.set_generic("background")
end
mm_texture.clear("header")
mm_texture.clear("footer")
engine.set_clouds(false)
mm_texture.set_generic("footer")
mm_texture.set_generic("header")
if not have_bg and
engine.setting_getbool("enable_clouds") then
engine.set_clouds(true)
end
end
--------------------------------------------------------------------------------
function mm_texture.update_game(gamedetails)
if mm_texture.gameid == gamedetails.id then
return
end
local have_bg = false
local have_overlay = mm_texture.set_game("overlay",gamedetails)
if not have_overlay then
have_bg = mm_texture.set_game("background",gamedetails)
end
mm_texture.clear("header")
mm_texture.clear("footer")
engine.set_clouds(false)
if not have_bg and
engine.setting_getbool("enable_clouds") then
engine.set_clouds(true)
end
mm_texture.set_game("footer",gamedetails)
mm_texture.set_game("header",gamedetails)
mm_texture.gameid = gamedetails.id
end
--------------------------------------------------------------------------------
function mm_texture.clear(identifier)
engine.set_background(identifier,"")
end
--------------------------------------------------------------------------------
function mm_texture.set_generic(identifier)
--try texture pack first
if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM .."menu_" ..
identifier .. ".png"
if engine.set_background(identifier,path) then
return true
end
end
if mm_texture.defaulttexturedir ~= nil then
local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" ..
identifier .. ".png"
if engine.set_background(identifier,path) then
return true
end
end
return false
end
--------------------------------------------------------------------------------
function mm_texture.set_game(identifier,gamedetails)
if gamedetails == nil then
return false
end
if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM ..
gamedetails.id .. "_menu_" .. identifier .. ".png"
if engine.set_background(identifier,path) then
return true
end
end
local path = gamedetails.path .. DIR_DELIM .."menu" ..
DIR_DELIM .. identifier .. ".png"
if engine.set_background(identifier,path) then
return true
end
return false
end

1130
builtin/modmgr.lua Normal file

File diff suppressed because it is too large Load Diff

615
builtin/modstore.lua Normal file
View File

@@ -0,0 +1,615 @@
--Minetest
--Copyright (C) 2013 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--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.
--------------------------------------------------------------------------------
--modstore implementation
modstore = {}
--------------------------------------------------------------------------------
-- @function [parent=#modstore] init
function modstore.init()
modstore.tabnames = {}
table.insert(modstore.tabnames,"dialog_modstore_unsorted")
table.insert(modstore.tabnames,"dialog_modstore_search")
modstore.modsperpage = 5
modstore.basetexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM
modstore.lastmodtitle = ""
modstore.last_search = ""
modstore.searchlist = filterlist.create(
function()
if modstore.modlist_unsorted ~= nil and
modstore.modlist_unsorted.data ~= nil then
return modstore.modlist_unsorted.data
end
return {}
end,
function(element,modid)
if element.id == modid then
return true
end
return false
end, --compare fct
nil, --uid match fct
function(element,substring)
if substring == nil or
substring == "" then
return false
end
substring = substring:upper()
if element.title ~= nil and
element.title:upper():find(substring) ~= nil then
return true
end
if element.details ~= nil and
element.details.author ~= nil and
element.details.author:upper():find(substring) ~= nil then
return true
end
if element.details ~= nil and
element.details.description ~= nil and
element.details.description:upper():find(substring) ~= nil then
return true
end
return false
end --filter fct
)
modstore.current_list = nil
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] nametoindex
function modstore.nametoindex(name)
for i=1,#modstore.tabnames,1 do
if modstore.tabnames[i] == name then
return i
end
end
return 1
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] getsuccessfuldialog
function modstore.getsuccessfuldialog()
local retval = ""
retval = retval .. "size[6,2]"
if modstore.lastmodentry ~= nil then
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
retval = retval .. "label[3,0.75;" .. engine.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
end
retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]"
return retval
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] gettab
function modstore.gettab(tabname)
local retval = ""
local is_modstore_tab = false
if tabname == "dialog_modstore_unsorted" then
modstore.modsperpage = 5
retval = modstore.getmodlist(modstore.modlist_unsorted)
is_modstore_tab = true
end
if tabname == "dialog_modstore_search" then
retval = modstore.getsearchpage()
is_modstore_tab = true
end
if is_modstore_tab then
return modstore.tabheader(tabname) .. retval
end
if tabname == "modstore_mod_installed" then
return modstore.getsuccessfuldialog()
end
if tabname == "modstore_downloading" then
return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
" " .. modstore.lastmodtitle .. " " ..
fgettext("please wait...") .. "]"
end
return ""
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] tabheader
function modstore.tabheader(tabname)
local retval = "size[12,10.25]"
retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" ..
"Unsorted,Search;" ..
modstore.nametoindex(tabname) .. ";true;false]" ..
"button[4,9.9;4,0.5;btn_modstore_close;" ..
fgettext("Close modstore") .. "]"
return retval
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] handle_buttons
function modstore.handle_buttons(current_tab,fields)
if fields["modstore_tab"] then
local index = tonumber(fields["modstore_tab"])
if index > 0 and
index <= #modstore.tabnames then
if modstore.tabnames[index] == "dialog_modstore_search" then
filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search)
filterlist.refresh(modstore.searchlist)
modstore.modsperpage = 4
modstore.currentlist = {
page = 0,
pagecount =
math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
data = filterlist.get_list(modstore.searchlist),
}
end
return {
current_tab = modstore.tabnames[index],
is_dialog = true,
show_buttons = false
}
end
end
if fields["btn_modstore_page_up"] then
if modstore.current_list ~= nil and modstore.current_list.page > 0 then
modstore.current_list.page = modstore.current_list.page - 1
end
end
if fields["btn_modstore_page_down"] then
if modstore.current_list ~= nil and
modstore.current_list.page <modstore.current_list.pagecount-1 then
modstore.current_list.page = modstore.current_list.page +1
end
end
if fields["btn_hidden_close_download"] ~= nil then
if fields["btn_hidden_close_download"].successfull then
modstore.lastmodentry = fields["btn_hidden_close_download"]
return {
current_tab = "modstore_mod_installed",
is_dialog = true,
show_buttons = false
}
else
modstore.lastmodtitle = ""
return {
current_tab = modstore.tabnames[1],
is_dialog = true,
show_buttons = false
}
end
end
if fields["btn_confirm_mod_successfull"] then
modstore.lastmodentry = nil
modstore.lastmodtitle = ""
return {
current_tab = modstore.tabnames[1],
is_dialog = true,
show_buttons = false
}
end
if fields["btn_modstore_search"] or
(fields["key_enter"] and fields["te_modstore_search"] ~= nil) then
modstore.last_search = fields["te_modstore_search"]
filterlist.set_filtercriteria(modstore.searchlist,fields["te_modstore_search"])
filterlist.refresh(modstore.searchlist)
modstore.currentlist = {
page = 0,
pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
data = filterlist.get_list(modstore.searchlist),
}
end
if fields["btn_modstore_close"] then
return {
is_dialog = false,
show_buttons = true,
current_tab = engine.setting_get("main_menu_tab")
}
end
for key,value in pairs(fields) do
local foundat = key:find("btn_install_mod_")
if ( foundat == 1) then
local modid = tonumber(key:sub(17))
for i=1,#modstore.modlist_unsorted.data,1 do
if modstore.modlist_unsorted.data[i].id == modid then
local moddetails = modstore.modlist_unsorted.data[i].details
if modstore.lastmodtitle ~= "" then
modstore.lastmodtitle = modstore.lastmodtitle .. ", "
end
modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title
engine.handle_async(
function(param)
local fullurl = engine.setting_get("modstore_download_url") ..
param.moddetails.download_url
if param.version ~= nil then
local found = false
for i=1,#param.moddetails.versions, 1 do
if param.moddetails.versions[i].date:sub(1,10) == param.version then
fullurl = engine.setting_get("modstore_download_url") ..
param.moddetails.versions[i].download_url
found = true
end
end
if not found then
return {
moddetails = param.moddetails,
successfull = false
}
end
end
if engine.download_file(fullurl,param.filename) then
return {
texturename = param.texturename,
moddetails = param.moddetails,
filename = param.filename,
successfull = true
}
else
return {
modtitle = param.title,
successfull = false
}
end
end,
{
moddetails = moddetails,
version = fields["dd_version" .. modid],
filename = os.tempfolder() .. "_MODNAME_" .. moddetails.basename .. ".zip",
texturename = modstore.modlist_unsorted.data[i].texturename
},
function(result)
if result.successfull then
modmgr.installmod(result.filename,result.moddetails.basename)
os.remove(result.filename)
else
gamedata.errormessage = "Failed to download " .. result.moddetails.title
end
if gamedata.errormessage == nil then
engine.button_handler({btn_hidden_close_download=result})
else
engine.button_handler({btn_hidden_close_download={successfull=false}})
end
end
)
return {
current_tab = "modstore_downloading",
is_dialog = true,
show_buttons = false,
ignore_menu_quit = true
}
end
end
break
end
end
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] update_modlist
function modstore.update_modlist()
modstore.modlist_unsorted = {}
modstore.modlist_unsorted.data = {}
modstore.modlist_unsorted.pagecount = 1
modstore.modlist_unsorted.page = 0
engine.handle_async(
function(param)
return engine.get_modstore_list()
end,
nil,
function(result)
if result ~= nil then
modstore.modlist_unsorted = {}
modstore.modlist_unsorted.data = result
if modstore.modlist_unsorted.data ~= nil then
modstore.modlist_unsorted.pagecount =
math.ceil((#modstore.modlist_unsorted.data / modstore.modsperpage))
else
modstore.modlist_unsorted.data = {}
modstore.modlist_unsorted.pagecount = 1
end
modstore.modlist_unsorted.page = 0
modstore.fetchdetails()
engine.event_handler("Refresh")
end
end
)
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] fetchdetails
function modstore.fetchdetails()
for i=1,#modstore.modlist_unsorted.data,1 do
engine.handle_async(
function(param)
param.details = engine.get_modstore_details(tostring(param.modid))
return param
end,
{
modid=modstore.modlist_unsorted.data[i].id,
listindex=i
},
function(result)
if result ~= nil and
modstore.modlist_unsorted ~= nil
and modstore.modlist_unsorted.data ~= nil and
modstore.modlist_unsorted.data[result.listindex] ~= nil and
modstore.modlist_unsorted.data[result.listindex].id ~= nil then
modstore.modlist_unsorted.data[result.listindex].details = result.details
engine.event_handler("Refresh")
end
end
)
end
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] getscreenshot
function modstore.getscreenshot(ypos,listentry)
if listentry.details ~= nil and
(listentry.details.screenshot_url == nil or
listentry.details.screenshot_url == "") then
if listentry.texturename == nil then
listentry.texturename = modstore.basetexturedir .. "no_screenshot.png"
end
return "image[0,".. ypos .. ";3,2;" ..
engine.formspec_escape(listentry.texturename) .. "]"
end
if listentry.details ~= nil and
listentry.texturename == nil then
--make sure we don't download multiple times
listentry.texturename = "in progress"
--prepare url and filename
local fullurl = engine.setting_get("modstore_download_url") ..
listentry.details.screenshot_url
local filename = os.tempfolder() .. "_MID_" .. listentry.id
--trigger download
engine.handle_async(
--first param is downloadfct
function(param)
param.successfull = engine.download_file(param.fullurl,param.filename)
return param
end,
--second parameter is data passed to async job
{
fullurl = fullurl,
filename = filename,
modid = listentry.id
},
--integrate result to raw list
function(result)
if result.successfull then
local found = false
for i=1,#modstore.modlist_unsorted.data,1 do
if modstore.modlist_unsorted.data[i].id == result.modid then
found = true
modstore.modlist_unsorted.data[i].texturename = result.filename
break
end
end
if found then
engine.event_handler("Refresh")
else
engine.log("error","got screenshot but didn't find matching mod: " .. result.modid)
end
end
end
)
end
if listentry.texturename ~= nil and
listentry.texturename ~= "in progress" then
return "image[0,".. ypos .. ";3,2;" ..
engine.formspec_escape(listentry.texturename) .. "]"
end
return ""
end
--------------------------------------------------------------------------------
--@function [parent=#modstore] getshortmodinfo
function modstore.getshortmodinfo(ypos,listentry,details)
local retval = ""
retval = retval .. "box[0," .. ypos .. ";11.4,1.75;#FFFFFF]"
--screenshot
retval = retval .. modstore.getscreenshot(ypos,listentry)
--title + author
retval = retval .."label[2.75," .. ypos .. ";" ..
engine.formspec_escape(details.title) .. " (" .. details.author .. ")]"
--description
local descriptiony = ypos + 0.5
retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" ..
engine.formspec_escape(details.description) .. ";]"
--rating
local ratingy = ypos
retval = retval .."label[7," .. ratingy .. ";" ..
fgettext("Rating") .. ":]"
retval = retval .. "label[8.7," .. ratingy .. ";" .. details.rating .."]"
--versions (IMPORTANT has to be defined AFTER rating)
if details.versions ~= nil and
#details.versions > 1 then
local versiony = ypos + 0.05
retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";"
local versions = ""
for i=1,#details.versions , 1 do
if versions ~= "" then
versions = versions .. ","
end
versions = versions .. details.versions[i].date:sub(1,10)
end
retval = retval .. versions .. ";1]"
end
if details.basename then
--install button
local buttony = ypos + 1.2
retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";"
if modmgr.mod_exists(details.basename) then
retval = retval .. fgettext("re-Install") .."]"
else
retval = retval .. fgettext("Install") .."]"
end
end
return retval
end
--------------------------------------------------------------------------------
--@function [parent=#modstore] getmodlist
function modstore.getmodlist(list,yoffset)
modstore.current_list = list
if #list.data == 0 then
return ""
end
if yoffset == nil then
yoffset = 0
end
local scrollbar = ""
scrollbar = scrollbar .. "label[0.1,9.5;"
.. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]"
scrollbar = scrollbar .. "box[11.6," .. (yoffset + 0.35) .. ";0.28,"
.. (8.6 - yoffset) .. ";#000000]"
local scrollbarpos = (yoffset + 0.75) +
((7.7 -yoffset)/(list.pagecount-1)) * list.page
scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]"
scrollbar = scrollbar .. "button[11.6," .. (yoffset + (0.3))
.. ";0.5,0.5;btn_modstore_page_up;^]"
scrollbar = scrollbar .. "button[11.6," .. 9.0
.. ";0.5,0.5;btn_modstore_page_down;v]"
local retval = ""
local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage
if (endmod > #list.data) then
endmod = #list.data
end
for i=(list.page * modstore.modsperpage) +1, endmod, 1 do
--getmoddetails
local details = list.data[i].details
if details == nil then
details = {}
details.title = list.data[i].title
details.author = ""
details.rating = -1
details.description = ""
end
if details ~= nil then
local screenshot_ypos =
yoffset +(i-1 - (list.page * modstore.modsperpage))*1.9 +0.2
retval = retval .. modstore.getshortmodinfo(screenshot_ypos,
list.data[i],
details)
end
end
return retval .. scrollbar
end
--------------------------------------------------------------------------------
--@function [parent=#modstore] getsearchpage
function modstore.getsearchpage()
local retval = ""
local search = ""
if modstore.last_search ~= nil then
search = modstore.last_search
end
retval = retval ..
"button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" ..
"field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]"
--show 4 mods only
modstore.modsperpage = 4
retval = retval ..
modstore.getmodlist(
modstore.currentlist,
1.75)
return retval;
end

View File

@@ -178,7 +178,7 @@ function minetest.deserialize(sdata)
if okay then
return results
end
print('error:'.. results)
minetest.log('error', 'minetest.deserialize(): '.. results)
return nil
end

146
builtin/vector.lua Normal file
View File

@@ -0,0 +1,146 @@
vector = {}
local function assert_vector(v)
assert(type(v) == "table" and v.x and v.y and v.z, "Invalid vector")
end
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}
end
function vector.equals(a, b)
assert_vector(a)
assert_vector(b)
return a.x == b.x and
a.y == b.y and
a.z == b.z
end
function vector.length(v)
assert_vector(v)
return math.hypot(v.x, math.hypot(v.y, v.z))
end
function vector.normalize(v)
assert_vector(v)
local len = vector.length(v)
if len == 0 then
return {x=0, y=0, z=0}
else
return vector.divide(v, len)
end
end
function vector.round(v)
assert_vector(v)
return {
x = math.floor(v.x + 0.5),
y = math.floor(v.y + 0.5),
z = math.floor(v.z + 0.5)
}
end
function vector.distance(a, b)
assert_vector(a)
assert_vector(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))
end
function vector.direction(pos1, pos2)
assert_vector(pos1)
assert_vector(pos2)
local x_raw = pos2.x - pos1.x
local y_raw = pos2.y - pos1.y
local z_raw = pos2.z - pos1.z
local x_abs = math.abs(x_raw)
local y_abs = math.abs(y_raw)
local z_abs = math.abs(z_raw)
if x_abs >= y_abs and
x_abs >= z_abs then
y_raw = y_raw * (1 / x_abs)
z_raw = z_raw * (1 / x_abs)
x_raw = x_raw / x_abs
end
if y_abs >= x_abs and
y_abs >= z_abs then
x_raw = x_raw * (1 / y_abs)
z_raw = z_raw * (1 / y_abs)
y_raw = y_raw / y_abs
end
if z_abs >= y_abs and
z_abs >= x_abs then
x_raw = x_raw * (1 / z_abs)
y_raw = y_raw * (1 / z_abs)
z_raw = z_raw / z_abs
end
return {x=x_raw, y=y_raw, z=z_raw}
end
function vector.add(a, b)
assert_vector(a)
if type(b) == "table" then
assert_vector(b)
return {x = a.x + b.x,
y = a.y + b.y,
z = a.z + b.z}
else
return {x = a.x + b,
y = a.y + b,
z = a.z + b}
end
end
function vector.subtract(a, b)
assert_vector(a)
if type(b) == "table" then
assert_vector(b)
return {x = a.x - b.x,
y = a.y - b.y,
z = a.z - b.z}
else
return {x = a.x - b,
y = a.y - b,
z = a.z - b}
end
end
function vector.multiply(a, b)
assert_vector(a)
if type(b) == "table" then
assert_vector(b)
return {x = a.x * b.x,
y = a.y * b.y,
z = a.z * b.z}
else
return {x = a.x * b,
y = a.y * b,
z = a.z * b}
end
end
function vector.divide(a, b)
assert_vector(a)
if type(b) == "table" then
assert_vector(b)
return {x = a.x / b.x,
y = a.y / b.y,
z = a.z / b.z}
else
return {x = a.x / b,
y = a.y / b,
z = a.z / b}
end
end

103
builtin/voxelarea.lua Normal file
View File

@@ -0,0 +1,103 @@
VoxelArea = {
MinEdge = {x=1, y=1, z=1},
MaxEdge = {x=0, y=0, z=0},
ystride = 0,
zstride = 0,
}
function VoxelArea:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
local e = o:getExtent()
o.ystride = e.x
o.zstride = e.x * e.y
return o
end
function VoxelArea:getExtent()
return {
x = self.MaxEdge.x - self.MinEdge.x + 1,
y = self.MaxEdge.y - self.MinEdge.y + 1,
z = self.MaxEdge.z - self.MinEdge.z + 1,
}
end
function VoxelArea:getVolume()
local e = self:getExtent()
return e.x * e.y * e.z
end
function VoxelArea:index(x, y, z)
local i = (z - self.MinEdge.z) * self.zstride +
(y - self.MinEdge.y) * self.ystride +
(x - self.MinEdge.x) + 1
return math.floor(i)
end
function VoxelArea:indexp(p)
local i = (p.z - self.MinEdge.z) * self.zstride +
(p.y - self.MinEdge.y) * self.ystride +
(p.x - self.MinEdge.x) + 1
return math.floor(i)
end
function VoxelArea:position(i)
local p = {}
i = i - 1
p.z = math.floor(i / self.zstride) + self.MinEdge.z
i = i % self.zstride
p.y = math.floor(i / self.ystride) + self.MinEdge.y
i = i % self.ystride
p.x = math.floor(i) + self.MinEdge.x
return p
end
function VoxelArea:contains(x, y, z)
return (x >= self.MinEdge.x) and (x <= self.MaxEdge.x) and
(y >= self.MinEdge.y) and (y <= self.MaxEdge.y) and
(z >= self.MinEdge.z) and (z <= self.MaxEdge.z)
end
function VoxelArea:containsp(p)
return (p.x >= self.MinEdge.x) and (p.x <= self.MaxEdge.x) and
(p.y >= self.MinEdge.y) and (p.y <= self.MaxEdge.y) and
(p.z >= self.MinEdge.z) and (p.z <= self.MaxEdge.z)
end
function VoxelArea:containsi(i)
return (i >= 1) and (i <= self:getVolume())
end
function VoxelArea:iter(minx, miny, minz, maxx, maxy, maxz)
local i = self:index(minx, miny, minz) - 1
local last = self:index(maxx, maxy, maxz)
local ystride = self.ystride
local zstride = self.zstride
local yoff = (last+1) % ystride
local zoff = (last+1) % zstride
local ystridediff = (i - last) % ystride
local zstridediff = (i - last) % zstride
return function()
i = i + 1
if i % zstride == zoff then
i = i + zstridediff
elseif i % ystride == yoff then
i = i + ystridediff
end
if i <= last then
return i
end
end
end
function VoxelArea:iterp(minp, maxp)
return self:iter(minp.x, minp.y, minp.z, maxp.x, maxp.y, maxp.z)
end

View File

@@ -0,0 +1,71 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_PARALLAX_OCCLUSION
float height;
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
if (use_normalmap > 0.0) {
float map_height = texture2D(normalTexture, uv).a;
if (map_height < 1.0){
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
uv = uv + height * tsEye;
}
}
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / e;
col.g = 1.0 - exp(1.0 - col.g) / e;
col.b = 1.0 - exp(1.0 - col.b) / e;
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
}

View File

@@ -0,0 +1,102 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
void main(void)
{
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
#ifdef ENABLE_PARALLAX_OCCLUSION
vec3 normal,tangent,binormal;
normal = normalize(gl_NormalMatrix * gl_Normal);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.x < -0.5) {
// -1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.y > 0.5) {
// 0.0, 1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.y < -0.5) {
// 0.0, -1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.z > 0.5) {
// 0.0, 0.0, 1.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.z < -0.5) {
// 0.0, 0.0, -1.0
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
}
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
tangent.y, binormal.y, normal.y,
tangent.z, binormal.z, normal.z);
tsEyeVec = normalize(eyeVec * tbnMatrix);
#endif
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
float light_source = gl_Color.b;
/*color.r = mix(night, day, dayNightRatio);
color.g = color.r;
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 13.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = clamp(rg,0.0,1.0);
color.g = clamp(rg,0.0,1.0);
color.b = clamp(b,0.0,1.0);
// Make sides and bottom darker than the top
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -0,0 +1,54 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / e;
col.g = 1.0 - exp(1.0 - col.g) / e;
col.b = 1.0 - exp(1.0 - col.b) / e;
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
}

View File

@@ -0,0 +1,87 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform float dayNightRatio;
uniform float animationTimer;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_WAVING_LEAVES
float smoothCurve( float x ) {
return x * x *( 3.0 - 2.0 * x );
}
float triangleWave( float x ) {
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
}
float smoothTriangleWave( float x ) {
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
}
#endif
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#ifdef ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex;
vec4 pos2 = mTransWorld*gl_Vertex;
pos.x += (smoothTriangleWave(animationTimer*10.0 + pos2.x * 0.01 + pos2.z * 0.01) * 2.0 - 1.0) * 0.4;
pos.y += (smoothTriangleWave(animationTimer*15.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.2;
pos.z += (smoothTriangleWave(animationTimer*10.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.4;
gl_Position = mWorldViewProj * pos;
#else
gl_Position = mWorldViewProj * gl_Vertex;
#endif
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
float light_source = gl_Color.b;
/*color.r = mix(night, day, dayNightRatio);
color.g = color.r;
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 13.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = clamp(rg,0.0,1.0);
color.g = clamp(rg,0.0,1.0);
color.b = clamp(b,0.0,1.0);
// Make sides and bottom darker than the top
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -0,0 +1,54 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(vec3(-1.0, -0.4, 0.5), bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = gl_Color.a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / e;
col.g = 1.0 - exp(1.0 - col.g) / e;
col.b = 1.0 - exp(1.0 - col.b) / e;
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
}

View File

@@ -1,15 +1,27 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform float dayNightRatio;
uniform float animationTimer;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
void main(void)
{
#ifdef ENABLE_WAVING_WATER
vec4 pos2 = gl_Vertex;
pos2.y -= 2.0;
pos2.y -= sin (pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) * WATER_WAVE_HEIGHT
+ sin ((pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) / 7.0) * WATER_WAVE_HEIGHT;
gl_Position = mWorldViewProj * pos2;
#else
gl_Position = mWorldViewProj * gl_Vertex;
#endif
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
vec4 color;
@@ -24,7 +36,7 @@ void main(void)
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 1.0; // Make light sources brighter
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
@@ -39,13 +51,13 @@ void main(void)
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
color.r = clamp(rg,0.0,1.0);
color.g = clamp(rg,0.0,1.0);
color.b = clamp(b,0.0,1.0);
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -0,0 +1 @@
trans_alphach_ref

View File

@@ -0,0 +1,54 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / e;
col.g = 1.0 - exp(1.0 - col.g) / e;
col.b = 1.0 - exp(1.0 - col.b) / e;
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
}

View File

@@ -1,16 +1,45 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform float dayNightRatio;
uniform float animationTimer;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_WAVING_PLANTS
float smoothCurve( float x ) {
return x * x *( 3.0 - 2.0 * x );
}
float triangleWave( float x ) {
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
}
float smoothTriangleWave( float x ) {
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
}
#endif
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#ifdef ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex;
vec4 pos2 = mTransWorld * gl_Vertex;
if (gl_TexCoord[0].y < 0.05) {
pos.x += (smoothTriangleWave(animationTimer * 20.0 + pos2.x * 0.1 + pos2.z * 0.1) * 2.0 - 1.0) * 0.8;
pos.y -= (smoothTriangleWave(animationTimer * 10.0 + pos2.x * -0.5 + pos2.z * -0.5) * 2.0 - 1.0) * 0.4;
}
gl_Position = mWorldViewProj * pos;
#else
gl_Position = mWorldViewProj * gl_Vertex;
#endif
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
@@ -24,7 +53,7 @@ void main(void)
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 1.0; // Make light sources brighter
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
@@ -39,9 +68,9 @@ void main(void)
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
color.r = clamp(rg,0.0,1.0);
color.g = clamp(rg,0.0,1.0);
color.b = clamp(b,0.0,1.0);
// Make sides and bottom darker than the top
color = color * color; // SRGB -> Linear
@@ -54,5 +83,4 @@ void main(void)
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -0,0 +1 @@
trans_alphach_ref

View File

@@ -0,0 +1,90 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_PARALLAX_OCCLUSION
float height;
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
if (use_normalmap > 0.0) {
float map_height = texture2D(normalTexture, uv).a;
if (map_height < 1.0){
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
uv = uv + height * tsEye;
}
}
#endif
/* Steep parallax code, for future use
if ((parallaxMappingMode == 2.0) && (use_normalmap > 0.0)) {
const float numSteps = 40.0;
float height = 1.0;
float step = 1.0 / numSteps;
vec4 NB = texture2D(normalTexture, uv);
vec2 delta = tsEye * parallaxMappingScale / numSteps;
for (float i = 0.0; i < numSteps; i++) {
if (NB.a < height) {
height -= step;
uv += delta;
NB = texture2D(normalTexture, uv);
} else {
break;
}
}
}
*/
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / e;
col.g = 1.0 - exp(1.0 - col.g) / e;
col.b = 1.0 - exp(1.0 - col.b) / e;
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
}

View File

@@ -0,0 +1,102 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
void main(void)
{
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
#ifdef ENABLE_PARALLAX_OCCLUSION
vec3 normal,tangent,binormal;
normal = normalize(gl_NormalMatrix * gl_Normal);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.x < -0.5) {
// -1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.y > 0.5) {
// 0.0, 1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.y < -0.5) {
// 0.0, -1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.z > 0.5) {
// 0.0, 0.0, 1.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.z < -0.5) {
// 0.0, 0.0, -1.0
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
}
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
tangent.y, binormal.y, normal.y,
tangent.z, binormal.z, normal.z);
tsEyeVec = normalize(eyeVec * tbnMatrix);
#endif
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
float light_source = gl_Color.b;
/*color.r = mix(night, day, dayNightRatio);
color.g = color.r;
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 13.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = clamp(rg,0.0,1.0);
color.g = clamp(rg,0.0,1.0);
color.b = clamp(b,0.0,1.0);
// Make sides and bottom darker than the top
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -1,25 +0,0 @@
uniform sampler2D myTexture;
uniform vec4 skyBgColor;
uniform float fogDistance;
varying vec3 vPosition;
void main (void)
{
//vec4 col = vec4(1.0, 0.0, 0.0, 1.0);
vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
float a = col.a;
col *= gl_Color;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / exp(1.0);
col.g = 1.0 - exp(1.0 - col.g) / exp(1.0);
col.b = 1.0 - exp(1.0 - col.b) / exp(1.0);
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, a);
}

View File

@@ -1,23 +0,0 @@
uniform sampler2D myTexture;
uniform float fogDistance;
varying vec3 vPosition;
void main (void)
{
vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
col *= gl_Color;
float a = gl_Color.a;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / exp(1.0);
col.g = 1.0 - exp(1.0 - col.g) / exp(1.0);
col.b = 1.0 - exp(1.0 - col.b) / exp(1.0);
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
a = mix(a, 0.0, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, a);
}

View File

@@ -1,51 +0,0 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform float dayNightRatio;
varying vec3 vPosition;
void main(void)
{
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
float light_source = gl_Color.b;
/*color.r = mix(night, day, dayNightRatio);
color.g = color.r;
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 1.0; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 13.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -1,25 +0,0 @@
uniform sampler2D myTexture;
uniform float fogDistance;
varying vec3 vPosition;
void main (void)
{
vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
col *= gl_Color;
float a = col.a;
col = col * col; // SRGB -> Linear
col *= 1.8;
col.r = 1.0 - exp(1.0 - col.r) / exp(1.0);
col.g = 1.0 - exp(1.0 - col.g) / exp(1.0);
col.b = 1.0 - exp(1.0 - col.b) / exp(1.0);
col = sqrt(col); // Linear -> SRGB
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
a = mix(a, 0.0, d);
}
gl_FragColor = vec4(col.r, col.g, col.b, a);
}

View File

@@ -20,6 +20,10 @@ if( UNIX )
else( UNIX )
FIND_PATH(CURL_INCLUDE_DIR NAMES curl/curl.h) # Look for the header file.
FIND_LIBRARY(CURL_LIBRARY NAMES curl) # Look for the library.
FIND_FILE(CURL_DLL NAMES libcurl.dll
PATHS
"c:/windows/system32"
DOC "Path of the cURL dll (for installation)")
INCLUDE(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE if
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL DEFAULT_MSG CURL_LIBRARY CURL_INCLUDE_DIR) # all listed variables are TRUE
endif( UNIX )
@@ -40,3 +44,4 @@ endif ( WIN32 )
MESSAGE(STATUS "CURL_INCLUDE_DIR = ${CURL_INCLUDE_DIR}")
MESSAGE(STATUS "CURL_LIBRARY = ${CURL_LIBRARY}")
MESSAGE(STATUS "CURL_DLL = ${CURL_DLL}")

View File

@@ -1,18 +0,0 @@
# Look for jthread, use our own if not found
FIND_PATH(JTHREAD_INCLUDE_DIR jthread.h)
FIND_LIBRARY(JTHREAD_LIBRARY NAMES jthread)
IF(JTHREAD_LIBRARY AND JTHREAD_INCLUDE_DIR)
SET( JTHREAD_FOUND TRUE )
ENDIF(JTHREAD_LIBRARY AND JTHREAD_INCLUDE_DIR)
IF(JTHREAD_FOUND)
MESSAGE(STATUS "Found system jthread header file in ${JTHREAD_INCLUDE_DIR}")
MESSAGE(STATUS "Found system jthread library ${JTHREAD_LIBRARY}")
ELSE(JTHREAD_FOUND)
SET(JTHREAD_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/jthread)
SET(JTHREAD_LIBRARY jthread)
MESSAGE(STATUS "Using project jthread library")
ENDIF(JTHREAD_FOUND)

View File

@@ -0,0 +1,20 @@
# Always run during 'make'
if(VERSION_EXTRA)
set(VERSION_GITHASH "${VERSION_STRING}")
else(VERSION_EXTRA)
execute_process(COMMAND git describe --always --tag --dirty
WORKING_DIRECTORY "${GENERATE_VERSION_SOURCE_DIR}"
OUTPUT_VARIABLE VERSION_GITHASH OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(VERSION_GITHASH)
message(STATUS "*** Detected git version ${VERSION_GITHASH} ***")
else()
set(VERSION_GITHASH "${VERSION_STRING}")
endif()
endif()
configure_file(
${GENERATE_VERSION_SOURCE_DIR}/cmake_config_githash.h.in
${GENERATE_VERSION_BINARY_DIR}/cmake_config_githash.h)

View File

@@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU 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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

502
doc/lgpl-2.1.txt Normal file
View File

@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@@ -1,4 +1,4 @@
Minetest Lua Modding API Reference 0.4.7
Minetest Lua Modding API Reference 0.4.9
========================================
More information at http://www.minetest.net/
Developer Wiki: http://dev.minetest.net/
@@ -100,6 +100,8 @@ Mod directory structure
mods
|-- modname
| |-- depends.txt
| |-- screenshot.png
| |-- description.txt
| |-- init.lua
| |-- textures
| | |-- modname_stuff.png
@@ -121,12 +123,11 @@ depends.txt:
to a single modname. Their meaning is that if the specified mod
is missing, that does not prevent this mod from being loaded.
optdepends.txt:
An alternative way of specifying optional dependencies.
Like depends.txt, a single line contains a single modname.
screenshot.png:
A screenshot shown in modmanager within mainmenu.
NOTE: This file exists for compatibility purposes only and
support for it will be removed from the engine by the end of 2013.
description.txt:
File containing desctiption to be shown within mainmenu.
init.lua:
The main Lua script. Running this script should register everything it
@@ -322,6 +323,8 @@ param2 is reserved for the engine when any of these are used:
facedir modulo 4 = axisdir
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
facedir's two less significant bits are rotation around the axis
paramtype2 == "leveled"
^ The drawn node level is read from param2, like flowingliquid
Nodes can also contain extra data. See "Node Metadata".
@@ -353,7 +356,7 @@ Node selection boxes are defined using "node boxes"
The "nodebox" node drawtype allows defining visual of nodes consisting of
arbitrary number of boxes. It allows defining stuff like stairs. Only the
"fixed" box type is supported for these.
"fixed" and "leveled" box type is supported for these.
^ Please note that this is still experimental, and may be incompatibly
changed in the future.
@@ -381,6 +384,8 @@ A box is defined as:
A box of a regular node would look like:
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
type = "leveled" is same as "fixed", but y2 will be automaticaly setted to level from param2
Ore types
---------------
These tell in what manner the ore is generated.
@@ -410,6 +415,50 @@ Currently supported flags: absheight
Also produce this same ore between the height range of -height_max and -height_min.
Useful for having ore in sky realms without having to duplicate ore entries.
Decoration types
-------------------
The varying types of decorations that can be placed.
The default value is simple, and is currently the only type supported.
- simple
Creates a 1xHx1 column of a specified node (or a random node from a list, if a decoration
list is specified). Can specify a certain node it must spawn next to, such as water or lava,
for example. Can also generate a decoration of random height between a specified lower and
upper bound. This type of decoration is intended for placement of grass, flowers, cacti,
papyrus, and so on.
- schematic
Copies a box of MapNodes from a specified schematic file (or raw description). Can specify a
probability of a node randomly appearing when placed. This decoration type is intended to be used
for multi-node sized discrete structures, such as trees, cave spikes, rocks, and so on.
Schematic specifier
--------------------
A schematic specifier identifies a schematic by either a filename to a Minetest Schematic file (.mts)
or through raw data supplied through Lua, in the form of a table. This table must specify two fields:
- The 'size' field is a 3d vector containing the dimensions of the provided schematic.
- The 'data' field is a flat table of MapNodes making up the schematic, in the order of [z [y [x]]].
Important: The default value for param1 in MapNodes here is 255, which represents "always place".
In the bulk MapNode data, param1, instead of the typical light values, instead represents the
probability of that node appearing in the structure.
When passed to minetest.create_schematic, probability is an integer value ranging from 0 to 255:
- A probability value of 0 means that node will never appear (0% chance).
- A probability value of 255 means the node will always appear (100% chance).
- If the probability value p is greater than 0, then there is a (p / 256 * 100)% chance that node
will appear when the schematic is placed on the map.
Important note: Node aliases cannot be used for a raw schematic provided when registering as a decoration.
Schematic attributes
---------------------
Currently supported flags: place_center_x, place_center_y, place_center_z
- place_center_x
Placement of this decoration is centered along the X axis.
- place_center_y
Placement of this decoration is centered along the Y axis.
- place_center_z
Placement of this decoration is centered along the Z axis.
HUD element types
-------------------
The position field is used for all element types.
@@ -430,8 +479,10 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still
- image
Displays an image on the HUD.
- scale: The scale of the image, with 1 being the original texture size.
Only the X coordinate scale is used.
- scale: The scale of the image, with 1 being the original texture size.
Only the X coordinate scale is used (positive values)
Negative values represent that percentage of the screen it
should take; e.g. x=-100 means 100% (width)
- text: The name of the texture that is displayed.
- alignment: The alignment of the image.
- offset: offset in pixels from position.
@@ -461,8 +512,7 @@ Representations of simple things
--------------------------------
Position/vector:
{x=num, y=num, z=num}
Currently the API does not provide any helper functions for addition,
subtraction and whatever; you can define those that you need yourself.
For helper functions see "Vector helpers".
pointed_thing:
{type="nothing"}
@@ -824,6 +874,22 @@ list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;<starting item index>]
^ Show an inventory list
listcolors[<slot_bg_normal>;<slot_bg_hover>]
^ Sets background color of slots in HEX-Color format
^ Sets background color of slots on mouse hovering
listcolors[<slot_bg_normal>;<slot_bg_hover>;<slot_border>]
^ Sets background color of slots in HEX-Color format
^ Sets background color of slots on mouse hovering
^ Sets color of slots border
listcolors[<slot_bg_normal>;<slot_bg_hover>;<slot_border>;<tooltip_bgcolor>;<tooltip_fontcolor>]
^ Sets background color of slots in HEX-Color format
^ Sets background color of slots on mouse hovering
^ Sets color of slots border
^ Sets background color of tooltips
^ Sets font color of tooltips
image[<X>,<Y>;<W>,<H>;<texture name>]
^ Show an image
^ Position and size units are inventory slots
@@ -832,11 +898,30 @@ item_image[<X>,<Y>;<W>,<H>;<item name>]
^ Show an inventory image of registered item/node
^ Position and size units are inventory slots
bgcolor[<color>;<fullscreen>]
^ Sets background color of formspec in HEX-Color format
^ If true the background color is drawn fullscreen (does not effect the size of the formspec)
background[<X>,<Y>;<W>,<H>;<texture name>]
^ Use a background. Inventory rectangles are not drawn then.
^ Position and size units are inventory slots
^ Example for formspec 8x4 in 16x resolution: image shall be sized 8*16px x 4*16px
background[<X>,<Y>;<W>,<H>;<texture name>;<auto_clip>]
^ Use a background. Inventory rectangles are not drawn then.
^ Position and size units are inventory slots
^ Example for formspec 8x4 in 16x resolution: image shall be sized 8*16px x 4*16px
^ If true the background is clipped to formspec size (x and y are used as offset values, w and h are ignored)
pwdfield[<X>,<Y>;<W>,<H>;<name>;<label>]
^ Textual password style field; will be sent to server when a button is clicked
^ x and y position the field relative to the top left of the menu
^ w and h are the size of the field
^ fields are a set height, but will be vertically centred on h
^ Position and size units are inventory slots
^ name is the name of the field as returned in fields to on_receive_fields
^ label, if not blank, will be text printed on the top left above the field
field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
^ Textual field; will be sent to server when a button is clicked
^ x and y position the field relative to the top left of the menu
@@ -864,6 +949,12 @@ label[<X>,<Y>;<label>]
^ label is the text on the label
^ Position and size units are inventory slots
vertlabel[<X>,<Y>;<label>]
^ Textual label drawn verticaly
^ x and y work as per field
^ label is the text on the label
^ Position and size units are inventory slots
button[<X>,<Y>;<W>,<H>;<name>;<label>]
^ Clickable button. When clicked, fields will be sent.
^ x, y and name work as per field
@@ -873,9 +964,24 @@ button[<X>,<Y>;<W>,<H>;<name>;<label>]
image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
^ x, y, w, h, and name work as per button
^ image is the filename of an image
^ texture name is the filename of an image
^ Position and size units are inventory slots
image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>;<noclip>;<drawborder>]
^ x, y, w, h, and name work as per button
^ texture name is the filename of an image
^ Position and size units are inventory slots
^ noclip true meand imagebutton doesn't need to be within specified formsize
^ drawborder draw button bodrer or not
image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>;<noclip>;<drawborder>;<pressed texture name>]
^ x, y, w, h, and name work as per button
^ texture name is the filename of an image
^ Position and size units are inventory slots
^ noclip true meand imagebutton doesn't need to be within specified formsize
^ drawborder draw button bodrer or not
^ pressed texture name is the filename of an image on pressed state
item_image_button[<X>,<Y>;<W>,<H>;<item name>;<name>;<label>]
^ x, y, w, h, name and label work as per button
^ item name is the registered name of an item/node,
@@ -888,6 +994,58 @@ button_exit[<X>,<Y>;<W>,<H>;<name>;<label>]
image_button_exit[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
^ When clicked, fields will be sent and the form will quit.
textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>]
^Scrollabel itemlist showing arbitrary text elements
^ x and y position the itemlist relative to the top left of the menu
^ w and h are the size of the itemlist
^ name fieldname sent to server on doubleclick value is current selected element
^ listelements can be prepended by #color in hexadecimal format RRGGBB (only),
^ if you want a listelement to start with # write ##
textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>;<selected idx>;<transparent>]
^Scrollabel itemlist showing arbitrary text elements
^ x and y position the itemlist relative to the top left of the menu
^ w and h are the size of the itemlist
^ name fieldname sent to server on doubleclick value is current selected element
^ listelements can be prepended by #RRGGBB (only) in hexadecimal format
^ if you want a listelement to start with # write ##
^ index to be selected within textlist
^ true/false draw transparent background
tabheader[<X>,<Y>;<name>;<caption 1>,<caption 2>,...,<caption n>;<current_tab>;<transparent>;<draw_border>]
^ show a tabHEADER at specific position (ignores formsize)
^ x and y position the itemlist relative to the top left of the menu
^ name fieldname data is transfered to lua
^ caption 1... name shown on top of tab
^ current_tab index of selected tab 1...
^ transparent (optional) show transparent
^ draw_border (optional) draw border
box[<X>,<Y>;<W>,<H>;<color>]
^ simple colored semitransparent box
^ x and y position the box relative to the top left of the menu
^ w and h are the size of box
^ color in HEX-Color format
dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]
^ show a dropdown field
^ x and y position of dropdown
^ width of dropdown
^ fieldname data is transfered to lua
^ items to be shown in dropdown
^ index of currently selected dropdown item
^ color in hexadecimal format RRGGBB (only)
checkbox[<X>,<Y>;<name>;<label>;<selected>]
^ show a checkbox
^ x and y position of checkbox
^ name fieldname data is transfered to lua
^ label to be shown left of checkbox
^ selected (optional) true/false
Note: do NOT use a element name starting with "key_" those names are reserved to
pass key press events to formspec!
Inventory location:
- "context": Selected node metadata (deprecated: "current_name")
@@ -896,12 +1054,42 @@ Inventory location:
- "nodemeta:<X>,<Y>,<Z>": Any node metadata
- "detached:<name>": A detached inventory
HEX-Color
---------
#RGB
^ defines a color in hexadecimal format
#RGBA
^ defines a color in hexadecimal format and alpha channel
#RRGGBB
^ defines a color in hexadecimal format
#RRGGBBAA
^ defines a color in hexadecimal format and alpha channel
Vector helpers
---------------
vector.new([x[, y, z]]) -> vector
^ x is a table or the x position.
vector.direction(p1, p2) -> vector
vector.distance(p1, p2) -> number
vector.length(v) -> number
vector.normalize(v) -> vector
vector.round(v) -> vector
vector.equals(v1, v2) -> bool
For the folowing x can be either a vector or a number.
vector.add(v, x) -> vector
vector.subtract(v, x) -> vector
vector.multiply(v, x) -> vector
vector.divide(v, x) -> vector
Helper functions
-----------------
dump2(obj, name="_", dumped={})
^ Return object serialized as a string, handles reference loops
dump(obj, dumped={})
^ Return object serialized as a string
math.hypot(x, y)
^ Get the hypotenuse of a triangle with legs x and y.
Usefull for distance calculation.
string:split(separator)
^ eg. string:split("a,b", ",") == {"a","b"}
string:trim()
@@ -911,7 +1099,9 @@ minetest.pos_to_string({x=X,y=Y,z=Z}) -> "(X,Y,Z)"
minetest.string_to_pos(string) -> position
^ Same but in reverse
minetest.formspec_escape(string) -> string
^ escapes characters like [, ], and \ that can not be used in formspecs
^ escapes characters [ ] \ , ; that can not be used in formspecs
minetest.is_yes(arg)
^ returns whether arg can be interpreted as yes
minetest namespace reference
-----------------------------
@@ -946,10 +1136,11 @@ minetest.register_craftitem(name, item definition)
minetest.register_alias(name, convert_to)
minetest.register_craft(recipe)
minetest.register_ore(ore definition)
minetest.register_decoration(decoration definition)
Global callback registration functions: (Call these only at load time)
minetest.register_globalstep(func(dtime))
^ Called every server step, usually interval of 0.05s
^ Called every server step, usually interval of 0.1s
minetest.register_on_shutdown(func())
^ Called before server shutdown
^ WARNING: If the server terminates abnormally (i.e. crashes), the registered
@@ -977,16 +1168,41 @@ minetest.register_on_respawnplayer(func(ObjectRef))
^ Called when player is to be respawned
^ Called _before_ repositioning of player occurs
^ return true in func to disable regular player placement
minetest.register_on_prejoinplayer(func(name, ip))
^ Called before a player joins the game
^ If it returns a string, the player is disconnected with that string as reason
minetest.register_on_joinplayer(func(ObjectRef))
^ Called when a player joins the game
minetest.register_on_leaveplayer(func(ObjectRef))
^ Called when a player leaves the game
minetest.register_on_cheat(func(ObjectRef, cheat))
^ Called when a player cheats
^ cheat: {type="moved_too_fast"/"interacted_too_far"/"finished_unknown_dig"/"dug_unbreakable"/"dug_too_fast"}
minetest.register_on_chat_message(func(name, message))
^ Called always when a player says something
minetest.register_on_player_receive_fields(func(player, formname, fields))
^ Called when a button is pressed in player's inventory form
^ Newest functions are called first
^ If function returns true, remaining functions are not called
minetest.register_on_mapgen_init(func(MapgenParams))
^ Called just before the map generator is initialized but before the environment is initialized
^ MapgenParams consists of a table with the fields mgname, seed, water_level, and flags
minetest.register_on_craft(func(itemstack, player, old_craft_grid, craft_inv))
^ Called when player crafts something
^ itemstack is the output
^ old_craft_grid contains the recipe (Note: the one in the inventory is cleared)
^ craft_inv is the inventory with the crafting grid
^ Return either an ItemStack, to replace the output, or nil, to not modify it
minetest.register_craft_predict(func(itemstack, player, old_craft_grid, craft_inv))
^ The same as before, except that it is called before the player crafts, to make
^ craft prediction, and it should not change anything.
minetest.register_on_protection_violation(func(pos, name))
^ Called by builtin and mods when a player violates protection at a position
(eg, digs a node or punches a protected entity).
^ The registered functions can be called using minetest.record_protection_violation
^ The provided function should check that the position is protected by the mod
calling this function before it prints a message, if it does, to allow for
multiple protection mods.
Other registration functions:
minetest.register_chatcommand(cmd, chatcommand definition)
@@ -1002,10 +1218,10 @@ minetest.register_authentication_handler(handler)
Setting-related:
minetest.setting_set(name, value)
minetest.setting_get(name) -> string or nil
minetest.setting_setbool(name, value)
minetest.setting_getbool(name) -> boolean value or nil
minetest.setting_get_pos(name) -> position or nil
minetest.setting_save() -> nil, save all settings to config file
minetest.add_to_creative_inventory(itemstring)
Authentication:
minetest.notify_authentication_modified(name)
@@ -1035,6 +1251,8 @@ Environment access:
minetest.set_node(pos, node)
minetest.add_node(pos, node): alias set_node(pos, node)
^ Set node at position (node = {name="foo", param1=0, param2=0})
minetest.swap_node(pos, node)
^ Set node at position, but don't remove metadata
minetest.remove_node(pos)
^ Equivalent to set_node(pos, "air")
minetest.get_node(pos)
@@ -1062,16 +1280,34 @@ minetest.get_player_by_name(name) -- Get an ObjectRef to a player
minetest.get_objects_inside_radius(pos, radius)
minetest.set_timeofday(val): val: 0...1; 0 = midnight, 0.5 = midday
minetest.get_timeofday()
minetest.get_gametime(): returns the time, in seconds, since the world was created
minetest.find_node_near(pos, radius, nodenames) -> pos or nil
^ nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
minetest.find_nodes_in_area(minp, maxp, nodenames) -> list of positions
^ nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
minetest.get_perlin(seeddiff, octaves, persistence, scale)
^ Return world-specific perlin noise (int(worldseed)+seeddiff)
minetest.get_voxel_manip()
^ Return voxel manipulator object
minetest.set_gen_notify(flags)
^ Set the types of on-generate notifications that should be collected
^ flags is a comma-delimited combination of:
^ dungeon, temple, cave_begin, cave_end, large_cave_begin, large_cave_end
minetest.get_mapgen_object(objectname)
^ Return requested mapgen object if available (see Mapgen objects)
minetest.set_mapgen_params(MapgenParams)
^ Set map generation parameters
^ Function cannot be called after the registration period; only initialization and on_mapgen_init
^ Takes a table as an argument with the fields mgname, seed, water_level, flags, and flagmask.
^ Leave field unset to leave that parameter unchanged
^ flagmask field must be set to all mapgen flags that are being modified
^ flags contains only the flags that are being set
^ flags and flagmask are in the same format and have the same options as 'mgflags' in minetest.conf
minetest.clear_objects()
^ clear all objects in the environments
minetest.line_of_sight(pos1,pos2,stepsize) ->true/false
^ checkif there is a direct line of sight between pos1 and pos2
minetest.line_of_sight(pos1, pos2, stepsize) -> true/false, pos
^ Check if there is a direct line of sight between pos1 and pos2
^ Returns the position of the blocking node when false
^ pos1 First position
^ pos2 Second position
^ stepsize smaller gives more accurate results but requires more computing
@@ -1087,6 +1323,20 @@ minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm)
^ algorithm: A*_noprefetch(default), A*, Dijkstra
minetest.spawn_tree (pos, {treedef})
^ spawns L-System tree at given pos with definition in treedef table
minetest.transforming_liquid_add(pos)
^ add node to liquid update queue
minetest.get_node_max_level(pos)
^ get max available level for leveled node
minetest.get_node_level(pos)
^ get level of leveled node (water, snow)
minetest.set_node_level(pos, level)
^ set level of leveled node, default level = 1, if totallevel > maxlevel returns rest (total-max).
minetest.add_node_level(pos, level)
^ increase level of leveled node by level, default level = 1, if totallevel > maxlevel returns rest (total-max). can be negative for decreasing
minetest.get_heat(pos)
^ heat at pos
minetest.get_humidity(pos)
^ humidity at pos
Inventory:
minetest.get_inventory(location) -> InvRef
@@ -1107,8 +1357,10 @@ minetest.inventorycube(img1, img2, img3)
^ Returns a string for making an image of a cube (useful as an item image)
minetest.get_pointed_thing_position(pointed_thing, above)
^ Get position of a pointed_thing (that you can get from somewhere)
minetest.dir_to_facedir(dir)
^ Convert a vector to a facedir value, used in param2 for paramtype2="facedir"
minetest.dir_to_facedir(dir, is6d)
^ Convert a vector to a facedir value, used in param2 for paramtype2="facedir"; passing something non-nil/false for the optional second parameter causes it to take the y component into account
minetest.facedir_to_dir(facedir)
^ Convert a facedir back into a vector aimed directly out the "back" of a node
minetest.dir_to_wallmounted(dir)
^ Convert a vector to a wallmounted value, used for paramtype2="wallmounted"
minetest.get_node_drops(nodename, toolname)
@@ -1154,8 +1406,8 @@ minetest.handle_node_drops(pos, drops, digger)
^ Can be overridden to get different functionality (eg. dropping items on
ground)
Rollbacks:
minetest.rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
Rollback:
minetest.rollback_get_node_actions(pos, range, seconds, limit) -> {{actor, pos, time, oldnode, newnode}, ...}
^ Find who has done something to a node, or near a node
^ actor: "player:<name>", also "liquid".
minetest.rollback_revert_actions_by(actor, seconds) -> bool, log messages
@@ -1164,14 +1416,18 @@ minetest.rollback_revert_actions_by(actor, seconds) -> bool, log messages
Defaults for the on_* item definition functions:
(These return the leftover itemstack)
minetest.item_place_node(itemstack, placer, pointed_thing)
minetest.item_place_node(itemstack, placer, pointed_thing, param2)
^ Place item as a node
^ param2 overrides facedir and wallmounted param2
^ returns itemstack, success
minetest.item_place_object(itemstack, placer, pointed_thing)
^ Place item as-is
minetest.item_place(itemstack, placer, pointed_thing)
minetest.item_place(itemstack, placer, pointed_thing, param2)
^ Use one of the above based on what the item is.
^ Calls on_rightclick of pointed_thing.under if defined instead
^ Note: is not called when wielded item overrides on_place
^ param2 overrides facedir and wallmounted param2
^ returns itemstack, success
minetest.item_drop(itemstack, dropper, pos)
^ Drop the item
minetest.item_eat(hp_change, replace_with_item)
@@ -1236,6 +1492,27 @@ minetest.delete_particlespawner(id, player)
^ If playername is specified, only deletes on the player's client,
^ otherwise on all clients
Schematics:
minetest.create_schematic(p1, p2, probability_list, filename, slice_prob_list)
^ Create a schematic from the volume of map specified by the box formed by p1 and p2.
^ Apply the specified probability values to the specified nodes in probability_list.
^ probability_list is an array of tables containing two fields, pos and prob.
^ pos is the 3d vector specifying the absolute coordinates of the node being modified,
^ and prob is the integer value from 0 to 255 of the probability (see: Schematic specifier).
^ If there are two or more entries with the same pos value, the last occuring in the array is used.
^ If pos is not inside the box formed by p1 and p2, it is ignored.
^ If probability_list is nil, no probabilities are applied.
^ Slice probability works in the same manner, except takes a field called ypos instead which indicates
^ the y position of the slice with a probability applied.
^ If slice probability list is nil, no slice probabilities are applied.
^ Saves schematic in the Minetest Schematic format to filename.
minetest.place_schematic(pos, schematic, rotation, replacements)
^ Place the schematic specified by schematic (see: Schematic specifier) at pos.
^ Rotation can be "0", "90", "180", "270", or "random".
^ If the rotation parameter is omitted, the schematic is not rotated.
^ replacements = {{"oldname", "convert_to"}, ...}
Random:
minetest.get_connected_players() -> list of ObjectRefs
minetest.hash_node_position({x=,y=,z=}) -> 48-bit integer
@@ -1244,6 +1521,25 @@ minetest.get_item_group(name, group) -> rating
^ Get rating of a group of an item. (0 = not in group)
minetest.get_node_group(name, group) -> rating
^ Deprecated: An alias for the former.
minetest.get_content_id(name) -> integer
^ Gets the internal content ID of name
minetest.get_name_from_content_id(content_id) -> string
^ Gets the name of the content with that content ID
minetest.parse_json(string[, nullvalue]) -> something
^ Convert a string containing JSON data into the Lua equivalent
^ nullvalue: returned in place of the JSON null; defaults to nil
^ On success returns a table, a string, a number, a boolean or nullvalue
^ On failure outputs an error message and returns nil
^ Example: parse_json("[10, {\"a\":false}]") -> {10, {a = false}}
minetest.write_json(data[, styled]) -> string or nil and error message
^ Convert a Lua table into a JSON string
^ styled: Outputs in a human-readable format if this is set, defaults to false
^ Un-serializable things like functions and userdata are saved as null.
^ Warning: JSON is more strict than the Lua table format.
1. You can only use strings and positive integers of at least one as keys.
2. You can not mix string and integer keys.
This is due to the fact that Javascript has two distinct array and object values.
^ Example: write_json({10, {a = false}}) -> "[10, {\"a\": false}]"
minetest.serialize(table) -> string
^ Convert a table containing tables, strings, numbers, booleans and nils
into string form readable by minetest.deserialize
@@ -1255,6 +1551,44 @@ minetest.deserialize(string) -> table
^ Example: deserialize('return { ["foo"] = "bar" }') -> {foo='bar'}
^ Example: deserialize('print("foo")') -> nil (function call fails)
^ error:[string "print("foo")"]:1: attempt to call global 'print' (a nil value)
minetest.is_protected(pos, name) -> bool
^ This function should be overriden by protection mods and should be used to
check if a player can interact at a position.
^ This function should call the old version of itself if the position is not
protected by the mod.
^ Example:
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
if mymod:position_protected_from(pos, name) then
return true
end
return old_is_protected(pos, name)
end
minetest.record_protection_violation(pos, name)
^ This function calls functions registered with
minetest.register_on_protection_violation.
minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags)
^ Attempt to predict the desired orientation of the facedir-capable node
defined by itemstack, and place it accordingly (on-wall, on the floor, or
hanging from the ceiling). Stacks are handled normally if the infinitestacks
field is false or omitted (else, the itemstack is not changed). orient_flags
is an optional table containing extra tweaks to the placement code:
invert_wall: if true, place wall-orientation on the ground and ground-
orientation on the wall.
force_wall: if true, always place the node in wall orientation.
force_ceiling: if true, always place on the ceiling.
force_floor: if true, always place the node on the floor.
The above four options are mutually-exclusive; the last in the list takes
precedence over the first.
force_facedir: if true, forcably reset the facedir to north when placing on
the floor or ceiling
minetest.rotate_node(itemstack, placer, pointed_thing)
^ calls rotate_and_place() with infinitestacks set according to the state of
the creative mode setting, and checks for "sneak" to set the invert_wall
parameter.
Global objects:
minetest.env - EnvRef of the server environment and world.
@@ -1280,15 +1614,6 @@ minetest.object_refs
minetest.luaentities
^ List of lua entities, indexed by active object id
Deprecated but defined for backwards compatibility:
minetest.digprop_constanttime(time)
minetest.digprop_stonelike(toughness)
minetest.digprop_dirtlike(toughness)
minetest.digprop_gravellike(toughness)
minetest.digprop_woodlike(toughness)
minetest.digprop_leaveslike(toughness)
minetest.digprop_glasslike(toughness)
Class reference
----------------
NodeMetaRef: Node metadata - reference extra data and functionality stored
@@ -1379,6 +1704,11 @@ Player-only: (no-op for other objects)
- get_look_yaw(): yaw in radians (wraps around pretty randomly as of now)
- set_look_pitch(radians): sets look pitch
- set_look_yaw(radians): sets look yaw
- get_breath() : returns players breath
- set_breath(value) : sets players breath
values: 0 player is drowning,
1-10 number of bubbles remain,
11 bubbles bar is not shown
- set_inventory_formspec(formspec)
^ Redefine player's inventory form
^ Should usually be called in on_joinplayer
@@ -1387,10 +1717,13 @@ Player-only: (no-op for other objects)
{jump=bool,right=bool,left=bool,LMB=bool,RMB=bool,sneak=bool,aux1=bool,down=bool,up=bool}
- get_player_control_bits(): returns integer with bit packed player pressed keys
bit nr/meaning: 0/up ,1/down ,2/left ,3/right ,4/jump ,5/aux1 ,6/sneak ,7/LMB ,8/RMB
- set_physics_override(speed, jump, gravity)
modifies per-player walking speed, jump height, and gravity.
Values default to 1 and act as offsets to the physics settings
in minetest.conf. nil will keep the current setting.
- set_physics_override({
speed = 1.0, -- multiplier to default value
jump = 1.0, -- multiplier to default value
gravity = 1.0, -- multiplier to default value
sneak = true, -- whether player can sneak
sneak_glitch = true, -- whether player can use the sneak glitch
})
- hud_add(hud definition): add a HUD element described by HUD def, returns ID number on success
- hud_remove(id): remove the HUD element of the specified id
- hud_change(id, stat, value): change a value of a previously added HUD element
@@ -1402,12 +1735,17 @@ Player-only: (no-op for other objects)
^ if a flag is nil, the flag is not modified
- hud_set_hotbar_itemcount(count): sets number of items in builtin hotbar
^ count: number of items, must be between 1 and 23
- hud_set_hotbar_image(texturename)
^ sets background image for hotbar
- hud_set_hotbar_selected_image(texturename)
^ sets image for selected item of hotbar
InvRef: Reference to an inventory
methods:
- is_empty(listname): return true if list is empty
- get_size(listname): get size of a list
- set_size(listname, size): set size of a list
^ returns false on error (e.g. invalid listname or listsize)
- get_width(listname): get width of a list
- set_width(listname, width): set width of list; currently used for crafting
- get_stack(listname, i): get a copy of stack index i in list
@@ -1429,9 +1767,13 @@ ItemStack: A stack of items.
methods:
- is_empty(): return true if stack is empty
- get_name(): returns item name (e.g. "default:stone")
- set_name(itemname)
- get_count(): returns number of items on the stack
- set_count(count)
- get_wear(): returns tool wear (0-65535), 0 for non-tools
- set_wear(wear)
- get_metadata(): returns metadata (a string attached to an item stack)
- set_metadata(metadata)
- clear(): removes all items from the stack, making it empty
- replace(item): replace the contents of this stack (item can also
be an itemstring or table)
@@ -1469,6 +1811,108 @@ methods:
- get2d(pos) -> 2d noise value at pos={x=,y=}
- get3d(pos) -> 3d noise value at pos={x=,y=,z=}
PerlinNoiseMap: A fast, bulk perlin noise generator
- Can be created via PerlinNoiseMap(noiseparams, size)
- Also minetest.get_perlin_map(noiseparams, size)
methods:
- get2dMap(pos) -> <size.x>X<size.y> 2d array of 2d noise values starting at pos={x=,y=}
- get3dMap(pos) -> <size.x>X<size.y>X<size.z> 3d array of 3d noise values starting at pos={x=,y=,z=}
- get2dMap_flat(pos) -> Flat <size.x * size.y> element array of 2d noise values starting at pos={x=,y=}
- get3dMap_flat(pos) -> Same as get2dMap_flat, but 3d noise
VoxelManip: An interface to the MapVoxelManipulator for Lua
- Can be created via VoxelManip()
- Also minetest.get_voxel_manip()
methods:
- read_from_map(p1, p2): Reads a chunk of map from the map containing the region formed by p1 and p2.
^ returns actual emerged pmin, actual emerged pmax
- write_to_map(): Writes the data loaded from the VoxelManip back to the map.
^ important: data must be set using VoxelManip:set_data before calling this
- get_data(): Gets the data read into the VoxelManip object
^ returns raw node data is in the form of an array of node content ids
- set_data(data): Sets the data contents of the VoxelManip object
- update_map(): Update map after writing chunk back to map.
^ To be used only by VoxelManip objects created by the mod itself; not a VoxelManip that was
^ retrieved from minetest.get_mapgen_object
- set_lighting(light, p1, p2): Set the lighting within the VoxelManip to a uniform value
^ light is a table, {day=<0...15>, night=<0...15>}
^ To be used only by a VoxelManip object from minetest.get_mapgen_object
^ (p1, p2) is the area in which lighting is set; defaults to the whole area if left out
- get_light_data(): Gets the light data read into the VoxelManip object
^ Returns an array (indicies 1 to volume) of integers ranging from 0 to 255
^ Each value is the bitwise combination of day and night light values (0..15 each)
^ light = day + (night * 16)
- set_light_data(light_data): Sets the param1 (light) contents of each node in the VoxelManip
^ expects lighting data in the same format that get_light_data() returns
- calc_lighting(p1, p2): Calculate lighting within the VoxelManip
^ To be used only by a VoxelManip object from minetest.get_mapgen_object
^ (p1, p2) is the area in which lighting is set; defaults to the whole area if left out
- update_liquids(): Update liquid flow
VoxelArea: A helper class for voxel areas
- Can be created via VoxelArea:new{MinEdge=pmin, MaxEdge=pmax}
- Coordinates are *inclusive*, like most other things in Minetest
methods:
- getExtent(): returns a 3d vector containing the size of the area formed by MinEdge and MaxEdge
- getVolume(): returns the volume of the area formed by MinEdge and MaxEdge
- index(x, y, z): returns the index of an absolute position in a flat array starting at 1
^ useful for things like VoxelManip, raw Schematic specifiers, PerlinNoiseMap:get2d/3dMap, and so on
- indexp(p): same as above, except takes a vector
- position(i): returns the absolute position vector corresponding to index i
- contains(x, y, z): check if (x,y,z) is inside area formed by MinEdge and MaxEdge
- containsp(p): same as above, except takes a vector
- containsi(i): same as above, except takes an index
- iter(minx, miny, minz, maxx, maxy, maxz): returns an iterator that returns indices
^ from (minx,miny,minz) to (maxx,maxy,maxz) in the order of [z [y [x]]]
- iterp(minp, maxp): same as above, except takes a vector
Settings: An interface to read config files in the format of minetest.conf
- Can be created via Settings(filename)
methods:
- get(key) -> value
- get_bool(key) -> boolean
- set(key, value)
- remove(key) -> success
- get_names() -> {key1,...}
- write() -> success
^ write changes to file
- to_table() -> {[key1]=value1,...}
Mapgen objects
---------------
A mapgen object is a construct used in map generation. Mapgen objects can be used by an on_generate
callback to speed up operations by avoiding unnecessary recalculations; these can be retrieved using the
minetest.get_mapgen_object() function. If the requested Mapgen object is unavailable, or
get_mapgen_object() was called outside of an on_generate() callback, nil is returned.
The following Mapgen objects are currently available:
- voxelmanip
This returns three values; the VoxelManip object to be used, minimum and maximum emerged position, in that
order. All mapgens support this object.
- heightmap
Returns an array containing the y coordinates of the ground levels of nodes in the most recently
generated chunk by the current mapgen.
- biomemap
Returns an array containing the biome IDs of nodes in the most recently generated chunk by the
current mapgen.
- heatmap
Returns an array containing the temperature values of nodes in the most recently generated chunk by
the current mapgen.
- humiditymap
Returns an array containing the humidity values of nodes in the most recently generated chunk by the
current mapgen.
- gennotify
Returns a table mapping requested generation notification types to arrays of positions at which the
corresponding generated structures are located at within the current chunk. To set the capture of positions
of interest to be recorded on generate, use minetest.set_gen_notify().
Possible fields of the table returned are: dungeon, temple, cave_begin, cave_end, large_cave_begin, large_cave_end
Registered entities
--------------------
- Functions receive a "luaentity" as self:
@@ -1479,7 +1923,7 @@ Registered entities
- on_activate(self, staticdata)
^ Called when the object is instantiated.
- on_step(self, dtime)
^ Called on every server tick (dtime is usually 0.05 seconds)
^ Called on every server tick (dtime is usually 0.1 seconds)
- on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
^ Called when somebody punches the object.
^ Note that you probably want to handle most punches using the
@@ -1563,6 +2007,7 @@ Object Properties
{
hp_max = 1,
physical = true,
collide_with_objects = true, -- collide with other objects if physical=true
weight = 5,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "cube"/"sprite"/"upright_sprite"/"mesh",
@@ -1575,6 +2020,9 @@ Object Properties
is_visible = true,
makes_footstep_sound = false,
automatic_rotate = false,
stepheight = 0,
automatic_face_movement_dir = 0.0,
^ automatically set yaw to movement direction; offset in degrees; false to disable
}
Entity definition (register_entity)
@@ -1619,6 +2067,7 @@ Item definition (register_node, register_craftitem, register_tool)
wield_image = "",
wield_scale = {x=1,y=1,z=1},
stack_max = 99,
range = 4.0,
liquids_pointable = false,
tool_capabilities = {
full_punch_interval = 1.0,
@@ -1654,6 +2103,15 @@ Item definition (register_node, register_craftitem, register_tool)
eg. itemstack:take_item(); return itemstack
^ Otherwise, the function is free to do what it wants.
^ The default functions handle regular use cases.
after_use = func(itemstack, user, node, digparams),
^ default: nil
^ If defined, should return an itemstack and will be called instead of
wearing out the tool. If returns nil, does nothing.
If after_use doesn't exist, it is the same as:
function(itemstack, user, node, digparams)
itemstack:add_wear(digparams.wear)
return itemstack
end
}
Tile definition:
@@ -1673,6 +2131,10 @@ Node definition (register_node)
drawtype = "normal", -- See "Node drawtypes"
visual_scale = 1.0,
^ Supported for drawtypes "plantlike", "signlike", "torchlike".
^ For plantlike, the image will start at the bottom of the node; for the
^ other drawtypes, the image will be centered on the node.
^ Note that positioning for "torchlike" may still change.
tiles = {tile definition 1, def2, def3, def4, def5, def6},
^ Textures of node; +Y, -Y, +X, -X, +Z, -Z (old field name: tile_images)
^ List can be shortened to needed length
@@ -1696,8 +2158,11 @@ Node definition (register_node)
liquid_alternative_flowing = "", -- Flowing version of source liquid
liquid_alternative_source = "", -- Source version of flowing liquid
liquid_viscosity = 0, -- Higher viscosity = slower flow (max. 7)
liquid_renewable = true, -- Can new liquid source be created by placing
two or more sources nearly?
liquid_renewable = true, -- Can new liquid source be created by placing two or more sources nearby?
freezemelt = "", -- water for snow/ice, ice/snow for water
leveled = 0, -- Block contain level in param2. value - default level, used for snow. Dont forget use "leveled" type nodebox
liquid_range = 8, -- number of flowing nodes arround source (max. 8)
drowning = 0, -- Player will take this amount of damage if no bubbles are left
light_source = 0, -- Amount of light emitted by node
damage_per_second = 0, -- If player is inside node, this damage is caused
node_box = {type="regular"}, -- See "Node boxes"
@@ -1835,9 +2300,10 @@ Recipe for register_craft (furnace fuel)
Ore definition (register_ore)
{
ore_type = "scatter" -- See "Ore types"
ore_type = "scatter", -- See "Ore types"
ore = "default:stone_with_coal",
wherein = "default:stone",
^ a list of nodenames is supported too
clust_scarcity = 8*8*8,
^ Ore has a 1 out of clust_scarcity chance of spawning in a node
^ This value should be *MUCH* higher than your intuition might tell you!
@@ -1857,6 +2323,61 @@ Ore definition (register_ore)
^ Needed for sheet ore_type. Omit from scatter ore_type for a uniform ore distribution
}
Decoration definition (register_decoration)
{
deco_type = "simple", -- See "Decoration types"
place_on = "default:dirt_with_grass",
^ Node that decoration can be placed on
sidelen = 8,
^ Size of divisions made in the chunk being generated.
^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size.
fill_ratio = 0.02,
^ Ratio of the area to be uniformly filled by the decoration.
^ Used only if noise_params is not specified.
noise_params = {offset=0, scale=.45, spread={x=100, y=100, z=100}, seed=354, octaves=3, persist=0.7},
^ NoiseParams structure describing the perlin noise used for decoration distribution.
^ The result of this is multiplied by the 2d area of the division being decorated.
biomes = {"Oceanside", "Hills", "Plains"},
^ List of biomes in which this decoration occurs. Occurs in all biomes if this is omitted,
^ and ignored if the Mapgen being used does not support biomes.
----- Simple-type parameters
decoration = "default:grass",
^ The node name used as the decoration.
^ If instead a list of strings, a randomly selected node from the list is placed as the decoration.
height = 1,
^ Number of nodes high the decoration is made.
^ If height_max is not 0, this is the lower bound of the randomly selected height.
height_max = 0,
^ Number of nodes the decoration can be at maximum.
^ If absent, the parameter 'height' is used as a constant.
spawn_by = "default:water",
^ Node that the decoration only spawns next to, in a 1-node square radius.
num_spawn_by = 1,
^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
^ If absent or -1, decorations occur next to any nodes.
----- Schematic-type parameters
schematic = "foobar.mts",
^ If schematic is a string, it is the filepath relative to the current working directory of the
^ specified Minetest schematic file.
^ - OR -, could instead be a table containing two fields, size and data:
schematic = {
size = {x=4, y=6, z=4},
data = {
{name="cobble", param1=255, param2=0},
{name="dirt_with_grass", param1=255, param2=0},
...
}
},
^ See 'Schematic specifier' for details.
replacements = {{"oldname", "convert_to"}, ...},
flags = "place_center_x, place_center_z",
^ Flags for schematic decorations. See 'Schematic attributes'.
rotation = "90" --rotate schematic 90 degrees on placement
^ Rotation can be "0", "90", "180", "270", or "random".
}
Chatcommand definition (register_chatcommand)
{
params = "<name> <privilege>", -- short parameter description

207
doc/menu_lua_api.txt Normal file
View File

@@ -0,0 +1,207 @@
Minetest Lua Mainmenu API Reference 0.4.9
========================================
Introduction
-------------
The main menu is defined as a formspec by Lua in builtin/mainmenu.lua
Description of formspec language to show your menu is in lua_api.txt
Callbacks
---------
engine.buttonhandler(fields): called when a button is pressed.
^ fields = {name1 = value1, name2 = value2, ...}
engine.event_handler(event)
^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter"
Gamedata
--------
The "gamedata" table is read when calling engine.start(). It should contain:
{
playername = <name>,
password = <password>,
address = <IP/adress>,
port = <port>,
selected_world = <index>, -- 0 for client mode
singleplayer = <true/false>,
}
Functions
---------
engine.start()
engine.close()
Filesystem:
engine.get_scriptdir()
^ returns directory of script
engine.get_modpath() (possible in async calls)
^ returns path to global modpath
engine.get_modstore_details(modid) (possible in async calls)
^ modid numeric id of mod in modstore
^ returns {
id = <numeric id of mod in modstore>,
title = <human readable title>,
basename = <basename for mod>,
description = <description of mod>,
author = <author of mod>,
download_url= <best match download url>,
license = <short description of license>,
rating = <float value of current rating>
}
engine.get_modstore_list() (possible in async calls)
^ returns {
[1] = {
id = <numeric id of mod in modstore>,
title = <human readable title>,
basename = <basename for mod>
}
}
engine.get_gamepath() (possible in async calls)
^ returns path to global gamepath
engine.get_texturepath() (possible in async calls)
^ returns path to default textures
engine.get_dirlist(path,onlydirs) (possible in async calls)
^ path to get subdirs from
^ onlydirs should result contain only dirs?
^ returns list of folders within path
engine.create_dir(absolute_path) (possible in async calls)
^ absolute_path to directory to create (needs to be absolute)
^ returns true/false
engine.delete_dir(absolute_path) (possible in async calls)
^ absolute_path to directory to delete (needs to be absolute)
^ returns true/false
engine.copy_dir(source,destination,keep_soure) (possible in async calls)
^ source folder
^ destination folder
^ keep_source DEFAULT true --> if set to false source is deleted after copying
^ returns true/false
engine.extract_zip(zipfile,destination) [unzip within path required]
^ zipfile to extract
^ destination folder to extract to
^ returns true/false
engine.download_file(url,target) (possible in async calls)
^ url to download
^ target to store to
^ returns true/false
engine.get_version() (possible in async calls)
^ returns current minetest version
engine.sound_play(spec, looped) -> handle
^ spec = SimpleSoundSpec (see lua-api.txt)
^ looped = bool
engine.sound_stop(handle)
GUI:
engine.update_formspec(formspec)
- engine.set_background(type, texturepath)
^ type: "background", "overlay", "header" or "footer"
engine.set_clouds(<true/false>)
engine.set_topleft_text(text)
Games:
engine.get_game(index)
^ returns {
id = <id>,
path = <full path to game>,
gamemods_path = <path>,
name = <name of game>,
menuicon_path = <full path to menuicon>,
DEPRECATED:
addon_mods_paths = {[1] = <path>,},
}
engine.get_games() -> table of all games in upper format (possible in async calls)
Favorites:
engine.get_favorites(location) -> list of favorites (possible in async calls)
^ location: "local" or "online"
^ returns {
[1] = {
clients = <number of clients/nil>,
clients_max = <maximum number of clients/nil>,
version = <server version/nil>,
password = <true/nil>,
creative = <true/nil>,
damage = <true/nil>,
pvp = <true/nil>,
description = <server description/nil>,
name = <server name/nil>,
address = <address of server/nil>,
port = <port>
},
}
engine.delete_favorite(id, location) -> success
Logging:
engine.debug(line) (possible in async calls)
^ Always printed to stderr and logfile (print() is redirected here)
engine.log(line) (possible in async calls)
engine.log(loglevel, line) (possible in async calls)
^ loglevel one of "error", "action", "info", "verbose"
Settings:
engine.setting_set(name, value)
engine.setting_get(name) -> string or nil (possible in async calls)
engine.setting_setbool(name, value)
engine.setting_getbool(name) -> bool or nil (possible in async calls)
engine.setting_save() -> nil, save all settings to config file
Worlds:
engine.get_worlds() -> list of worlds (possible in async calls)
^ returns {
[1] = {
path = <full path to world>,
name = <name of world>,
gameid = <gameid of world>,
},
}
engine.create_world(worldname, gameid)
engine.delete_world(index)
UI:
engine.get_textlist_index(textlistname) -> index
engine.show_keys_menu()
engine.file_open_dialog(formname,caption)
^ shows a file open dialog
^ formname is base name of dialog response returned in fields
^ -if dialog was accepted "_accepted"
^^ will be added to fieldname containing the path
^ -if dialog was canceled "_cancelled"
^ will be added to fieldname value is set to formname itself
^ returns nil or selected file/folder
Helpers:
engine.formspec_escape(string) -> string
^ escapes characters [ ] \ , ; that can not be used in formspecs
engine.gettext(string) -> string
^ look up the translation of a string in the gettext message catalog
fgettext(string, ...) -> string
^ call engine.gettext(string), replace "$1"..."$9" with the given
^ extra arguments, call engine.formspec_escape and return the result
engine.parse_json(string[, nullvalue]) -> something (possible in async calls)
^ see minetest.parse_json (lua_api.txt)
dump(obj, dumped={})
^ Return object serialized as a string
string:split(separator)
^ eg. string:split("a,b", ",") == {"a","b"}
string:trim()
^ eg. string.trim("\n \t\tfoo bar\t ") == "foo bar"
minetest.is_yes(arg) (possible in async calls)
^ returns whether arg can be interpreted as yes
Async:
engine.handle_async(async_job,parameters,finished)
^ execute a function asynchronously
^ async_job is a function receiving one parameter and returning one parameter
^ parameters parameter table passed to async_job
^ finished function to be called once async_job has finished
^ the result of async_job is passed to this function
Limitations of Async operations
-No access to global lua variables, don't even try
-Limited set of available functions
e.g. No access to functions modifying menu like engine.start,engine.close,
engine.file_open_dialog
Class reference
----------------
Settings: see lua_api.txt

View File

@@ -1,5 +1,5 @@
.\" Minetest man page
.TH minetest 6 "11 March 2012" "" ""
.TH minetest 6 "10 September 2013" "" ""
.SH NAME
minetest \- Multiplayer infinite-world block sandbox
@@ -37,6 +37,9 @@ Disable main menu
\-\-help
Show allowed options
.TP
\-\-version
Show version information
.TP
\-\-logfile <value>
Set logfile path (debug.txt)
.TP
@@ -75,6 +78,10 @@ Print enormous amounts of information to console
.TP
\-\-world <value>
Set world path
.TP
\-\-migrate <value>
Migrate from current map backend to another. Possible values are sqlite3
and leveldb. Only works when using --server.
.SH BUGS
Please report all bugs to Perttu Ahola <celeron55@gmail.com>.

View File

@@ -1,5 +1,5 @@
.\" Minetestserver man page
.TH minetestserver 6 "11 March 2012" "" ""
.TH minetestserver 6 "10 September 2013" "" ""
.SH NAME
minetestserver \- Minetest server
@@ -31,6 +31,9 @@ Set gameid
\-\-help
Show allowed options
.TP
\-\-version
Show version information
.TP
\-\-logfile <value>
Set logfile path (debug.txt)
.TP
@@ -51,6 +54,10 @@ Print enormous amounts of information to console
.TP
\-\-world <value>
Set world path
.TP
\-\-migrate <value>
Migrate from current map backend to another. Possible values are sqlite3
and leveldb.
.SH BUGS
Please report all bugs to Perttu Ahola <celeron55@gmail.com>.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
fonts/fontlucida.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 B

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 180 B

View File

@@ -712,7 +712,6 @@ end
minetest.register_node("default:stone", {
description = "Stone",
tiles ={"default_stone.png"},
is_ground_content = true,
groups = {cracky=3},
drop = 'default:cobble',
legacy_mineral = true,
@@ -722,7 +721,6 @@ minetest.register_node("default:stone", {
minetest.register_node("default:stone_with_coal", {
description = "Stone with coal",
tiles ={"default_stone.png^default_mineral_coal.png"},
is_ground_content = true,
groups = {cracky=3},
drop = 'default:coal_lump',
sounds = default.node_sound_stone_defaults(),
@@ -731,7 +729,6 @@ minetest.register_node("default:stone_with_coal", {
minetest.register_node("default:stone_with_iron", {
description = "Stone with iron",
tiles ={"default_stone.png^default_mineral_iron.png"},
is_ground_content = true,
groups = {cracky=3},
drop = 'default:iron_lump',
sounds = default.node_sound_stone_defaults(),
@@ -740,7 +737,6 @@ minetest.register_node("default:stone_with_iron", {
minetest.register_node("default:dirt_with_grass", {
description = "Dirt with grass",
tiles ={"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
is_ground_content = true,
groups = {crumbly=3, soil=1},
drop = 'default:dirt',
sounds = default.node_sound_dirt_defaults({
@@ -751,7 +747,6 @@ minetest.register_node("default:dirt_with_grass", {
minetest.register_node("default:dirt_with_grass_footsteps", {
description = "Dirt with grass and footsteps",
tiles ={"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
is_ground_content = true,
groups = {crumbly=3, soil=1},
drop = 'default:dirt',
sounds = default.node_sound_dirt_defaults({
@@ -762,7 +757,6 @@ minetest.register_node("default:dirt_with_grass_footsteps", {
minetest.register_node("default:dirt", {
description = "Dirt",
tiles ={"default_dirt.png"},
is_ground_content = true,
groups = {crumbly=3, soil=1},
sounds = default.node_sound_dirt_defaults(),
})
@@ -770,7 +764,6 @@ minetest.register_node("default:dirt", {
minetest.register_node("default:sand", {
description = "Sand",
tiles ={"default_sand.png"},
is_ground_content = true,
groups = {crumbly=3, falling_node=1},
sounds = default.node_sound_sand_defaults(),
})
@@ -778,7 +771,6 @@ minetest.register_node("default:sand", {
minetest.register_node("default:gravel", {
description = "Gravel",
tiles ={"default_gravel.png"},
is_ground_content = true,
groups = {crumbly=2, falling_node=1},
sounds = default.node_sound_dirt_defaults({
footstep = {name="default_gravel_footstep", gain=0.45},
@@ -788,7 +780,6 @@ minetest.register_node("default:gravel", {
minetest.register_node("default:sandstone", {
description = "Sandstone",
tiles ={"default_sandstone.png"},
is_ground_content = true,
groups = {crumbly=2,cracky=2},
drop = 'default:sand',
sounds = default.node_sound_stone_defaults(),
@@ -797,7 +788,6 @@ minetest.register_node("default:sandstone", {
minetest.register_node("default:clay", {
description = "Clay",
tiles ={"default_clay.png"},
is_ground_content = true,
groups = {crumbly=3},
drop = 'default:clay_lump 4',
sounds = default.node_sound_dirt_defaults({
@@ -808,7 +798,6 @@ minetest.register_node("default:clay", {
minetest.register_node("default:brick", {
description = "Brick",
tiles ={"default_brick.png"},
is_ground_content = true,
groups = {cracky=3},
drop = 'default:clay_brick 4',
sounds = default.node_sound_stone_defaults(),
@@ -817,7 +806,6 @@ minetest.register_node("default:brick", {
minetest.register_node("default:tree", {
description = "Tree",
tiles ={"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
is_ground_content = true,
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1},
sounds = default.node_sound_wood_defaults(),
})
@@ -825,7 +813,6 @@ minetest.register_node("default:tree", {
minetest.register_node("default:jungletree", {
description = "Jungle Tree",
tiles ={"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"},
is_ground_content = true,
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1},
sounds = default.node_sound_wood_defaults(),
})
@@ -849,6 +836,7 @@ minetest.register_node("default:leaves", {
visual_scale = 1.3,
tiles ={"default_leaves.png"},
paramtype = "light",
is_ground_content = false,
groups = {snappy=3},
drop = {
max_items = 1,
@@ -871,7 +859,6 @@ minetest.register_node("default:leaves", {
minetest.register_node("default:cactus", {
description = "Cactus",
tiles ={"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"},
is_ground_content = true,
groups = {snappy=2,choppy=3},
sounds = default.node_sound_wood_defaults(),
})
@@ -883,7 +870,6 @@ minetest.register_node("default:papyrus", {
inventory_image = "default_papyrus.png",
wield_image = "default_papyrus.png",
paramtype = "light",
is_ground_content = true,
walkable = false,
groups = {snappy=3},
sounds = default.node_sound_leaves_defaults(),
@@ -892,7 +878,6 @@ minetest.register_node("default:papyrus", {
minetest.register_node("default:bookshelf", {
description = "Bookshelf",
tiles ={"default_wood.png", "default_wood.png", "default_bookshelf.png"},
is_ground_content = true,
groups = {snappy=2,choppy=3,oddly_breakable_by_hand=2},
sounds = default.node_sound_wood_defaults(),
})
@@ -904,7 +889,6 @@ minetest.register_node("default:glass", {
inventory_image = minetest.inventorycube("default_glass.png"),
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
sounds = default.node_sound_glass_defaults(),
})
@@ -916,7 +900,6 @@ minetest.register_node("default:fence_wood", {
inventory_image = "default_fence.png",
wield_image = "default_fence.png",
paramtype = "light",
is_ground_content = true,
selection_box = {
type = "fixed",
fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7},
@@ -932,7 +915,6 @@ minetest.register_node("default:rail", {
inventory_image = "default_rail.png",
wield_image = "default_rail.png",
paramtype = "light",
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
@@ -949,7 +931,6 @@ minetest.register_node("default:ladder", {
wield_image = "default_ladder.png",
paramtype = "light",
paramtype2 = "wallmounted",
is_ground_content = true,
walkable = false,
climbable = true,
selection_box = {
@@ -966,7 +947,6 @@ minetest.register_node("default:ladder", {
minetest.register_node("default:wood", {
description = "Wood",
tiles ={"default_wood.png"},
is_ground_content = true,
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
sounds = default.node_sound_wood_defaults(),
})
@@ -974,7 +954,6 @@ minetest.register_node("default:wood", {
minetest.register_node("default:mese", {
description = "Mese",
tiles ={"default_mese.png"},
is_ground_content = true,
groups = {cracky=1,level=2},
sounds = default.node_sound_defaults(),
})
@@ -982,7 +961,6 @@ minetest.register_node("default:mese", {
minetest.register_node("default:cloud", {
description = "Cloud",
tiles ={"default_cloud.png"},
is_ground_content = true,
sounds = default.node_sound_defaults(),
})
@@ -1001,6 +979,7 @@ minetest.register_node("default:water_flowing", {
pointable = false,
diggable = false,
buildable_to = true,
drowning = 1,
liquidtype = "flowing",
liquid_alternative_flowing = "default:water_flowing",
liquid_alternative_source = "default:water_source",
@@ -1024,6 +1003,7 @@ minetest.register_node("default:water_source", {
pointable = false,
diggable = false,
buildable_to = true,
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "default:water_flowing",
liquid_alternative_source = "default:water_source",
@@ -1055,6 +1035,7 @@ minetest.register_node("default:lava_flowing", {
pointable = false,
diggable = false,
buildable_to = true,
drowning = 1,
liquidtype = "flowing",
liquid_alternative_flowing = "default:lava_flowing",
liquid_alternative_source = "default:lava_source",
@@ -1082,6 +1063,7 @@ minetest.register_node("default:lava_source", {
pointable = false,
diggable = false,
buildable_to = true,
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "default:lava_flowing",
liquid_alternative_source = "default:lava_source",
@@ -1100,6 +1082,7 @@ minetest.register_node("default:torch", {
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
is_ground_content = false,
walkable = false,
light_source = LIGHT_MAX-1,
selection_box = {
@@ -1122,6 +1105,7 @@ minetest.register_node("default:sign_wall", {
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
is_ground_content = false,
walkable = false,
selection_box = {
type = "wallmounted",
@@ -1156,6 +1140,7 @@ minetest.register_node("default:chest", {
paramtype2 = "facedir",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
@@ -1188,6 +1173,7 @@ minetest.register_node("default:chest_locked", {
paramtype2 = "facedir",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
@@ -1273,6 +1259,7 @@ minetest.register_node("default:furnace", {
paramtype2 = "facedir",
groups = {cracky=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
@@ -1306,6 +1293,7 @@ minetest.register_node("default:furnace_active", {
drop = "default:furnace",
groups = {cracky=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
@@ -1330,18 +1318,13 @@ minetest.register_node("default:furnace_active", {
end,
})
function hacky_swap_node(pos,name)
function swap_node(pos,name)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local meta0 = meta:to_table()
if node.name == name then
return
end
node.name = name
local meta0 = meta:to_table()
minetest.set_node(pos,node)
meta = minetest.get_meta(pos)
meta:from_table(meta0)
minetest.swap_node(pos, node)
end
minetest.register_abm({
@@ -1396,7 +1379,7 @@ minetest.register_abm({
local percent = math.floor(meta:get_float("fuel_time") /
meta:get_float("fuel_totaltime") * 100)
meta:set_string("infotext","Furnace active: "..percent.."%")
hacky_swap_node(pos,"default:furnace_active")
swap_node(pos,"default:furnace_active")
meta:set_string("formspec",
"size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
@@ -1422,7 +1405,7 @@ minetest.register_abm({
if fuel.time <= 0 then
meta:set_string("infotext","Furnace out of fuel")
hacky_swap_node(pos,"default:furnace")
swap_node(pos,"default:furnace")
meta:set_string("formspec", default.furnace_inactive_formspec)
return
end
@@ -1430,7 +1413,7 @@ minetest.register_abm({
if cooked.item:is_empty() then
if was_active then
meta:set_string("infotext","Furnace is empty")
hacky_swap_node(pos,"default:furnace")
swap_node(pos,"default:furnace")
meta:set_string("formspec", default.furnace_inactive_formspec)
end
return
@@ -1448,7 +1431,6 @@ minetest.register_abm({
minetest.register_node("default:cobble", {
description = "Cobble",
tiles ={"default_cobble.png"},
is_ground_content = true,
groups = {cracky=3},
sounds = default.node_sound_stone_defaults(),
})
@@ -1456,7 +1438,6 @@ minetest.register_node("default:cobble", {
minetest.register_node("default:mossycobble", {
description = "Mossy Cobble",
tiles ={"default_mossycobble.png"},
is_ground_content = true,
groups = {cracky=3},
sounds = default.node_sound_stone_defaults(),
})
@@ -1464,7 +1445,6 @@ minetest.register_node("default:mossycobble", {
minetest.register_node("default:steelblock", {
description = "Steel Block",
tiles ={"default_steel_block.png"},
is_ground_content = true,
groups = {snappy=1,bendy=2},
sounds = default.node_sound_stone_defaults(),
})
@@ -1477,6 +1457,7 @@ minetest.register_node("default:nyancat", {
paramtype2 = "facedir",
groups = {cracky=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_defaults(),
})
@@ -1484,6 +1465,7 @@ minetest.register_node("default:nyancat_rainbow", {
description = "Nyancat Rainbow",
tiles ={"default_nc_rb.png"},
inventory_image = "default_nc_rb.png",
is_ground_content = false,
groups = {cracky=2},
sounds = default.node_sound_defaults(),
})
@@ -1515,6 +1497,133 @@ minetest.register_node("default:apple", {
sounds = default.node_sound_defaults(),
})
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local c_tree = minetest.get_content_id("default:tree")
local c_leaves = minetest.get_content_id("default:leaves")
local c_apple = minetest.get_content_id("default:apple")
function default.grow_tree(data, a, pos, is_apple_tree, seed)
--[[
NOTE: Tree-placing code is currently duplicated in the engine
and in games that have saplings; both are deprecated but not
replaced yet
]]--
local pr = PseudoRandom(seed)
local th = pr:next(4, 5)
local x, y, z = pos.x, pos.y, pos.z
for yy = y, y+th-1 do
local vi = a:index(x, yy, z)
if a:contains(x, yy, z) and (data[vi] == c_air or yy == y) then
data[vi] = c_tree
end
end
y = y+th-1 -- (x, y, z) is now last piece of trunk
local leaves_a = VoxelArea:new{MinEdge={x=-2, y=-1, z=-2}, MaxEdge={x=2, y=2, z=2}}
local leaves_buffer = {}
-- Force leaves near the trunk
local d = 1
for xi = -d, d do
for yi = -d, d do
for zi = -d, d do
leaves_buffer[leaves_a:index(xi, yi, zi)] = true
end
end
end
-- Add leaves randomly
for iii = 1, 8 do
local d = 1
local xx = pr:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d)
local yy = pr:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d)
local zz = pr:next(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d)
for xi = 0, d do
for yi = 0, d do
for zi = 0, d do
leaves_buffer[leaves_a:index(xx+xi, yy+yi, zz+zi)] = true
end
end
end
end
-- Add the leaves
for xi = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do
for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do
for zi = leaves_a.MinEdge.z, leaves_a.MaxEdge.z do
if a:contains(x+xi, y+yi, z+zi) then
local vi = a:index(x+xi, y+yi, z+zi)
if data[vi] == c_air or data[vi] == c_ignore then
if leaves_buffer[leaves_a:index(xi, yi, zi)] then
if is_apple_tree and pr:next(1, 100) <= 10 then
data[vi] = c_apple
else
data[vi] = c_leaves
end
end
end
end
end
end
end
end
minetest.register_abm({
nodenames = {"default:sapling"},
interval = 10,
chance = 50,
action = function(pos, node)
local is_soil = minetest.registered_nodes[minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name].groups.soil
if is_soil == nil or is_soil == 0 then return end
print("A sapling grows into a tree at "..minetest.pos_to_string(pos))
local vm = minetest.get_voxel_manip()
local minp, maxp = vm:read_from_map({x=pos.x-16, y=pos.y, z=pos.z-16}, {x=pos.x+16, y=pos.y+16, z=pos.z+16})
local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
local data = vm:get_data()
default.grow_tree(data, a, pos, math.random(1, 4) == 1, math.random(1,100000))
vm:set_data(data)
vm:write_to_map(data)
vm:update_map()
end
})
minetest.register_abm({
nodenames = {"default:dirt"},
interval = 2,
chance = 200,
action = function(pos, node)
local above = {x=pos.x, y=pos.y+1, z=pos.z}
local name = minetest.get_node(above).name
local nodedef = minetest.registered_nodes[name]
if nodedef and (nodedef.sunlight_propagates or nodedef.paramtype == "light")
and nodedef.liquidtype == "none"
and (minetest.get_node_light(above) or 0) >= 13 then
if name == "default:snow" or name == "default:snowblock" then
minetest.set_node(pos, {name = "default:dirt_with_snow"})
else
minetest.set_node(pos, {name = "default:dirt_with_grass"})
end
end
end
})
minetest.register_abm({
nodenames = {"default:dirt_with_grass"},
interval = 2,
chance = 20,
action = function(pos, node)
local above = {x=pos.x, y=pos.y+1, z=pos.z}
local name = minetest.get_node(above).name
local nodedef = minetest.registered_nodes[name]
if name ~= "ignore" and nodedef
and not ((nodedef.sunlight_propagates or nodedef.paramtype == "light")
and nodedef.liquidtype == "none") then
minetest.set_node(pos, {name = "default:dirt"})
end
end
})
--
-- Crafting items
--

View File

@@ -4,7 +4,6 @@
-- Aliases for map generator outputs
--
minetest.register_alias("mapgen_air", "air")
minetest.register_alias("mapgen_stone", "default:stone")
minetest.register_alias("mapgen_tree", "default:tree")
minetest.register_alias("mapgen_leaves", "default:leaves")
@@ -22,6 +21,7 @@ minetest.register_alias("mapgen_junglegrass", "default:junglegrass")
minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal")
minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron")
minetest.register_alias("mapgen_mese", "default:mese")
minetest.register_alias("mapgen_stair_cobble", "stairs:stair_cobble")
--
-- Ore generation

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 B

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 933 B

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 830 B

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 B

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 874 B

After

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 936 B

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 B

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

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