Compare commits

...

339 Commits

Author SHA1 Message Date
Perttu Ahola
960009d619 Update changelog 2011-09-27 18:11:12 +03:00
Kahrl
5ca877b836 minetestmapper: Fix the way ylist is computed, use cStringIO instead of rolling own Bytestream, remove some artifacts when drawing underground blocks, introduce a --drawunderground switch (defaults to of), 'blocknum' renamed to 'content'. 2011-09-27 16:18:22 +03:00
Perttu Ahola
b0c2c83861 minetestmapper speed tweaks (kahrl & JacobF) 2011-09-27 16:18:22 +03:00
Perttu Ahola
1a63c6e016 Add apple color to minetestmapper and fix cactus color 2011-09-26 21:57:18 +03:00
Perttu Ahola
fd7c8706ce Fix minetestmapper.py 2011-09-26 21:57:18 +03:00
Kahrl
aefa3b630b Support Python 2 and 3 in sectors2sqlite.py. 2011-09-26 21:57:18 +03:00
Kahrl
d5281eaa2e Fix processing of blocks below y=0 in sectors2sqlite.py. 2011-09-26 21:57:18 +03:00
Perttu Ahola
7504a748d0 Move PLATFORM_LIBS around to make sqlite3 link with libdl on some distros 2011-09-26 21:57:17 +03:00
Perttu Ahola
bdf54908aa Make client report a newer version number to the server than 2011-07-31 does and make the server enforce it 2011-09-22 20:47:47 +03:00
Perttu Ahola
7244f09111 Oh well, let's call it just 0.2.20110922 2011-09-22 18:22:04 +03:00
Perttu Ahola
ca748ad44c Update changelog and version to 0.2.20110922_rc1 2011-09-22 18:15:05 +03:00
Perttu Ahola
ae6d83a41e Better apple tree generation 2011-09-21 23:31:55 +03:00
Perttu Ahola
b22cb69a15 Merge remote-tracking branch 'sfan5/apple-trees' 2011-09-16 19:09:13 +03:00
Kahrl
40707e3c5b SQLite needs to be linked with -ldl on some Linux distros. 2011-09-16 19:06:45 +03:00
JacobF
7f51bccf47 update minetestmapper so it can read the database also 2011-09-16 18:59:33 +03:00
Perttu Ahola
bfa5ad483f Update changelog 2011-09-16 18:59:17 +03:00
Kahrl
ae89aa55b9 Updated colors.txt (which is used by minetestmapper) 2011-09-15 23:09:00 +02:00
sfan5
88dc8c694e Added Iron Apple which heals 4 Hearts 2011-09-12 20:10:17 +02:00
sfan5
785a2fd23a Changed the Heal Amount of Apples from 6 to 2 2011-09-12 19:44:26 +02:00
sfan5
4328a6442b Fixed duplication bug 2011-09-11 19:17:14 +02:00
sfan5
6496b1cf1f Removed Spaces 2011-09-11 18:16:07 +02:00
sfan5
c0caedc373 Added Apple Trees 2011-09-11 17:50:44 +02:00
Perttu Ahola
d28ea57083 Note about texture atlas 2011-09-07 01:27:04 +03:00
Perttu Ahola
8e26c5c066 Add note about trans_table_19. 2011-09-07 01:19:48 +03:00
Perttu Ahola
5c1074aa7d Remove block file from disk when saved to database 2011-09-06 20:28:45 +03:00
JacobF
bd72091150 Pause in unloaded territory instead of collide 2011-09-06 20:07:43 +03:00
Perttu Ahola
faf3d7902a Make Connection::Send cancel silently if peer doesn't exist. 2011-09-06 19:39:23 +03:00
Perttu Ahola
63f1ded167 Update version number to something more proper for this stage of development (0.2.201109xx_dev) 2011-09-06 19:22:00 +03:00
Perttu Ahola
3c30ab2807 Speed up periodical map unloading by moving beginSave() and endSave() to outer loop in Map::timerUpdate() 2011-09-06 19:16:36 +03:00
Perttu Ahola
310fa10035 Merge remote-tracking branch 'queatz/sqlite-map' 2011-09-06 18:04:02 +03:00
Perttu Ahola
bc847e8cc2 Fix bug in posix file/directory removal wrapper, as pointed out by kahrl 2011-09-06 17:52:03 +03:00
Perttu Ahola
b82952bdba Fix some texture stuff: remove item_fence.png, use fence.png, remove inexisting cactus.png from texture atlas (replace with nothing because cactus is rare) 2011-09-06 17:13:24 +03:00
Kahrl
570a8dbf22 allow specifying a fixed seed in the config file for generating the map (fixed_map_seed) 2011-09-06 17:05:17 +03:00
JacobF
c68ea19e8d Now SAOs will reflect changes to their temporary inventory object
Also, the temp item wasn't being deleted, might have been a memory leak.
Now you will only eat 1 item off a stack
2011-09-06 16:36:11 +03:00
JacobF
0c91d01866 Cull empty lines... 2011-09-04 17:06:23 -04:00
JacobF
e34cef312f Files to database converter 2011-09-04 17:02:50 -04:00
JacobF
d670c831c2 These numbers were well exceeding 2^32... 2011-09-04 17:01:28 -04:00
JacobF
d1a16f24cf Initial sqlite3 maps.
* The map will reside in world/map.sqlite
* It will load from the sectors folder but will not save there
2011-09-02 19:07:14 -04:00
JacobF
2d872ce3fa Furnace was crashing stuff again 2011-09-02 17:33:06 -04:00
JacobF
e3c58eff1c Merge branch 'master' of /media/Field/Software/minetest-queatz/minetest-sqlite/.. into sqlite-map 2011-09-02 16:59:17 -04:00
JacobF
99de37ff94 Update to SQLite 3.7.7.1 2011-09-01 18:27:30 -04:00
JacobF
5e3b9e3578 * Furnace would say it was overloaded when it had a non-cookable source
* I didn't understand that expression last fix and now the furnace would burn fuel
even when it had no source item.
2011-09-01 15:39:15 -04:00
Perttu Ahola
ad795c9f0c Merge remote-tracking branch 'queatz/furnace-fix' 2011-08-31 17:04:12 +03:00
Perttu Ahola
d6d479f94c Updated changelog 2011-08-31 00:43:34 +03:00
JacobF
6415528f96 If there was no source item in a furnace it would cause a segmentation fault. 2011-08-30 11:38:53 -04:00
Perttu Ahola
4af1f2963c Merge remote-tracking branch 'kahrl/dissector' 2011-08-30 14:24:33 +03:00
Perttu Ahola
ba0322f353 Merge remote-tracking branch 'queatz/mmb10' 2011-08-30 14:24:23 +03:00
Perttu Ahola
1a705523c0 Merge remote-tracking branch 'queatz/furnace-is-not-blackhole' 2011-08-30 14:24:12 +03:00
Perttu Ahola
87b9e5467d Merge remote-tracking branch 'queatz/furnace-is-not-out-nor-can-rat-escape' 2011-08-30 14:24:07 +03:00
Perttu Ahola
625dac8d8c Merge remote-tracking branch 'queatz/privs' 2011-08-30 14:23:44 +03:00
JacobF
134e49cc8e Merged 2 branches because they relied on each other.
This one contains these changes from main c55:
* Adds a function to check if there is room for a specific item
* Using that, you can now pick up rats if you have a full inventory and a not full rat stack
* Furnace would cook only 1 item if that item used the last available result slot, now it will continue
* Furnace will say it's overloaded
* Furnace won't wait until the next step to start on the next item
 - This caused small fuels to cook slower than meant to
 - Also caused furnaces to say they were out of fuel after finishing the last fuel item
2011-08-25 19:27:50 -04:00
Kahrl
cab426ffa3 dissector branch: fix for doc/protocol.txt: CONTROLTYPE_DISCO is 3 2011-08-25 21:32:48 +02:00
Kahrl
3edf2bb417 dissector branch: fix description of TOCLIENT_PLAYERITEM in clientserver.h 2011-08-25 21:31:28 +02:00
Kahrl
9ebfbd150e dissector branch: added wireshark dissector minetest.lua 2011-08-25 21:29:41 +02:00
JacobF
e278742c5e Middle mouse click will move 10 items around at a time. 2011-08-25 12:43:19 -04:00
JacobF
ef08163c38 Don't remove furnace if something is inside it. 2011-08-24 18:53:06 -04:00
JacobF
2e82268a67 If a user doesn't have build rights, don't allow them to move items to and from their inventory 2011-08-23 22:08:09 -04:00
JacobF
00bdfad5f6 The password box in the mainmenu is focused if there is already a name and address filled in 2011-08-23 22:06:35 -04:00
Perttu Ahola
efd8dabd91 Lava is now better visible inside water. (a crappy hack) 2011-08-23 03:01:01 +03:00
Perttu Ahola
e4f443a57a Inventory transparency; very loosely based on sapier's commits.
Also contains some commented-out code for testing out different looks
in the future.
2011-08-23 00:33:38 +03:00
Perttu Ahola
d4df20a913 if creative mode and player has no build privileges, cannot drop items. 2011-08-22 22:55:17 +03:00
Perttu Ahola
db495668ae Fixed water mesh generation acting weird next to sand 2011-08-22 22:44:43 +03:00
Perttu Ahola
996c653490 Fix byte count in serialization of "F1000"
Some access violations and segfaults and strange behaviour might have
been caused by this.
2011-08-22 22:17:26 +03:00
Perttu Ahola
4acad897cf Fixed some protocol comment errors in clientserver.h and elsewhere
-- TOCLIENT_OBJECTDATA: peer ID field is missing
-- TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD: added: init length should be u32, not u16
2011-08-22 22:04:46 +03:00
Giuseppe Bilotta
b37fffc2c5 Hopefully fix 'dangling water'
If a block has (at least visible) liquids, the block below should also
be flowed in.
2011-08-22 21:45:13 +03:00
Perttu Ahola
a99450ab72 Possibly fixed the extremely rare PeerNotFound loop bug.
See explanation in http://2pktfkt.de/irc/minetest-delta/2011-08-22.html
2011-08-22 21:27:11 +03:00
Perttu Ahola
7776d6228e Update README.txt 2011-08-22 15:01:09 +03:00
Perttu Ahola
5415256a52 Merge remote-tracking branch 'oblomov/me_cmd' 2011-08-22 14:46:54 +03:00
Perttu Ahola
836e43db60 Merge remote-tracking branch 'oblomov/new_input' 2011-08-22 14:46:52 +03:00
Giuseppe Bilotta
9c94538fb7 Change way commands are displayed in chat window 2011-08-22 13:43:53 +02:00
Giuseppe Bilotta
53eedd3ba4 Introduce hotkey for calling up a command window
This is just a chat window with the / text pre-loaded.
2011-08-22 13:02:08 +02:00
Giuseppe Bilotta
42134bb49e Send KEY_END when (re)creating a text input
This ensures that on creation and when resizing the cursor is at the end
of the text rather than at the beginnig.
2011-08-22 13:02:08 +02:00
Giuseppe Bilotta
0488bf54d3 /me command 2011-08-22 13:02:08 +02:00
Giuseppe Bilotta
da19aee307 Server now supports replies without prefix 2011-08-22 13:02:08 +02:00
Giuseppe Bilotta
d2c0b4905a Defines for server command context flags 2011-08-22 13:02:08 +02:00
Giuseppe Bilotta
153f07fdfb Remove distinction between /# and / commands
No need to make the server command syntax more complicated than
necessary. If the need ever arise, we'll find some other way to
distinguish the client commands. Also, the /# syntax is deprecated and
will be made obsolete in time.
2011-08-22 13:02:08 +02:00
Giuseppe Bilotta
7e610aece5 Overhaul the input system
This allows us to map the keys which are not considered in
irrlicht's EKEY_CODE system, such as \, [, /, ] etc.
2011-08-22 13:01:11 +02:00
Giuseppe Bilotta
16aedc0ef6 Fix typos in key names 2011-08-22 12:52:15 +02:00
Perttu Ahola
6596e585fe Flowing lava updates lighting 2011-08-22 13:19:07 +03:00
Perttu Ahola
f98eda4d52 Merge remote-tracking branch 'oblomov/liquid_fixes' 2011-08-22 12:53:18 +03:00
Perttu Ahola
23717510c2 Merge branch 'lava' 2011-08-22 12:53:02 +03:00
Giuseppe Bilotta
c51564ab5b Optimize for viscosity 1 2011-08-16 20:38:44 +02:00
Giuseppe Bilotta
1eb14c7743 Viscous fluids 2011-08-16 20:37:46 +02:00
Giuseppe Bilotta
56e9f97294 Make sure all neighbors of changed fluids are activated
This should fix the remaining cases of fluid not advancing or not
retreating.
2011-08-16 18:05:28 +02:00
Giuseppe Bilotta
774faf4e85 Let the liquids flow in the open
No need to curb their spread artificially.
2011-08-16 17:42:28 +02:00
Giuseppe Bilotta
d0711821f3 Ensure air neighbors to liquids that can flow are enqueued for transformation 2011-08-16 17:42:14 +02:00
Giuseppe Bilotta
7024b45197 Ensure param2 is set correctly in transformLiquids 2011-08-16 16:50:38 +02:00
Giuseppe Bilotta
5fce673a56 Use defines for liquid levels 2011-08-16 16:50:38 +02:00
Perttu Ahola
29c9d3d5f4 Implemented MEET_OTHER 2011-08-16 12:23:19 +03:00
Giuseppe Bilotta
708f1c336e transformLiquid: small optimization and whitespace cleanup 2011-08-16 06:42:11 +02:00
Perttu Ahola
dc4ac0b96f small fix to transformLiquids 2011-08-15 18:49:44 +03:00
Perttu Ahola
296748d32e Fixed liquid mesh generation 2011-08-15 17:45:35 +03:00
Perttu Ahola
ad408f269c Add lava to creative inventory (hmm, we're shortly running out of creative inventory space) 2011-08-15 16:57:57 +03:00
Perttu Ahola
e57754868f Hopefully fixed msvc "'sqrt' : ambiguous call to overloaded function" 2011-08-15 15:11:00 +03:00
Perttu Ahola
0c7e7f4998 Non-vertex-alpha texture material for lava 2011-08-15 12:08:41 +03:00
Giuseppe Bilotta
136657bcc1 Get rid of makepackage_binary.sh
It's outdated, and it would be better to use cmake's packaging
capabilities instead, for better cross-platformness.
2011-08-15 11:07:30 +02:00
Giuseppe Bilotta
dc16820e02 Cleanup root
These scripts should not be in the root but in util/ and in fact
they are, so let's get rid of these.
2011-08-15 11:05:05 +02:00
Perttu Ahola
4b85608e30 modified mapgen to generate less lava 2011-08-15 11:56:16 +03:00
Perttu Ahola
8ab77f4153 Added #define WATER_ALPHA in content_mapnode.cpp 2011-08-15 11:51:33 +03:00
Perttu Ahola
472585a7e8 tuned lava/universal damage code 2011-08-15 11:49:39 +03:00
Perttu Ahola
8f42a8be0c lava! 2011-08-15 02:04:56 +03:00
Perttu Ahola
c4b707bca2 Windows.h -> windows.h for cross-mingw build 2011-08-14 21:26:07 +03:00
Perttu Ahola
9e35fe8c37 Merge remote-tracking branch 'speedprog/fixedNotFindingData' 2011-08-13 14:05:01 +03:00
Giuseppe Bilotta
385904d75a Let Settings accept a const char* directly 2011-08-13 07:33:43 +02:00
Giuseppe Bilotta
b1e0b7728b Fix keycode_to_keyname return value 2011-08-13 07:31:46 +02:00
Giuseppe Bilotta
eb255e6870 Clean up key names handling
Constify keycode and move the static array of localizable names from the
guiKeyChangeMenu header to the implementation file, changing its name.
2011-08-12 23:42:00 +02:00
Giuseppe Bilotta
72e4c8f523 Fix use of && instead of & 2011-08-12 23:34:12 +02:00
Perttu Ahola
835d2e4b5f Removed assert if creating texture atlas image fails; cancel creating image instead. 2011-08-12 17:17:47 +03:00
Constantin Wenger
94b42a79d7 fixed not finding data dir if installed 2011-08-12 14:26:37 +02:00
Perttu Ahola
e40da2341c Fixed/extended/modified ban stuff to be good for inclusion 2011-08-12 13:11:27 +03:00
Perttu Ahola
7aa72c56b6 Merge remote-tracking branch 'speedprog/banByIp' 2011-08-12 11:55:51 +03:00
Constantin Wenger
5784c14ab7 added ipban support
commands:
/#ipban <nick>
/#ipunban <ip>
2011-08-12 03:37:18 +02:00
Perttu Ahola
3028bbb95b Updated .gitignore to ignore vim swap files 2011-08-12 00:33:24 +03:00
Giuseppe Bilotta
dfdc817db3 Typo fix 2011-08-11 19:45:44 +02:00
Giuseppe Bilotta
f4856a33c9 .gitattributes
Marking *.cpp files as C++ files makes for nicer diffs when using
--color-words or similar options.
2011-08-11 17:57:40 +02:00
Giuseppe Bilotta
371af9c241 Notify other players of wielded item change 2011-08-11 15:22:36 +02:00
Giuseppe Bilotta
88a9bae160 constify inventory item serialization 2011-08-11 15:22:36 +02:00
Giuseppe Bilotta
ecd5c5f920 Clients inform server on wielded item
This is done with the new TOSERVER_PLAYERITEM message, that informs the
server on the index of the wielded item.
2011-08-11 15:22:36 +02:00
Giuseppe Bilotta
91d1186cbb Keep track of player item 2011-08-11 15:22:36 +02:00
Giuseppe Bilotta
467b3cf4c1 Some inventory const-ification 2011-08-11 15:22:35 +02:00
Giuseppe Bilotta
c007d8219e Server should use the same eye position as the client 2011-08-11 15:22:35 +02:00
Giuseppe Bilotta
b318e82356 Refactor player's eye position coding
Collect the player's eye position coding in a Player method, and
use it in client to pass the eye position information to the game.
2011-08-11 15:22:35 +02:00
Giuseppe Bilotta
98fa00db12 Introduce Player::getLightPosition
This is currently only used in the lighting update for remote
players in client.
2011-08-11 15:22:35 +02:00
Perttu Ahola
69fca4f3cb Merged some FreeBSD fixes 2011-08-11 12:32:36 +03:00
q66
f6ed45fc20 Proper placement of binary files. 2011-08-11 11:19:33 +02:00
q66
e81ff1e833 Gettext fix for *BSD - require special linkage as glibc is not used 2011-08-11 11:19:05 +02:00
q66
43b6ca0d14 Prevent threadid_t from losing precision when casted on 64bit systems 2011-08-11 10:52:27 +02:00
Giuseppe Bilotta
34492ce480 Respect base virtual functions' signatures 2011-08-08 16:15:53 +02:00
Giuseppe Bilotta
163c38e175 Always return from non-void functions
This quiets a warning in Clang.
2011-08-08 16:13:48 +02:00
Giuseppe Bilotta
11be390110 Keys should be s32, not u32
At least two reasons for this:
* activeKey is treated as signed (check for sign, assign -1, etc)
* the ID retrieved from Irrlicht's events are signed
2011-08-08 16:12:15 +02:00
Giuseppe Bilotta
ea26a9f543 Remove spurious assignment 2011-08-08 16:11:37 +02:00
Giuseppe Bilotta
f9e1b0cd97 InventoryAction is a struct, not a class 2011-08-08 15:38:20 +02:00
Giuseppe Bilotta
805564dcf2 Clang doesn't like -Wno-unused-but-set-variable
The release versions of CMake don't yet properly support flag checking
in Clang, so we need to exclude it explicitly for the time being.
2011-08-11 10:08:58 +02:00
Giuseppe Bilotta
76fb792544 Project uses C++, so use CHECK_CXX_COMPILER_FLAG
Although this doesn't change much for our specific case, it can make a
difference for some flags, so use the appropriate macro.
2011-08-11 10:06:48 +02:00
Dmitry Marakasov
ff35014eff Fix data paths for FreeBSD 2011-08-02 02:50:16 +04:00
Dmitry Marakasov
de868d24c1 Fix "integer constant is too large for 'long' type" error 2011-08-02 02:49:15 +04:00
Dmitry Marakasov
318a730c45 Check whether -Wno-unused-but-set-variable is supported before using
it. It seems to only be available on recent (>=4.6) versions of gcc.
2011-08-01 22:17:32 +04:00
Perttu Ahola
9017c51e7f the zlib error print function now prints to dstream (debug.txt) 2011-08-08 12:11:41 +03:00
Perttu Ahola
bdb66aced7 removed broken and old tags and re-added 0.2.20110731_3 2011-08-05 11:54:54 +03:00
Perttu Ahola
ab83444cc3 Added tag 0.2.20110731_3 for changeset a519d6832511 2011-08-05 11:52:58 +03:00
Perttu Ahola
64a6da3e45 merged delta and c55 2011-08-05 11:22:13 +03:00
Giuseppe Bilotta
dd9909a574 minetestmapper can be run from any directory
If it doesn't find colors.txt locally, it looks for the one in the
directory of the script itself.
2011-08-05 08:45:15 +02:00
Giuseppe Bilotta
59c58f230e Some obvious errors in the new fluid flow management 2011-08-05 08:45:15 +02:00
Giuseppe Bilotta
f79069f5b3 MapNode is a struct, not a class 2011-08-05 08:45:15 +02:00
Giuseppe Bilotta
f5e0ba266e Some more Italian translations 2011-08-05 08:45:15 +02:00
Constantin Wenger
7361f29527 fixed some error :/ 2011-08-05 08:45:15 +02:00
Constantin Wenger
1d009a37df changed on string in german translation to fit to gui 2011-08-05 08:45:15 +02:00
Constantin Wenger
0fb208e63c updated po update script to detect wgettext and N_ 2011-08-05 08:45:15 +02:00
Constantin Wenger
dade01be29 update op PO files 2011-08-05 08:45:15 +02:00
Constantin Wenger
45057667f1 update to german translation 2011-08-05 08:45:15 +02:00
Constantin Wenger
4ab4e33450 marked strings as translation
now translated if set to a button
2011-08-05 08:45:15 +02:00
Constantin Wenger
0cfca69b42 fixed displaying special chars in the keychange menu 2011-08-05 08:45:15 +02:00
Constantin Wenger
1278a57afe added danish translation made by Frederik Helth 2011-08-05 08:45:15 +02:00
Nils Dagsson Moskopp
071c0b5536 * Welcome to OMSK. 2011-08-05 08:45:15 +02:00
Nils Dagsson Moskopp
735fa8b652 * README updated 2011-08-03 19:01:55 +02:00
Perttu Ahola
0b37f98e16 * fix for broken water 2011-08-03 19:00:25 +02:00
Perttu Ahola
5f8809e425 Fixed farmesh to such that it was a long time ago. 2011-08-03 13:03:30 +03:00
Nils Dagsson Moskopp
f143e269f4 Merge pull request #48 from Oblomov/master
Minor code cleanups (always in the gettext area, but no functional changs)
2011-08-02 01:49:31 -07:00
Giuseppe Bilotta
1d1aec9631 Use wgettext 2011-08-02 10:11:40 +02:00
Giuseppe Bilotta
817180bd55 Introduce wgettext
All usages of gettext() are converted to wchars, so let's factor this
into a single inline.
2011-08-02 10:11:40 +02:00
Giuseppe Bilotta
60bd878f0a Get rid of unused variables 2011-08-02 10:11:39 +02:00
Nils Dagsson Moskopp
bbd8e645a2 * README updated 2011-08-01 21:18:57 +02:00
Perttu Ahola
97d659c9fd added TODO in main.cpp 2011-08-01 19:21:43 +03:00
Nils Dagsson Moskopp
7b8227039f * papyrus texture now darker and edgier 2011-08-01 16:49:42 +02:00
Nils Dagsson Moskopp
363487c97b * less clumsy ladder texture, based on rails 2011-08-01 15:47:02 +02:00
Nils Dagsson Moskopp
f6bc662194 Merge pull request #47 from MarkTraceur/master
More better ladders
2011-08-01 05:59:40 -07:00
Mark Holmquist
7bd9e53ae6 Changing CONTENT_LADDER to be an extended block 2011-08-01 09:22:56 +02:00
Mark Holmquist
267744a568 Fixing ladders again 2011-08-01 09:22:44 +02:00
Mark Holmquist
8e67f4c4e6 Fixed a few problems in the ladder update, and changed the speed to account for gravity 2011-08-01 09:22:36 +02:00
Mark Holmquist
1c59cff832 Ladders implemented! 2011-08-01 09:22:36 +02:00
Mark Holmquist
bc2819cab2 Added ladders--they don't have any use yet, though 2011-08-01 09:22:36 +02:00
Nils Dagsson Moskopp
7ece67727d Merge remote-tracking branch 'origin/upstream' 2011-07-31 20:04:04 +02:00
Perttu Ahola
303351de6d Added tag 0.2.20110731_3 for changeset b277d01700f6 2011-07-31 15:55:00 +03:00
Nils Dagsson Moskopp
831003156c Merge pull request #44 from SpeedProg/master
last fix was shit, so a fix for the fix -_-
2011-07-31 05:35:27 -07:00
Constantin Wenger
54de4afd75 last fix was shit but this one works (tested) 2011-07-31 14:28:07 +02:00
Nils Dagsson Moskopp
c01c487c62 Merge branch 'master' of github.com:erlehmann/minetest-delta 2011-07-30 23:08:52 +02:00
Nils Dagsson Moskopp
2f6e931921 Merge pull request #41 from SpeedProg/master
fixe gettext I hope
2011-07-30 14:08:18 -07:00
Constantin Wenger
50dc2d8112 fixe for msvc broke linux 2011-07-30 23:05:40 +02:00
Nils Dagsson Moskopp
f4d7530587 Merge branch 'master' of github.com:erlehmann/minetest-delta 2011-07-30 22:33:26 +02:00
Nils Dagsson Moskopp
185c0bd587 Merge pull request #40 from SpeedProg/master
translated some word to german
2011-07-30 13:33:08 -07:00
Constantin Wenger
3c0090c0df german translation update, translated some of the new strings 2011-07-30 22:28:18 +02:00
Nils Dagsson Moskopp
6199252cda Merge pull request #39 from SpeedProg/master
fixes for gettext to workaround some bad behaviour of Irrlicht
2011-07-30 13:28:14 -07:00
Constantin Wenger
c08720bfba this fixes problem with msvc++ and should work on other systems and so on anyway. 2011-07-30 22:08:16 +02:00
Constantin Wenger
4882bda667 changed one forgotten en_US.UTF-8 to C 2011-07-30 22:08:16 +02:00
Constantin Wenger
a817419fe4 fixed redefinitivon of gettext.h is included more than once 2011-07-30 22:08:16 +02:00
Constantin Wenger
37bf9a666a set some more text to gettext and updated po files 2011-07-30 22:08:16 +02:00
Constantin Wenger
cd6d204a9d changed some strings of the german translation to fit in the areas 2011-07-30 22:08:16 +02:00
Constantin Wenger
9baae3a701 set locales to C because en_US not installed on some systems, only UTF-8 version and en_US.UTF-8 does not work. 2011-07-30 22:08:16 +02:00
Constantin Wenger
92f504f98d fixed displaying "umlauts" (deutsch umlaute) and hopefully other non ASCII chars, too 2011-07-30 22:03:25 +02:00
Nils Dagsson Moskopp
75816150ec * honor environment variables, use utf-8 2011-07-30 21:17:04 +02:00
Nils Dagsson Moskopp
4681392bac * PEP 8 compliance 2011-07-30 21:05:33 +02:00
Nils Dagsson Moskopp
17830c5894 - removed old minetestmapper 2011-07-30 20:37:53 +02:00
Wolfgang Fellger
edbcf7c039 * support for content types extension in minetestmapper 2011-07-30 20:35:55 +02:00
Nils Dagsson Moskopp
96bee29e35 Merge branch 'upstream/master' 2011-07-30 19:47:55 +02:00
Nils Dagsson Moskopp
82ea534997 * README updated 2011-07-30 19:30:43 +02:00
Nils Dagsson Moskopp
a4fe2a7c75 - compiling with translations works again 2011-07-30 19:28:44 +02:00
Nils Dagsson Moskopp
4ef9c7675a Merge remote-tracking branch 'origin/upstream' 2011-07-30 18:55:43 +02:00
Nils Dagsson Moskopp
f69123050b Merge branch 'master' of github.com:erlehmann/minetest-delta 2011-07-24 20:04:20 +02:00
Nils Dagsson Moskopp
a5a9c9f799 Merge pull request #36 from Oblomov/master
Some more gettext stuff
2011-07-24 11:00:38 -07:00
Giuseppe Bilotta
cce210f676 Locale dir should be parallel to global data dir 2011-07-24 19:23:03 +02:00
Giuseppe Bilotta
a8e493122e Read config from gettext.h
Otherwise the USE_GETTEXT define might not be visible.
2011-07-24 19:13:34 +02:00
Giuseppe Bilotta
e00d7ee5be Italian translations 2011-07-24 19:06:17 +02:00
Nils Dagsson Moskopp
ad6b087353 + 24x24 rendering of SVG minetest icon, polished manually to look crisp 2011-07-24 18:51:44 +02:00
Giuseppe Bilotta
3715e39e5d Actually make USE_GETTEXT available in the source 2011-07-24 18:34:10 +02:00
Giuseppe Bilotta
423109e64c Two more instances of unhardcoding the project name 2011-07-24 18:12:11 +02:00
Nils Dagsson Moskopp
71b7d92597 Merge pull request #35 from Oblomov/master
some more gettext fixes
2011-07-24 09:01:10 -07:00
Giuseppe Bilotta
e034f8a2a3 Sanitize GETTEXT usage macros
Now the user-level option is called ENABLE_GETTEXT, and USE_GETTEXT is
only set to true if gettext was enabled and found. This simplifies all
check to USE_GETTEXT only rather than the double checks for it being
enabled and found.
2011-07-24 16:52:59 +02:00
Giuseppe Bilotta
47381bde3b Bring po update out of cmake again
This solves two issues at once:
* CMake would delete po files during ‘make clean’ because it thought
  they were autogenerated and not just managed
* the only gettext tools readily available in Windows are so old they
  don't support options like --package-name

The change also moves minetest.pot down one level, so we don't need to
special case ‘en’ anymore.

The downside is of course that you need some sane POSIX shell to update
the po files.
2011-07-24 16:52:59 +02:00
Giuseppe Bilotta
c578efb32b Refactor gettext init
Put the gettext init code in a macro and define it appropriately
depending on whether gettext is actually available or not.
2011-07-24 16:52:59 +02:00
Giuseppe Bilotta
5aa2679be7 Do not package en translation, since we don't build it 2011-07-24 09:19:25 +02:00
Giuseppe Bilotta
d4e7faca21 Gettext domain should match the project name
This partially reverts 023cc0d37776976b4b192b7363f73a5d2debdef6, goes
back to using PROJECT_NAME for the filename and also uses PROJECT_NAME
as text domain in the source code.
2011-07-24 09:19:25 +02:00
Giuseppe Bilotta
4ffba76bb3 Place project name and gettext use in config 2011-07-24 09:18:29 +02:00
Nils Dagsson Moskopp
f4a08f7fb3 Merge pull request #34 from SpeedProg/master
Changes to make gettext enabled if it is found
2011-07-23 19:01:51 -07:00
Constantin Wenger
f6d9bcc9bb updated cmakerules to autodetect if gettext can be used
fixed error if gettext is disabled
2011-07-23 22:36:11 +02:00
Nils Dagsson Moskopp
a7daf8e652 * README updated 2011-07-22 21:56:00 +02:00
Constantin Wenger
4771b4951d change in readme of a lib 2011-07-22 20:55:00 +02:00
Constantin Wenger
383698186f Merge remote-tracking branch 'upstream/master' 2011-07-22 20:53:29 +02:00
Constantin Wenger
fb4c3ab4fb fixed some problems with filenames of the translations 2011-07-22 20:40:47 +02:00
Constantin Wenger
96ad0c8638 updated some parts which don't really make a problem but are better this way 2011-07-22 20:40:46 +02:00
Nils Dagsson Moskopp
7985d746f9 Merge branch 'upstream/master' 2011-07-22 20:16:58 +02:00
Nils Dagsson Moskopp
a45f287ae1 Merge pull request #32 from Oblomov/master
Gettext + misc fixes
2011-07-22 10:30:55 -07:00
Giuseppe Bilotta
7d9dd352cf Declare USE_GETTEXT option 2011-07-22 14:42:04 +02:00
Constantin Wenger
a09660dc85 fixed problem with displaying special chars 2011-07-22 13:27:30 +02:00
Giuseppe Bilotta
d78e5e7329 updatepo cmake rule
Get rid of the system-specific updatelocales.sh and introduce an
updatepo cmake rule. po files are also updated before creating the mo
files, and we now keep the .pot file (in the po/en directory). To
stabilize the po file creation, file contents are sorted by source
filename.

Update po files in the process.
2011-07-22 12:40:29 +02:00
Giuseppe Bilotta
e61b2f99c1 Static naming of po file
The po file should not be named c55 if we're in ∆. But since it is not
exposed at installation time, we don't actually need its name to be
based on the project name at all, so just call it minetest.po
2011-07-22 09:58:02 +02:00
Giuseppe Bilotta
d386f02893 Refactor mo creation/installation 2011-07-22 09:36:17 +02:00
Giuseppe Bilotta
5a3218e535 Use project name for mo files 2011-07-22 08:33:08 +02:00
Giuseppe Bilotta
02653573d2 Merge remote-tracking branch 'erlehmann/master'
Conflicts (from the introduction of fr translations):
	src/CMakeLists.txt
2011-07-22 07:48:22 +02:00
Constantin Wenger
5c66664aef changed some lines to fit the 80chars limit 2011-07-22 07:25:40 +02:00
Nils Dagsson Moskopp
21b7a272c4 * nicer firefly texture 2011-07-21 20:13:31 +02:00
Nils Dagsson Moskopp
17a47b3335 + unknown block is sick 2011-07-21 17:36:23 +02:00
Nils Dagsson Moskopp
89bbff18e5 Merge pull request #29 from cisoun/master
Add french translation.
2011-07-21 07:33:34 -07:00
Constantin Wenger
fc95d00b2f fixed not finding dll for gettext in MSVC 2011-07-21 16:21:01 +02:00
Cyriaque Skrapits
3f4f844eeb Added missing .po fil.e 2011-07-21 16:14:18 +02:00
Cyriaque Skrapits
6875ead7cf Added french translation. 2011-07-21 16:09:57 +02:00
Nils Dagsson Moskopp
5388e8b124 * different collision box for fireflies so they now hover above the ground 2011-07-21 15:40:00 +02:00
Giuseppe Bilotta
02b14090c2 Reorganize cmake gettext message output to ease debugging 2011-07-21 15:16:59 +02:00
Giuseppe Bilotta
56a744599f Restore "Leave address blank" position 2011-07-21 15:12:58 +02:00
Giuseppe Bilotta
9fa4b72a47 Find correct library for MSVC vs MingW in Winows 2011-07-21 14:50:15 +02:00
Giuseppe Bilotta
3e78b29cae Only install locale files if using gettext 2011-07-21 14:46:23 +02:00
Giuseppe Bilotta
d63c160bd6 Uppercase DEFINED or cmake 2.8.4 complains 2011-07-21 13:59:50 +02:00
Constantin Wenger
2a6c0fc17f updated some path because the dlls are mostly under bin not lib
added explanation why libintl must not belinked under some oses
2011-07-21 13:24:37 +02:00
Giuseppe Bilotta
1340da7b54 Refactor and clean up gettext management 2011-07-21 12:33:29 +02:00
Giuseppe Bilotta
89af509d10 Make gettext optional 2011-07-21 09:03:41 +02:00
Weedy
89b8b792c1 Tweak makefiles to add -delta suffix. 2011-07-21 09:03:20 +02:00
Weedy
a19491dbd2 Fix win32 MSVC compile. (screw gettext) 2011-07-21 09:03:17 +02:00
Nils Dagsson Moskopp
f5c6e3973c Merge pull request #27 from Oblomov/master
* regression fix for windows build.
2011-07-20 14:29:01 -07:00
Giuseppe Bilotta
e7beaac6f5 Move package search out of conditional
This unbreaks the Windows build which would otherwise have problems at
the jthread level.
2011-07-20 23:09:28 +02:00
Nils Dagsson Moskopp
84684e53ed + fireflies 2011-07-20 22:05:57 +02:00
Nils Dagsson Moskopp
4c0e36a5e9 * README updated 2011-07-20 19:14:40 +02:00
Nils Dagsson Moskopp
8ed83250d7 Merge branch 'master' of github.com:erlehmann/minetest-delta 2011-07-20 18:56:32 +02:00
Nils Dagsson Moskopp
360a8918dd Merge pull request #24 from SpeedProg/master
gettext paths problem
2011-07-20 09:56:23 -07:00
Constantin Wenger
4d43a67419 fixed problem with wront paths in gettext 2011-07-20 18:49:18 +02:00
Nils Dagsson Moskopp
33e80dae7f Merge branch 'master' of github.com:erlehmann/minetest-delta 2011-07-20 18:29:48 +02:00
Nils Dagsson Moskopp
4f53619a15 Merge pull request #23 from Oblomov/master
Some misc usability patches
2011-07-20 09:29:07 -07:00
Giuseppe Bilotta
3fb5b7a3bd Set the window caption for the initial window too 2011-07-20 17:59:48 +02:00
Giuseppe Bilotta
bcd3e1af2f Check the data path before usage
When not running in place, check if the assumed data path in
../share/APPNAME exists. If it doesn't exist, fall back to ../data
instead. This allows the program to run successfully from the checkout
directory even without the run-in-place flag active.
2011-07-20 17:59:48 +02:00
Giuseppe Bilotta
cd45ae3d0f Use system sqlite3/jthread libs if available 2011-07-20 17:59:48 +02:00
Nils Dagsson Moskopp
e5dc58e710 Merge branch 'master' of github.com:erlehmann/minetest-delta 2011-07-20 17:56:49 +02:00
Nils Dagsson Moskopp
cef7bb0619 Merge pull request #22 from SpeedProg/master
added gettext support
2011-07-20 08:56:35 -07:00
Constantin Wenger
a006b828a6 updated german po file for minetest-delta (prior it was for minetest)
set +x on bashscript
2011-07-20 17:00:54 +02:00
Constantin Wenger
052bb24c7f added gettext support
german translation file
and bashscript to update translations
2011-07-20 16:51:19 +02:00
Nils Dagsson Moskopp
3c630c0d90 Merge branch 'upstream/master' 2011-07-20 14:20:07 +02:00
Nils Dagsson Moskopp
d0810b0156 * README updated (graphics licensing) 2011-07-20 02:45:15 +02:00
Nils Dagsson Moskopp
ffd3cdf519 * by popular request, fewer clouds 2011-07-20 02:44:51 +02:00
Nils Dagsson Moskopp
ac2e822ea1 * README updated 2011-07-19 23:35:12 +02:00
Nils Dagsson Moskopp
0cd2972d60 + minetest application icon 2011-07-19 23:32:01 +02:00
Nils Dagsson Moskopp
821ff68f54 * initialize liquid_kind properly so compiler does not bitch about it 2011-07-19 02:02:50 +02:00
Nils Dagsson Moskopp
e8eb4d233b + fake shading for the volumetric clouds 2011-07-19 01:43:30 +02:00
Nils Dagsson Moskopp
414d1ff9e2 + volumetric clouds (thanks teddydestodes) 2011-07-18 22:50:14 +02:00
Felix Krause
7d92ce061d final fixes to liquid flow, works now as intended 2011-07-18 02:38:57 +02:00
Felix Krause
a1e2a8bec6 fixes to liquid transformation 2011-07-18 02:38:48 +02:00
Felix Krause
f34a9b6a71 fixed refactoring issues // slowed down water flow a bit
* liquid flow no longer does random things when transformed
* if a flowi
ng liquid node doesn't have a solid block as neighbor, its spread distan
ce is shortened by 1
2011-07-18 02:38:32 +02:00
Felix Krause
def870953a * refactored liquid transformation code (has some flaws)
Completely rewrote the liquid transformation. The algorithm now exclusively modifies the current node in one iteration. Another change is that MapNode.param2 now stores a bit that tells other nodes if a flowing liquid node flows downwards. This is accomplished by two masks on param2 for the "flow down" bit and the "liquid level" bits.

This will be the base of future improvements to the liquid flow. However, in the current state flowing liquid does not always disappear when cut off its source. Be aware that this branch is work in progress.
2011-07-18 02:37:19 +02:00
Nils Dagsson Moskopp
f2c6330505 * Омская птица 2011-07-18 02:09:55 +02:00
Nils Dagsson Moskopp
077ffa5231 * changed GUI to indicate Minetest Δ 2011-07-17 22:33:51 +02:00
Nils Dagsson Moskopp
0802edf582 * README updated 2011-07-16 17:14:58 +02:00
Nils Dagsson Moskopp
8bfa56648d Merge remote-tracking branch 'origin/upstream' 2011-07-16 16:52:45 +02:00
Nils Dagsson Moskopp
4d20f1283f * fix automerge regression 2011-07-15 20:16:02 +02:00
Nils Dagsson Moskopp
0a38e542c1 * regression fix, clay occurs again now 2011-07-15 06:37:47 +02:00
Nils Dagsson Moskopp
96f551a287 * possibly nicer trees 2011-07-15 02:23:41 +02:00
Nils Dagsson Moskopp
af05e4b2de Merge branch 'upstream/master'
Conflicts:
	data/oerkki1.png
	src/client.cpp
2011-07-14 22:43:28 +02:00
Nils Dagsson Moskopp
4415d95c50 * possibly improved water flow, by flyx86
- When flowing liquid starts to flow down, it stops contributing to its neighboring nodes' liquid level (possibly transforming it back to air)
- Flowing liquid turns into a source if there are at least 2 adjacent liquid source nodes
- If a new liquid flow reaches existing flowing liquid, the existing liquid is now updated properly.
2011-07-14 16:17:53 +02:00
Nils Dagsson Moskopp
1cdf210e4f * possible fix for large cubic holes in map 2011-07-13 23:12:18 +02:00
Nils Dagsson Moskopp
b0ad5ce8e2 * slightly different values for 3d perlin noise 2011-07-13 23:10:41 +02:00
Nils Dagsson Moskopp
b2447393e4 * regression fix, papyrus should appear again now 2011-07-13 16:21:20 +02:00
Nils Dagsson Moskopp
63ce6eee5c * README updated 2011-07-11 16:22:14 +02:00
Jiří Procházka
858b2d7439 + farmesh config options 2011-07-11 15:01:43 +02:00
Nils Dagsson Moskopp
6103e59c19 * amended upstream branch notes 2011-07-09 18:22:39 +02:00
Nils Dagsson Moskopp
a106c0dbdc + notes regarding upstream conversion from mercurial using hg-fast-export 2011-07-09 18:14:05 +02:00
Nils Dagsson Moskopp
f37a3a84fa Merge pull request #13 from Bahamada/upstream_merge
Upstream merge
2011-06-27 06:56:26 -07:00
Sebastian Rühl
13cf5425db backported cactus, papyrus and clay 2011-06-26 13:47:21 +02:00
Sebastian Rühl
fb6ac9a1a6 small fix 2011-06-26 12:52:03 +02:00
Sebastian Rühl
033ae0dcae Merge branch 'master' of https://github.com/erlehmann/minetest-delta.git into upstream_merge
Conflicts:
	.gitignore
	CMakeLists.txt
	data/heart.png
	src/CMakeLists.txt
	src/game.cpp
	src/guiMainMenu.cpp
	src/inventory.cpp
	src/map.cpp
	src/mapblock.cpp
	src/mapnode.cpp
	src/mapnode.h
	src/materials.cpp
	src/server.cpp

Signed-off-by: Sebastian Rühl <bahamada_basti@yahoo.de>
2011-06-26 12:24:32 +02:00
Nils Dagsson Moskopp
e261cc9e8f + rail block bounding box 2011-06-08 05:27:55 +02:00
Nils Dagsson Moskopp
2ec160454a * README updated 2011-06-07 19:41:03 +02:00
Nils Dagsson Moskopp
51d308c666 + rail 2011-06-07 19:24:30 +02:00
Nils Dagsson Moskopp
b3c439fb16 * README updated 2011-06-03 13:39:07 +02:00
Nils Dagsson Moskopp
15ae9ca8a2 + bookshelf in minetestmapper, same color as wood 2011-06-03 13:31:42 +02:00
Nils Dagsson Moskopp
c3cd89705d * point out setInventoryTextureCube() is broken with a FIXME 2011-06-03 13:13:31 +02:00
Nils Dagsson Moskopp
1bd25925cb + paper, book, bookshelf 2011-06-03 13:12:56 +02:00
Nils Dagsson Moskopp
17e17ceb59 * README updated 2011-06-03 00:57:39 +02:00
Nils Dagsson Moskopp
8da4a4276f + papyrus in minetestmapper 2011-06-03 00:56:27 +02:00
Nils Dagsson Moskopp
3bb1cfdf36 + papyrus 2011-06-03 00:55:28 +02:00
Nils Dagsson Moskopp
e627f023a0 * made cactus color darker 2011-06-03 00:52:46 +02:00
Nils Dagsson Moskopp
bd5cdbf1a4 + check if sectors/sectors2 directories exist before attempting to read them 2011-06-02 17:21:58 +02:00
Nils Dagsson Moskopp
34e57da1ca * encoding fix 2011-06-02 17:19:50 +02:00
Nils Dagsson Moskopp
de8996ac3b * tabs to spaces 2011-06-02 17:13:05 +02:00
Nils Dagsson Moskopp
33264d0fb6 * ignore minetestmapper output 2011-06-02 16:54:05 +02:00
Nils Dagsson Moskopp
cc65bda2cc + sandstone color value now in minetestmapper 2011-06-02 16:52:25 +02:00
Nils Dagsson Moskopp
4b2b65df9f + minetestmapper2, colors modified for Minetest Δ 2011-06-02 16:17:50 +02:00
Nils Dagsson Moskopp
4800f1df97 * README updated 2011-06-02 03:03:47 +02:00
Nils Dagsson Moskopp
9850df35ae Merge pull request #1 from TeddyDesTodes/master
+ submenu for key assignment, fast_move and free_move can now be toggled
2011-06-01 17:20:37 -07:00
teddydestodes
7dfa3442fe Merge remote-tracking branch 'upstream/master' 2011-06-01 19:47:10 +02:00
teddydestodes
58bc6f3a18 added new submenu for key assignment
configwriting/saving isn't complete and will break your config if you use fancy keys
2011-06-01 19:44:07 +02:00
Nils Dagsson Moskopp
a75c31143a * README updated 2011-06-01 17:19:28 +02:00
Nils Dagsson Moskopp
15b375827e Merge pull request #5 from bucket-T/master
MacOSX build support
2011-06-01 08:08:41 -07:00
Nils Dagsson Moskopp
60578e0950 * README updated 2011-06-01 16:46:49 +02:00
teddydestodes
09d7654f46 Merge remote-tracking branch 'bucket-t/master' 2011-06-01 14:43:27 +02:00
MrLoom
28234f6e54 MacOSX build support 2011-06-01 14:13:22 +02:00
teddydestodes
63fe487d93 Merge remote-tracking branch 'upstream/master' 2011-06-01 14:11:52 +02:00
Nils Dagsson Moskopp
d2b2c7c09e * improved fence dimensions (cuboid side lengths now multiples of 2, textures should fit better) 2011-06-01 20:06:16 +08:00
Nils Dagsson Moskopp
c930a92b72 * clay is rarer now 2011-06-01 08:09:28 +02:00
Nils Dagsson Moskopp
cffd40c5d6 + clay and associated items 2011-06-01 04:57:46 +02:00
Nils Dagsson Moskopp
fb78854e9b + brick 2011-05-31 22:04:09 +02:00
Nils Dagsson Moskopp
461f53945d * menulogo now shows minetest delta 2011-05-31 20:52:20 +02:00
Nils Dagsson Moskopp
6c3ca42e0e + fence inventory icon 2011-05-31 03:54:39 +02:00
Nils Dagsson Moskopp
0f4c83eb98 * improved fence dimensions (cuboid side lengths now multiples of 2, textures should fit better) 2011-05-31 02:56:23 +02:00
Nils Dagsson Moskopp
880aa870a0 + cactii 2011-05-30 14:42:08 +02:00
Nils Dagsson Moskopp
cf136f1935 + .gitignore 2011-05-30 01:21:37 +08:00
teddydestodes
ca26de72c9 fast_move and free_move can now be toggled 2011-05-29 19:17:42 +02:00
Nils Dagsson Moskopp
af574e58fe + .gitignore 2011-05-29 19:08:59 +02:00
Nils Dagsson Moskopp
ed81aa8aae + README in main directory 2011-05-29 19:03:59 +02:00
Nils Dagsson Moskopp
9ab64658ba * better heart icon 2011-05-29 18:49:02 +02:00
Nils Dagsson Moskopp
3504a66eda * better glass graphics 2011-05-29 18:48:39 +02:00
Nils Dagsson Moskopp
3f0ac7adce * better rat graphics 2011-05-29 18:48:21 +02:00
Nils Dagsson Moskopp
0076339914 * enemies are now omsk birds 2011-05-29 18:47:40 +02:00
Nils Dagsson Moskopp
2176f4d697 * better player graphics 2011-05-29 18:45:50 +02:00
Nils Dagsson Moskopp
843ffba567 + sandstone 2011-05-29 18:44:42 +02:00
95 changed files with 12337 additions and 4735 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
*.cpp diff=cpp
*.h diff=cpp

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@ src/jthread/CMakeFiles/*
src/jthread/Makefile
src/jthread/cmake_config.h
src/jthread/cmake_install.cmake
.*.swp
minetest.conf
bin/
CMakeCache.txt

29
.hgtags
View File

@@ -1,28 +1 @@
c37bcfd89dd627fdb131ae3f77fcaab02721bf76 working
69547bd6be420eb40f55524fd2131cbbaa2e0e29 110107195706-exp
e3c3c8e27bbc8c9b61710517a78944deb1c61696 110211211322
23880c78e40c50ad54fcd8844510f7a423b37f2a 110212200513
20c49c98c92a62df457b773c562df41d4167492b 110214175330
10be2b71f965585af90af96903e83b4ddff52bf9 20110424_0
9b05d4bfee9312aef4182fa6f63b4237368cec34 0.2.20110529_0
6fa0a8b40406aa567f8fa84b5e2045a7e3762c1d 0.2.20110529_1
cf6dd618ef0b7514c81ae87749733b5a328fc763 0.2.20110529_2
96efc17b4cd92aacbe947b520a6ba91727d42f03 0.2.20110602_0
0000000000000000000000000000000000000000 0.2.20110602_0
6f17cd3f6c5481e6abc906fc441980c764632cbc 0.2.20110602_0
dd08a9b5cb84d55b7576bb3fde3068dd263bc3bc 0.2.20110618_0_dev
25aa2021937f7a8b36808390983cebbc16ae6965 0.2.20110704_0
25aa2021937f7a8b36808390983cebbc16ae6965 0.2.20110704_0
0000000000000000000000000000000000000000 0.2.20110704_0
0000000000000000000000000000000000000000 0.2.20110704_0
65263ec55caf526e3f3e0bdc6657ce42daee46bc 0.2.20110704_0
06c62112b503e746d5d8cc40f951974447d590b7 0.2.20110731_0
705a7e95b8710c8cada5524d8c7bb658f4b710d9 0.2.20110731_1
4a6cf9491306988b24c79438ee6398885c432fce 0.2.20110731_2
4a6cf9491306988b24c79438ee6398885c432fce 0.2.20110731_2
0000000000000000000000000000000000000000 0.2.20110731_2
0000000000000000000000000000000000000000 0.2.20110731_2
8ad16fbce9a4da45b2552ad8b400a5a127722acc 0.2.20110731_2
c87e28deaabf4a776c261b3a09b6bf5ea3e04abf 0.2.20110731_3
c87e28deaabf4a776c261b3a09b6bf5ea3e04abf 0.2.20110731_3
0000000000000000000000000000000000000000 0.2.20110731_3
a519d683251105654d2a146ae7b91d3850b6504c 0.2.20110731_3

View File

@@ -9,7 +9,7 @@ project(minetest)
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)
set(VERSION_PATCH 20110731_3)
set(VERSION_PATCH 20110922_1)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
# Configuration options

View File

@@ -26,11 +26,11 @@ Map directory:
- Map is stored in a directory, which can be removed to generate a new map.
- There is a command-line option for it: --map-dir
- For a RUN_IN_PLACE build, it is located in:
../map
../world
- Otherwise something like this:
Windows: C:\Documents and Settings\user\Application Data\minetest\map
Linux: ~/.minetest/map
OS X: ~/Library/Application Support/minetest/map
Windows: C:\Documents and Settings\user\Application Data\minetest\world
Linux: ~/.minetest/world
OS X: ~/Library/Application Support/minetest/world
Configuration file:
-------------------
@@ -157,6 +157,8 @@ Compiling on Windows:
GETTEXT_MSGFMT DIR/gettext/bin/msgfmt
-----------------
- Hit "Configure"
- Hit "Configure" once again 8)
- If something is still coloured red, you have a problem.
- Hit "Generate"
If using MSVC:
- Open the generated minetest.sln

View File

@@ -16,21 +16,6 @@ FIND_PROGRAM(GETTEXT_MSGFMT
PATHS "${CUSTOM_GETTEXT_PATH}/bin"
DOC "path to msgfmt")
FIND_PROGRAM(GETTEXT_MSGMERGE
NAMES msgmerge
PATHS "${CUSTOM_GETTEXT_PATH}/bin"
DOC "path to msgmerge")
FIND_PROGRAM(GETTEXT_MSGEN
NAMES msgen
PATHS "${CUSTOM_GETTEXT_PATH}/bin"
DOC "path to msgen")
FIND_PROGRAM(GETTEXT_EXTRACT
NAMES xgettext
PATHS "${CUSTOM_GETTEXT_PATH}/bin"
DOC "path to xgettext")
# modern Linux, as well as Mac, seem to not need require special linking
# they do not because gettext is part of glibc
# TODO check the requirements on other BSDs and older Linux
@@ -56,7 +41,6 @@ IF (WIN32)
DOC "gettext *iconv*.lib")
ENDIF(WIN32)
IF(GETTEXT_INCLUDE_DIR AND GETTEXT_MSGFMT)
IF (WIN32)
# in the Win32 case check also for the extra linking requirements
@@ -64,6 +48,10 @@ IF(GETTEXT_INCLUDE_DIR AND GETTEXT_MSGFMT)
SET(GETTEXT_FOUND TRUE)
ENDIF()
ELSE(WIN32)
# *BSD variants require special linkage as they don't use glibc
IF(${CMAKE_SYSTEM_NAME} MATCHES "BSD")
SET(GETTEXT_LIBRARY "intl")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "BSD")
SET(GETTEXT_FOUND TRUE)
ENDIF(WIN32)
ENDIF()
@@ -71,10 +59,14 @@ ENDIF()
IF(GETTEXT_FOUND)
SET(GETTEXT_PO_PATH ${CMAKE_SOURCE_DIR}/po)
SET(GETTEXT_MO_BUILD_PATH ${CMAKE_BINARY_DIR}/locale/<locale>/LC_MESSAGES)
SET(GETTEXT_MO_DEST_PATH locale/<locale>/LC_MESSAGES)
SET(GETTEXT_MO_DEST_PATH ${DATADIR}/../locale/<locale>/LC_MESSAGES)
FILE(GLOB GETTEXT_AVAILABLE_LOCALES RELATIVE ${GETTEXT_PO_PATH} "${GETTEXT_PO_PATH}/*")
LIST(REMOVE_ITEM GETTEXT_AVAILABLE_LOCALES minetest.pot)
MACRO(SET_MO_PATHS _buildvar _destvar _locale)
STRING(REPLACE "<locale>" ${_locale} ${_buildvar} ${GETTEXT_MO_BUILD_PATH})
STRING(REPLACE "<locale>" ${_locale} ${_destvar} ${GETTEXT_MO_DEST_PATH})
ENDMACRO(SET_MO_PATHS)
ELSE()
SET(GETTEXT_INCLUDE_DIR "")
SET(GETTEXT_LIBRARY "")
ENDIF()

BIN
data/apple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

BIN
data/apple_iron.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

BIN
data/ladder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

BIN
data/lava.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

View File

@@ -3,6 +3,25 @@ Minetest-c55 changelog
This should contain all the major changes.
For minor stuff, refer to the commit log of the repository.
0.2.20110922_2:
- Move PLATFORM_LIBS around to make sqlite3 link with libdl on some distros
- sectors2sqlite.py and minetestmapper.py fixes
0.2.20110922_1:
- Make client report a newer version number to the server than 2011-07-31 does and make server disallow old clients
0.2.20110922:
- Map is saved in an SQLite database file (by Queatz)
- Ladders (MarkTraceur)
- Lava
- Apple trees (sfan5)
- Slightly better looking inventory with transparency
- /me chat command (Oblomov)
- Using chosen map seed possible through fixed_map_seed configuration option (kahrl)
- Fix the long-existed PeerNotFound loop bug
- Some translations and localization-related fixes
- Lots of small fixes
2011-07-31_3:
- Fixes a bug that made the server to deny non-empty passwords from players connecting the first time

View File

@@ -42,7 +42,7 @@ Initialization:
u8 channel = 0
# Control packet header
u8 type = TYPE_CONTROL = 0
u8 controltype = CONTROLTYPE_DISCO = 2
u8 controltype = CONTROLTYPE_DISCO = 3
- Here's a quick untested connect-disconnect done in PHP:
# host: ip of server (use gethostbyname(hostname) to get from a dns name)
@@ -61,7 +61,7 @@ function check_if_minetestserver_up($host, $port)
$peer_id = substr($buf, 9, 2);
# Disconnect
$buf = "\x4f\x45\x74\x03".$peer_id."\x00\x00\x02";
$buf = "\x4f\x45\x74\x03".$peer_id."\x00\x00\x03";
socket_sendto($socket, $buf, strlen($buf), 0, $host, $port);
socket_close($socket);

271
genmap.py
View File

@@ -1,271 +0,0 @@
#!/usr/bin/python2
# This is an example script that generates some valid map data.
import struct
import random
import os
import sys
import zlib
import array
from pnoise import pnoise
# Old directory format:
# world/sectors/XXXXZZZZ/YYYY
# XXXX,YYYY,ZZZZ = coordinates in hexadecimal
# fffe = -2
# ffff = -1
# 0000 = 0
# 0001 = 1
#
# New directory format:
# world/sectors2/XXX/ZZZ/YYYY
# XXX,YYYY,ZZZ = coordinates in hexadecimal
# fffe = -2
# ffff = -1
# 0000 = 0
# 0001 = 1
# ffe = -2
# fff = -1
# 000 = 0
# 001 = 1
#
# For more proper file format documentation, refer to mapformat.txt
# For node type documentation, refer to mapnode.h
# NodeMetadata documentation is not complete, refer to nodemeta.cpp
#
# Seed for generating terrain
SEED = 0
# 0=old, 1=new
SECTOR_DIR_FORMAT = 1
mapdir = "world"
def to4h(i):
s = "";
s += '{0:1x}'.format((i>>12) & 0x000f)
s += '{0:1x}'.format((i>>8) & 0x000f)
s += '{0:1x}'.format((i>>4) & 0x000f)
s += '{0:1x}'.format((i>>0) & 0x000f)
return s
def to3h(i):
s = "";
s += '{0:1x}'.format((i>>8) & 0x000f)
s += '{0:1x}'.format((i>>4) & 0x000f)
s += '{0:1x}'.format((i>>0) & 0x000f)
return s
def get_sector_dir(px, pz):
global SECTOR_DIR_FORMAT
if SECTOR_DIR_FORMAT == 0:
return "/sectors/"+to4h(px)+to4h(pz)
elif SECTOR_DIR_FORMAT == 1:
return "/sectors2/"+to3h(px)+"/"+to3h(pz)
else:
assert(0)
def getrand_air_stone():
i = random.randrange(0,2)
if i==0:
return 0
return 254
# 3-dimensional vector (position)
class v3:
def __init__(self, x=0, y=0, z=0):
self.X = x
self.Y = y
self.Z = z
class NodeMeta:
def __init__(self, type_id, data):
self.type_id = type_id
self.data = data
class StaticObject:
def __init__(self):
self.type_id = 0
self.data = ""
def ser_u16(i):
return chr((i>>8)&0xff) + chr((i>>0)&0xff)
def ser_u32(i):
return (chr((i>>24)&0xff) + chr((i>>16)&0xff)
+ chr((i>>8)&0xff) + chr((i>>0)&0xff))
# A 16x16x16 chunk of map
class MapBlock:
def __init__(self):
self.content = array.array('B')
self.param1 = array.array('B')
self.param2 = array.array('B')
for i in range(16*16*16):
# Initialize to air
self.content.append(254)
# Full light on sunlight, none when no sunlight
self.param1.append(15)
# No additional parameters
self.param2.append(0)
# key = v3 pos
# value = NodeMeta
self.nodemeta = {}
# key = v3 pos
# value = StaticObject
self.static_objects = {}
def set_content(self, v3, b):
self.content[v3.Z*16*16+v3.Y*16+v3.X] = b
def set_param1(self, v3, b):
self.param1[v3.Z*16*16+v3.Y*16+v3.X] = b
def set_param2(self, v3, b):
self.param2[v3.Z*16*16+v3.Y*16+v3.X] = b
# Get data for serialization. Returns a string.
def serialize_data(self):
s = ""
for i in range(16*16*16):
s += chr(self.content[i])
for i in range(16*16*16):
s += chr(self.param1[i])
for i in range(16*16*16):
s += chr(self.param2[i])
return s
def serialize_nodemeta(self):
s = ""
s += ser_u16(1)
s += ser_u16(len(self.nodemeta))
for pos, meta in self.nodemeta.items():
pos_i = pos.Z*16*16 + pos.Y*16 + pos.X
s += ser_u16(pos_i)
s += ser_u16(meta.type_id)
s += ser_u16(len(meta.data))
s += meta.data
return s
def serialize_staticobj(self):
s = ""
s += chr(0)
s += ser_u16(len(self.static_objects))
for pos, obj in self.static_objects.items():
pos_i = pos.Z*16*16 + pos.Y*16 + pos.X
s += ser_s32(pos.X*1000)
s += ser_s32(pos.Y*1000)
s += ser_s32(pos.Z*1000)
s += ser_u16(obj.type_id)
s += ser_u16(len(obj.data))
s += obj.data
return s
def writeblock(mapdir, px,py,pz, block):
sectordir = mapdir + get_sector_dir(px, pz);
try:
os.makedirs(sectordir)
except OSError:
pass
path = sectordir+"/"+to4h(py)
print("writing block file "+path)
f = open(sectordir+"/"+to4h(py), "wb")
if f == None:
return
# version
version = 17
f.write(struct.pack('B', version))
# flags
# 0x01=is_undg, 0x02=dn_diff, 0x04=lighting_expired
flags = 0 + 0x02 + 0x04
f.write(struct.pack('B', flags))
# data
c_obj = zlib.compressobj()
c_obj.compress(block.serialize_data())
f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number
f.write(c_obj.flush())
# node metadata
c_obj = zlib.compressobj()
c_obj.compress(block.serialize_nodemeta())
f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number
f.write(c_obj.flush())
# mapblockobject count
f.write(ser_u16(0))
# static objects
f.write(block.serialize_staticobj())
# timestamp
f.write(ser_u32(0xffffffff))
f.close()
for z0 in range(-1,3):
for x0 in range(-1,3):
for y0 in range(-1,3):
print("generating block "+str(x0)+","+str(y0)+","+str(z0))
#v3 blockp = v3(x0,y0,z0)
# Create a MapBlock
block = MapBlock()
# Generate stuff in it
for z in range(0,16):
for x in range(0,16):
h = 20.0*pnoise((x0*16+x)/100.,(z0*16+z)/100.,SEED+0)
h += 5.0*pnoise((x0*16+x)/25.,(z0*16+z)/25.,SEED+0)
if pnoise((x0*16+x)/25.,(z0*16+z)/25.,SEED+92412) > 0.05:
h += 10
#print("r="+str(r))
# This enables comparison by ==
h = int(h)
for y in range(0,16):
p = v3(x,y,z)
b = 254
y1 = y0*16+y
if y1 <= h-3:
b = 0 #stone
elif y1 <= h and y1 <= 0:
b = 8 #mud
elif y1 == h:
b = 1 #grass
elif y1 < h:
b = 8 #mud
elif y1 <= 1:
b = 9 #water
# Material content
block.set_content(p, b)
# Place a sign at the center at surface level.
# Placing a sign means placing the sign node and
# adding node metadata to the mapblock.
if x == 8 and z == 8 and y0*16 <= h-1 and (y0+1)*16-1 > h:
p = v3(8,h+1-y0*16,8)
# 14 = Sign
content_type = 14
block.set_content(p, content_type)
# This places the sign to the bottom of the cube.
# Working values: 0x01, 0x02, 0x04, 0x08, 0x10, 0x20
block.set_param2(p, 0x08)
# Then add metadata to hold the text of the sign
s = "Hello at sector ("+str(x0)+","+str(z0)+")"
meta = NodeMeta(content_type, ser_u16(len(s))+s)
block.nodemeta[p] = meta
# Write it on disk
writeblock(mapdir, x0,y0,z0, block)
#END

View File

@@ -1,67 +0,0 @@
#!/bin/sh
PROJECT_NAME=minetest-delta
PACKAGEDIR=../$PROJECT_NAME-packages
PACKAGENAME=$PROJECT_NAME-binary-`date +%y%m%d%H%M%S`
PACKAGEPATH=$PACKAGEDIR/$PACKAGENAME
mkdir -p $PACKAGEPATH
mkdir -p $PACKAGEPATH/bin
mkdir -p $PACKAGEPATH/data
mkdir -p $PACKAGEPATH/doc
mkdir -p $PACKAGEPATH/locale/de/LC_MESSAGES/
cp minetest.conf.example $PACKAGEPATH/
cp bin/$PROJECT_NAME.exe $PACKAGEPATH/bin/
cp bin/Irrlicht.dll $PACKAGEPATH/bin/
cp bin/zlibwapi.dll $PACKAGEPATH/bin/
#cp bin/test $PACKAGEPATH/bin/
#cp bin/fasttest $PACKAGEPATH/bin/
#cp bin/server $PACKAGEPATH/bin/
#cp ../irrlicht/irrlicht-1.7.1/lib/Linux/libIrrlicht.a $PACKAGEPATH/bin/
#cp ../jthread/jthread-1.2.1/src/.libs/libjthread-1.2.1.so $PACKAGEPATH/bin/
cp -r data/fontlucida.png $PACKAGEPATH/data/
cp -r data/player.png $PACKAGEPATH/data/
cp -r data/player_back.png $PACKAGEPATH/data/
cp -r data/stone.png $PACKAGEPATH/data/
cp -r data/grass.png $PACKAGEPATH/data/
cp -r data/grass_footsteps.png $PACKAGEPATH/data/
cp -r data/water.png $PACKAGEPATH/data/
cp -r data/tree.png $PACKAGEPATH/data/
cp -r data/leaves.png $PACKAGEPATH/data/
cp -r data/mese.png $PACKAGEPATH/data/
cp -r data/cloud.png $PACKAGEPATH/data/
cp -r data/sign.png $PACKAGEPATH/data/
cp -r data/sign_back.png $PACKAGEPATH/data/
cp -r data/rat.png $PACKAGEPATH/data/
cp -r data/mud.png $PACKAGEPATH/data/
cp -r data/torch.png $PACKAGEPATH/data/
cp -r data/torch_on_floor.png $PACKAGEPATH/data/
cp -r data/torch_on_ceiling.png $PACKAGEPATH/data/
cp -r data/tree_top.png $PACKAGEPATH/data/
cp -r data/coalstone.png $PACKAGEPATH/data/
cp -r data/crack.png $PACKAGEPATH/data/
cp -r data/wood.png $PACKAGEPATH/data/
cp -r data/stick.png $PACKAGEPATH/data/
cp -r data/tool_wpick.png $PACKAGEPATH/data/
cp -r data/tool_stpick.png $PACKAGEPATH/data/
cp -r data/tool_mesepick.png $PACKAGEPATH/data/
cp -r data/grass_side.png $PACKAGEPATH/data/
cp -r data/lump_of_coal.png $PACKAGEPATH/data/
cp -r data/lump_of_iron.png $PACKAGEPATH/data/
cp -r data/mineral_coal.png $PACKAGEPATH/data/
cp -r data/mineral_iron.png $PACKAGEPATH/data/
cp -r data/sand.png $PACKAGEPATH/data/
#cp -r data/pauseMenu.gui $PACKAGEPATH/data/
cp -r doc/README.txt $PACKAGEPATH/doc/README.txt
cp -r locale/de/LC_MESSAGES/$PROJECT_NAME.mo $PACKAGEPATH/locale/de/LC_MESSAGES/
cd $PACKAGEDIR
rm $PACKAGENAME.zip
zip -r $PACKAGENAME.zip $PACKAGENAME

BIN
minetest-icon-24x24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

View File

@@ -1,25 +0,0 @@
0 128 128 128
1 107 134 51
2 39 66 106
3 255 255 0
4 86 58 31
5 48 95 8
6 102 129 38
7 178 178 0
8 101 84 36
9 39 66 106
12 104 78 42
13 210 194 156
14 117 86 41
15 128 79 0
16 118 118 118
18 123 123 123
19 199 199 199
20 183 183 222
21 103 78 42
22 219 202 178
23 78 154 6
24 204 0 0
25 211 215 207
26 138 226 52
27 104 78 42

View File

@@ -1,275 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Made by j0gge, modified by celeron55
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://sam.zoy.org/wtfpl/COPYING for more details.
# Requires Python Imaging Library: http://www.pythonware.com/products/pil/
# Some speed-up: ...lol, actually it slows it down.
#import psyco ; psyco.full()
#from psyco.classes import *
import zlib
import Image, ImageDraw
import os
import string
import time
def hex_to_int(h):
i = int(h,16)
if(i > 2047):
i-=4096
return i
def hex4_to_int(h):
i = int(h,16)
if(i > 32767):
i-=65536
return i
def int_to_hex3(i):
if(i < 0):
return "%03X" % (i + 4096)
else:
return "%03X" % i
def int_to_hex4(i):
if(i < 0):
return "%04X" % (i + 65536)
else:
return "%04X" % i
def limit(i,l,h):
if(i>h):
i=h
if(i<l):
i=l
return i
# Fix these!
path="../map/"
output="map.png"
sector_xmin = -1000/16
sector_xmax = 1000/16
sector_zmin = -1000/16
sector_zmax = 1000/16
# Load color information for the blocks.
colors = {}
f = file("colors.txt")
for line in f:
values = string.split(line)
colors[int(values[0])] = (int(values[1]), int(values[2]), int(values[3]))
f.close()
xlist = []
zlist = []
# List all sectors to memory and calculate the width and heigth of the resulting picture.
if os.path.exists(path + "sectors2"):
for filename in os.listdir(path + "sectors2"):
for filename2 in os.listdir(path + "sectors2/" + filename):
x = hex_to_int(filename)
z = hex_to_int(filename2)
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
if os.path.exists(path + "sectors"):
for filename in os.listdir(path + "sectors"):
x = hex4_to_int(filename[:4])
z = hex4_to_int(filename[-4:])
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
w = (max(xlist) - min(xlist)) * 16 + 16
h = (max(zlist) - min(zlist)) * 16 + 16
print "w="+str(w)+" h="+str(h)
im = Image.new("RGB", (w, h), "white")
impix = im.load()
stuff={}
starttime = time.time()
# Go through all sectors.
for n in range(len(xlist)):
#if n > 500:
# break
if n % 200 == 0:
nowtime = time.time()
dtime = nowtime - starttime
n_per_second = 1.0 * n / dtime
if n_per_second != 0:
seconds_per_n = 1.0 / n_per_second
time_guess = seconds_per_n * len(xlist)
remaining_s = time_guess - dtime
remaining_minutes = int(remaining_s / 60)
remaining_s -= remaining_minutes * 60;
print("Processing sector "+str(n)+" of "+str(len(xlist))
+" ("+str(round(100.0*n/len(xlist), 1))+"%)"
+" (ETA: "+str(remaining_minutes)+"m "
+str(int(remaining_s))+"s)")
xpos = xlist[n]
zpos = zlist[n]
xhex = int_to_hex3(xpos)
zhex = int_to_hex3(zpos)
xhex4 = int_to_hex4(xpos)
zhex4 = int_to_hex4(zpos)
sector1 = xhex4.lower() + zhex4.lower()
sector2 = xhex.lower() + "/" + zhex.lower()
ylist=[]
sectortype = ""
try:
for filename in os.listdir(path + "sectors/" + sector1):
if(filename != "meta"):
pos = int(filename,16)
if(pos > 32767):
pos-=65536
ylist.append(pos)
sectortype = "old"
except OSError:
pass
if sectortype != "old":
try:
for filename in os.listdir(path + "sectors2/" + sector2):
if(filename != "meta"):
pos = int(filename,16)
if(pos > 32767):
pos-=65536
ylist.append(pos)
sectortype = "new"
except OSError:
pass
if sectortype == "":
continue
ylist.sort()
# Make a list of pixels of the sector that are to be looked for.
pixellist = []
for x in range(16):
for y in range(16):
pixellist.append((x,y))
# Go through the Y axis from top to bottom.
for ypos in reversed(ylist):
yhex = int_to_hex4(ypos)
filename = ""
if sectortype == "old":
filename = path + "sectors/" + sector1 + "/" + yhex.lower()
else:
filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
f = file(filename, "rb")
# Let's just memorize these even though it's not really necessary.
version = f.read(1)
flags = f.read(1)
dec_o = zlib.decompressobj()
try:
mapdata = dec_o.decompress(f.read())
except:
mapdata = []
f.close()
if(len(mapdata)<4096):
print "bad: " + xhex+zhex+"/"+yhex + " " + len(mapdata)
else:
chunkxpos=xpos*16
chunkypos=ypos*16
chunkzpos=zpos*16
for (x,z) in reversed(pixellist):
for y in reversed(range(16)):
datapos=x+y*16+z*256
if(ord(mapdata[datapos])!=254):
try:
pixellist.remove((x,z))
# Memorize information on the type and height of the block and for drawing the picture.
stuff[(chunkxpos+x,chunkzpos+z)]=(chunkypos+y,ord(mapdata[datapos]))
break
except:
print "strange block: " + xhex+zhex+"/"+yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " block: " + str(ord(mapdata[datapos]))
# After finding all the pixeld in the sector, we can move on to the next sector without having to continue the Y axis.
if(len(pixellist)==0):
break
print "Drawing image"
# Drawing the picture
starttime = time.time()
n = 0
minx = min(xlist)
minz = min(zlist)
for (x,z) in stuff.iterkeys():
if n % 500000 == 0:
nowtime = time.time()
dtime = nowtime - starttime
n_per_second = 1.0 * n / dtime
if n_per_second != 0:
listlen = len(stuff)
seconds_per_n = 1.0 / n_per_second
time_guess = seconds_per_n * listlen
remaining_s = time_guess - dtime
remaining_minutes = int(remaining_s / 60)
remaining_s -= remaining_minutes * 60;
print("Drawing pixel "+str(n)+" of "+str(listlen)
+" ("+str(round(100.0*n/listlen, 1))+"%)"
+" (ETA: "+str(remaining_minutes)+"m "
+str(int(remaining_s))+"s)")
n += 1
(r,g,b)=colors[stuff[(x,z)][1]]
# Comparing heights of a couple of adjacent blocks and changing brightness accordingly.
try:
y1=stuff[(x-1,z)][0]
y2=stuff[(x,z-1)][0]
y=stuff[(x,z)][0]
d=(y-y1+y-y2)*12
if(d>36):
d=36
r=limit(r+d,0,255)
g=limit(g+d,0,255)
b=limit(b+d,0,255)
except:
pass
#impix[w-1-(x-minx*16),h-1-(z-minz*16)]=(r,g,b)
impix[x-minx*16,h-1-(z-minz*16)]=(r,g,b)
# Flip the picture to make it right and save.
#print "Transposing"
#im=im.transpose(Image.FLIP_TOP_BOTTOM)
print "Saving"
im.save(output)

486
po/da/minetest.po Normal file
View File

@@ -0,0 +1,486 @@
# German translations for minetest-c55 package.
# Copyright (C) 2011 celeron
# This file is distributed under the same license as the minetest-c55 package.
# Frederik Helth <Guides@live.dk>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: 0.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-08-02 12:36+0200\n"
"PO-Revision-Date: 2011-08-02 00:31+0100\n"
"Last-Translator: Frederik Helth <Guides@live.dk>\n"
"Language-Team: \n"
"Language: da\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiKeyChangeMenu.cpp:84
msgid "KEYBINDINGS"
msgstr ""
#: src/guiKeyChangeMenu.cpp:94
msgid "Forward"
msgstr "Frem"
#: src/guiKeyChangeMenu.cpp:111
msgid "Backward"
msgstr "Tilbage"
#: src/guiKeyChangeMenu.cpp:127 src/guiKeyChangeMenu.h:38
msgid "Left"
msgstr "Venstre"
#: src/guiKeyChangeMenu.cpp:142 src/guiKeyChangeMenu.h:38
msgid "Right"
msgstr "Højre"
#: src/guiKeyChangeMenu.cpp:158
msgid "Use"
msgstr "Brug"
#: src/guiKeyChangeMenu.cpp:173
msgid "Sneak"
msgstr "Snig"
#: src/guiKeyChangeMenu.cpp:189
msgid "Jump"
msgstr "Hop"
#: src/guiKeyChangeMenu.cpp:204
msgid "Inventory"
msgstr "Ting"
#: src/guiKeyChangeMenu.cpp:220
msgid "Chat"
msgstr "Chat"
#: src/guiKeyChangeMenu.cpp:236
msgid "Toggle fly"
msgstr "Flyvning"
#: src/guiKeyChangeMenu.cpp:251
msgid "Toggle fast"
msgstr "Hurtig flyvning"
#: src/guiKeyChangeMenu.cpp:266
msgid "Range select"
msgstr "Afstands load"
#: src/guiKeyChangeMenu.cpp:283
msgid "Print stacks"
msgstr "Print stykker"
#: src/guiKeyChangeMenu.cpp:298
msgid "Save"
msgstr "Gem"
#: src/guiKeyChangeMenu.cpp:304 src/guiKeyChangeMenu.h:33
msgid "Cancel"
msgstr "Afslut"
#: src/guiKeyChangeMenu.cpp:537 src/guiKeyChangeMenu.cpp:542
#: src/guiKeyChangeMenu.cpp:547 src/guiKeyChangeMenu.cpp:552
#: src/guiKeyChangeMenu.cpp:557 src/guiKeyChangeMenu.cpp:562
#: src/guiKeyChangeMenu.cpp:567 src/guiKeyChangeMenu.cpp:572
#: src/guiKeyChangeMenu.cpp:577 src/guiKeyChangeMenu.cpp:582
#: src/guiKeyChangeMenu.cpp:587 src/guiKeyChangeMenu.cpp:592
#: src/guiKeyChangeMenu.cpp:597
msgid "press Key"
msgstr "Tryk knap"
#: src/guiKeyChangeMenu.h:33
msgid "Left Button"
msgstr "Venstre Knap"
#: src/guiKeyChangeMenu.h:33
msgid "Middle Button"
msgstr "Midt Knap"
#: src/guiKeyChangeMenu.h:33
msgid "Right Button"
msgstr "Højre Knap"
#: src/guiKeyChangeMenu.h:33
msgid "X Button 1"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Back"
msgstr "Tilbage"
#: src/guiKeyChangeMenu.h:34
msgid "Clear"
msgstr "Rens"
#: src/guiKeyChangeMenu.h:34
msgid "Return"
msgstr "Tilbage"
#: src/guiKeyChangeMenu.h:34
msgid "Tab"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "X Button 2"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Capital"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Control"
msgstr "Kontrol"
#: src/guiKeyChangeMenu.h:35
msgid "Kana"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Pause"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Convert"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Escape"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Final"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Junja"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Kanji"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Nonconvert"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Accept"
msgstr "Accepter"
#: src/guiKeyChangeMenu.h:37
msgid "End"
msgstr "Slut"
#: src/guiKeyChangeMenu.h:37
msgid "Home"
msgstr "Hjem"
#: src/guiKeyChangeMenu.h:37
msgid "Mode Change"
msgstr "Mode skift"
#: src/guiKeyChangeMenu.h:37
msgid "Next"
msgstr "Næste"
#: src/guiKeyChangeMenu.h:37
msgid "Priot"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Space"
msgstr "Mellemrum"
#: src/guiKeyChangeMenu.h:38
msgid "Down"
msgstr "Ned"
#: src/guiKeyChangeMenu.h:38
msgid "Execute"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Print"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Select"
msgstr "Vælge"
#: src/guiKeyChangeMenu.h:38
msgid "Up"
msgstr "Op"
#: src/guiKeyChangeMenu.h:39
msgid "Delete"
msgstr "Slet"
#: src/guiKeyChangeMenu.h:39
msgid "Help"
msgstr "Hjælp"
#: src/guiKeyChangeMenu.h:39
msgid "Insert"
msgstr "Indset"
#: src/guiKeyChangeMenu.h:39
msgid "Snapshot"
msgstr "Screenshot"
#: src/guiKeyChangeMenu.h:42
msgid "Left Windows"
msgstr "Venstre windows"
#: src/guiKeyChangeMenu.h:43
msgid "Apps"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 0"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 1"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Right Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Sleep"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 2"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 3"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 4"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 5"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 6"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 7"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad *"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad +"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad -"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad /"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 8"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 9"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Num Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Scroll Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Left Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Right Shight"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Comma"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Minus"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Period"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Plus"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "Attn"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "CrSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Erase OEF"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "ExSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "OEM Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "PA1"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Play"
msgstr "Spil"
#: src/guiKeyChangeMenu.h:58
msgid "Zoom"
msgstr ""
#: src/guiMainMenu.cpp:181
msgid "Name/Password"
msgstr "Navn/kodeord"
#: src/guiMainMenu.cpp:206
msgid "Address/Port"
msgstr "Adresse/port"
#: src/guiMainMenu.cpp:228
msgid "Leave address blank to start a local server."
msgstr "Lad black for at spille localt"
#: src/guiMainMenu.cpp:235
msgid "Fancy trees"
msgstr "Fancy trær"
#: src/guiMainMenu.cpp:241
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Start Game / Connect"
msgstr "Start spil"
#: src/guiMainMenu.cpp:258
msgid "Change keys"
msgstr "Indstillinger"
#: src/guiMainMenu.cpp:281
msgid "Creative Mode"
msgstr "Kreativ mode"
#: src/guiMainMenu.cpp:287
msgid "Enable Damage"
msgstr "Tag imod skade"
#: src/guiMainMenu.cpp:295
msgid "Delete map"
msgstr "Slet mappen"
#: src/guiMessageMenu.cpp:94 src/guiTextInputMenu.cpp:112
msgid "Proceed"
msgstr "Fortsæt"
#: src/guiPasswordChange.cpp:103
msgid "Old Password"
msgstr "Gamle kodeord"
#: src/guiPasswordChange.cpp:120
msgid "New Password"
msgstr "Nye kodeord"
#: src/guiPasswordChange.cpp:136
msgid "Confirm Password"
msgstr "Gentag kodeord"
#: src/guiPasswordChange.cpp:153
msgid "Change"
msgstr "Skift"
#: src/guiPasswordChange.cpp:162
msgid "Passwords do not match!"
msgstr "Kodeordne matcher ikke hinanden!"
#: src/guiPauseMenu.cpp:111
msgid "Continue"
msgstr "Fortsæt"
#: src/guiPauseMenu.cpp:118
msgid "Change Password"
msgstr "Skift kodeord"
#: src/guiPauseMenu.cpp:125
msgid "Disconnect"
msgstr "Logud"
#: src/guiPauseMenu.cpp:132
msgid "Exit to OS"
msgstr "Afslut til OS"
#: src/guiPauseMenu.cpp:139
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-07-22 11:00+0200\n"
"PO-Revision-Date: 2011-07-20 16:58+0100\n"
"POT-Creation-Date: 2011-08-02 12:36+0200\n"
"PO-Revision-Date: 2011-08-02 11:54+0100\n"
"Last-Translator: Constantin Wenger <constantin.wenger@googlemail.com>\n"
"Language-Team: Deutsch <>\n"
"Language: de\n"
@@ -17,92 +17,467 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
#: src/guiMainMenu.cpp:180
#: src/guiKeyChangeMenu.cpp:84
msgid "KEYBINDINGS"
msgstr "TASTEN EINST."
#: src/guiKeyChangeMenu.cpp:94
msgid "Forward"
msgstr "Vorwärts"
#: src/guiKeyChangeMenu.cpp:111
msgid "Backward"
msgstr "Rückwärts"
#: src/guiKeyChangeMenu.cpp:127 src/guiKeyChangeMenu.h:38
msgid "Left"
msgstr "Links"
#: src/guiKeyChangeMenu.cpp:142 src/guiKeyChangeMenu.h:38
msgid "Right"
msgstr "Rechts"
#: src/guiKeyChangeMenu.cpp:158
msgid "Use"
msgstr "Benutzen"
#: src/guiKeyChangeMenu.cpp:173
msgid "Sneak"
msgstr "Kriechen"
#: src/guiKeyChangeMenu.cpp:189
msgid "Jump"
msgstr "Springen"
#: src/guiKeyChangeMenu.cpp:204
msgid "Inventory"
msgstr "Inventar"
#: src/guiKeyChangeMenu.cpp:220
msgid "Chat"
msgstr "Chat"
#: src/guiKeyChangeMenu.cpp:236
msgid "Toggle fly"
msgstr "Fliegen umsch."
#: src/guiKeyChangeMenu.cpp:251
msgid "Toggle fast"
msgstr "Speed umsch."
#: src/guiKeyChangeMenu.cpp:266
msgid "Range select"
msgstr "Entfernung wählen"
#: src/guiKeyChangeMenu.cpp:283
msgid "Print stacks"
msgstr "Stack ausgeben"
#: src/guiKeyChangeMenu.cpp:298
msgid "Save"
msgstr "Speichern"
#: src/guiKeyChangeMenu.cpp:304 src/guiKeyChangeMenu.h:33
msgid "Cancel"
msgstr "Abbrechen"
#: src/guiKeyChangeMenu.cpp:537 src/guiKeyChangeMenu.cpp:542
#: src/guiKeyChangeMenu.cpp:547 src/guiKeyChangeMenu.cpp:552
#: src/guiKeyChangeMenu.cpp:557 src/guiKeyChangeMenu.cpp:562
#: src/guiKeyChangeMenu.cpp:567 src/guiKeyChangeMenu.cpp:572
#: src/guiKeyChangeMenu.cpp:577 src/guiKeyChangeMenu.cpp:582
#: src/guiKeyChangeMenu.cpp:587 src/guiKeyChangeMenu.cpp:592
#: src/guiKeyChangeMenu.cpp:597
msgid "press Key"
msgstr "Taste drücken"
#: src/guiKeyChangeMenu.h:33
msgid "Left Button"
msgstr "linke Taste"
#: src/guiKeyChangeMenu.h:33
msgid "Middle Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Right Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "X Button 1"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Back"
msgstr "Rücktaste"
#: src/guiKeyChangeMenu.h:34
msgid "Clear"
msgstr "löschen"
#: src/guiKeyChangeMenu.h:34
msgid "Return"
msgstr "Return"
#: src/guiKeyChangeMenu.h:34
msgid "Tab"
msgstr "Tab"
#: src/guiKeyChangeMenu.h:34
msgid "X Button 2"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Capital"
msgstr "Feststellen"
#: src/guiKeyChangeMenu.h:35
msgid "Control"
msgstr "Strg"
#: src/guiKeyChangeMenu.h:35
msgid "Kana"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Menu"
msgstr "Menü"
#: src/guiKeyChangeMenu.h:35
msgid "Pause"
msgstr "Pause"
#: src/guiKeyChangeMenu.h:35
msgid "Shift"
msgstr "Umsch."
#: src/guiKeyChangeMenu.h:36
msgid "Convert"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Escape"
msgstr "Escape"
#: src/guiKeyChangeMenu.h:36
msgid "Final"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Junja"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Kanji"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Nonconvert"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Accept"
msgstr "Annehmen"
#: src/guiKeyChangeMenu.h:37
msgid "End"
msgstr "Ende"
#: src/guiKeyChangeMenu.h:37
msgid "Home"
msgstr "Pos1"
#: src/guiKeyChangeMenu.h:37
msgid "Mode Change"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Next"
msgstr "Bild runter"
#: src/guiKeyChangeMenu.h:37
msgid "Priot"
msgstr "Bild hoch"
#: src/guiKeyChangeMenu.h:37
msgid "Space"
msgstr "Leertaste"
#: src/guiKeyChangeMenu.h:38
msgid "Down"
msgstr "Runter"
#: src/guiKeyChangeMenu.h:38
msgid "Execute"
msgstr "Ausführen"
#: src/guiKeyChangeMenu.h:38
msgid "Print"
msgstr "Druck"
#: src/guiKeyChangeMenu.h:38
msgid "Select"
msgstr "Select"
#: src/guiKeyChangeMenu.h:38
msgid "Up"
msgstr "Hoch"
#: src/guiKeyChangeMenu.h:39
msgid "Delete"
msgstr "Entf"
#: src/guiKeyChangeMenu.h:39
msgid "Help"
msgstr "Hilfe"
#: src/guiKeyChangeMenu.h:39
msgid "Insert"
msgstr "Einfg"
#: src/guiKeyChangeMenu.h:39
msgid "Snapshot"
msgstr "Schnapschuss"
#: src/guiKeyChangeMenu.h:42
msgid "Left Windows"
msgstr "Win links"
#: src/guiKeyChangeMenu.h:43
msgid "Apps"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 0"
msgstr "Ziffernblock 0"
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 1"
msgstr "Ziffernblock 1"
#: src/guiKeyChangeMenu.h:43
msgid "Right Windows"
msgstr "Win rechts"
#: src/guiKeyChangeMenu.h:43
msgid "Sleep"
msgstr "Schlaf"
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 2"
msgstr "Ziffernblock 2"
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 3"
msgstr "Ziffernblock 3"
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 4"
msgstr "Ziffernblock 4"
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 5"
msgstr "Ziffernblock 5"
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 6"
msgstr "Ziffernblock 6"
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 7"
msgstr "Ziffernblock 7"
#: src/guiKeyChangeMenu.h:45
msgid "Numpad *"
msgstr "Ziffernblock *"
#: src/guiKeyChangeMenu.h:45
msgid "Numpad +"
msgstr "Ziffernblock +"
#: src/guiKeyChangeMenu.h:45
msgid "Numpad -"
msgstr "Ziffernblock -"
#: src/guiKeyChangeMenu.h:45
msgid "Numpad /"
msgstr "Ziffernblock /"
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 8"
msgstr "Ziffernblock 8"
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 9"
msgstr "Ziffernblock 9"
#: src/guiKeyChangeMenu.h:49
msgid "Num Lock"
msgstr "Num"
#: src/guiKeyChangeMenu.h:49
msgid "Scroll Lock"
msgstr "Rollen"
#: src/guiKeyChangeMenu.h:50
msgid "Left Shift"
msgstr "Umsch. links"
#: src/guiKeyChangeMenu.h:50
msgid "Right Shight"
msgstr "Umsch. rechts"
#: src/guiKeyChangeMenu.h:51
msgid "Left Control"
msgstr "Strg links"
#: src/guiKeyChangeMenu.h:51
msgid "Left Menu"
msgstr "Alt"
#: src/guiKeyChangeMenu.h:51
msgid "Right Control"
msgstr "Strg rechts"
#: src/guiKeyChangeMenu.h:51
msgid "Right Menu"
msgstr "Alt Gr"
#: src/guiKeyChangeMenu.h:53
msgid "Comma"
msgstr "Komma"
#: src/guiKeyChangeMenu.h:53
msgid "Minus"
msgstr "Minus"
#: src/guiKeyChangeMenu.h:53
msgid "Period"
msgstr "Punkt"
#: src/guiKeyChangeMenu.h:53
msgid "Plus"
msgstr "Plus"
#: src/guiKeyChangeMenu.h:57
msgid "Attn"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "CrSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Erase OEF"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "ExSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "OEM Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "PA1"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Play"
msgstr "Play"
#: src/guiKeyChangeMenu.h:58
msgid "Zoom"
msgstr "Zoom"
#: src/guiMainMenu.cpp:181
msgid "Name/Password"
msgstr "Name/Passwort"
#: src/guiMainMenu.cpp:203
#: src/guiMainMenu.cpp:206
msgid "Address/Port"
msgstr "Adresse / Port"
#: src/guiMainMenu.cpp:223
#: src/guiMainMenu.cpp:228
msgid "Leave address blank to start a local server."
msgstr "Lasse die Adresse frei um einen eigenen Server zu starten"
#: src/guiMainMenu.cpp:230
#: src/guiMainMenu.cpp:235
msgid "Fancy trees"
msgstr "Schöne Bäume"
#: src/guiMainMenu.cpp:236
#: src/guiMainMenu.cpp:241
msgid "Smooth Lighting"
msgstr "Besseres Licht"
#: src/guiMainMenu.cpp:244
#: src/guiMainMenu.cpp:249
msgid "Start Game / Connect"
msgstr "Spiel starten / Verbinden"
#: src/guiMainMenu.cpp:253
#: src/guiMainMenu.cpp:258
msgid "Change keys"
msgstr "Tastenbelegung ändern"
msgstr "Tasten ändern"
#: src/guiMainMenu.cpp:276
#: src/guiMainMenu.cpp:281
msgid "Creative Mode"
msgstr "Kreativitätsmodus"
#: src/guiMainMenu.cpp:282
#: src/guiMainMenu.cpp:287
msgid "Enable Damage"
msgstr "Schaden einschalten"
#: src/guiMainMenu.cpp:290
#: src/guiMainMenu.cpp:295
msgid "Delete map"
msgstr "Karte löschen"
#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
#: src/guiMessageMenu.cpp:94 src/guiTextInputMenu.cpp:112
msgid "Proceed"
msgstr "Fortsetzen"
#: src/guiPasswordChange.cpp:102
#: src/guiPasswordChange.cpp:103
msgid "Old Password"
msgstr "Altes Passwort"
#: src/guiPasswordChange.cpp:117
#: src/guiPasswordChange.cpp:120
msgid "New Password"
msgstr "Neues Passwort"
#: src/guiPasswordChange.cpp:131
#: src/guiPasswordChange.cpp:136
msgid "Confirm Password"
msgstr "Passwort wiederholen"
#: src/guiPasswordChange.cpp:146
#: src/guiPasswordChange.cpp:153
msgid "Change"
msgstr "Ändern"
#: src/guiPasswordChange.cpp:155
#: src/guiPasswordChange.cpp:162
msgid "Passwords do not match!"
msgstr "Passwörter passen nicht zusammen"
#: src/guiPauseMenu.cpp:110
#: src/guiPauseMenu.cpp:111
msgid "Continue"
msgstr "Weiter"
#: src/guiPauseMenu.cpp:117
#: src/guiPauseMenu.cpp:118
msgid "Change Password"
msgstr "Passwort ändern"
#: src/guiPauseMenu.cpp:124
#: src/guiPauseMenu.cpp:125
msgid "Disconnect"
msgstr "Verbindung trennen"
#: src/guiPauseMenu.cpp:131
#: src/guiPauseMenu.cpp:132
msgid "Exit to OS"
msgstr "Programm beenden"
#: src/guiPauseMenu.cpp:138
#: src/guiPauseMenu.cpp:139
#, fuzzy
msgid ""
"Keys:\n"
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig blocks\n"
"- Mouse right: place blocks\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
@@ -113,11 +488,11 @@ msgid ""
msgstr ""
"Tastenkürzel:\n"
"- WASD: Gehen\n"
"- linke Maustaste: dig blocks\n"
"- rechte Maustaste: place blocks\n"
"- linke Maustaste: Blöcke aufnehmen \n"
"- rechte Maustaste: Blöche ablegen\n"
"- Mausrad: Item auswählen\n"
"- 0...9: Item auswählen\n"
"- Shift: ducken\n"
"- R: Alle geladenen Kartenteile anzeigen, umschalten\n"
"- R: alle geladenen Blöcke anzeigen (wechseln)\n"
"- I: Inventarmenü\n"
"- T: Chat\n"

View File

@@ -1,113 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-07-24 11:32+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiMainMenu.cpp:180
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:203
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:223
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:230
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:236
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:244
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:253
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:276
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:282
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:290
msgid "Delete map"
msgstr ""
#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
msgid "Proceed"
msgstr ""
#: src/guiPasswordChange.cpp:102
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:117
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:131
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:146
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:155
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:110
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:117
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:124
msgid "Disconnect"
msgstr ""
#: src/guiPauseMenu.cpp:131
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:138
msgid ""
"Keys:\n"
"- WASD: Walk\n"
"- Mouse left: dig blocks\n"
"- Mouse right: place blocks\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-07-22 11:00+0200\n"
"POT-Creation-Date: 2011-08-02 12:36+0200\n"
"PO-Revision-Date: 2011-07-21 15:48+0200\n"
"Last-Translator: Cyriaque 'Cisoun' Skrapits <cysoun@gmail.com>\n"
"Language-Team: Français <>\n"
@@ -17,92 +17,469 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
#: src/guiMainMenu.cpp:180
#: src/guiKeyChangeMenu.cpp:84
msgid "KEYBINDINGS"
msgstr ""
#: src/guiKeyChangeMenu.cpp:94
msgid "Forward"
msgstr ""
#: src/guiKeyChangeMenu.cpp:111
msgid "Backward"
msgstr ""
#: src/guiKeyChangeMenu.cpp:127 src/guiKeyChangeMenu.h:38
msgid "Left"
msgstr ""
#: src/guiKeyChangeMenu.cpp:142 src/guiKeyChangeMenu.h:38
msgid "Right"
msgstr ""
#: src/guiKeyChangeMenu.cpp:158
msgid "Use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:173
msgid "Sneak"
msgstr ""
#: src/guiKeyChangeMenu.cpp:189
msgid "Jump"
msgstr ""
#: src/guiKeyChangeMenu.cpp:204
msgid "Inventory"
msgstr ""
#: src/guiKeyChangeMenu.cpp:220
msgid "Chat"
msgstr ""
#: src/guiKeyChangeMenu.cpp:236
msgid "Toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:251
msgid "Toggle fast"
msgstr ""
#: src/guiKeyChangeMenu.cpp:266
msgid "Range select"
msgstr ""
#: src/guiKeyChangeMenu.cpp:283
msgid "Print stacks"
msgstr ""
#: src/guiKeyChangeMenu.cpp:298
msgid "Save"
msgstr ""
#: src/guiKeyChangeMenu.cpp:304 src/guiKeyChangeMenu.h:33
msgid "Cancel"
msgstr ""
#: src/guiKeyChangeMenu.cpp:537 src/guiKeyChangeMenu.cpp:542
#: src/guiKeyChangeMenu.cpp:547 src/guiKeyChangeMenu.cpp:552
#: src/guiKeyChangeMenu.cpp:557 src/guiKeyChangeMenu.cpp:562
#: src/guiKeyChangeMenu.cpp:567 src/guiKeyChangeMenu.cpp:572
#: src/guiKeyChangeMenu.cpp:577 src/guiKeyChangeMenu.cpp:582
#: src/guiKeyChangeMenu.cpp:587 src/guiKeyChangeMenu.cpp:592
#: src/guiKeyChangeMenu.cpp:597
msgid "press Key"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Left Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Middle Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Right Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "X Button 1"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Back"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Return"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Tab"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "X Button 2"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Capital"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Control"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Kana"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Pause"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Convert"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Escape"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Final"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Junja"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Kanji"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Nonconvert"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Accept"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "End"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Home"
msgstr ""
#: src/guiKeyChangeMenu.h:37
#, fuzzy
msgid "Mode Change"
msgstr "Changer"
#: src/guiKeyChangeMenu.h:37
msgid "Next"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Priot"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Space"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Down"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Execute"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Print"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Select"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Up"
msgstr ""
#: src/guiKeyChangeMenu.h:39
#, fuzzy
msgid "Delete"
msgstr "Supprimer carte"
#: src/guiKeyChangeMenu.h:39
msgid "Help"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Insert"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Snapshot"
msgstr ""
#: src/guiKeyChangeMenu.h:42
msgid "Left Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Apps"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 0"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 1"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Right Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Sleep"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 2"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 3"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 4"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 5"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 6"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 7"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad *"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad +"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad -"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad /"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 8"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 9"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Num Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Scroll Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Left Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Right Shight"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Comma"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Minus"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Period"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Plus"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "Attn"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "CrSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Erase OEF"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "ExSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "OEM Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "PA1"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Play"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Zoom"
msgstr ""
#: src/guiMainMenu.cpp:181
msgid "Name/Password"
msgstr "Nom / MdP"
#: src/guiMainMenu.cpp:203
#: src/guiMainMenu.cpp:206
msgid "Address/Port"
msgstr "Adresse / Port"
#: src/guiMainMenu.cpp:223
#: src/guiMainMenu.cpp:228
msgid "Leave address blank to start a local server."
msgstr "Laisser l'adresse vide pour lancer un serveur local."
#: src/guiMainMenu.cpp:230
#: src/guiMainMenu.cpp:235
msgid "Fancy trees"
msgstr "Arbres spéciaux"
#: src/guiMainMenu.cpp:236
#: src/guiMainMenu.cpp:241
msgid "Smooth Lighting"
msgstr "Lumière douce"
#: src/guiMainMenu.cpp:244
#: src/guiMainMenu.cpp:249
msgid "Start Game / Connect"
msgstr "Démarrer / Connecter"
#: src/guiMainMenu.cpp:253
#: src/guiMainMenu.cpp:258
msgid "Change keys"
msgstr "Changer touches"
#: src/guiMainMenu.cpp:276
#: src/guiMainMenu.cpp:281
msgid "Creative Mode"
msgstr "Mode créatif"
#: src/guiMainMenu.cpp:282
#: src/guiMainMenu.cpp:287
msgid "Enable Damage"
msgstr "Activer blessures"
#: src/guiMainMenu.cpp:290
#: src/guiMainMenu.cpp:295
msgid "Delete map"
msgstr "Supprimer carte"
#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
#: src/guiMessageMenu.cpp:94 src/guiTextInputMenu.cpp:112
msgid "Proceed"
msgstr "OK"
#: src/guiPasswordChange.cpp:102
#: src/guiPasswordChange.cpp:103
msgid "Old Password"
msgstr "Ancien mot de passe"
#: src/guiPasswordChange.cpp:117
#: src/guiPasswordChange.cpp:120
msgid "New Password"
msgstr "Nouveau mot de passe"
#: src/guiPasswordChange.cpp:131
#: src/guiPasswordChange.cpp:136
msgid "Confirm Password"
msgstr "Confirmer mot de passe"
#: src/guiPasswordChange.cpp:146
#: src/guiPasswordChange.cpp:153
msgid "Change"
msgstr "Changer"
#: src/guiPasswordChange.cpp:155
#: src/guiPasswordChange.cpp:162
msgid "Passwords do not match!"
msgstr "Mauvaise correspondance!"
#: src/guiPauseMenu.cpp:110
#: src/guiPauseMenu.cpp:111
msgid "Continue"
msgstr "Continuer"
#: src/guiPauseMenu.cpp:117
#: src/guiPauseMenu.cpp:118
msgid "Change Password"
msgstr "Changer mot de passe"
#: src/guiPauseMenu.cpp:124
#: src/guiPauseMenu.cpp:125
msgid "Disconnect"
msgstr "Déconnection"
#: src/guiPauseMenu.cpp:131
#: src/guiPauseMenu.cpp:132
msgid "Exit to OS"
msgstr "Quitter le jeu"
#: src/guiPauseMenu.cpp:138
#: src/guiPauseMenu.cpp:139
#, fuzzy
msgid ""
"Keys:\n"
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig blocks\n"
"- Mouse right: place blocks\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"

499
po/it/minetest.po Normal file
View File

@@ -0,0 +1,499 @@
# Italian translations for minetest package.
# Copyright (C) 2011 THE minetest'S COPYRIGHT HOLDER
# This file is distributed under the same license as the minetest package.
# Giuseppe Bilotta <giuseppe.bilotta@gmail.com>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-08-02 12:36+0200\n"
"PO-Revision-Date: 2011-07-24 18:56+0200\n"
"Last-Translator: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\n"
"Language-Team: Italian\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/guiKeyChangeMenu.cpp:84
msgid "KEYBINDINGS"
msgstr ""
#: src/guiKeyChangeMenu.cpp:94
msgid "Forward"
msgstr "Avanti"
#: src/guiKeyChangeMenu.cpp:111
msgid "Backward"
msgstr "Indietro"
#: src/guiKeyChangeMenu.cpp:127 src/guiKeyChangeMenu.h:38
msgid "Left"
msgstr "Sinistra"
#: src/guiKeyChangeMenu.cpp:142 src/guiKeyChangeMenu.h:38
msgid "Right"
msgstr "Destra"
#: src/guiKeyChangeMenu.cpp:158
msgid "Use"
msgstr "Usa"
#: src/guiKeyChangeMenu.cpp:173
msgid "Sneak"
msgstr ""
#: src/guiKeyChangeMenu.cpp:189
msgid "Jump"
msgstr "Salta"
#: src/guiKeyChangeMenu.cpp:204
msgid "Inventory"
msgstr "Invetario"
#: src/guiKeyChangeMenu.cpp:220
msgid "Chat"
msgstr "Parla"
#: src/guiKeyChangeMenu.cpp:236
msgid "Toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:251
msgid "Toggle fast"
msgstr ""
#: src/guiKeyChangeMenu.cpp:266
msgid "Range select"
msgstr ""
#: src/guiKeyChangeMenu.cpp:283
msgid "Print stacks"
msgstr ""
#: src/guiKeyChangeMenu.cpp:298
msgid "Save"
msgstr "Salva"
#: src/guiKeyChangeMenu.cpp:304 src/guiKeyChangeMenu.h:33
msgid "Cancel"
msgstr "Annulla"
#: src/guiKeyChangeMenu.cpp:537 src/guiKeyChangeMenu.cpp:542
#: src/guiKeyChangeMenu.cpp:547 src/guiKeyChangeMenu.cpp:552
#: src/guiKeyChangeMenu.cpp:557 src/guiKeyChangeMenu.cpp:562
#: src/guiKeyChangeMenu.cpp:567 src/guiKeyChangeMenu.cpp:572
#: src/guiKeyChangeMenu.cpp:577 src/guiKeyChangeMenu.cpp:582
#: src/guiKeyChangeMenu.cpp:587 src/guiKeyChangeMenu.cpp:592
#: src/guiKeyChangeMenu.cpp:597
msgid "press Key"
msgstr "premi tasto"
#: src/guiKeyChangeMenu.h:33
msgid "Left Button"
msgstr "Tasto sinistro"
#: src/guiKeyChangeMenu.h:33
msgid "Middle Button"
msgstr "Tasto centrale"
#: src/guiKeyChangeMenu.h:33
msgid "Right Button"
msgstr "Tasto destro"
#: src/guiKeyChangeMenu.h:33
msgid "X Button 1"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Back"
msgstr "Indietro"
#: src/guiKeyChangeMenu.h:34
msgid "Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Return"
msgstr "Invio"
#: src/guiKeyChangeMenu.h:34
msgid "Tab"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "X Button 2"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Capital"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Control"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Kana"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Pause"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Convert"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Escape"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Final"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Junja"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Kanji"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Nonconvert"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Accept"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "End"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Home"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Mode Change"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Next"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Priot"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Space"
msgstr "Spazio"
#: src/guiKeyChangeMenu.h:38
msgid "Down"
msgstr "Giù"
#: src/guiKeyChangeMenu.h:38
msgid "Execute"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Print"
msgstr "Stampa"
#: src/guiKeyChangeMenu.h:38
msgid "Select"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Up"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Delete"
msgstr "Cancella"
#: src/guiKeyChangeMenu.h:39
msgid "Help"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Insert"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Snapshot"
msgstr ""
#: src/guiKeyChangeMenu.h:42
msgid "Left Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Apps"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 0"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 1"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Right Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Sleep"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 2"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 3"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 4"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 5"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 6"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 7"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad *"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad +"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad -"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad /"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 8"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 9"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Num Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Scroll Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Left Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Right Shight"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Comma"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Minus"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Period"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Plus"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "Attn"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "CrSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Erase OEF"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "ExSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "OEM Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "PA1"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Play"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Zoom"
msgstr ""
#: src/guiMainMenu.cpp:181
msgid "Name/Password"
msgstr "Nome/Password"
#: src/guiMainMenu.cpp:206
msgid "Address/Port"
msgstr "Indirizzo/Porta"
#: src/guiMainMenu.cpp:228
msgid "Leave address blank to start a local server."
msgstr "Lascia vuoto l'indirizzo per avviare un server locale"
#: src/guiMainMenu.cpp:235
msgid "Fancy trees"
msgstr "Alberi strani"
#: src/guiMainMenu.cpp:241
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Start Game / Connect"
msgstr "Avvia Gioco / Connetti"
#: src/guiMainMenu.cpp:258
msgid "Change keys"
msgstr "Modifica tasti"
#: src/guiMainMenu.cpp:281
msgid "Creative Mode"
msgstr "Modalità creativa"
#: src/guiMainMenu.cpp:287
msgid "Enable Damage"
msgstr "Attiva Danno"
#: src/guiMainMenu.cpp:295
msgid "Delete map"
msgstr "Cancella mappa"
#: src/guiMessageMenu.cpp:94 src/guiTextInputMenu.cpp:112
msgid "Proceed"
msgstr "Procedi"
#: src/guiPasswordChange.cpp:103
msgid "Old Password"
msgstr "Vecchia password"
#: src/guiPasswordChange.cpp:120
msgid "New Password"
msgstr "Nuova password"
#: src/guiPasswordChange.cpp:136
msgid "Confirm Password"
msgstr "Conferma password"
#: src/guiPasswordChange.cpp:153
msgid "Change"
msgstr "Modifica"
#: src/guiPasswordChange.cpp:162
msgid "Passwords do not match!"
msgstr "Le password non corrispondono!"
#: src/guiPauseMenu.cpp:111
msgid "Continue"
msgstr "Continua"
#: src/guiPauseMenu.cpp:118
msgid "Change Password"
msgstr "Cambia password"
#: src/guiPauseMenu.cpp:125
msgid "Disconnect"
msgstr "Disconnetti"
#: src/guiPauseMenu.cpp:132
msgid "Exit to OS"
msgstr "Esci al S.O."
#: src/guiPauseMenu.cpp:139
#, fuzzy
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""
"Tasti:\n"
"- WASD: Cammina\n"
"- Mouse left: scava blocchi\n"
"- Mouse right: piazza blocchi\n"
"- Mouse wheel: seleziona oggetto\n"
"- 0...9: seleziona oggetto\n"
"- Shift: furtivo\n"
"- R: (Dis)attiva motra tutti i blocchi caricati\n"
"- I: Inventario\n"
"- ESC: Questo menu\n"
"- T: Parla\n"

487
po/minetest.pot Normal file
View File

@@ -0,0 +1,487 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-08-02 12:36+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiKeyChangeMenu.cpp:84
msgid "KEYBINDINGS"
msgstr ""
#: src/guiKeyChangeMenu.cpp:94
msgid "Forward"
msgstr ""
#: src/guiKeyChangeMenu.cpp:111
msgid "Backward"
msgstr ""
#: src/guiKeyChangeMenu.cpp:127 src/guiKeyChangeMenu.h:38
msgid "Left"
msgstr ""
#: src/guiKeyChangeMenu.cpp:142 src/guiKeyChangeMenu.h:38
msgid "Right"
msgstr ""
#: src/guiKeyChangeMenu.cpp:158
msgid "Use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:173
msgid "Sneak"
msgstr ""
#: src/guiKeyChangeMenu.cpp:189
msgid "Jump"
msgstr ""
#: src/guiKeyChangeMenu.cpp:204
msgid "Inventory"
msgstr ""
#: src/guiKeyChangeMenu.cpp:220
msgid "Chat"
msgstr ""
#: src/guiKeyChangeMenu.cpp:236
msgid "Toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:251
msgid "Toggle fast"
msgstr ""
#: src/guiKeyChangeMenu.cpp:266
msgid "Range select"
msgstr ""
#: src/guiKeyChangeMenu.cpp:283
msgid "Print stacks"
msgstr ""
#: src/guiKeyChangeMenu.cpp:298
msgid "Save"
msgstr ""
#: src/guiKeyChangeMenu.cpp:304 src/guiKeyChangeMenu.h:33
msgid "Cancel"
msgstr ""
#: src/guiKeyChangeMenu.cpp:537 src/guiKeyChangeMenu.cpp:542
#: src/guiKeyChangeMenu.cpp:547 src/guiKeyChangeMenu.cpp:552
#: src/guiKeyChangeMenu.cpp:557 src/guiKeyChangeMenu.cpp:562
#: src/guiKeyChangeMenu.cpp:567 src/guiKeyChangeMenu.cpp:572
#: src/guiKeyChangeMenu.cpp:577 src/guiKeyChangeMenu.cpp:582
#: src/guiKeyChangeMenu.cpp:587 src/guiKeyChangeMenu.cpp:592
#: src/guiKeyChangeMenu.cpp:597
msgid "press Key"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Left Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Middle Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "Right Button"
msgstr ""
#: src/guiKeyChangeMenu.h:33
msgid "X Button 1"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Back"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Return"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "Tab"
msgstr ""
#: src/guiKeyChangeMenu.h:34
msgid "X Button 2"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Capital"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Control"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Kana"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Pause"
msgstr ""
#: src/guiKeyChangeMenu.h:35
msgid "Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Convert"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Escape"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Final"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Junja"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Kanji"
msgstr ""
#: src/guiKeyChangeMenu.h:36
msgid "Nonconvert"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Accept"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "End"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Home"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Mode Change"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Next"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Priot"
msgstr ""
#: src/guiKeyChangeMenu.h:37
msgid "Space"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Down"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Execute"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Print"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Select"
msgstr ""
#: src/guiKeyChangeMenu.h:38
msgid "Up"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Delete"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Help"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Insert"
msgstr ""
#: src/guiKeyChangeMenu.h:39
msgid "Snapshot"
msgstr ""
#: src/guiKeyChangeMenu.h:42
msgid "Left Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Apps"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 0"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Numpad 1"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Right Windows"
msgstr ""
#: src/guiKeyChangeMenu.h:43
msgid "Sleep"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 2"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 3"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 4"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 5"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 6"
msgstr ""
#: src/guiKeyChangeMenu.h:44
msgid "Numpad 7"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad *"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad +"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad -"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad /"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 8"
msgstr ""
#: src/guiKeyChangeMenu.h:45
msgid "Numpad 9"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Num Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:49
msgid "Scroll Lock"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Left Shift"
msgstr ""
#: src/guiKeyChangeMenu.h:50
msgid "Right Shight"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Left Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Control"
msgstr ""
#: src/guiKeyChangeMenu.h:51
msgid "Right Menu"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Comma"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Minus"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Period"
msgstr ""
#: src/guiKeyChangeMenu.h:53
msgid "Plus"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "Attn"
msgstr ""
#: src/guiKeyChangeMenu.h:57
msgid "CrSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Erase OEF"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "ExSel"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "OEM Clear"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "PA1"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Play"
msgstr ""
#: src/guiKeyChangeMenu.h:58
msgid "Zoom"
msgstr ""
#: src/guiMainMenu.cpp:181
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:206
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:228
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:235
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:241
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:258
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:281
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:287
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:295
msgid "Delete map"
msgstr ""
#: src/guiMessageMenu.cpp:94 src/guiTextInputMenu.cpp:112
msgid "Proceed"
msgstr ""
#: src/guiPasswordChange.cpp:103
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:120
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:136
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:153
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:162
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:111
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:118
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:125
msgid "Disconnect"
msgstr ""
#: src/guiPauseMenu.cpp:132
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:139
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""

View File

@@ -1,15 +1,19 @@
cmake_minimum_required( VERSION 2.6 )
project(minetest)
cmake_minimum_required( VERSION 2.6 )
if(RUN_IN_PLACE)
add_definitions ( -DRUN_IN_PLACE )
endif(RUN_IN_PLACE)
OPTION(USE_GETTEXT "Use GetText for internationalization" OFF)
# user-visible option to enable/disable gettext usage
OPTION(ENABLE_GETTEXT "Use GetText for internationalization" ON)
if(USE_GETTEXT)
find_package(GettextLib REQUIRED)
# this is only set to 1 if gettext is enabled _and_ available
set(USE_GETTEXT 0)
find_package(GettextLib)
if(GETTEXT_FOUND AND ENABLE_GETTEXT)
message(STATUS "gettext include path: ${GETTEXT_INCLUDE_DIR}")
message(STATUS "gettext msgfmt path: ${GETTEXT_MSGFMT}")
if(WIN32)
@@ -17,16 +21,13 @@ if(USE_GETTEXT)
message(STATUS "gettext dll: ${GETTEXT_DLL}")
message(STATUS "gettext iconv dll: ${GETTEXT_ICONV_DLL}")
endif()
if (GETTEXT_FOUND)
add_definitions( -DUSE_GETTEXT )
message(STATUS "GetText enabled; locales found: ${GETTEXT_AVAILABLE_LOCALES}")
else()
message(STATUS "ERROR: GetText enabled but not found, disabling")
set(USE_GETTEXT FALSE)
endif(GETTEXT_FOUND)
else(USE_GETTEXT)
set(USE_GETTEXT 1)
message(STATUS "GetText enabled; locales found: ${GETTEXT_AVAILABLE_LOCALES}")
elseif(GETTEXT_FOUND AND NOT ENABLE_GETTEXT)
MESSAGE(STATUS "GetText found but disabled;")
else(GETTEXT_FOUND AND ENABLE_GETTEXT)
message(STATUS "GetText disabled")
endif(USE_GETTEXT)
endif(GETTEXT_FOUND AND ENABLE_GETTEXT)
if(NOT MSVC)
set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
@@ -73,7 +74,7 @@ else()
endif(APPLE)
endif(BUILD_CLIENT)
find_package(ZLIB REQUIRED)
set(PLATFORM_LIBS -lpthread)
set(PLATFORM_LIBS -lpthread ${CMAKE_DL_LIBS})
#set(CLIENT_PLATFORM_LIBS -lXxf86vm)
# This way Xxf86vm is found on OpenBSD too
find_library(XXF86VM_LIBRARY Xxf86vm)
@@ -126,6 +127,7 @@ set(common_SRCS
test.cpp
sha1.cpp
base64.cpp
ban.cpp
)
# This gives us the icon
@@ -172,7 +174,7 @@ include_directories(
${SQLITE3_INCLUDE_DIR}
)
set(EXECUTABLE_OUTPUT_PATH ../bin)
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin")
if(BUILD_CLIENT)
add_executable(${PROJECT_NAME} ${minetest_SRCS})
@@ -186,10 +188,10 @@ if(BUILD_CLIENT)
${PNG_LIBRARIES}
${X11_LIBRARIES}
${GETTEXT_LIBRARY}
${PLATFORM_LIBS}
${CLIENT_PLATFORM_LIBS}
${JTHREAD_LIBRARY}
${SQLITE3_LIBRARY}
${PLATFORM_LIBS}
${CLIENT_PLATFORM_LIBS}
)
endif(BUILD_CLIENT)
@@ -198,9 +200,9 @@ if(BUILD_SERVER)
target_link_libraries(
${PROJECT_NAME}server
${ZLIB_LIBRARIES}
${PLATFORM_LIBS}
${JTHREAD_LIBRARY}
${SQLITE3_LIBRARY}
${PLATFORM_LIBS}
)
endif(BUILD_SERVER)
@@ -208,6 +210,8 @@ endif(BUILD_SERVER)
# Set some optimizations and tweaks
#
include(CheckCXXCompilerFlag)
if(MSVC)
# Visual Studio
@@ -234,8 +238,11 @@ else()
set(RELEASE_WARNING_FLAGS "")
endif()
if(NOT APPLE)
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-but-set-variable")
if(NOT APPLE AND NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
CHECK_CXX_COMPILER_FLAG("-Wno-unused-but-set-variable" HAS_UNUSED_BUT_SET_VARIABLE_WARNING)
if(HAS_UNUSED_BUT_SET_VARIABLE_WARNING)
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-but-set-variable")
endif(HAS_UNUSED_BUT_SET_VARIABLE_WARNING)
endif()
if(APPLE)
@@ -274,7 +281,7 @@ if(BUILD_CLIENT)
install(FILES ${images} DESTINATION ${DATADIR})
if (USE_GETTEXT)
if(USE_GETTEXT)
foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
set(MO_BUILD_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
@@ -305,54 +312,29 @@ if(BUILD_SERVER)
endif(BUILD_SERVER)
if (USE_GETTEXT)
add_custom_command(OUTPUT "${GETTEXT_PO_PATH}/en"
COMMAND ${CMAKE_COMMAND} -E make_directory "${GETTEXT_PO_PATH}/en"
COMMENT "po-update [en]: creating translation template base directory")
set(POT_FILE "${GETTEXT_PO_PATH}/en/minetest.pot")
file(GLOB GETTEXT_POT_DEPS *.cpp *.h)
file(GLOB GETTEXT_POT_DEPS_REL RELATIVE ${CMAKE_SOURCE_DIR} *.cpp *.h)
add_custom_command(OUTPUT ${POT_FILE}
COMMAND ${GETTEXT_EXTRACT} -F -n -o ${POT_FILE} ${GETTEXT_POT_DEPS_REL}
DEPENDS "${GETTEXT_PO_PATH}/en" ${GETTEXT_POT_DEPS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "po-update [en]: updating translation template")
set(PO_FILES)
set(MO_FILES)
foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
# skip the 'en' locale which is treated separately
if (NOT LOCALE STREQUAL "en")
set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/minetest.po")
add_custom_command(OUTPUT ${PO_FILE_PATH}
COMMAND ${GETTEXT_MSGMERGE} -F -U ${PO_FILE_PATH} ${POT_FILE}
DEPENDS ${POT_FILE}
WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
COMMENT "po-update [${LOCALE}]: updating strings")
set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/minetest.po")
set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
set(MO_FILE_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
add_custom_command(OUTPUT ${MO_BUILD_PATH}
COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH}
COMMENT "mo-update [${LOCALE}]: Creating locale directory.")
set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
add_custom_command(OUTPUT ${MO_BUILD_PATH}
COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH}
COMMENT "mo-update [${LOCALE}]: Creating locale directory.")
add_custom_command(
OUTPUT ${MO_FILE_PATH}
COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH}
DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH}
WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
COMMENT "mo-update [${LOCALE}]: Creating mo file."
)
set(MO_FILE_PATH "${MO_BUILD_PATH}/minetest.mo")
add_custom_command(
OUTPUT ${MO_FILE_PATH}
COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH}
DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH}
WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
COMMENT "mo-update [${LOCALE}]: Creating mo file."
)
set(MO_FILES ${MO_FILES} ${MO_FILE_PATH})
set(PO_FILES ${PO_FILES} ${PO_FILE_PATH})
endif(NOT LOCALE STREQUAL "en")
set(MO_FILES ${MO_FILES} ${MO_FILE_PATH})
endforeach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
add_custom_target(translations ALL COMMENT "mo update" DEPENDS ${MO_FILES})
add_custom_target(updatepo COMMENT "po update" DEPENDS ${PO_FILES})
endif(USE_GETTEXT)
# Subdirectories

View File

@@ -40,6 +40,8 @@ std::string privsToString(u64 privs)
os<<"privs,";
if(privs & PRIV_SHOUT)
os<<"shout,";
if(privs & PRIV_BAN)
os<<"ban,";
if(os.tellp())
{
// Drop the trailing comma. (Why on earth can't
@@ -70,6 +72,8 @@ u64 stringToPrivs(std::string str)
privs |= PRIV_PRIVS;
else if(s == "shout")
privs |= PRIV_SHOUT;
else if(s == "ban")
privs |= PRIV_BAN;
else
return PRIV_INVALID;
}

View File

@@ -38,6 +38,7 @@ const u64 PRIV_SERVER = 16; // Can manage the server (e.g. shutodwn
// ,settings)
const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all
// players
const u64 PRIV_BAN = 64; // Can ban players
// Default privileges - these can be overriden for new players using the
// config option "default_privs" - however, this value still applies for

163
src/ban.cpp Normal file
View File

@@ -0,0 +1,163 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
*/
#include "ban.h"
#include <fstream>
#include <jmutexautolock.h>
#include <sstream>
#include <set>
#include "strfnd.h"
#include "debug.h"
BanManager::BanManager(const std::string &banfilepath):
m_banfilepath(banfilepath),
m_modified(false)
{
m_mutex.Init();
try{
load();
}
catch(SerializationError &e)
{
dstream<<"WARNING: BanManager: creating "
<<m_banfilepath<<std::endl;
}
}
BanManager::~BanManager()
{
save();
}
void BanManager::load()
{
JMutexAutoLock lock(m_mutex);
dstream<<"BanManager: loading from "<<m_banfilepath<<std::endl;
std::ifstream is(m_banfilepath.c_str(), std::ios::binary);
if(is.good() == false)
{
dstream<<"BanManager: failed loading from "<<m_banfilepath<<std::endl;
throw SerializationError("BanManager::load(): Couldn't open file");
}
for(;;)
{
if(is.eof() || is.good() == false)
break;
std::string line;
std::getline(is, line, '\n');
Strfnd f(line);
std::string ip = trim(f.next("|"));
std::string name = trim(f.next("|"));
if(ip.empty())
continue;
m_ips[ip] = name;
}
m_modified = false;
}
void BanManager::save()
{
JMutexAutoLock lock(m_mutex);
dstream<<"BanManager: saving to "<<m_banfilepath<<std::endl;
std::ofstream os(m_banfilepath.c_str(), std::ios::binary);
if(os.good() == false)
{
dstream<<"BanManager: failed loading from "<<m_banfilepath<<std::endl;
throw SerializationError("BanManager::load(): Couldn't open file");
}
for(std::map<std::string, std::string>::iterator
i = m_ips.begin();
i != m_ips.end(); i++)
{
os<<i->first<<"|"<<i->second<<"\n";
}
m_modified = false;
}
bool BanManager::isIpBanned(const std::string &ip)
{
JMutexAutoLock lock(m_mutex);
return m_ips.find(ip) != m_ips.end();
}
std::string BanManager::getBanDescription(const std::string &ip_or_name)
{
JMutexAutoLock lock(m_mutex);
std::string s = "";
for(std::map<std::string, std::string>::iterator
i = m_ips.begin();
i != m_ips.end(); i++)
{
if(i->first == ip_or_name || i->second == ip_or_name
|| ip_or_name == "")
s += i->first + "|" + i->second + ", ";
}
s = s.substr(0, s.size()-2);
return s;
}
std::string BanManager::getBanName(const std::string &ip)
{
JMutexAutoLock lock(m_mutex);
std::map<std::string, std::string>::iterator i = m_ips.find(ip);
if(i == m_ips.end())
return "";
return i->second;
}
void BanManager::add(const std::string &ip, const std::string &name)
{
JMutexAutoLock lock(m_mutex);
m_ips[ip] = name;
m_modified = true;
}
void BanManager::remove(const std::string &ip_or_name)
{
JMutexAutoLock lock(m_mutex);
//m_ips.erase(m_ips.find(ip));
// Find out all ip-name pairs that match the ip or name
std::set<std::string> ips_to_delete;
for(std::map<std::string, std::string>::iterator
i = m_ips.begin();
i != m_ips.end(); i++)
{
if(i->first == ip_or_name || i->second == ip_or_name)
ips_to_delete.insert(i->first);
}
// Erase them
for(std::set<std::string>::iterator
i = ips_to_delete.begin();
i != ips_to_delete.end(); i++)
{
m_ips.erase(*i);
}
m_modified = true;
}
bool BanManager::isModified()
{
JMutexAutoLock lock(m_mutex);
return m_modified;
}

52
src/ban.h Normal file
View File

@@ -0,0 +1,52 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
*/
#ifndef BAN_HEADER
#define BAN_HEADER
#include <map>
#include <string>
#include <jthread.h>
#include <jmutex.h>
#include "common_irrlicht.h"
#include "exceptions.h"
class BanManager
{
public:
BanManager(const std::string &bannfilepath);
~BanManager();
void load();
void save();
bool isIpBanned(const std::string &ip);
// Supplying ip_or_name = "" lists all bans.
std::string getBanDescription(const std::string &ip_or_name);
std::string getBanName(const std::string &ip);
void add(const std::string &ip, const std::string &name);
void remove(const std::string &ip_or_name);
bool isModified();
private:
JMutex m_mutex;
std::string m_banfilepath;
std::map<std::string, std::string> m_ips;
bool m_modified;
};
#endif

View File

@@ -431,7 +431,7 @@ void Client::step(float dtime)
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
// This should be incremented in each version
writeU16(&data[51], 1);
writeU16(&data[51], 2);
// Send as unreliable
Send(0, data, false);
@@ -936,7 +936,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
*/
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
/*
Add it to mesh update queue and set it to be acknowledged after update.
*/
@@ -1418,7 +1417,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
for all added objects {
u16 id
u8 type
u16 initialization data length
u32 initialization data length
string initialization data
}
*/
@@ -1550,6 +1549,47 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
// get damage from falling on ground
m_ignore_damage_timer = 3.0;
}
else if(command == TOCLIENT_PLAYERITEM)
{
std::string datastring((char*)&data[2], datasize-2);
std::istringstream is(datastring, std::ios_base::binary);
u16 count = readU16(is);
for (u16 i = 0; i < count; ++i) {
u16 peer_id = readU16(is);
Player *player = m_env.getPlayer(peer_id);
if (player == NULL)
{
dout_client<<DTIME<<"Client: ignoring player item "
<< deSerializeString(is)
<< " for non-existing peer id " << peer_id
<< std::endl;
continue;
} else if (player->isLocal()) {
dout_client<<DTIME<<"Client: ignoring player item "
<< deSerializeString(is)
<< " for local player" << std::endl;
continue;
} else {
InventoryList *inv = player->inventory.getList("main");
std::string itemstring(deSerializeString(is));
if (itemstring.empty()) {
inv->deleteItem(0);
dout_client<<DTIME
<<"Client: empty player item for peer "
<< peer_id << std::endl;
} else {
std::istringstream iss(itemstring);
delete inv->changeItem(0, InventoryItem::deSerialize(iss));
dout_client<<DTIME<<"Client: player item for peer " << peer_id << ": ";
player->getWieldItem()->serialize(dout_client);
dout_client<<std::endl;
}
}
}
}
else
{
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
@@ -1865,6 +1905,28 @@ void Client::sendPlayerPos()
Send(0, data, false);
}
void Client::sendPlayerItem(u16 item)
{
Player *myplayer = m_env.getLocalPlayer();
if(myplayer == NULL)
return;
u16 our_peer_id = m_con.GetPeerID();
// Set peer id if not set already
if(myplayer->peer_id == PEER_ID_INEXISTENT)
myplayer->peer_id = our_peer_id;
// Check that an existing peer_id is the same as the connection's
assert(myplayer->peer_id == our_peer_id);
SharedBuffer<u8> data(2+2);
writeU16(&data[0], TOSERVER_PLAYERITEM);
writeU16(&data[2], item);
// Send as reliable
Send(0, data, true);
}
void Client::removeNode(v3s16 p)
{
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
@@ -1936,11 +1998,13 @@ NodeMetadata* Client::getNodeMetadata(v3s16 p)
return m_env.getMap().getNodeMetadata(p);
}
v3f Client::getPlayerPosition()
v3f Client::getPlayerPosition(v3f *eye_position)
{
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
if (eye_position)
*eye_position = player->getEyePosition();
return player->getPosition();
}
@@ -1952,6 +2016,16 @@ void Client::setPlayerControl(PlayerControl &control)
player->control = control;
}
void Client::selectPlayerItem(u16 item)
{
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->wieldItem(item);
sendPlayerItem(item);
}
// Returns true if the inventory of the local player has been
// updated from the server. If it is true, it is set to false.
bool Client::getLocalInventoryUpdated()

View File

@@ -206,10 +206,14 @@ class Client : public con::PeerHandler, public InventoryManager
// Wrapper to Map
NodeMetadata* getNodeMetadata(v3s16 p);
v3f getPlayerPosition();
// Get the player position, and optionally put the
// eye position in *eye_position
v3f getPlayerPosition(v3f *eye_position=NULL);
void setPlayerControl(PlayerControl &control);
void selectPlayerItem(u16 item);
// Returns true if the inventory of the local player has been
// updated from the server. If it is true, it is set to false.
bool getLocalInventoryUpdated();
@@ -266,6 +270,12 @@ class Client : public con::PeerHandler, public InventoryManager
void addChatMessage(const std::wstring &message)
{
if (message[0] == L'/') {
m_chat_queue.push_back(
(std::wstring)L"issued command: "+message);
return;
}
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
@@ -314,6 +324,8 @@ class Client : public con::PeerHandler, public InventoryManager
void sendPlayerPos();
// This sends the player's current name etc to the server
void sendPlayerInfo();
// Send the item number 'item' as player item to the server
void sendPlayerItem(u16 item);
float m_packetcounter_timer;
float m_connection_reinit_timer;

View File

@@ -90,6 +90,7 @@ enum ToClientCommand
u16 command
u16 number of player positions
for each player:
u16 peer_id
v3s32 position*100
v3s32 speed*100
s32 pitch*100
@@ -124,7 +125,7 @@ enum ToClientCommand
for all added objects {
u16 id
u8 type
u16 initialization data length
u32 initialization data length
string initialization data
}
*/
@@ -160,6 +161,17 @@ enum ToClientCommand
u16 reason_length
wstring reason
*/
TOCLIENT_PLAYERITEM = 0x36,
/*
u16 command
u16 count of player items
for all player items {
u16 peer id
u16 length of serialized item
string serialized item
}
*/
};
enum ToServerCommand
@@ -301,6 +313,14 @@ enum ToServerCommand
[30] u8[28] new password
*/
TOSERVER_PLAYERITEM=0x37,
/*
Sent to change selected item.
[0] u16 TOSERVER_PLAYERITEM
[2] u16 item
*/
};
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)

View File

@@ -3,14 +3,16 @@
#ifndef CMAKE_CONFIG_H
#define CMAKE_CONFIG_H
#define PROJECT_NAME "@PROJECT_NAME@"
#define INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
#define VERSION_STRING "@VERSION_STRING@"
#define USE_GETTEXT @USE_GETTEXT@
#ifdef NDEBUG
#define BUILD_TYPE "Release"
#else
#define BUILD_TYPE "Debug"
#endif
#define BUILD_INFO "VER="VERSION_STRING" RUN_IN_PLACE=@RUN_IN_PLACE@ INSTALL_PREFIX=@CMAKE_INSTALL_PREFIX@ BUILD_TYPE="BUILD_TYPE
#define BUILD_INFO "VER="VERSION_STRING" RUN_IN_PLACE=@RUN_IN_PLACE@ USE_GETTEXT=@USE_GETTEXT@ INSTALL_PREFIX=@CMAKE_INSTALL_PREFIX@ BUILD_TYPE="BUILD_TYPE
#endif

View File

@@ -9,6 +9,8 @@
#ifdef USE_CMAKE_CONFIG_H
#include "cmake_config.h"
#else
#define PROJECT_NAME "minetest"
//#define INSTALL_PREFIX ""
#define VERSION_STRING "unknown"
#ifdef NDEBUG
@@ -21,8 +23,13 @@
#else
#define RUN_IN_PLACE_BOOLSTRING "0"
#endif
#define BUILD_INFO "NON-CMAKE RUN_IN_PLACE="RUN_IN_PLACE_BOOLSTRING" BUILD_TYPE="BUILD_TYPE
#endif
#if USE_GETTEXT
#define USE_GETTEXT_BOOLSTRING "1"
#else
#define USE_GETTEXT_BOOLSTRING "0"
#endif
#define BUILD_INFO "NON-CMAKE RUN_IN_PLACE="RUN_IN_PLACE_BOOLSTRING" USE_GETTEXT="USE_GETTEXT_BOOLSTRING" BUILD_TYPE="BUILD_TYPE
#endif
#endif

View File

@@ -1121,7 +1121,9 @@ void Connection::Send(u16 peer_id, u8 channelnum,
{
assert(channelnum < CHANNEL_COUNT);
Peer *peer = GetPeer(peer_id);
Peer *peer = GetPeerNoEx(peer_id);
if(peer == NULL)
return;
Channel *channel = &(peer->channels[channelnum]);
u32 chunksize_max = m_max_packet_size - BASE_HEADER_SIZE;

View File

@@ -28,13 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
//#define HAXMODE 0
#define APPNAME "minetest"
#define DEBUGFILE "debug.txt"
#define WATER_ALPHA 160
//#define WATER_ALPHA 190
// Define for simulating the quirks of sending through internet.
// Causes the socket class to deliberately drop random packets.
// This disables unit testing of socket and connection.

View File

@@ -413,6 +413,36 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
// Ladder
{
ItemSpec specs[9];
specs[0] = ItemSpec(ITEM_CRAFT, "Stick");
specs[2] = ItemSpec(ITEM_CRAFT, "Stick");
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
specs[5] = ItemSpec(ITEM_CRAFT, "Stick");
specs[6] = ItemSpec(ITEM_CRAFT, "Stick");
specs[8] = ItemSpec(ITEM_CRAFT, "Stick");
if(checkItemCombination(items, specs))
{
return new MaterialItem(CONTENT_LADDER, 1);
}
}
// Iron Apple
{
ItemSpec specs[9];
specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot");
specs[4] = ItemSpec(ITEM_CRAFT, "apple");
specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot");
specs[7] = ItemSpec(ITEM_CRAFT, "steel_ingot");
if(checkItemCombination(items, specs))
{
return new CraftItem("apple_iron", 1);
}
}
return NULL;
}
@@ -470,6 +500,7 @@ void craft_set_creative_inventory(Player *player)
CONTENT_CHEST,
CONTENT_FURNACE,
CONTENT_SIGN_WALL,
CONTENT_LAVASOURCE,
CONTENT_IGNORE
};

View File

@@ -71,6 +71,10 @@ std::string item_craft_get_image_name(const std::string &subname)
return "scorched_stuff.png";
else if(subname == "firefly")
return "firefly.png";
else if(subname == "apple")
return "apple.png";
else if(subname == "apple_iron")
return "apple_iron.png";
else
return "cloud.png"; // just something
}
@@ -126,6 +130,10 @@ bool item_craft_is_eatable(const std::string &subname)
{
if(subname == "cooked_rat")
return true;
else if(subname == "apple")
return true;
else if(subname == "apple_iron")
return true;
return false;
}
@@ -133,6 +141,10 @@ s16 item_craft_eat_hp_change(const std::string &subname)
{
if(subname == "cooked_rat")
return 6; // 3 hearts
else if(subname == "apple")
return 4; // 2 hearts
else if(subname == "apple_iron")
return 8; // 4 hearts
return 0;
}

View File

@@ -133,23 +133,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
//bool smooth_lighting = g_settings.getBool("smooth_lighting");
bool invisible_stone = g_settings.getBool("invisible_stone");
float node_water_level = 1.0;
float node_liquid_level = 1.0;
if(new_style_water)
node_water_level = 0.85;
node_liquid_level = 0.85;
v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;
// Flowing water material
video::SMaterial material_water1;
material_water1.setFlag(video::EMF_LIGHTING, false);
material_water1.setFlag(video::EMF_BACK_FACE_CULLING, false);
material_water1.setFlag(video::EMF_BILINEAR_FILTER, false);
material_water1.setFlag(video::EMF_FOG_ENABLE, true);
material_water1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
AtlasPointer pa_water1 = g_texturesource->getTexture(
g_texturesource->getTextureId("water.png"));
material_water1.setTexture(0, pa_water1.atlas);
// New-style leaves material
video::SMaterial material_leaves1;
material_leaves1.setFlag(video::EMF_LIGHTING, false);
@@ -199,6 +188,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer pa_papyrus = g_texturesource->getTexture(
g_texturesource->getTextureId("papyrus.png"));
material_papyrus.setTexture(0, pa_papyrus.atlas);
// Apple material
video::SMaterial material_apple;
material_apple.setFlag(video::EMF_LIGHTING, false);
material_apple.setFlag(video::EMF_BILINEAR_FILTER, false);
material_apple.setFlag(video::EMF_FOG_ENABLE, true);
material_apple.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer pa_apple = g_texturesource->getTexture(
g_texturesource->getTextureId("apple.png"));
material_apple.setTexture(0, pa_apple.atlas);
// junglegrass material
video::SMaterial material_junglegrass;
@@ -337,30 +336,40 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
collector.append(material, vertices, 4, indices, 6);
}
/*
Add flowing water to mesh
Add flowing liquid to mesh
*/
else if(n.getContent() == CONTENT_WATER)
else if(content_features(n).liquid_type == LIQUID_FLOWING)
{
bool top_is_water = false;
assert(content_features(n).special_material);
video::SMaterial &liquid_material =
*content_features(n).special_material;
assert(content_features(n).special_atlas);
AtlasPointer &pa_liquid1 =
*content_features(n).special_atlas;
bool top_is_same_liquid = false;
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
if(ntop.getContent() == CONTENT_WATER || ntop.getContent() == CONTENT_WATERSOURCE)
top_is_water = true;
content_t c_flowing = content_features(n).liquid_alternative_flowing;
content_t c_source = content_features(n).liquid_alternative_source;
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
top_is_same_liquid = true;
u8 l = 0;
// Use the light of the node on top if possible
if(content_features(ntop).param_type == CPT_LIGHT)
l = decode_light(ntop.getLightBlend(data->m_daynight_ratio));
// Otherwise use the light of this node (the water)
// Otherwise use the light of this node (the liquid)
else
l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c = MapBlock_LightColor(WATER_ALPHA, l);
video::SColor c = MapBlock_LightColor(
content_features(n).vertex_alpha, l);
// Neighbor water levels (key = relative position)
// Neighbor liquid levels (key = relative position)
// Includes current node
core::map<v3s16, f32> neighbor_levels;
core::map<v3s16, content_t> neighbor_contents;
core::map<v3s16, u8> neighbor_flags;
const u8 neighborflag_top_is_water = 0x01;
const u8 neighborflag_top_is_same_liquid = 0x01;
v3s16 neighbor_dirs[9] = {
v3s16(0,0,0),
v3s16(0,0,1),
@@ -374,7 +383,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
};
for(u32 i=0; i<9; i++)
{
u8 content = CONTENT_AIR;
content_t content = CONTENT_AIR;
float level = -0.5 * BS;
u8 flags = 0;
// Check neighbor
@@ -384,19 +393,20 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{
content = n2.getContent();
if(n2.getContent() == CONTENT_WATERSOURCE)
level = (-0.5+node_water_level) * BS;
else if(n2.getContent() == CONTENT_WATER)
level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0
* node_water_level) * BS;
if(n2.getContent() == c_source)
level = (-0.5+node_liquid_level) * BS;
else if(n2.getContent() == c_flowing)
level = (-0.5 + ((float)(n2.param2&LIQUID_LEVEL_MASK)
+ 0.5) / 8.0 * node_liquid_level) * BS;
// Check node above neighbor.
// NOTE: This doesn't get executed if neighbor
// doesn't exist
p2.Y += 1;
n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
if(n2.getContent() == CONTENT_WATERSOURCE || n2.getContent() == CONTENT_WATER)
flags |= neighborflag_top_is_water;
if(n2.getContent() == c_source ||
n2.getContent() == c_flowing)
flags |= neighborflag_top_is_same_liquid;
}
neighbor_levels.insert(neighbor_dirs[i], level);
@@ -404,10 +414,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
neighbor_flags.insert(neighbor_dirs[i], flags);
}
//float water_level = (-0.5 + ((float)n.param2 + 0.5) / 8.0) * BS;
//float water_level = neighbor_levels[v3s16(0,0,0)];
// Corner heights (average between four waters)
// Corner heights (average between four liquids)
f32 corner_levels[4];
v3s16 halfdirs[4] = {
@@ -421,29 +428,40 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
v3s16 cornerdir = halfdirs[i];
float cornerlevel = 0;
u32 valid_count = 0;
u32 air_count = 0;
for(u32 j=0; j<4; j++)
{
v3s16 neighbordir = cornerdir - halfdirs[j];
u8 content = neighbor_contents[neighbordir];
// Special case for source nodes
if(content == CONTENT_WATERSOURCE)
content_t content = neighbor_contents[neighbordir];
// If top is liquid, draw starting from top of node
if(neighbor_flags[neighbordir] &
neighborflag_top_is_same_liquid)
{
cornerlevel = (-0.5+node_water_level)*BS;
cornerlevel = 0.5*BS;
valid_count = 1;
break;
}
else if(content == CONTENT_WATER)
// Source is always the same height
else if(content == c_source)
{
cornerlevel = (-0.5+node_liquid_level)*BS;
valid_count = 1;
break;
}
// Flowing liquid has level information
else if(content == c_flowing)
{
cornerlevel += neighbor_levels[neighbordir];
valid_count++;
}
else if(content == CONTENT_AIR)
{
cornerlevel += -0.5*BS;
valid_count++;
air_count++;
}
}
if(valid_count > 0)
if(air_count >= 2)
cornerlevel = -0.5*BS;
else if(valid_count > 0)
cornerlevel /= valid_count;
corner_levels[i] = cornerlevel;
}
@@ -469,24 +487,27 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
v3s16 dir = side_dirs[i];
/*
If our topside is water and neighbor's topside
is water, don't draw side face
If our topside is liquid and neighbor's topside
is liquid, don't draw side face
*/
if(top_is_water &&
neighbor_flags[dir] & neighborflag_top_is_water)
if(top_is_same_liquid &&
neighbor_flags[dir] & neighborflag_top_is_same_liquid)
continue;
u8 neighbor_content = neighbor_contents[dir];
content_t neighbor_content = neighbor_contents[dir];
// Don't draw face if neighbor is not air or water
// Don't draw face if neighbor is not air or liquid
if(neighbor_content != CONTENT_AIR
&& neighbor_content != CONTENT_WATER)
&& content_liquid(neighbor_content) == false)
continue;
bool neighbor_is_water = (neighbor_content == CONTENT_WATER);
bool neighbor_is_same_liquid = (neighbor_content == c_source
|| neighbor_content == c_flowing);
// Don't draw any faces if neighbor is water and top is water
if(neighbor_is_water == true && top_is_water == false)
// Don't draw any faces if neighbor same is liquid and top is
// same liquid
if(neighbor_is_same_liquid == true
&& top_is_same_liquid == false)
continue;
video::S3DVertex vertices[4] =
@@ -496,20 +517,20 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y1()),
pa_liquid1.x0(), pa_liquid1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y1()),
pa_liquid1.x1(), pa_liquid1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y0()),
pa_liquid1.x1(), pa_liquid1.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y0()),
pa_liquid1.x0(), pa_liquid1.y0()),
};
/*
If our topside is water, set upper border of face
If our topside is liquid, set upper border of face
at upper border of node
*/
if(top_is_water)
if(top_is_same_liquid)
{
vertices[2].Pos.Y = 0.5*BS;
vertices[3].Pos.Y = 0.5*BS;
@@ -524,16 +545,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
}
/*
If neighbor is water, lower border of face is corner
water levels
If neighbor is liquid, lower border of face is corner
liquid levels
*/
if(neighbor_is_water)
if(neighbor_is_same_liquid)
{
vertices[0].Pos.Y = corner_levels[side_corners[i][1]];
vertices[1].Pos.Y = corner_levels[side_corners[i][0]];
}
/*
If neighbor is not water, lower border of face is
If neighbor is not liquid, lower border of face is
lower border of node
*/
else
@@ -552,20 +573,27 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
vertices[j].Pos.rotateXZBy(90);
if(dir == v3s16(1,0,-0))
vertices[j].Pos.rotateXZBy(-90);
// Do this to not cause glitches when two liquids are
// side-by-side
if(neighbor_is_same_liquid == false){
vertices[j].Pos.X *= 0.98;
vertices[j].Pos.Z *= 0.98;
}
vertices[j].Pos += intToFloat(p + blockpos_nodes, BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_water1, vertices, 4, indices, 6);
collector.append(liquid_material, vertices, 4, indices, 6);
}
/*
Generate top side, if appropriate
*/
if(top_is_water == false)
if(top_is_same_liquid == false)
{
video::S3DVertex vertices[4] =
{
@@ -574,13 +602,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y1()),
pa_liquid1.x0(), pa_liquid1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y1()),
pa_liquid1.x1(), pa_liquid1.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y0()),
pa_liquid1.x1(), pa_liquid1.y0()),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y0()),
pa_liquid1.x0(), pa_liquid1.y0()),
};
// This fixes a strange bug
@@ -588,7 +616,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
for(s32 i=0; i<4; i++)
{
//vertices[i].Pos.Y += water_level;
//vertices[i].Pos.Y += liquid_level;
//vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
s32 j = corner_resolve[i];
vertices[i].Pos.Y += corner_levels[j];
@@ -597,29 +625,33 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_water1, vertices, 4, indices, 6);
collector.append(liquid_material, vertices, 4, indices, 6);
}
}
/*
Add water sources to mesh if using new style
*/
else if(n.getContent() == CONTENT_WATERSOURCE && new_style_water)
else if(content_features(n).liquid_type == LIQUID_SOURCE
&& new_style_water)
{
//bool top_is_water = false;
assert(content_features(n).special_material);
video::SMaterial &liquid_material =
*content_features(n).special_material;
assert(content_features(n).special_atlas);
AtlasPointer &pa_liquid1 =
*content_features(n).special_atlas;
bool top_is_air = false;
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
/*if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE)
top_is_water = true;*/
if(n.getContent() == CONTENT_AIR)
top_is_air = true;
/*if(top_is_water == true)
continue;*/
if(top_is_air == false)
continue;
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c = MapBlock_LightColor(WATER_ALPHA, l);
video::SColor c = MapBlock_LightColor(
content_features(n).vertex_alpha, l);
video::S3DVertex vertices[4] =
{
@@ -628,24 +660,24 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y1()),
pa_liquid1.x0(), pa_liquid1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y1()),
pa_liquid1.x1(), pa_liquid1.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y0()),
pa_liquid1.x1(), pa_liquid1.y0()),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y0()),
pa_liquid1.x0(), pa_liquid1.y0()),
};
for(s32 i=0; i<4; i++)
{
vertices[i].Pos.Y += (-0.5+node_water_level)*BS;
vertices[i].Pos.Y += (-0.5+node_liquid_level)*BS;
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_water1, vertices, 4, indices, 6);
collector.append(liquid_material, vertices, 4, indices, 6);
}
/*
Add leaves if using new style
@@ -1134,6 +1166,103 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
u16 indices[] = {0,1,2,2,3,0};
collector.append(material_rail, vertices, 4, indices, 6);
}
else if (n.getContent() == CONTENT_LADDER) {
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c(255,l,l,l);
float d = (float)BS/16;
// Assume wall is at X+
video::S3DVertex vertices[4] =
{
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
};
v3s16 dir = unpackDir(n.param2);
for(s32 i=0; i<4; i++)
{
if(dir == v3s16(1,0,0))
vertices[i].Pos.rotateXZBy(0);
if(dir == v3s16(-1,0,0))
vertices[i].Pos.rotateXZBy(180);
if(dir == v3s16(0,0,1))
vertices[i].Pos.rotateXZBy(90);
if(dir == v3s16(0,0,-1))
vertices[i].Pos.rotateXZBy(-90);
if(dir == v3s16(0,-1,0))
vertices[i].Pos.rotateXYBy(-90);
if(dir == v3s16(0,1,0))
vertices[i].Pos.rotateXYBy(90);
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
}
video::SMaterial material_ladder;
material_ladder.setFlag(video::EMF_LIGHTING, false);
material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
material_ladder.setTexture(0, g_texturesource->getTextureRaw("ladder.png"));
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_ladder, vertices, 4, indices, 6);
}
else if(n.getContent() == CONTENT_APPLE)
{
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
video::SColor c = MapBlock_LightColor(255, l);
for(u32 j=0; j<4; j++)
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
pa_apple.x0(), pa_apple.y1()),
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
pa_apple.x1(), pa_apple.y1()),
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
pa_apple.x1(), pa_apple.y0()),
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
pa_apple.x0(), pa_apple.y0()),
};
if(j == 0)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(45);
}
else if(j == 1)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(-45);
}
else if(j == 2)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(135);
}
else if(j == 3)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(-135);
}
for(u16 i=0; i<4; i++)
{
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_apple, vertices, 4, indices, 6);
}
}
}
}
#endif

View File

@@ -24,6 +24,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapnode.h"
#include "content_nodemeta.h"
#define WATER_ALPHA 160
#define WATER_VISC 1
#define LAVA_VISC 7
// TODO: Get rid of these and set up some attributes like toughness,
// fluffyness, and a funciton to calculate time and durability loss
// (and sound? and whatever else) from them
@@ -31,6 +36,11 @@ void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
/*
A conversion table for backwards compatibility.
Maps <=v19 content types to current ones.
Should never be touched.
*/
content_t trans_table_19[21][2] = {
{CONTENT_GRASS, 1},
{CONTENT_TREE, 4},
@@ -288,7 +298,7 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
f->solidness = 0; // drawn separately, makes no faces
f->air_equivalent = true; // grass grows underneath
f->setInventoryTexture("item_fence.png");
f->setInventoryTexture("fence.png");
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
i = CONTENT_RAIL;
@@ -303,6 +313,20 @@ void content_mapnode_init()
f->walkable = false;
setDirtLikeDiggingProperties(f->digging_properties, 0.75);
i = CONTENT_LADDER;
f = &content_features(i);
f->setInventoryTexture("ladder.png");
f->light_propagates = true;
f->param_type = CPT_LIGHT;
f->is_ground_content = true;
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
f->wall_mounted = true;
f->solidness = 0;
f->air_equivalent = true;
f->walkable = false;
f->climbable = true;
setWoodLikeDiggingProperties(f->digging_properties, 0.5);
// Deprecated
i = CONTENT_COALSTONE;
f = &content_features(i);
@@ -351,6 +375,7 @@ void content_mapnode_init()
f->param_type = CPT_LIGHT;
f->light_propagates = true;
f->solidness = 0; // Drawn separately, makes no faces
f->visual_solidness = 1;
f->walkable = false;
f->pointable = false;
f->diggable = false;
@@ -358,6 +383,22 @@ void content_mapnode_init()
f->liquid_type = LIQUID_FLOWING;
f->liquid_alternative_flowing = CONTENT_WATER;
f->liquid_alternative_source = CONTENT_WATERSOURCE;
f->liquid_viscosity = WATER_VISC;
f->vertex_alpha = WATER_ALPHA;
if(f->special_material == NULL && g_texturesource)
{
// Flowing water material
f->special_material = new video::SMaterial;
f->special_material->setFlag(video::EMF_LIGHTING, false);
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
AtlasPointer *pa_water1 = new AtlasPointer(g_texturesource->getTexture(
g_texturesource->getTextureId("water.png")));
f->special_material->setTexture(0, pa_water1->atlas);
f->special_atlas = pa_water1;
}
i = CONTENT_WATERSOURCE;
f = &content_features(i);
@@ -390,6 +431,104 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
f->liquid_alternative_flowing = CONTENT_WATER;
f->liquid_alternative_source = CONTENT_WATERSOURCE;
f->liquid_viscosity = WATER_VISC;
f->vertex_alpha = WATER_ALPHA;
if(f->special_material == NULL && g_texturesource)
{
// Flowing water material
f->special_material = new video::SMaterial;
f->special_material->setFlag(video::EMF_LIGHTING, false);
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
AtlasPointer *pa_water1 = new AtlasPointer(g_texturesource->getTexture(
g_texturesource->getTextureId("water.png")));
f->special_material->setTexture(0, pa_water1->atlas);
f->special_atlas = pa_water1;
}
i = CONTENT_LAVA;
f = &content_features(i);
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
f->param_type = CPT_LIGHT;
f->light_propagates = false;
f->light_source = LIGHT_MAX-1;
f->solidness = 0; // Drawn separately, makes no faces
f->visual_solidness = 2;
f->walkable = false;
f->pointable = false;
f->diggable = false;
f->buildable_to = true;
f->liquid_type = LIQUID_FLOWING;
f->liquid_alternative_flowing = CONTENT_LAVA;
f->liquid_alternative_source = CONTENT_LAVASOURCE;
f->liquid_viscosity = LAVA_VISC;
f->damage_per_second = 4*2;
if(f->special_material == NULL && g_texturesource)
{
// Flowing lava material
f->special_material = new video::SMaterial;
f->special_material->setFlag(video::EMF_LIGHTING, false);
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
f->special_material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer *pa_lava1 = new AtlasPointer(
g_texturesource->getTexture(
g_texturesource->getTextureId("lava.png")));
f->special_material->setTexture(0, pa_lava1->atlas);
f->special_atlas = pa_lava1;
}
i = CONTENT_LAVASOURCE;
f = &content_features(i);
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
if(new_style_water)
{
f->solidness = 0; // drawn separately, makes no faces
}
else // old style
{
f->solidness = 2;
TileSpec t;
if(g_texturesource)
t.texture = g_texturesource->getTexture("lava.png");
//t.alpha = 255;
//t.material_type = MATERIAL_ALPHA_VERTEX;
//t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
f->setAllTiles(t);
}
f->param_type = CPT_LIGHT;
f->light_propagates = false;
f->light_source = LIGHT_MAX-1;
f->walkable = false;
f->pointable = false;
f->diggable = false;
f->buildable_to = true;
f->liquid_type = LIQUID_SOURCE;
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
f->liquid_alternative_flowing = CONTENT_LAVA;
f->liquid_alternative_source = CONTENT_LAVASOURCE;
f->liquid_viscosity = LAVA_VISC;
f->damage_per_second = 4*2;
if(f->special_material == NULL && g_texturesource)
{
// Flowing lava material
f->special_material = new video::SMaterial;
f->special_material->setFlag(video::EMF_LIGHTING, false);
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
f->special_material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer *pa_lava1 = new AtlasPointer(
g_texturesource->getTexture(
g_texturesource->getTextureId("lava.png")));
f->special_material->setTexture(0, pa_lava1->atlas);
f->special_atlas = pa_lava1;
}
i = CONTENT_TORCH;
f = &content_features(i);
@@ -491,6 +630,18 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
setStoneLikeDiggingProperties(f->digging_properties, 3.0);
i = CONTENT_APPLE;
f = &content_features(i);
f->setInventoryTexture("apple.png");
f->param_type = CPT_LIGHT;
f->light_propagates = true;
f->sunlight_propagates = true;
f->solidness = 0; // drawn separately, makes no faces
f->walkable = false;
f->air_equivalent = true;
f->dug_item = std::string("CraftItem apple 1");
f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
// NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp

View File

@@ -37,15 +37,24 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
// 0x000...0x07f (0...127): param2 is fully usable
// 126 and 127 are reserved.
// Use these sparingly, only when the extra space in param2 might be needed.
// Add a space when there is unused space between numbers.
#define CONTENT_STONE 0
#define CONTENT_WATER 2
#define CONTENT_TORCH 3
#define CONTENT_WATERSOURCE 9
#define CONTENT_SIGN_WALL 14
#define CONTENT_CHEST 15
#define CONTENT_FURNACE 16
#define CONTENT_FENCE 21
#define CONTENT_RAIL 30
#define CONTENT_LADDER 31
#define CONTENT_LAVA 32
#define CONTENT_LAVASOURCE 33
// 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable
#define CONTENT_GRASS 0x800 //1
@@ -74,6 +83,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_JUNGLEGRASS 0x816
#define CONTENT_NC 0x817
#define CONTENT_NC_RB 0x818
#define CONTENT_APPLE 0x819
#endif

View File

@@ -178,23 +178,49 @@ std::string FurnaceNodeMetadata::infoText()
//return "Furnace";
if(m_fuel_time >= m_fuel_totaltime)
{
InventoryList *src_list = m_inventory->getList("src");
const InventoryList *src_list = m_inventory->getList("src");
assert(src_list);
InventoryItem *src_item = src_list->getItem(0);
const InventoryItem *src_item = src_list->getItem(0);
if(src_item)
if(src_item && src_item->isCookable()) {
InventoryList *dst_list = m_inventory->getList("dst");
if(!dst_list->roomForCookedItem(src_item))
return "Furnace is overloaded";
return "Furnace is out of fuel";
}
else
return "Furnace is inactive";
}
else
{
std::string s = "Furnace is active (";
s += itos(m_fuel_time/m_fuel_totaltime*100);
s += "%)";
std::string s = "Furnace is active";
// Do this so it doesn't always show (0%) for weak fuel
if(m_fuel_totaltime > 3) {
s += " (";
s += itos(m_fuel_time/m_fuel_totaltime*100);
s += "%)";
}
return s;
}
}
bool FurnaceNodeMetadata::nodeRemovalDisabled()
{
/*
Disable removal if furnace is not empty
*/
InventoryList *list[3] = {m_inventory->getList("src"),
m_inventory->getList("dst"), m_inventory->getList("fuel")};
for(int i = 0; i < 3; i++) {
if(list[i] == NULL)
continue;
if(list[i]->getUsedSlots() == 0)
continue;
return true;
}
return false;
}
void FurnaceNodeMetadata::inventoryModified()
{
dstream<<"Furnace inventory modification callback"<<std::endl;
@@ -221,9 +247,14 @@ bool FurnaceNodeMetadata::step(float dtime)
assert(src_list);
InventoryItem *src_item = src_list->getItem(0);
bool room_available = false;
if(src_item && src_item->isCookable())
room_available = dst_list->roomForCookedItem(src_item);
// Start only if there are free slots in dst, so that it can
// accomodate any result item
if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
if(room_available)
{
m_src_totaltime = 3;
}
@@ -252,13 +283,23 @@ bool FurnaceNodeMetadata::step(float dtime)
m_src_totaltime = 0;
}
changed = true;
continue;
// If the fuel was not used up this step, just keep burning it
if(m_fuel_time < m_fuel_totaltime)
continue;
}
/*
If there is no source item or source item is not cookable, stop loop.
Get the source again in case it has all burned
*/
if(src_item == NULL || m_src_totaltime < 0.001)
src_item = src_list->getItem(0);
/*
If there is no source item, or the source item is not cookable,
or the furnace is still cooking, or the furnace became overloaded, stop loop.
*/
if(src_item == NULL || !room_available || m_fuel_time < m_fuel_totaltime ||
dst_list->roomForCookedItem(src_item) == false)
{
m_step_accumulator = 0;
break;
@@ -268,7 +309,7 @@ bool FurnaceNodeMetadata::step(float dtime)
InventoryList *fuel_list = m_inventory->getList("fuel");
assert(fuel_list);
InventoryItem *fuel_item = fuel_list->getItem(0);
const InventoryItem *fuel_item = fuel_list->getItem(0);
if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
{

View File

@@ -76,6 +76,7 @@ class FurnaceNodeMetadata : public NodeMetadata
virtual Inventory* getInventory() {return m_inventory;}
virtual void inventoryModified();
virtual bool step(float dtime);
virtual bool nodeRemovalDisabled();
virtual std::string getInventoryDrawSpecString();
private:

View File

@@ -226,6 +226,11 @@ void ItemSAO::rightClick(Player *player)
if(to_be_deleted)
m_removed = true;
else
// Reflect changes to the item here
m_inventorystring = item->getItemString();
delete item;
}
/*

View File

@@ -68,9 +68,9 @@ Nullstream dummyout;
void assert_fail(const char *assertion, const char *file,
unsigned int line, const char *function)
{
DEBUGPRINT("\nIn thread %x:\n"
DEBUGPRINT("\nIn thread %lx:\n"
"%s:%d: %s: Assertion '%s' failed.\n",
(unsigned int)get_current_thread_id(),
(unsigned long)get_current_thread_id(),
file, line, function, assertion);
debug_stacks_print();
@@ -95,8 +95,8 @@ DebugStack::DebugStack(threadid_t id)
void DebugStack::print(FILE *file, bool everything)
{
fprintf(file, "DEBUG STACK FOR THREAD %x:\n",
(unsigned int)threadid);
fprintf(file, "DEBUG STACK FOR THREAD %lx:\n",
(unsigned long)threadid);
for(int i=0; i<stack_max_i; i++)
{

View File

@@ -85,7 +85,7 @@ class Debugbuf : public std::streambuf
return c;
}
int xsputn(const char *s, int n)
std::streamsize xsputn(const char *s, std::streamsize n)
{
for(int i=0; i<DEBUGSTREAM_COUNT; i++)
{

View File

@@ -39,6 +39,7 @@ void set_default_settings()
g_settings.setDefault("keymap_sneak", "KEY_LSHIFT");
g_settings.setDefault("keymap_inventory", "KEY_KEY_I");
g_settings.setDefault("keymap_chat", "KEY_KEY_T");
g_settings.setDefault("keymap_cmd", "/");
g_settings.setDefault("keymap_rangeselect", "KEY_KEY_R");
g_settings.setDefault("keymap_freemove", "KEY_KEY_K");
g_settings.setDefault("keymap_fastmove", "KEY_KEY_J");
@@ -70,8 +71,6 @@ void set_default_settings()
g_settings.setDefault("fast_move", "false");
g_settings.setDefault("invert_mouse", "false");
g_settings.setDefault("enable_farmesh", "false");
g_settings.setDefault("farmesh_trees", "true");
g_settings.setDefault("farmesh_distance", "40");
g_settings.setDefault("enable_clouds", "true");
g_settings.setDefault("invisible_stone", "false");
g_settings.setDefault("screenshot_path", ".");
@@ -86,6 +85,7 @@ void set_default_settings()
g_settings.setDefault("default_privs", "build, shout");
g_settings.setDefault("profiler_print_interval", "0");
g_settings.setDefault("enable_mapgen_debug_info", "false");
g_settings.setDefault("fixed_map_seed", "");
g_settings.setDefault("objectdata_interval", "0.2");
g_settings.setDefault("active_object_range", "2");

View File

@@ -1191,7 +1191,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
delete object;
return 0;
}
/*dstream<<"INGO: ServerEnvironment::addActiveObjectRaw(): "
/*dstream<<"INFO: ServerEnvironment::addActiveObjectRaw(): "
<<"added (id="<<object->getId()<<")"<<std::endl;*/
m_active_objects.insert(object->getId(), object);
@@ -1511,6 +1511,13 @@ void ClientEnvironment::step(float dtime)
/*
Get the speed the player is going
*/
bool is_climbing = lplayer->is_climbing;
/*
Check if the player is frozen (don't apply physics)
*/
bool is_frozen = lplayer->is_frozen;
f32 player_speed = 0.001; // just some small value
player_speed = lplayer->getSpeed().getLength();
@@ -1568,7 +1575,7 @@ void ClientEnvironment::step(float dtime)
v3f lplayerpos = lplayer->getPosition();
// Apply physics
if(free_move == false)
if(free_move == false && is_climbing == false && is_frozen == false)
{
// Gravity
v3f speed = lplayer->getSpeed();
@@ -1630,6 +1637,38 @@ void ClientEnvironment::step(float dtime)
}
}
/*
A quick draft of lava damage
*/
if(m_lava_hurt_interval.step(dtime, 1.0))
{
v3f pf = lplayer->getPosition();
// Feet, middle and head
v3s16 p1 = floatToInt(pf + v3f(0, BS*0.1, 0), BS);
MapNode n1 = m_map->getNodeNoEx(p1);
v3s16 p2 = floatToInt(pf + v3f(0, BS*0.8, 0), BS);
MapNode n2 = m_map->getNodeNoEx(p2);
v3s16 p3 = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
MapNode n3 = m_map->getNodeNoEx(p2);
u32 damage_per_second = 0;
damage_per_second = MYMAX(damage_per_second,
content_features(n1).damage_per_second);
damage_per_second = MYMAX(damage_per_second,
content_features(n2).damage_per_second);
damage_per_second = MYMAX(damage_per_second,
content_features(n3).damage_per_second);
if(damage_per_second != 0)
{
ClientEnvEvent event;
event.type = CEE_PLAYER_DAMAGE;
event.player_damage.amount = damage_per_second;
m_client_event_queue.push_back(event);
}
}
/*
Stuff that can be done in an arbitarily large dtime
*/
@@ -1651,7 +1690,7 @@ void ClientEnvironment::step(float dtime)
u8 light = LIGHT_MAX;
try{
// Get node at head
v3s16 p = floatToInt(playerpos + v3f(0,BS+BS/2,0), BS);
v3s16 p = player->getLightPosition();
MapNode n = m_map->getNode(p);
light = n.getLightBlend(getDayNightRatio());
}
@@ -1790,7 +1829,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
delete object;
return 0;
}
dstream<<"INGO: ClientEnvironment::addActiveObject(): "
dstream<<"INFO: ClientEnvironment::addActiveObject(): "
<<"added (id="<<object->getId()<<")"<<std::endl;
m_active_objects.insert(object->getId(), object);
object->addToScene(m_smgr);
@@ -1915,6 +1954,13 @@ void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos)
core::rect<s32> rect(0,0, ss.X, ss.Y);
driver->draw2DRectangle(video::SColor(64, 100, 100, 200), rect);
}
else if(content_features(n).solidness == 2 &&
g_settings.getBool("free_move") == false)
{
v2u32 ss = driver->getScreenSize();
core::rect<s32> rect(0,0, ss.X, ss.Y);
driver->draw2DRectangle(video::SColor(255, 0, 0, 0), rect);
}
}
#endif // #ifndef SERVER

View File

@@ -416,6 +416,7 @@ class ClientEnvironment : public Environment
core::map<u16, ClientActiveObject*> m_active_objects;
Queue<ClientEnvEvent> m_client_event_queue;
IntervalLimiter m_active_object_light_update_interval;
IntervalLimiter m_lava_hurt_interval;
};
#endif

View File

@@ -70,7 +70,6 @@ FarMesh::FarMesh(
m_box = core::aabbox3d<f32>(-BS*1000000,-BS*31000,-BS*1000000,
BS*1000000,BS*31000,BS*1000000);
trees = g_settings.getBool("farmesh_trees");
}
FarMesh::~FarMesh()
@@ -314,11 +313,12 @@ void FarMesh::render()
}
else
{
// Trees if there are over 0.01 trees per MapNode
if(trees && tree_amount_avg > 0.01)
/*// Trees if there are over 0.01 trees per MapNode
if(tree_amount_avg > 0.01)
c = video::SColor(255,50,128,50);
else
c = video::SColor(255,107,134,51);
c = video::SColor(255,107,134,51);*/
c = video::SColor(255,107,134,51);
ground_is_mud = true;
}
}
@@ -351,7 +351,7 @@ void FarMesh::render()
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
// Add some trees if appropriate
if(trees && tree_amount_avg >= 0.0065 && steepness < 1.4
if(tree_amount_avg >= 0.0065 && steepness < 1.4
&& ground_is_mud == true)
{
driver->setMaterial(m_materials[1]);
@@ -404,11 +404,11 @@ void FarMesh::step(float dtime)
m_time += dtime;
}
void FarMesh::update(v2f camera_p, float brightness)
void FarMesh::update(v2f camera_p, float brightness, s16 render_range)
{
m_camera_pos = camera_p;
m_brightness = brightness;
m_render_range = g_settings.getS16("farmesh_distance")*10;
m_render_range = render_range;
}

View File

@@ -67,7 +67,7 @@ class FarMesh : public scene::ISceneNode
void step(float dtime);
void update(v2f camera_p, float brightness);
void update(v2f camera_p, float brightness, s16 render_range);
private:
video::SMaterial m_materials[FARMESH_MATERIAL_COUNT];
@@ -79,7 +79,6 @@ class FarMesh : public scene::ISceneNode
float m_time;
Client *m_client;
s16 m_render_range;
bool trees;
};
#endif

View File

@@ -28,7 +28,7 @@ namespace fs
#ifdef _WIN32 // WINDOWS
#define _WIN32_WINNT 0x0501
#include <Windows.h>
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#include <tchar.h>
@@ -254,7 +254,7 @@ bool RecursiveDelete(std::string path)
execv(argv[0], argv);
// Execv shouldn't return. Failed.
return false;
_exit(1);
}
else
{

View File

@@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "materials.h"
#include "config.h"
#include "clouds.h"
#include "keycode.h"
#include "farmesh.h"
#include "mapblock.h"
@@ -115,18 +114,6 @@ struct TextDestChat : public TextDest
// Discard empty line
if(text == L"")
return;
// Parse command (server command starts with "/#")
if(text[0] == L'/' && text[1] != L'#')
{
std::wstring reply = L"Local: ";
reply += L"Local commands not yet supported. "
L"Server prefix is \"/#\".";
m_client->addChatMessage(reply);
return;
}
// Send to others
m_client->sendChatMessage(text);
@@ -332,17 +319,61 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
if(g_selected_item == i)
{
driver->draw2DRectangle(video::SColor(255,255,0,0),
core::rect<s32>(rect.UpperLeftCorner - v2s32(1,1)*padding,
rect.LowerRightCorner + v2s32(1,1)*padding),
NULL);
}
else
{
video::SColor bgcolor2(128,0,0,0);
driver->draw2DRectangle(bgcolor2, rect, NULL);
video::SColor c_outside(255,255,0,0);
//video::SColor c_outside(255,0,0,0);
//video::SColor c_inside(255,192,192,192);
s32 x1 = rect.UpperLeftCorner.X;
s32 y1 = rect.UpperLeftCorner.Y;
s32 x2 = rect.LowerRightCorner.X;
s32 y2 = rect.LowerRightCorner.Y;
// Black base borders
driver->draw2DRectangle(c_outside,
core::rect<s32>(
v2s32(x1 - padding, y1 - padding),
v2s32(x2 + padding, y1)
), NULL);
driver->draw2DRectangle(c_outside,
core::rect<s32>(
v2s32(x1 - padding, y2),
v2s32(x2 + padding, y2 + padding)
), NULL);
driver->draw2DRectangle(c_outside,
core::rect<s32>(
v2s32(x1 - padding, y1),
v2s32(x1, y2)
), NULL);
driver->draw2DRectangle(c_outside,
core::rect<s32>(
v2s32(x2, y1),
v2s32(x2 + padding, y2)
), NULL);
/*// Light inside borders
driver->draw2DRectangle(c_inside,
core::rect<s32>(
v2s32(x1 - padding/2, y1 - padding/2),
v2s32(x2 + padding/2, y1)
), NULL);
driver->draw2DRectangle(c_inside,
core::rect<s32>(
v2s32(x1 - padding/2, y2),
v2s32(x2 + padding/2, y2 + padding/2)
), NULL);
driver->draw2DRectangle(c_inside,
core::rect<s32>(
v2s32(x1 - padding/2, y1),
v2s32(x1, y2)
), NULL);
driver->draw2DRectangle(c_inside,
core::rect<s32>(
v2s32(x2, y1),
v2s32(x2 + padding/2, y2)
), NULL);
*/
}
video::SColor bgcolor2(128,0,0,0);
driver->draw2DRectangle(bgcolor2, rect, NULL);
if(item != NULL)
{
drawInventoryItem(driver, font, item, rect, NULL);
@@ -538,6 +569,56 @@ void getPointedNode(Client *client, v3f player_position,
}
}
}
else if(n.getContent() == CONTENT_LADDER)
{
v3s16 dir = unpackDir(n.param2);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f;
f32 distance = (cpf - camera_position).getLength();
v3f vertices[4] =
{
v3f(BS*0.42,-BS/2,-BS/2),
v3f(BS*0.49, BS/2, BS/2),
};
for(s32 i=0; i<2; i++)
{
if(dir == v3s16(1,0,0))
vertices[i].rotateXZBy(0);
if(dir == v3s16(-1,0,0))
vertices[i].rotateXZBy(180);
if(dir == v3s16(0,0,1))
vertices[i].rotateXZBy(90);
if(dir == v3s16(0,0,-1))
vertices[i].rotateXZBy(-90);
if(dir == v3s16(0,-1,0))
vertices[i].rotateXYBy(-90);
if(dir == v3s16(0,1,0))
vertices[i].rotateXYBy(90);
vertices[i] += npf;
}
core::aabbox3d<f32> box;
box = core::aabbox3d<f32>(vertices[0]);
box.addInternalPoint(vertices[1]);
if(distance < mindistance)
{
if(box.intersectsWithLine(shootline))
{
nodefound = true;
nodepos = np;
neighbourpos = np;
mindistance = distance;
nodehilightbox = box;
}
}
}
else if(n.getContent() == CONTENT_RAIL)
{
v3s16 dir = unpackDir(n.param0);
@@ -1012,6 +1093,14 @@ void the_game(
{
//std::cerr<<"frame"<<std::endl;
if(client.accessDenied())
{
error_message = L"Access denied. Reason: "
+client.accessDeniedReason();
std::cout<<DTIME<<wide_to_narrow(error_message)<<std::endl;
break;
}
if(g_gamecallback->disconnect_requested)
{
g_gamecallback->disconnect_requested = false;
@@ -1256,7 +1345,7 @@ void the_game(
menu->drop();
}
else if(input->wasKeyDown(KEY_ESCAPE))
else if(input->wasKeyDown(EscapeKey))
{
dstream<<DTIME<<"the_game: "
<<"Launching pause menu"<<std::endl;
@@ -1275,6 +1364,14 @@ void the_game(
&g_menumgr, dest,
L""))->drop();
}
else if(input->wasKeyDown(getKeySetting("keymap_cmd")))
{
TextDest *dest = new TextDestChat(&client);
(new GUITextInputMenu(guienv, guiroot, -1,
&g_menumgr, dest,
L"/"))->drop();
}
else if(input->wasKeyDown(getKeySetting("keymap_freemove")))
{
if(g_settings.getBool("free_move"))
@@ -1359,10 +1456,8 @@ void the_game(
// Item selection
for(u16 i=0; i<10; i++)
{
s32 keycode = irr::KEY_KEY_1 + i;
if(i == 9)
keycode = irr::KEY_KEY_0;
if(input->wasKeyDown((irr::EKEY_CODE)keycode))
const KeyPress *kp = NumberKey + (i + 1) % 10;
if(input->wasKeyDown(*kp))
{
if(i < PLAYER_INVENTORY_SIZE && i < hotbar_itemcount)
{
@@ -1471,7 +1566,8 @@ void the_game(
}
// Get player position
v3f player_position = client.getPlayerPosition();
v3f camera_position;
v3f player_position = client.getPlayerPosition(&camera_position);
//TimeTaker //timer2("//timer2");
@@ -1531,11 +1627,6 @@ void the_game(
v3f camera_direction = v3f(0,0,1);
camera_direction.rotateYZBy(camera_pitch);
camera_direction.rotateXZBy(camera_yaw);
// This is at the height of the eyes of the current figure
//v3f camera_position = player_position + v3f(0, BS+BS/2, 0);
// This is more like in minecraft
v3f camera_position = player_position + v3f(0, BS+BS*0.625, 0);
camera->setPosition(camera_position);
// *100.0 helps in large map coordinates
@@ -1955,9 +2046,15 @@ void the_game(
*/
if(farmesh)
{
farmesh_range = draw_control.wanted_range * 10;
if(draw_control.range_all && farmesh_range < 500)
farmesh_range = 500;
if(farmesh_range > 1000)
farmesh_range = 1000;
farmesh->step(dtime);
farmesh->update(v2f(player_position.X, player_position.Z),
0.05+brightness*0.95);
0.05+brightness*0.95, farmesh_range);
}
// Store brightness value
@@ -2148,6 +2245,7 @@ void the_game(
if(client.getLocalInventoryUpdated()
|| g_selected_item != old_selected_item)
{
client.selectPlayerItem(g_selected_item);
old_selected_item = g_selected_item;
//std::cout<<"Updating local inventory"<<std::endl;
client.getLocalInventory(local_inventory);
@@ -2254,6 +2352,13 @@ void the_game(
// 0-1ms
guienv->drawAll();
/*
Environment post fx
*/
{
client.getEnv()->drawPostFx(driver, camera_position);
}
/*
Draw hotbar
*/
@@ -2276,13 +2381,6 @@ void the_game(
NULL);
}
/*
Environment post fx
*/
{
client.getEnv()->drawPostFx(driver, camera_position);
}
/*
End scene
*/

View File

@@ -23,6 +23,69 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h"
#include <string>
#include "keycode.h"
class KeyList : protected core::list<KeyPress>
{
typedef core::list<KeyPress> super;
typedef super::Iterator Iterator;
typedef super::ConstIterator ConstIterator;
virtual ConstIterator find(const KeyPress &key) const
{
ConstIterator f(begin());
ConstIterator e(end());
while (f!=e) {
if (*f == key)
return f;
++f;
}
return e;
}
virtual Iterator find(const KeyPress &key)
{
Iterator f(begin());
Iterator e(end());
while (f!=e) {
if (*f == key)
return f;
++f;
}
return e;
}
public:
void clear() { super::clear(); }
void set(const KeyPress &key)
{
if (find(key) == end())
push_back(key);
}
void unset(const KeyPress &key)
{
Iterator p(find(key));
if (p != end())
erase(p);
}
void toggle(const KeyPress &key)
{
Iterator p(this->find(key));
if (p != end())
erase(p);
else
push_back(key);
}
bool operator[](const KeyPress &key) const
{
return find(key) != end();
}
};
class InputHandler
{
public:
@@ -33,8 +96,8 @@ class InputHandler
{
}
virtual bool isKeyDown(EKEY_CODE keyCode) = 0;
virtual bool wasKeyDown(EKEY_CODE keyCode) = 0;
virtual bool isKeyDown(const KeyPress &keyCode) = 0;
virtual bool wasKeyDown(const KeyPress &keyCode) = 0;
virtual v2s32 getMousePos() = 0;
virtual void setMousePos(s32 x, s32 y) = 0;

View File

@@ -1,4 +1,8 @@
#ifdef USE_GETTEXT
#ifndef GETTEXT_HEADER
#include "config.h" // for USE_GETTEXT
#include <iostream>
#if USE_GETTEXT
#include <libintl.h>
#else
#define gettext(String) String
@@ -8,6 +12,17 @@
#define gettext_noop(String) String
#define N_(String) gettext_noop (String)
inline void init_gettext(const char *path) {
#if USE_GETTEXT
// don't do this if MSVC compiler is used, it gives an assertion fail
#ifndef _MSC_VER
setlocale(LC_MESSAGES, "");
#endif
bindtextdomain(PROJECT_NAME, path);
textdomain(PROJECT_NAME);
#endif
}
inline wchar_t* chartowchar_t(const char *str)
{
size_t l = strlen(str)+1;
@@ -15,3 +30,20 @@ inline wchar_t* chartowchar_t(const char *str)
mbstowcs(nstr, str, l);
return nstr;
}
inline wchar_t* wgettext(const char *str)
{
return chartowchar_t(gettext(str));
}
inline void changeCtype(const char *l)
{
char *ret = NULL;
ret = setlocale(LC_CTYPE, l);
if(ret == NULL)
std::cout<<"locale could not be set"<<std::endl;
else
std::cout<<"locale has been set to:"<<ret<<std::endl;
}
#define GETTEXT_HEADER
#endif

View File

@@ -41,7 +41,7 @@ void drawInventoryItem(video::IVideoDriver *driver,
driver->draw2DImage(texture, rect,
core::rect<s32>(core::position2d<s32>(0,0),
core::dimension2di(texture->getOriginalSize())),
clip, colors, false);
clip, colors, true);
}
else
{
@@ -241,22 +241,31 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s)
if(m_selected_item != NULL && m_selected_item->listname == s.listname
&& m_selected_item->i == i)
{
/*s32 border = imgsize.X/12;
driver->draw2DRectangle(video::SColor(255,192,192,192),
core::rect<s32>(rect.UpperLeftCorner - v2s32(1,1)*border,
rect.LowerRightCorner + v2s32(1,1)*border),
NULL);
driver->draw2DRectangle(video::SColor(255,0,0,0),
core::rect<s32>(rect.UpperLeftCorner - v2s32(1,1)*((border+1)/2),
rect.LowerRightCorner + v2s32(1,1)*((border+1)/2)),
NULL);*/
s32 border = 2;
driver->draw2DRectangle(video::SColor(255,255,0,0),
core::rect<s32>(rect.UpperLeftCorner - v2s32(2,2),
rect.LowerRightCorner + v2s32(2,2)),
core::rect<s32>(rect.UpperLeftCorner - v2s32(1,1)*border,
rect.LowerRightCorner + v2s32(1,1)*border),
&AbsoluteClippingRect);
}
video::SColor bgcolor(255,128,128,128);
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
if(item)
{
drawInventoryItem(driver, font, item,
rect, &AbsoluteClippingRect);
}
else
{
video::SColor bgcolor(255,128,128,128);
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
}
}
}
@@ -290,12 +299,9 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
{
quitMenu();
return true;
}
if(event.KeyInput.Key==getKeySetting("keymap_inventory") && event.KeyInput.PressedDown)
KeyPress kp(event.KeyInput);
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
kp == getKeySetting("keymap_inventory")))
{
quitMenu();
return true;
@@ -303,10 +309,17 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
}
if(event.EventType==EET_MOUSE_INPUT_EVENT)
{
if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN
|| event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
char amount = -1;
if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
amount = 0;
else if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
amount = 1;
else if(event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN)
amount = 10;
if(amount >= 0)
{
bool right = (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN);
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
//dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
ItemSpec s = getItemAtPos(p);
@@ -337,7 +350,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
{
dstream<<"Handing IACTION_MOVE to manager"<<std::endl;
IMoveAction *a = new IMoveAction();
a->count = right ? 1 : 0;
a->count = amount;
a->from_inv = m_selected_item->inventoryname;
a->from_list = m_selected_item->listname;
a->from_i = m_selected_item->i;
@@ -352,7 +365,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
}
// Remove selection if target was left-clicked or source
// slot was emptied
if(right == false || source_empties)
if(amount == 0 || source_empties)
{
delete m_selected_item;
m_selected_item = NULL;

View File

@@ -22,7 +22,6 @@
#include "guiKeyChangeMenu.h"
#include "debug.h"
#include "serialization.h"
#include "keycode.h"
#include "main.h"
#include <string>
@@ -76,13 +75,13 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
recalculateAbsolutePosition(false);
v2s32 topleft(0, 0);
changeCtype("");
{
core::rect < s32 > rect(0, 0, 125, 20);
rect += topleft + v2s32(25, 3);
const wchar_t *text = L"KEYBINDINGS";
//gui::IGUIStaticText *t =
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("KEYBINDINGS"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
v2s32 offset(25, 40);
@@ -91,8 +90,8 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Forward";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Forward"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -101,15 +100,15 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->forward = Environment->addButton(rect, this,
GUI_ID_KEY_FORWARD_BUTTON,
narrow_to_wide(KeyNames[key_forward]).c_str());
wgettext(key_forward.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Backward";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Backward"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -118,14 +117,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->backward = Environment->addButton(rect, this,
GUI_ID_KEY_BACKWARD_BUTTON,
narrow_to_wide(KeyNames[key_backward]).c_str());
wgettext(key_backward.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Left";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Left"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -133,14 +132,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->left = Environment->addButton(rect, this, GUI_ID_KEY_LEFT_BUTTON,
narrow_to_wide(KeyNames[key_left]).c_str());
wgettext(key_left.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Right";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Right"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -149,14 +148,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->right = Environment->addButton(rect, this,
GUI_ID_KEY_RIGHT_BUTTON,
narrow_to_wide(KeyNames[key_right]).c_str());
wgettext(key_right.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Use";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Use"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -164,14 +163,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->use = Environment->addButton(rect, this, GUI_ID_KEY_USE_BUTTON,
narrow_to_wide(KeyNames[key_use]).c_str());
wgettext(key_use.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Sneak";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Sneak"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -180,14 +179,13 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->sneak = Environment->addButton(rect, this,
GUI_ID_KEY_SNEAK_BUTTON,
narrow_to_wide(KeyNames[key_sneak]).c_str());
wgettext(key_sneak.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Jump";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Jump"), rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -195,15 +193,15 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->jump = Environment->addButton(rect, this, GUI_ID_KEY_JUMP_BUTTON,
narrow_to_wide(KeyNames[key_jump]).c_str());
wgettext(key_jump.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Inventory";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Inventory"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -212,14 +210,13 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->inventory = Environment->addButton(rect, this,
GUI_ID_KEY_INVENTORY_BUTTON,
narrow_to_wide(KeyNames[key_inventory]).c_str());
wgettext(key_inventory.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Chat";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Chat"), rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -227,16 +224,31 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->chat = Environment->addButton(rect, this, GUI_ID_KEY_CHAT_BUTTON,
narrow_to_wide(KeyNames[key_chat]).c_str());
wgettext(key_chat.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
Environment->addStaticText(wgettext("Command"), rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
{
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->cmd = Environment->addButton(rect, this, GUI_ID_KEY_CMD_BUTTON,
wgettext(key_cmd.name()));
}
//next col
offset = v2s32(250, 40);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Toggle fly";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Toggle fly"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -244,14 +256,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->fly = Environment->addButton(rect, this, GUI_ID_KEY_FLY_BUTTON,
narrow_to_wide(KeyNames[key_fly]).c_str());
wgettext(key_fly.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Toggle fast";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Toggle fast"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -259,14 +271,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->fast = Environment->addButton(rect, this, GUI_ID_KEY_FAST_BUTTON,
narrow_to_wide(KeyNames[key_fast]).c_str());
wgettext(key_fast.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Range select";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Range select"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -275,15 +287,15 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->range = Environment->addButton(rect, this,
GUI_ID_KEY_RANGE_BUTTON,
narrow_to_wide(KeyNames[key_range]).c_str());
wgettext(key_range.name()));
}
offset += v2s32(0, 25);
{
core::rect < s32 > rect(0, 0, 100, 20);
rect += topleft + v2s32(offset.X, offset.Y);
const wchar_t *text = L"Print stacks";
Environment->addStaticText(text, rect, false, true, this, -1);
Environment->addStaticText(wgettext("Print stacks"),
rect, false, true, this, -1);
//t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
}
@@ -291,18 +303,21 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
this->dump = Environment->addButton(rect, this, GUI_ID_KEY_DUMP_BUTTON,
narrow_to_wide(KeyNames[key_dump]).c_str());
wgettext(key_dump.name()));
}
{
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40);
Environment->addButton(rect, this, GUI_ID_BACK_BUTTON, L"Save");
Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
wgettext("Save"));
}
{
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40);
Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, L"Cancel");
Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
wgettext("Cancel"));
}
changeCtype("C");
}
void GUIKeyChangeMenu::drawMenu()
@@ -325,19 +340,20 @@ void GUIKeyChangeMenu::drawMenu()
bool GUIKeyChangeMenu::acceptInput()
{
g_settings.set("keymap_forward", keycode_to_keyname(key_forward));
g_settings.set("keymap_backward", keycode_to_keyname(key_backward));
g_settings.set("keymap_left", keycode_to_keyname(key_left));
g_settings.set("keymap_right", keycode_to_keyname(key_right));
g_settings.set("keymap_jump", keycode_to_keyname(key_jump));
g_settings.set("keymap_sneak", keycode_to_keyname(key_sneak));
g_settings.set("keymap_inventory", keycode_to_keyname(key_inventory));
g_settings.set("keymap_chat", keycode_to_keyname(key_chat));
g_settings.set("keymap_rangeselect", keycode_to_keyname(key_range));
g_settings.set("keymap_freemove", keycode_to_keyname(key_fly));
g_settings.set("keymap_fastmove", keycode_to_keyname(key_fast));
g_settings.set("keymap_special1", keycode_to_keyname(key_use));
g_settings.set("keymap_print_debug_stacks", keycode_to_keyname(key_dump));
g_settings.set("keymap_forward", key_forward.sym());
g_settings.set("keymap_backward", key_backward.sym());
g_settings.set("keymap_left", key_left.sym());
g_settings.set("keymap_right", key_right.sym());
g_settings.set("keymap_jump", key_jump.sym());
g_settings.set("keymap_sneak", key_sneak.sym());
g_settings.set("keymap_inventory", key_inventory.sym());
g_settings.set("keymap_chat", key_chat.sym());
g_settings.set("keymap_cmd", key_cmd.sym());
g_settings.set("keymap_rangeselect", key_range.sym());
g_settings.set("keymap_freemove", key_fly.sym());
g_settings.set("keymap_fastmove", key_fast.sym());
g_settings.set("keymap_special1", key_use.sym());
g_settings.set("keymap_print_debug_stacks", key_dump.sym());
clearKeyCache();
return true;
}
@@ -351,6 +367,7 @@ void GUIKeyChangeMenu::init_keys()
key_sneak = getKeySetting("keymap_sneak");
key_inventory = getKeySetting("keymap_inventory");
key_chat = getKeySetting("keymap_chat");
key_cmd = getKeySetting("keymap_cmd");
key_range = getKeySetting("keymap_rangeselect");
key_fly = getKeySetting("keymap_freemove");
key_fast = getKeySetting("keymap_fastmove");
@@ -366,45 +383,48 @@ bool GUIKeyChangeMenu::resetMenu()
{
case GUI_ID_KEY_FORWARD_BUTTON:
this->forward->setText(
narrow_to_wide(KeyNames[key_forward]).c_str());
wgettext(key_forward.name()));
break;
case GUI_ID_KEY_BACKWARD_BUTTON:
this->backward->setText(
narrow_to_wide(KeyNames[key_backward]).c_str());
wgettext(key_backward.name()));
break;
case GUI_ID_KEY_LEFT_BUTTON:
this->left->setText(narrow_to_wide(KeyNames[key_left]).c_str());
this->left->setText(wgettext(key_left.name()));
break;
case GUI_ID_KEY_RIGHT_BUTTON:
this->right->setText(narrow_to_wide(KeyNames[key_right]).c_str());
this->right->setText(wgettext(key_right.name()));
break;
case GUI_ID_KEY_JUMP_BUTTON:
this->jump->setText(narrow_to_wide(KeyNames[key_jump]).c_str());
this->jump->setText(wgettext(key_jump.name()));
break;
case GUI_ID_KEY_SNEAK_BUTTON:
this->sneak->setText(narrow_to_wide(KeyNames[key_sneak]).c_str());
this->sneak->setText(wgettext(key_sneak.name()));
break;
case GUI_ID_KEY_INVENTORY_BUTTON:
this->inventory->setText(
narrow_to_wide(KeyNames[key_inventory]).c_str());
wgettext(key_inventory.name()));
break;
case GUI_ID_KEY_CHAT_BUTTON:
this->chat->setText(narrow_to_wide(KeyNames[key_chat]).c_str());
this->chat->setText(wgettext(key_chat.name()));
break;
case GUI_ID_KEY_CMD_BUTTON:
this->cmd->setText(wgettext(key_cmd.name()));
break;
case GUI_ID_KEY_RANGE_BUTTON:
this->range->setText(narrow_to_wide(KeyNames[key_range]).c_str());
this->range->setText(wgettext(key_range.name()));
break;
case GUI_ID_KEY_FLY_BUTTON:
this->fly->setText(narrow_to_wide(KeyNames[key_fly]).c_str());
this->fly->setText(wgettext(key_fly.name()));
break;
case GUI_ID_KEY_FAST_BUTTON:
this->fast->setText(narrow_to_wide(KeyNames[key_fast]).c_str());
this->fast->setText(wgettext(key_fast.name()));
break;
case GUI_ID_KEY_USE_BUTTON:
this->use->setText(narrow_to_wide(KeyNames[key_use]).c_str());
this->use->setText(wgettext(key_use.name()));
break;
case GUI_ID_KEY_DUMP_BUTTON:
this->dump->setText(narrow_to_wide(KeyNames[key_dump]).c_str());
this->dump->setText(wgettext(key_dump.name()));
break;
}
activeKey = -1;
@@ -417,85 +437,80 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
&& event.KeyInput.PressedDown)
{
changeCtype("");
KeyPress kp(event.KeyInput);
if (activeKey == GUI_ID_KEY_FORWARD_BUTTON)
{
this->forward->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_forward = event.KeyInput.Key;
this->forward->setText(wgettext(kp.name()));
this->key_forward = kp;
}
else if (activeKey == GUI_ID_KEY_BACKWARD_BUTTON)
{
this->backward->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_backward = event.KeyInput.Key;
this->backward->setText(wgettext(kp.name()));
this->key_backward = kp;
}
else if (activeKey == GUI_ID_KEY_LEFT_BUTTON)
{
this->left->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_left = event.KeyInput.Key;
this->left->setText(wgettext(kp.name()));
this->key_left = kp;
}
else if (activeKey == GUI_ID_KEY_RIGHT_BUTTON)
{
this->right->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_right = event.KeyInput.Key;
this->right->setText(wgettext(kp.name()));
this->key_right = kp;
}
else if (activeKey == GUI_ID_KEY_JUMP_BUTTON)
{
this->jump->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_jump = event.KeyInput.Key;
this->jump->setText(wgettext(kp.name()));
this->key_jump = kp;
}
else if (activeKey == GUI_ID_KEY_SNEAK_BUTTON)
{
this->sneak->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_sneak = event.KeyInput.Key;
this->sneak->setText(wgettext(kp.name()));
this->key_sneak = kp;
}
else if (activeKey == GUI_ID_KEY_INVENTORY_BUTTON)
{
this->inventory->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_inventory = event.KeyInput.Key;
this->inventory->setText(wgettext(kp.name()));
this->key_inventory = kp;
}
else if (activeKey == GUI_ID_KEY_CHAT_BUTTON)
{
this->chat->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_chat = event.KeyInput.Key;
this->chat->setText(wgettext(kp.name()));
this->key_chat = kp;
}
else if (activeKey == GUI_ID_KEY_CMD_BUTTON)
{
this->cmd->setText(wgettext(kp.name()));
this->key_cmd = kp;
}
else if (activeKey == GUI_ID_KEY_RANGE_BUTTON)
{
this->range->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_range = event.KeyInput.Key;
this->range->setText(wgettext(kp.name()));
this->key_range = kp;
}
else if (activeKey == GUI_ID_KEY_FLY_BUTTON)
{
this->fly->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_fly = event.KeyInput.Key;
this->fly->setText(wgettext(kp.name()));
this->key_fly = kp;
}
else if (activeKey == GUI_ID_KEY_FAST_BUTTON)
{
this->fast->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_fast = event.KeyInput.Key;
this->fast->setText(wgettext(kp.name()));
this->key_fast = kp;
}
else if (activeKey == GUI_ID_KEY_USE_BUTTON)
{
this->use->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_use = event.KeyInput.Key;
this->use->setText(wgettext(kp.name()));
this->key_use = kp;
}
else if (activeKey == GUI_ID_KEY_DUMP_BUTTON)
{
this->dump->setText(
narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
this->key_dump = event.KeyInput.Key;
this->dump->setText(wgettext(kp.name()));
this->key_dump = kp;
}
changeCtype("C");
activeKey = -1;
return true;
}
@@ -514,6 +529,12 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
}
if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
{
if(event.GUIEvent.Caller->getID() != GUI_ID_BACK_BUTTON &&
event.GUIEvent.Caller->getID() != GUI_ID_ABORT_BUTTON)
{
changeCtype("");
}
switch (event.GUIEvent.Caller->getID())
{
case GUI_ID_BACK_BUTTON: //back
@@ -526,70 +547,76 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
case GUI_ID_KEY_FORWARD_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->forward->setText(L"press Key");
this->forward->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_BACKWARD_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->backward->setText(L"press Key");
this->backward->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_LEFT_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->left->setText(L"press Key");
this->left->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_RIGHT_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->right->setText(L"press Key");
this->right->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_USE_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->use->setText(L"press Key");
this->use->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_FLY_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->fly->setText(L"press Key");
this->fly->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_FAST_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->fast->setText(L"press Key");
this->fast->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_JUMP_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->jump->setText(L"press Key");
this->jump->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_CHAT_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->chat->setText(L"press Key");
this->chat->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_CMD_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->cmd->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_SNEAK_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->sneak->setText(L"press Key");
this->sneak->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_INVENTORY_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->inventory->setText(L"press Key");
this->inventory->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_DUMP_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->dump->setText(L"press Key");
this->dump->setText(wgettext("press Key"));
break;
case GUI_ID_KEY_RANGE_BUTTON:
resetMenu();
activeKey = event.GUIEvent.Caller->getID();
this->range->setText(L"press Key");
this->range->setText(wgettext("press Key"));
break;
}
//Buttons
changeCtype("C");
}
}

View File

@@ -26,53 +26,29 @@
#include "utility.h"
#include "modalMenu.h"
#include "client.h"
#include "gettext.h"
#include "keycode.h"
#include <string>
static const char *KeyNames[] =
{ "-", "Left Button", "Right Button", "Cancel", "Middle Button", "X Button 1",
"X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-",
"-", "Shift", "Control", "Menu", "Pause", "Capital", "Kana", "-",
"Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert",
"Accept", "Mode Change", "Space", "Priot", "Next", "End", "Home",
"Left", "Up", "Right", "Down", "Select", "Print", "Execute",
"Snapshot", "Insert", "Delete", "Help", "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C",
"D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
"R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Left Windows",
"Right Windows", "Apps", "-", "Sleep", "Numpad 0", "Numpad 1",
"Numpad 2", "Numpad 3", "Numpad 4", "Numpad 5", "Numpad 6", "Numpad 7",
"Numpad 8", "Numpad 9", "Numpad *", "Numpad +", "Numpad /", "Numpad -",
"Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
"F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18",
"F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-",
"-", "-", "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "Left Shift", "Right Shight",
"Left Control", "Right Control", "Left Menu", "Right Menu", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel",
"ExSel", "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" };
enum
{
GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
//buttons
GUI_ID_KEY_FORWARD_BUTTON,
GUI_ID_KEY_BACKWARD_BUTTON,
GUI_ID_KEY_LEFT_BUTTON,
GUI_ID_KEY_RIGHT_BUTTON,
GUI_ID_KEY_USE_BUTTON,
GUI_ID_KEY_FLY_BUTTON,
GUI_ID_KEY_FAST_BUTTON,
GUI_ID_KEY_JUMP_BUTTON,
GUI_ID_KEY_CHAT_BUTTON,
GUI_ID_KEY_SNEAK_BUTTON,
GUI_ID_KEY_INVENTORY_BUTTON,
GUI_ID_KEY_DUMP_BUTTON,
GUI_ID_KEY_RANGE_BUTTON
};
enum
{
GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
//buttons
GUI_ID_KEY_FORWARD_BUTTON,
GUI_ID_KEY_BACKWARD_BUTTON,
GUI_ID_KEY_LEFT_BUTTON,
GUI_ID_KEY_RIGHT_BUTTON,
GUI_ID_KEY_USE_BUTTON,
GUI_ID_KEY_FLY_BUTTON,
GUI_ID_KEY_FAST_BUTTON,
GUI_ID_KEY_JUMP_BUTTON,
GUI_ID_KEY_CHAT_BUTTON,
GUI_ID_KEY_CMD_BUTTON,
GUI_ID_KEY_SNEAK_BUTTON,
GUI_ID_KEY_INVENTORY_BUTTON,
GUI_ID_KEY_DUMP_BUTTON,
GUI_ID_KEY_RANGE_BUTTON
};
class GUIKeyChangeMenu: public GUIModalMenu
{
@@ -112,21 +88,23 @@ class GUIKeyChangeMenu: public GUIModalMenu
gui::IGUIButton *range;
gui::IGUIButton *dump;
gui::IGUIButton *chat;
gui::IGUIButton *cmd;
u32 activeKey;
u32 key_forward;
u32 key_backward;
u32 key_left;
u32 key_right;
u32 key_use;
u32 key_sneak;
u32 key_jump;
u32 key_inventory;
u32 key_fly;
u32 key_fast;
u32 key_range;
u32 key_chat;
u32 key_dump;
s32 activeKey;
KeyPress key_forward;
KeyPress key_backward;
KeyPress key_left;
KeyPress key_right;
KeyPress key_use;
KeyPress key_sneak;
KeyPress key_jump;
KeyPress key_inventory;
KeyPress key_fly;
KeyPress key_fast;
KeyPress key_range;
KeyPress key_chat;
KeyPress key_cmd;
KeyPress key_dump;
};
#endif

View File

@@ -164,6 +164,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
v2s32 topleft_client(40, 0);
v2s32 size_client = size - v2s32(40, 0);
changeCtype("");
{
core::rect<s32> rect(0, 0, 20, 125);
rect += topleft_client + v2s32(-15, 60);
@@ -177,9 +178,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, 50+6);
Environment->addStaticText(chartowchar_t(gettext("Name/Password")),
Environment->addStaticText(wgettext("Name/Password"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, 50);
@@ -194,21 +196,25 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
gui::IGUIEditBox *e =
Environment->addEditBox(L"", rect, true, this, 264);
e->setPasswordBox(true);
if(text_name != L"" && text_address != L"")
Environment->setFocus(e);
}
changeCtype("");
// Address + port
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, 100+6);
Environment->addStaticText(chartowchar_t(gettext("Address/Port")),
Environment->addStaticText(wgettext("Address/Port"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, 100);
gui::IGUIElement *e =
Environment->addEditBox(text_address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT);
if(text_name != L"")
if(text_name != L"" && text_address == L"")
Environment->setFocus(e);
}
{
@@ -217,23 +223,24 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
rect += topleft_client + v2s32(size_client.X-60-100, 100);
Environment->addEditBox(text_port.c_str(), rect, true, this, GUI_ID_PORT_INPUT);
}
changeCtype("");
{
core::rect<s32> rect(0, 0, 400, 20);
rect += topleft_client + v2s32(160, 100+35);
Environment->addStaticText(chartowchar_t(gettext("Leave address blank to start a local server.")),
Environment->addStaticText(wgettext("Leave address blank to start a local server."),
rect, false, true, this, -1);
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150);
Environment->addCheckBox(fancy_trees, rect, this, GUI_ID_FANCYTREE_CB,
chartowchar_t(gettext("Fancy trees")));
wgettext("Fancy trees"));
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150+30);
Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB,
chartowchar_t(gettext("Smooth Lighting")));
wgettext("Smooth Lighting"));
}
// Start game button
{
@@ -241,7 +248,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
//rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
rect += topleft_client + v2s32(size_client.X-180-40, 150+25);
Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
chartowchar_t(gettext("Start Game / Connect")));
wgettext("Start Game / Connect"));
}
// Key change button
@@ -250,7 +257,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
//rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
rect += topleft_client + v2s32(size_client.X-180-40-100-20, 150+25);
Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON,
chartowchar_t(gettext("Change keys")));
wgettext("Change keys"));
}
/*
Server section
@@ -273,13 +280,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_server + v2s32(35, 30);
Environment->addCheckBox(creative_mode, rect, this, GUI_ID_CREATIVE_CB,
chartowchar_t(gettext("Creative Mode")));
wgettext("Creative Mode"));
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_server + v2s32(35, 60);
Environment->addCheckBox(enable_damage, rect, this, GUI_ID_DAMAGE_CB,
chartowchar_t(gettext("Enable Damage")));
wgettext("Enable Damage"));
}
// Map delete button
{
@@ -287,8 +294,9 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
//rect += topleft_server + v2s32(size_server.X-40-130, 100+25);
rect += topleft_server + v2s32(40, 100+25);
Environment->addButton(rect, this, GUI_ID_DELETE_MAP_BUTTON,
chartowchar_t(gettext("Delete map")));
wgettext("Delete map"));
}
changeCtype("C");
}
void GUIMainMenu::drawMenu()

View File

@@ -85,14 +85,16 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize)
Environment->addStaticText(m_message_text.c_str(), rect, false,
true, this, 256);
}
changeCtype("");
{
core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
gui::IGUIElement *e =
Environment->addButton(rect, this, 257,
chartowchar_t(gettext("Proceed")));
wgettext("Proceed"));
Environment->setFocus(e);
}
changeCtype("C");
}
void GUIMessageMenu::drawMenu()

View File

@@ -96,12 +96,14 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
Add stuff
*/
s32 ypos = 50;
changeCtype("");
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
Environment->addStaticText(chartowchar_t(gettext("Old Password")),
Environment->addStaticText(wgettext("Old Password"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, ypos);
@@ -111,12 +113,14 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
e->setPasswordBox(true);
}
ypos += 50;
changeCtype("");
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
Environment->addStaticText(chartowchar_t(gettext("New Password")),
Environment->addStaticText(wgettext("New Password"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, ypos);
@@ -125,12 +129,14 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
e->setPasswordBox(true);
}
ypos += 50;
changeCtype("");
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
Environment->addStaticText(chartowchar_t(gettext("Confirm Password")),
Environment->addStaticText(wgettext("Confirm Password"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, ypos);
@@ -140,10 +146,11 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
}
ypos += 50;
changeCtype("");
{
core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, ypos);
Environment->addButton(rect, this, ID_change, chartowchar_t(gettext("Change")));
Environment->addButton(rect, this, ID_change, wgettext("Change"));
}
ypos += 50;
@@ -152,10 +159,11 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
rect += topleft_client + v2s32(35, ypos);
IGUIElement *e =
Environment->addStaticText(
chartowchar_t(gettext("Passwords do not match!")),
wgettext("Passwords do not match!"),
rect, false, true, this, ID_message);
e->setVisible(false);
}
changeCtype("C");
}

View File

@@ -103,32 +103,33 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
const s32 btn_gap = 20;
const s32 btn_num = 4;
s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
changeCtype("");
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 256,
chartowchar_t(gettext("Continue")));
wgettext("Continue"));
}
btn_y += btn_height + btn_gap;
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 261,
chartowchar_t(gettext("Change Password")));
wgettext("Change Password"));
}
btn_y += btn_height + btn_gap;
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 260,
chartowchar_t(gettext("Disconnect")));
wgettext("Disconnect"));
}
btn_y += btn_height + btn_gap;
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 257,
chartowchar_t(gettext("Exit to OS")));
wgettext("Exit to OS"));
}
{
@@ -172,7 +173,7 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
);*/
std::ostringstream os;
os<<"Minetest-c55\n";
os<<"Minetest\n";
os<<"by Perttu Ahola and contributors\n";
os<<"celeron55@gmail.com\n";
os<<BUILD_INFO<<"\n";
@@ -180,6 +181,7 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
}
changeCtype("C");
}
void GUIPauseMenu::drawMenu()

View File

@@ -103,13 +103,21 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize)
gui::IGUIElement *e =
Environment->addEditBox(text.c_str(), rect, true, this, 256);
Environment->setFocus(e);
irr::SEvent evt;
evt.EventType = EET_KEY_INPUT_EVENT;
evt.KeyInput.Key = KEY_END;
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
}
changeCtype("");
{
core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
Environment->addButton(rect, this, 257,
chartowchar_t(gettext("Proceed")));
wgettext("Proceed"));
}
changeCtype("C");
}
void GUITextInputMenu::drawMenu()

View File

@@ -122,16 +122,20 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
}
}
std::string InventoryItem::getItemString() {
// Get item string
std::ostringstream os(std::ios_base::binary);
serialize(os);
return os.str();
}
ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
{
/*
Create an ItemSAO
*/
// Get item string
std::ostringstream os(std::ios_base::binary);
serialize(os);
// Create object
ServerActiveObject *obj = new ItemSAO(env, 0, pos, os.str());
ServerActiveObject *obj = new ItemSAO(env, 0, pos, getItemString());
return obj;
}
@@ -139,12 +143,12 @@ ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f
MaterialItem
*/
bool MaterialItem::isCookable()
bool MaterialItem::isCookable() const
{
return item_material_is_cookable(m_content);
}
InventoryItem *MaterialItem::createCookResult()
InventoryItem *MaterialItem::createCookResult() const
{
return item_material_create_cook_result(m_content);
}
@@ -176,7 +180,7 @@ ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos
return InventoryItem::createSAO(env, id, pos);
}
u16 CraftItem::getDropCount()
u16 CraftItem::getDropCount() const
{
// Special cases
s16 dc = item_craft_get_drop_count(m_subname);
@@ -186,12 +190,12 @@ u16 CraftItem::getDropCount()
return InventoryItem::getDropCount();
}
bool CraftItem::isCookable()
bool CraftItem::isCookable() const
{
return item_craft_is_cookable(m_subname);
}
InventoryItem *CraftItem::createCookResult()
InventoryItem *CraftItem::createCookResult() const
{
return item_craft_create_cook_result(m_subname);
}
@@ -200,12 +204,17 @@ bool CraftItem::use(ServerEnvironment *env, Player *player)
{
if(item_craft_is_eatable(m_subname))
{
u16 result_count = getCount() - 1; // Eat one at a time
s16 hp_change = item_craft_eat_hp_change(m_subname);
if(player->hp + hp_change > 20)
player->hp = 20;
else
player->hp += hp_change;
return true;
if(result_count < 1)
return true;
else
setCount(result_count);
}
return false;
}
@@ -320,7 +329,7 @@ void InventoryList::clearItems()
//setDirty(true);
}
void InventoryList::serialize(std::ostream &os)
void InventoryList::serialize(std::ostream &os) const
{
//os.imbue(std::locale("C"));
@@ -416,7 +425,7 @@ InventoryList & InventoryList::operator = (const InventoryList &other)
return *this;
}
std::string InventoryList::getName()
const std::string &InventoryList::getName() const
{
return m_name;
}
@@ -443,6 +452,13 @@ u32 InventoryList::getFreeSlots()
return getSize() - getUsedSlots();
}
const InventoryItem * InventoryList::getItem(u32 i) const
{
if(i > m_items.size() - 1)
return NULL;
return m_items[i];
}
InventoryItem * InventoryList::getItem(u32 i)
{
if(i > m_items.size() - 1)
@@ -542,20 +558,20 @@ InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem)
}
}
bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
bool InventoryList::itemFits(const u32 i, const InventoryItem *newitem)
{
// If it is an empty position, it's an easy job.
InventoryItem *to_item = getItem(i);
const InventoryItem *to_item = getItem(i);
if(to_item == NULL)
{
return true;
}
// If not addable, return the item
// If not addable, fail
if(newitem->addableTo(to_item) == false)
return false;
// If the item fits fully in the slot, add counter and delete it
// If the item fits fully in the slot, pass
if(newitem->getCount() <= to_item->freeSpace())
{
return true;
@@ -564,6 +580,26 @@ bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
return false;
}
bool InventoryList::roomForItem(const InventoryItem *item)
{
for(u32 i=0; i<m_items.size(); i++)
if(itemFits(i, item))
return true;
return false;
}
bool InventoryList::roomForCookedItem(const InventoryItem *item)
{
if(!item)
return false;
const InventoryItem *cook = item->createCookResult();
if(!cook)
return false;
bool room = roomForItem(cook);
delete cook;
return room;
}
InventoryItem * InventoryList::takeItem(u32 i, u32 count)
{
if(count == 0)
@@ -654,7 +690,7 @@ Inventory & Inventory::operator = (const Inventory &other)
return *this;
}
void Inventory::serialize(std::ostream &os)
void Inventory::serialize(std::ostream &os) const
{
for(u32 i=0; i<m_lists.size(); i++)
{
@@ -736,7 +772,15 @@ InventoryList * Inventory::getList(const std::string &name)
return m_lists[i];
}
s32 Inventory::getListIndex(const std::string &name)
const InventoryList * Inventory::getList(const std::string &name) const
{
s32 i = getListIndex(name);
if(i == -1)
return NULL;
return m_lists[i];
}
const s32 Inventory::getListIndex(const std::string &name) const
{
for(u32 i=0; i<m_lists.size(); i++)
{
@@ -866,7 +910,7 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
Craft checking system
*/
bool ItemSpec::checkItem(InventoryItem *item)
bool ItemSpec::checkItem(const InventoryItem *item) const
{
if(type == ITEM_NONE)
{
@@ -916,7 +960,7 @@ bool ItemSpec::checkItem(InventoryItem *item)
return true;
}
bool checkItemCombination(InventoryItem **items, ItemSpec *specs)
bool checkItemCombination(InventoryItem const * const *items, const ItemSpec *specs)
{
u16 items_min_x = 100;
u16 items_max_x = 100;
@@ -979,8 +1023,8 @@ bool checkItemCombination(InventoryItem **items, ItemSpec *specs)
u16 items_y = items_min_y + y;
u16 specs_x = specs_min_x + x;
u16 specs_y = specs_min_y + y;
InventoryItem *item = items[items_y * 3 + items_x];
ItemSpec &spec = specs[specs_y * 3 + specs_x];
const InventoryItem *item = items[items_y * 3 + items_x];
const ItemSpec &spec = specs[specs_y * 3 + specs_x];
if(spec.checkItem(item) == false)
return false;

View File

@@ -49,7 +49,7 @@ class InventoryItem
virtual const char* getName() const = 0;
// Shall write the name and the parameters
virtual void serialize(std::ostream &os) = 0;
virtual void serialize(std::ostream &os) const = 0;
// Shall make an exact clone of the item
virtual InventoryItem* clone() = 0;
#ifndef SERVER
@@ -58,22 +58,24 @@ class InventoryItem
#endif
// Shall return a text to show in the GUI
virtual std::string getText() { return ""; }
// Returns the string used for inventory
virtual std::string getItemString();
// Creates an object from the item, to be placed in the world.
virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
// Gets amount of items that dropping one SAO will decrement
virtual u16 getDropCount(){ return getCount(); }
virtual u16 getDropCount() const { return getCount(); }
/*
Quantity methods
*/
// Shall return true if the item can be add()ed to the other
virtual bool addableTo(InventoryItem *other)
virtual bool addableTo(const InventoryItem *other) const
{
return false;
}
u16 getCount()
u16 getCount() const
{
return m_count;
}
@@ -82,7 +84,7 @@ class InventoryItem
m_count = count;
}
// This should return something else for stackable items
virtual u16 freeSpace()
virtual u16 freeSpace() const
{
return 0;
}
@@ -102,11 +104,11 @@ class InventoryItem
*/
// Whether it can be cooked
virtual bool isCookable(){return false;}
virtual bool isCookable() const {return false;}
// Time of cooking
virtual float getCookTime(){return 3.0;}
// Result of cooking (can randomize)
virtual InventoryItem *createCookResult(){return NULL;}
virtual InventoryItem *createCookResult() const {return NULL;}
// Eat, press, activate, whatever.
// Called when item is right-clicked when lying on ground.
@@ -133,7 +135,7 @@ class MaterialItem : public InventoryItem
{
return "MaterialItem";
}
virtual void serialize(std::ostream &os)
virtual void serialize(std::ostream &os) const
{
//os.imbue(std::locale("C"));
os<<"MaterialItem2";
@@ -160,7 +162,7 @@ class MaterialItem : public InventoryItem
return os.str();
}
virtual bool addableTo(InventoryItem *other)
virtual bool addableTo(const InventoryItem *other) const
{
if(std::string(other->getName()) != "MaterialItem")
return false;
@@ -169,7 +171,7 @@ class MaterialItem : public InventoryItem
return false;
return true;
}
u16 freeSpace()
u16 freeSpace() const
{
if(m_count > QUANTITY_ITEM_MAX_COUNT)
return 0;
@@ -178,8 +180,8 @@ class MaterialItem : public InventoryItem
/*
Other properties
*/
bool isCookable();
InventoryItem *createCookResult();
bool isCookable() const;
InventoryItem *createCookResult() const;
/*
Special methods
*/
@@ -208,18 +210,13 @@ class MapBlockObjectItem : public InventoryItem
{
return "MBOItem";
}
virtual void serialize(std::ostream &os)
virtual void serialize(std::ostream &os) const
{
for(;;)
{
size_t t = m_inventorystring.find('|');
if(t == std::string::npos)
break;
m_inventorystring[t] = '?';
}
std::string sane_string(m_inventorystring);
str_replace_char(sane_string, '|', '?');
os<<getName();
os<<" ";
os<<m_inventorystring;
os<<sane_string;
os<<"|";
}
virtual InventoryItem* clone()
@@ -266,7 +263,7 @@ class CraftItem : public InventoryItem
{
return "CraftItem";
}
virtual void serialize(std::ostream &os)
virtual void serialize(std::ostream &os) const
{
os<<getName();
os<<" ";
@@ -289,9 +286,9 @@ class CraftItem : public InventoryItem
}
ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
u16 getDropCount();
u16 getDropCount() const;
virtual bool addableTo(InventoryItem *other)
virtual bool addableTo(const InventoryItem *other) const
{
if(std::string(other->getName()) != "CraftItem")
return false;
@@ -300,7 +297,7 @@ class CraftItem : public InventoryItem
return false;
return true;
}
u16 freeSpace()
u16 freeSpace() const
{
if(m_count > QUANTITY_ITEM_MAX_COUNT)
return 0;
@@ -311,8 +308,8 @@ class CraftItem : public InventoryItem
Other properties
*/
bool isCookable();
InventoryItem *createCookResult();
bool isCookable() const;
InventoryItem *createCookResult() const;
bool use(ServerEnvironment *env, Player *player);
@@ -343,7 +340,7 @@ class ToolItem : public InventoryItem
{
return "ToolItem";
}
virtual void serialize(std::ostream &os)
virtual void serialize(std::ostream &os) const
{
os<<getName();
os<<" ";
@@ -461,13 +458,13 @@ class InventoryList
InventoryList(std::string name, u32 size);
~InventoryList();
void clearItems();
void serialize(std::ostream &os);
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
InventoryList(const InventoryList &other);
InventoryList & operator = (const InventoryList &other);
std::string getName();
const std::string &getName() const;
u32 getSize();
// Count used slots
u32 getUsedSlots();
@@ -477,6 +474,7 @@ class InventoryList
void setDirty(bool dirty=true){ m_dirty = dirty; }*/
// Get pointer to item
const InventoryItem * getItem(u32 i) const;
InventoryItem * getItem(u32 i);
// Returns old item (or NULL). Parameter can be NULL.
InventoryItem * changeItem(u32 i, InventoryItem *newitem);
@@ -494,7 +492,13 @@ class InventoryList
InventoryItem * addItem(u32 i, InventoryItem *newitem);
// Checks whether the item could be added to the given slot
bool itemFits(u32 i, InventoryItem *newitem);
bool itemFits(const u32 i, const InventoryItem *newitem);
// Checks whether there is room for a given item
bool roomForItem(const InventoryItem *item);
// Checks whether there is room for a given item aftr it has been cooked
bool roomForCookedItem(const InventoryItem *item);
// Takes some items from a slot.
// If there are not enough, takes as many as it can.
@@ -524,11 +528,12 @@ class Inventory
Inventory(const Inventory &other);
Inventory & operator = (const Inventory &other);
void serialize(std::ostream &os);
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
InventoryList * addList(const std::string &name, u32 size);
InventoryList * getList(const std::string &name);
const InventoryList * getList(const std::string &name) const;
bool deleteList(const std::string &name);
// A shorthand for adding items.
// Returns NULL if the item was fully added, leftover otherwise.
@@ -542,7 +547,7 @@ class Inventory
private:
// -1 if not found
s32 getListIndex(const std::string &name);
const s32 getListIndex(const std::string &name) const;
core::array<InventoryList*> m_lists;
};
@@ -558,7 +563,7 @@ struct InventoryContext
{}
};
class InventoryAction;
struct InventoryAction;
class InventoryManager
{
@@ -589,7 +594,7 @@ struct InventoryAction
static InventoryAction * deSerialize(std::istream &is);
virtual u16 getType() const = 0;
virtual void serialize(std::ostream &os) = 0;
virtual void serialize(std::ostream &os) const = 0;
virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
};
@@ -637,7 +642,7 @@ struct IMoveAction : public InventoryAction
return IACTION_MOVE;
}
void serialize(std::ostream &os)
void serialize(std::ostream &os) const
{
os<<"Move ";
os<<count<<" ";
@@ -689,14 +694,14 @@ struct ItemSpec
{
}
bool checkItem(InventoryItem *item);
bool checkItem(const InventoryItem *item) const;
};
/*
items: a pointer to an array of 9 pointers to items
specs: a pointer to an array of 9 ItemSpecs
*/
bool checkItemCombination(InventoryItem **items, ItemSpec *specs);
bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
#endif

View File

@@ -19,6 +19,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "keycode.h"
#include "main.h" // For g_settings
#include "exceptions.h"
class UnknownKeycode : public BaseException
{
public:
UnknownKeycode(const char *s) :
BaseException(s) {};
};
#define CHECKKEY(x){if(strcmp(name, #x)==0) return irr::x;}
@@ -168,7 +176,7 @@ irr::EKEY_CODE keyname_to_keycode(const char *name)
CHECKKEY(KEY_PA1)
CHECKKEY(KEY_OEM_CLEAR)
return irr::KEY_KEY_CODES_COUNT;
throw UnknownKeycode(name);
}
static const char *KeyNames[] =
@@ -206,31 +214,131 @@ static const char *KeyNames[] =
"-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel", "ExSel",
"Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" };
std::string keycode_to_keyname(s32 keycode)
#define N_(text) text
static const char *KeyNamesLang[] =
{ "-", N_("Left Button"), N_("Right Button"), N_("Cancel"), N_("Middle Button"), N_("X Button 1"),
N_("X Button 2"), "-", N_("Back"), N_("Tab"), "-", "-", N_("Clear"), N_("Return"), "-",
"-", N_("Shift"), N_("Control"), N_("Menu"), N_("Pause"), N_("Capital"), N_("Kana"), "-",
N_("Junja"), N_("Final"), N_("Kanji"), "-", N_("Escape"), N_("Convert"), N_("Nonconvert"),
N_("Accept"), N_("Mode Change"), N_("Space"), N_("Prior"), N_("Next"), N_("End"), N_("Home"),
N_("Left"), N_("Up"), N_("Right"), N_("Down"), N_("Select"), N_("Print"), N_("Execute"),
N_("Snapshot"), N_("Insert"), N_("Delete"), N_("Help"), "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C",
"D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
"R", "S", "T", "U", "V", "W", "X", "Y", "Z", N_("Left Windows"),
N_("Right Windows"), N_("Apps"), "-", N_("Sleep"), N_("Numpad 0"), N_("Numpad 1"),
N_("Numpad 2"), N_("Numpad 3"), N_("Numpad 4"), N_("Numpad 5"), N_("Numpad 6"), N_("Numpad 7"),
N_("Numpad 8"), N_("Numpad 9"), N_("Numpad *"), N_("Numpad +"), N_("Numpad /"), N_("Numpad -"),
"Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
"F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18",
"F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-",
"-", "-", N_("Num Lock"), N_("Scroll Lock"), "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", N_("Left Shift"), N_("Right Shift"),
N_("Left Control"), N_("Right Control"), N_("Left Menu"), N_("Right Menu"), "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", N_("Plus"), N_("Comma"), N_("Minus"), N_("Period"), "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", N_("Attn"), N_("CrSel"),
N_("ExSel"), N_("Erase OEF"), N_("Play"), N_("Zoom"), N_("PA1"), N_("OEM Clear"), "-" };
#undef N_
KeyPress::KeyPress() :
Key(irr::KEY_KEY_CODES_COUNT),
Char(L'\0')
{}
KeyPress::KeyPress(const char *name)
{
return KeyNames[keycode];
if (strlen(name) > 4) {
try {
Key = keyname_to_keycode(name);
m_name = name;
if (strlen(name) > 8)
mbtowc(&Char, name + 8, 1);
else
Char = L'\0';
return;
} catch (UnknownKeycode &e) {};
} else {
// see if we can set it up as a KEY_KEY_something
m_name = "KEY_KEY_";
m_name += name;
try {
Key = keyname_to_keycode(m_name.c_str());
mbtowc(&Char, name, 1);
return;
} catch (UnknownKeycode &e) {};
}
// it's not a (known) key, just take the first char and use that
Key = irr::KEY_KEY_CODES_COUNT;
mbtowc(&Char, name, 1);
m_name = name[0];
}
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in)
{
Key = in.Key;
Char = in.Char;
if (valid_kcode(Key)) {
m_name = KeyNames[Key];
} else {
size_t maxlen = wctomb(NULL, Char);
m_name.resize(maxlen+1, '\0');
wctomb(&m_name[0], Char);
}
}
const char *KeyPress::sym() const
{
if (Key && Key < irr::KEY_KEY_CODES_COUNT)
return KeyNames[Key];
else {
return m_name.c_str();
}
}
const char *KeyPress::name() const
{
if (Key && Key < irr::KEY_KEY_CODES_COUNT)
return KeyNamesLang[Key];
else {
return m_name.c_str();
}
}
const KeyPress EscapeKey("KEY_ESCAPE");
const KeyPress NumberKey[] = {
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"),
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"),
KeyPress("KEY_KEY_6"), KeyPress("KEY_KEY_7"), KeyPress("KEY_KEY_8"),
KeyPress("KEY_KEY_9")};
/*
Key config
*/
// A simple cache for quicker lookup
core::map<std::string, irr::EKEY_CODE> g_key_setting_cache;
core::map<std::string, KeyPress> g_key_setting_cache;
irr::EKEY_CODE getKeySetting(const char *settingname)
KeyPress getKeySetting(const char *settingname)
{
core::map<std::string, irr::EKEY_CODE>::Node *n;
core::map<std::string, KeyPress>::Node *n;
n = g_key_setting_cache.find(settingname);
if(n)
return n->getValue();
irr::EKEY_CODE c = keyname_to_keycode(g_settings.get(settingname).c_str());
g_key_setting_cache.insert(settingname, c);
return c;
g_key_setting_cache.insert(settingname,
g_settings.get(settingname).c_str());
return g_key_setting_cache.find(settingname)->getValue();
}
void clearKeyCache()
{
g_key_setting_cache.clear();
}

View File

@@ -23,11 +23,42 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h"
#include <string>
irr::EKEY_CODE keyname_to_keycode(const char *name);
std::string keycode_to_keyname(s32 keycode);
/* A key press, consisting of either an Irrlicht keycode
or an actual char */
class KeyPress
{
public:
KeyPress();
KeyPress(const char *name);
KeyPress(const irr::SEvent::SKeyInput &in);
bool operator==(const KeyPress &o) const
{
return valid_kcode(Key) ? Key == o.Key : Char == o.Char;
}
const char *sym() const;
const char *name() const;
std::string debug() const;
protected:
static bool valid_kcode(irr::EKEY_CODE k)
{
return k > 0 && k < irr::KEY_KEY_CODES_COUNT;
}
irr::EKEY_CODE Key;
wchar_t Char;
std::string m_name;
};
extern const KeyPress EscapeKey;
extern const KeyPress NumberKey[10];
// Key configuration getter
irr::EKEY_CODE getKeySetting(const char *settingname);
KeyPress getKeySetting(const char *settingname);
// Clear fast lookup cache
void clearKeyCache();

View File

@@ -367,6 +367,9 @@ TODO: Merge bahamada's audio stuff (clean patch available)
TODO: Move content_features to mapnode_content_features.{h,cpp} or so
TODO: Fix item use() stuff; dropping a stack of cooked rats and eating
it gives 3 hearts and consumes all the rats.
Making it more portable:
------------------------
@@ -560,10 +563,12 @@ class MyEventReceiver : public IEventReceiver
// Remember whether each key is down or up
if(event.EventType == irr::EET_KEY_INPUT_EVENT)
{
keyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
if(event.KeyInput.PressedDown)
keyWasDown[event.KeyInput.Key] = true;
if(event.KeyInput.PressedDown) {
keyIsDown.set(event.KeyInput);
keyWasDown.set(event.KeyInput);
} else {
keyIsDown.unset(event.KeyInput);
}
}
if(event.EventType == irr::EET_MOUSE_INPUT_EVENT)
@@ -607,16 +612,17 @@ class MyEventReceiver : public IEventReceiver
return false;
}
bool IsKeyDown(EKEY_CODE keyCode) const
bool IsKeyDown(const KeyPress &keyCode) const
{
return keyIsDown[keyCode];
}
// Checks whether a key was down and resets the state
bool WasKeyDown(EKEY_CODE keyCode)
bool WasKeyDown(const KeyPress &keyCode)
{
bool b = keyWasDown[keyCode];
keyWasDown[keyCode] = false;
if (b)
keyWasDown.unset(keyCode);
return b;
}
@@ -629,12 +635,9 @@ class MyEventReceiver : public IEventReceiver
void clearInput()
{
for(u32 i=0; i<KEY_KEY_CODES_COUNT; i++)
{
keyIsDown[i] = false;
keyWasDown[i] = false;
}
keyIsDown.clear();
keyWasDown.clear();
leftclicked = false;
rightclicked = false;
leftreleased = false;
@@ -667,9 +670,9 @@ class MyEventReceiver : public IEventReceiver
IrrlichtDevice *m_device;
// The current state of keys
bool keyIsDown[KEY_KEY_CODES_COUNT];
KeyList keyIsDown;
// Whether a key has been pressed or not
bool keyWasDown[KEY_KEY_CODES_COUNT];
KeyList keyWasDown;
};
/*
@@ -684,11 +687,11 @@ class RealInputHandler : public InputHandler
m_receiver(receiver)
{
}
virtual bool isKeyDown(EKEY_CODE keyCode)
virtual bool isKeyDown(const KeyPress &keyCode)
{
return m_receiver->IsKeyDown(keyCode);
}
virtual bool wasKeyDown(EKEY_CODE keyCode)
virtual bool wasKeyDown(const KeyPress &keyCode)
{
return m_receiver->WasKeyDown(keyCode);
}
@@ -769,14 +772,13 @@ class RandomInputHandler : public InputHandler
rightclicked = false;
leftreleased = false;
rightreleased = false;
for(u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
keydown[i] = false;
keydown.clear();
}
virtual bool isKeyDown(EKEY_CODE keyCode)
virtual bool isKeyDown(const KeyPress &keyCode)
{
return keydown[keyCode];
}
virtual bool wasKeyDown(EKEY_CODE keyCode)
virtual bool wasKeyDown(const KeyPress &keyCode)
{
return false;
}
@@ -845,8 +847,7 @@ class RandomInputHandler : public InputHandler
if(counter1 < 0.0)
{
counter1 = 0.1*Rand(1, 40);
keydown[getKeySetting("keymap_jump")] =
!keydown[getKeySetting("keymap_jump")];
keydown.toggle(getKeySetting("keymap_jump"));
}
}
{
@@ -855,8 +856,7 @@ class RandomInputHandler : public InputHandler
if(counter1 < 0.0)
{
counter1 = 0.1*Rand(1, 40);
keydown[getKeySetting("keymap_special1")] =
!keydown[getKeySetting("keymap_special1")];
keydown.toggle(getKeySetting("keymap_special1"));
}
}
{
@@ -865,8 +865,7 @@ class RandomInputHandler : public InputHandler
if(counter1 < 0.0)
{
counter1 = 0.1*Rand(1, 40);
keydown[getKeySetting("keymap_forward")] =
!keydown[getKeySetting("keymap_forward")];
keydown.toggle(getKeySetting("keymap_forward"));
}
}
{
@@ -875,8 +874,7 @@ class RandomInputHandler : public InputHandler
if(counter1 < 0.0)
{
counter1 = 0.1*Rand(1, 40);
keydown[getKeySetting("keymap_left")] =
!keydown[getKeySetting("keymap_left")];
keydown.toggle(getKeySetting("keymap_left"));
}
}
{
@@ -922,7 +920,7 @@ class RandomInputHandler : public InputHandler
return (myrand()%(max-min+1))+min;
}
private:
bool keydown[KEY_KEY_CODES_COUNT];
KeyList keydown;
v2s32 mousepos;
v2s32 mousespeed;
bool leftdown;
@@ -1161,11 +1159,7 @@ int main(int argc, char *argv[])
// Create user data directory
fs::CreateDir(porting::path_userdata);
#ifdef USE_GETTEXT
setlocale(LC_MESSAGES, "");
bindtextdomain("minetest", (porting::path_userdata+"/locale").c_str());
textdomain("minetest");
#endif
init_gettext((porting::path_data+"/../locale").c_str());
// Initialize debug streams
#ifdef RUN_IN_PLACE
@@ -1186,7 +1180,7 @@ int main(int argc, char *argv[])
BEGIN_DEBUG_EXCEPTION_HANDLER
// Print startup message
dstream<<DTIME<<"minetest-c55"
dstream<<DTIME<<PROJECT_NAME
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
<<", "<<BUILD_INFO
<<std::endl;
@@ -1379,9 +1373,6 @@ int main(int argc, char *argv[])
if (device == 0)
return 1; // could not create selected driver.
// Set device in game parameters
device = device;
// Set the window caption
device->setWindowCaption(L"Minetest [Main Menu]");

View File

@@ -29,12 +29,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h"
#include "nodemetadata.h"
extern "C" {
#include "sqlite3.h"
}
/*
SQLite format specification:
- Initially only replaces sectors/ and sectors2/
If map.sqlite does not exist in the save dir
or the block was not found in the database
the map will try to load from sectors folder.
In either case, map.sqlite will be created
and all future saves will save there.
Structure of map.sqlite:
Tables:
blocks
(PK) INT pos
BLOB data
*/
/*
@@ -1086,7 +1095,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2);
if(content_liquid(n2.getContent()))
if(content_liquid(n2.getContent()) || n2.getContent() == CONTENT_AIR)
{
m_transforming_liquid.push_back(p2);
}
@@ -1260,7 +1269,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2);
if(content_liquid(n2.getContent()))
if(content_liquid(n2.getContent()) || n2.getContent() == CONTENT_AIR)
{
m_transforming_liquid.push_back(p2);
}
@@ -1399,6 +1408,7 @@ void Map::timerUpdate(float dtime, float unload_timeout,
core::map<v2s16, MapSector*>::Iterator si;
beginSave();
si = m_sectors.getIterator();
for(; si.atEnd() == false; si++)
{
@@ -1408,6 +1418,7 @@ void Map::timerUpdate(float dtime, float unload_timeout,
core::list<MapBlock*> blocks;
sector->getBlocks(blocks);
for(core::list<MapBlock*>::Iterator i = blocks.begin();
i != blocks.end(); i++)
{
@@ -1446,6 +1457,7 @@ void Map::timerUpdate(float dtime, float unload_timeout,
sector_deletion_queue.push_back(si.getNode()->getKey());
}
}
endSave();
// Finally delete the empty sectors
deleteSectors(sector_deletion_queue);
@@ -1540,6 +1552,17 @@ void Map::PrintInfo(std::ostream &out)
#define WATER_DROP_BOOST 4
enum NeighborType {
NEIGHBOR_UPPER,
NEIGHBOR_SAME_LEVEL,
NEIGHBOR_LOWER
};
struct NodeNeighbor {
MapNode n;
NeighborType t;
v3s16 p;
};
void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
{
DSTACK(__FUNCTION_NAME);
@@ -1551,8 +1574,19 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
/*if(initial_size != 0)
dstream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
// list of nodes that due to viscosity have not reached their max level height
UniqueQueue<v3s16> must_reflow;
// List of MapBlocks that will require a lighting update (due to lava)
core::map<v3s16, MapBlock*> lighting_modified_blocks;
while(m_transforming_liquid.size() != 0)
{
// This should be done here so that it is done when continue is used
if(loopcount >= initial_size * 3)
break;
loopcount++;
/*
Get a queued transforming liquid node
*/
@@ -1560,241 +1594,216 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
MapNode n0 = getNodeNoEx(p0);
// Don't deal with non-liquids
if(content_liquid(n0.getContent()) == false)
continue;
bool is_source = !content_flowing_liquid(n0.getContent());
u8 liquid_level = 8;
if(is_source == false)
liquid_level = n0.param2 & 0x0f;
// Turn possible source into non-source
u8 nonsource_c = make_liquid_flowing(n0.getContent());
/*
If not source, check that some node flows into this one
and what is the level of liquid in this one
*/
if(is_source == false)
{
s8 new_liquid_level_max = -1;
v3s16 dirs_from[5] = {
v3s16(0,1,0), // top
v3s16(0,0,1), // back
v3s16(1,0,0), // right
v3s16(0,0,-1), // front
v3s16(-1,0,0), // left
};
for(u16 i=0; i<5; i++)
{
bool from_top = (i==0);
v3s16 p2 = p0 + dirs_from[i];
MapNode n2 = getNodeNoEx(p2);
if(content_liquid(n2.getContent()))
{
u8 n2_nonsource_c = make_liquid_flowing(n2.getContent());
// Check that the liquids are the same type
if(n2_nonsource_c != nonsource_c)
{
dstream<<"WARNING: Not handling: different liquids"
" collide"<<std::endl;
continue;
}
bool n2_is_source = !content_flowing_liquid(n2.getContent());
s8 n2_liquid_level = 8;
if(n2_is_source == false)
n2_liquid_level = n2.param2 & 0x07;
s8 new_liquid_level = -1;
if(from_top)
{
//new_liquid_level = 7;
if(n2_liquid_level >= 7 - WATER_DROP_BOOST)
new_liquid_level = 7;
else
new_liquid_level = n2_liquid_level + WATER_DROP_BOOST;
}
else if(n2_liquid_level > 0)
{
new_liquid_level = n2_liquid_level - 1;
}
if(new_liquid_level > new_liquid_level_max)
new_liquid_level_max = new_liquid_level;
}
} //for
/*
If liquid level should be something else, update it and
add all the neighboring water nodes to the transform queue.
*/
if(new_liquid_level_max != liquid_level)
{
if(new_liquid_level_max == -1)
{
// Remove water alltoghether
n0.setContent(CONTENT_AIR);
n0.param2 = 0;
setNode(p0, n0);
}
else
{
n0.param2 = new_liquid_level_max;
setNode(p0, n0);
}
// Block has been modified
{
v3s16 blockpos = getNodeBlockPos(p0);
MapBlock *block = getBlockNoCreateNoEx(blockpos);
if(block != NULL)
modified_blocks.insert(blockpos, block);
}
/*
Add neighboring non-source liquid nodes to transform queue.
*/
v3s16 dirs[6] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
v3s16(1,0,0), // right
v3s16(0,0,-1), // front
v3s16(0,-1,0), // bottom
v3s16(-1,0,0), // left
};
for(u16 i=0; i<6; i++)
{
v3s16 p2 = p0 + dirs[i];
MapNode n2 = getNodeNoEx(p2);
if(content_flowing_liquid(n2.getContent()))
{
m_transforming_liquid.push_back(p2);
}
}
}
}
// Get a new one from queue if the node has turned into non-water
if(content_liquid(n0.getContent()) == false)
continue;
/*
Flow water from this node
*/
v3s16 dirs_to[5] = {
v3s16(0,-1,0), // bottom
v3s16(0,0,1), // back
v3s16(1,0,0), // right
v3s16(0,0,-1), // front
v3s16(-1,0,0), // left
};
for(u16 i=0; i<5; i++)
{
bool to_bottom = (i == 0);
// If liquid is at lowest possible height, it's not going
// anywhere except down
if(liquid_level == 0 && to_bottom == false)
continue;
u8 liquid_next_level = 0;
// If going to bottom
if(to_bottom)
{
//liquid_next_level = 7;
if(liquid_level >= 7 - WATER_DROP_BOOST)
liquid_next_level = 7;
else
liquid_next_level = liquid_level + WATER_DROP_BOOST;
}
else
liquid_next_level = liquid_level - 1;
bool n2_changed = false;
bool flowed = false;
v3s16 p2 = p0 + dirs_to[i];
MapNode n2 = getNodeNoEx(p2);
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
if(content_liquid(n2.getContent()))
{
u8 n2_nonsource_c = make_liquid_flowing(n2.getContent());
// Check that the liquids are the same type
if(n2_nonsource_c != nonsource_c)
{
dstream<<"WARNING: Not handling: different liquids"
" collide"<<std::endl;
Collect information about current node
*/
s8 liquid_level = -1;
u8 liquid_kind = CONTENT_IGNORE;
LiquidType liquid_type = content_features(n0.getContent()).liquid_type;
switch (liquid_type) {
case LIQUID_SOURCE:
liquid_level = LIQUID_LEVEL_SOURCE;
liquid_kind = content_features(n0.getContent()).liquid_alternative_flowing;
break;
case LIQUID_FLOWING:
liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
liquid_kind = n0.getContent();
break;
case LIQUID_NONE:
// if this is an air node, it *could* be transformed into a liquid. otherwise,
// continue with the next node.
if (n0.getContent() != CONTENT_AIR)
continue;
}
bool n2_is_source = !content_flowing_liquid(n2.getContent());
u8 n2_liquid_level = 8;
if(n2_is_source == false)
n2_liquid_level = n2.param2 & 0x07;
if(to_bottom)
{
flowed = true;
}
if(n2_is_source)
{
// Just flow into the source, nothing changes.
// n2_changed is not set because destination didn't change
flowed = true;
}
else
{
if(liquid_next_level > liquid_level)
{
n2.param2 = liquid_next_level;
setNode(p2, n2);
n2_changed = true;
flowed = true;
}
}
}
else if(n2.getContent() == CONTENT_AIR)
{
n2.setContent(nonsource_c);
n2.param2 = liquid_next_level;
setNode(p2, n2);
n2_changed = true;
flowed = true;
}
//dstream<<"[2] n2.param="<<(int)n2.param<<std::endl;
if(n2_changed)
{
m_transforming_liquid.push_back(p2);
v3s16 blockpos = getNodeBlockPos(p2);
MapBlock *block = getBlockNoCreateNoEx(blockpos);
if(block != NULL)
modified_blocks.insert(blockpos, block);
}
// If n2_changed to bottom, don't flow anywhere else
if(to_bottom && flowed && !is_source)
liquid_kind = CONTENT_AIR;
break;
}
loopcount++;
//if(loopcount >= 100000)
if(loopcount >= initial_size * 1)
break;
/*
Collect information about the environment
*/
const v3s16 *dirs = g_6dirs;
NodeNeighbor sources[6]; // surrounding sources
int num_sources = 0;
NodeNeighbor flows[6]; // surrounding flowing liquid nodes
int num_flows = 0;
NodeNeighbor airs[6]; // surrounding air
int num_airs = 0;
NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid
int num_neutrals = 0;
bool flowing_down = false;
for (u16 i = 0; i < 6; i++) {
NeighborType nt = NEIGHBOR_SAME_LEVEL;
switch (i) {
case 1:
nt = NEIGHBOR_UPPER;
break;
case 4:
nt = NEIGHBOR_LOWER;
break;
}
v3s16 npos = p0 + dirs[i];
NodeNeighbor nb = {getNodeNoEx(npos), nt, npos};
switch (content_features(nb.n.getContent()).liquid_type) {
case LIQUID_NONE:
if (nb.n.getContent() == CONTENT_AIR) {
airs[num_airs++] = nb;
// if the current node is a water source the neighbor
// should be enqueded for transformation regardless of whether the
// current node changes or not.
if (nb.t != NEIGHBOR_UPPER && liquid_type != LIQUID_NONE)
m_transforming_liquid.push_back(npos);
// if the current node happens to be a flowing node, it will start to flow down here.
if (nb.t == NEIGHBOR_LOWER) {
flowing_down = true;
}
} else {
neutrals[num_neutrals++] = nb;
}
break;
case LIQUID_SOURCE:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR)
liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing;
if (content_features(nb.n.getContent()).liquid_alternative_flowing !=liquid_kind) {
neutrals[num_neutrals++] = nb;
} else {
sources[num_sources++] = nb;
}
break;
case LIQUID_FLOWING:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR)
liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing;
if (content_features(nb.n.getContent()).liquid_alternative_flowing != liquid_kind) {
neutrals[num_neutrals++] = nb;
} else {
flows[num_flows++] = nb;
if (nb.t == NEIGHBOR_LOWER)
flowing_down = true;
}
break;
}
}
/*
decide on the type (and possibly level) of the current node
*/
content_t new_node_content;
s8 new_node_level = -1;
s8 max_node_level = -1;
if (num_sources >= 2 || liquid_type == LIQUID_SOURCE) {
// liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
// or the flowing alternative of the first of the surrounding sources (if it's air), so
// it's perfectly safe to use liquid_kind here to determine the new node content.
new_node_content = content_features(liquid_kind).liquid_alternative_source;
} else if (num_sources == 1 && sources[0].t != NEIGHBOR_LOWER) {
// liquid_kind is set properly, see above
new_node_content = liquid_kind;
max_node_level = new_node_level = LIQUID_LEVEL_MAX;
} else {
// no surrounding sources, so get the maximum level that can flow into this node
for (u16 i = 0; i < num_flows; i++) {
u8 nb_liquid_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
switch (flows[i].t) {
case NEIGHBOR_UPPER:
if (nb_liquid_level + WATER_DROP_BOOST > max_node_level) {
max_node_level = LIQUID_LEVEL_MAX;
if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX)
max_node_level = nb_liquid_level + WATER_DROP_BOOST;
} else if (nb_liquid_level > max_node_level)
max_node_level = nb_liquid_level;
break;
case NEIGHBOR_LOWER:
break;
case NEIGHBOR_SAME_LEVEL:
if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level) {
max_node_level = nb_liquid_level - 1;
}
break;
}
}
u8 viscosity = content_features(liquid_kind).liquid_viscosity;
if (viscosity > 1 && max_node_level != liquid_level) {
// amount to gain, limited by viscosity
// must be at least 1 in absolute value
s8 level_inc = max_node_level - liquid_level;
if (level_inc < -viscosity || level_inc > viscosity)
new_node_level = liquid_level + level_inc/viscosity;
else if (level_inc < 0)
new_node_level = liquid_level - 1;
else if (level_inc > 0)
new_node_level = liquid_level + 1;
if (new_node_level != max_node_level)
must_reflow.push_back(p0);
} else
new_node_level = max_node_level;
if (new_node_level >= 0)
new_node_content = liquid_kind;
else
new_node_content = CONTENT_AIR;
}
/*
check if anything has changed. if not, just continue with the next node.
*/
if (new_node_content == n0.getContent() && (content_features(n0.getContent()).liquid_type != LIQUID_FLOWING ||
((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
== flowing_down)))
continue;
/*
update the current node
*/
bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
if (content_features(new_node_content).liquid_type == LIQUID_FLOWING) {
// set level to last 3 bits, flowing down bit to 4th bit
n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
} else {
// set the liquid level and flow bit to 0
n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
}
n0.setContent(new_node_content);
setNode(p0, n0);
v3s16 blockpos = getNodeBlockPos(p0);
MapBlock *block = getBlockNoCreateNoEx(blockpos);
if(block != NULL) {
modified_blocks.insert(blockpos, block);
// If node emits light, MapBlock requires lighting update
if(content_features(n0).light_source != 0)
lighting_modified_blocks[block->getPos()] = block;
}
/*
enqueue neighbors for update if neccessary
*/
switch (content_features(n0.getContent()).liquid_type) {
case LIQUID_SOURCE:
case LIQUID_FLOWING:
// make sure source flows into all neighboring nodes
for (u16 i = 0; i < num_flows; i++)
if (flows[i].t != NEIGHBOR_UPPER)
m_transforming_liquid.push_back(flows[i].p);
for (u16 i = 0; i < num_airs; i++)
if (airs[i].t != NEIGHBOR_UPPER)
m_transforming_liquid.push_back(airs[i].p);
break;
case LIQUID_NONE:
// this flow has turned to air; neighboring flows might need to do the same
for (u16 i = 0; i < num_flows; i++)
m_transforming_liquid.push_back(flows[i].p);
break;
}
}
//dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
while (must_reflow.size() > 0)
m_transforming_liquid.push_back(must_reflow.pop_front());
updateLighting(lighting_modified_blocks, modified_blocks);
}
NodeMetadata* Map::getNodeMetadata(v3s16 p)
@@ -1876,16 +1885,26 @@ void Map::nodeMetadataStep(float dtime,
ServerMap::ServerMap(std::string savedir):
Map(dout_server),
m_seed(0),
m_map_metadata_changed(true)
m_map_metadata_changed(true),
m_database(NULL),
m_database_read(NULL),
m_database_write(NULL)
{
dstream<<__FUNCTION_NAME<<std::endl;
//m_chunksize = 8; // Takes a few seconds
m_seed = (((u64)(myrand()%0xffff)<<0)
+ ((u64)(myrand()%0xffff)<<16)
+ ((u64)(myrand()%0xffff)<<32)
+ ((u64)(myrand()%0xffff)<<48));
if (g_settings.get("fixed_map_seed").empty())
{
m_seed = (((u64)(myrand()%0xffff)<<0)
+ ((u64)(myrand()%0xffff)<<16)
+ ((u64)(myrand()%0xffff)<<32)
+ ((u64)(myrand()%0xffff)<<48));
}
else
{
m_seed = g_settings.getU64("fixed_map_seed");
}
/*
Experimental and debug stuff
@@ -1997,6 +2016,16 @@ ServerMap::~ServerMap()
<<", exception: "<<e.what()<<std::endl;
}
/*
Close database if it was opened
*/
if(m_database_read)
sqlite3_finalize(m_database_read);
if(m_database_write)
sqlite3_finalize(m_database_write);
if(m_database)
sqlite3_close(m_database);
#if 0
/*
Free all MapChunks
@@ -2310,6 +2339,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
/*
Try to load metadata from disk
*/
#if 0
if(loadSectorMeta(p2d) == true)
{
ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d);
@@ -2320,7 +2350,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
}
return sector;
}
#endif
/*
Do not create over-limit
*/
@@ -2762,6 +2792,75 @@ s16 ServerMap::findGroundLevel(v2s16 p2d)
//return (s16)level;
}
void ServerMap::createDatabase() {
int e;
assert(m_database);
e = sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `blocks` ("
"`pos` INT NOT NULL PRIMARY KEY,"
"`data` BLOB"
");"
, NULL, NULL, NULL);
if(e == SQLITE_ABORT)
throw FileNotGoodException("Could not create database structure");
else
dstream<<"Server: Database structure was created";
}
void ServerMap::verifyDatabase() {
if(m_database)
return;
{
std::string dbp = m_savedir + "/map.sqlite";
bool needs_create = false;
int d;
/*
Open the database connection
*/
createDirs(m_savedir);
if(!fs::PathExists(dbp))
needs_create = true;
d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if(d != SQLITE_OK) {
dstream<<"WARNING: Database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot open database file");
}
if(needs_create)
createDatabase();
d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
if(d != SQLITE_OK) {
dstream<<"WARNING: Database read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare read statement");
}
d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?)", -1, &m_database_write, NULL);
if(d != SQLITE_OK) {
dstream<<"WARNING: Database write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare write statement");
}
dstream<<"Server: Database opened"<<std::endl;
}
}
bool ServerMap::loadFromFolders() {
if(!m_database && !fs::PathExists(m_savedir + "/map.sqlite"))
return true;
return false;
}
sqlite3_int64 ServerMap::getBlockAsInteger(const v3s16 pos) {
return (sqlite3_int64)pos.Z*16777216 +
(sqlite3_int64)pos.Y*4096 + (sqlite3_int64)pos.X;
}
void ServerMap::createDirs(std::string path)
{
if(fs::CreateAllDirs(path) == false)
@@ -2865,6 +2964,7 @@ void ServerMap::save(bool only_changed)
u32 block_count = 0;
u32 block_count_all = 0; // Number of blocks in memory
beginSave();
core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
for(; i.atEnd() == false; i++)
{
@@ -2879,6 +2979,8 @@ void ServerMap::save(bool only_changed)
core::list<MapBlock*> blocks;
sector->getBlocks(blocks);
core::list<MapBlock*>::Iterator j;
//sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL);
for(j=blocks.begin(); j!=blocks.end(); j++)
{
MapBlock *block = *j;
@@ -2897,8 +2999,10 @@ void ServerMap::save(bool only_changed)
<<block->getPos().Z<<")"
<<std::endl;*/
}
//sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL);
}
}
endSave();
/*
Only print if something happened or saved whole map
@@ -3157,6 +3261,18 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
}
#endif
void ServerMap::beginSave() {
verifyDatabase();
if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK)
dstream<<"WARNING: beginSave() failed, saving might be slow.";
}
void ServerMap::endSave() {
verifyDatabase();
if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK)
dstream<<"WARNING: endSave() failed, map might not have saved.";
}
void ServerMap::saveBlock(MapBlock *block)
{
DSTACK(__FUNCTION_NAME);
@@ -3176,6 +3292,8 @@ void ServerMap::saveBlock(MapBlock *block)
// Get destination
v3s16 p3d = block->getPos();
#if 0
v2s16 p2d(p3d.X, p3d.Z);
std::string sectordir = getSectorDir(p2d);
@@ -3185,11 +3303,16 @@ void ServerMap::saveBlock(MapBlock *block)
std::ofstream o(fullpath.c_str(), std::ios_base::binary);
if(o.good() == false)
throw FileNotGoodException("Cannot open block data");
#endif
/*
[0] u8 serialization version
[1] data
*/
verifyDatabase();
std::ostringstream o(std::ios_base::binary);
o.write((char*)&version, 1);
// Write basic data
@@ -3197,7 +3320,23 @@ void ServerMap::saveBlock(MapBlock *block)
// Write extra data stored on disk
block->serializeDiskExtra(o, version);
// Write block to database
std::string tmp = o.str();
const char *bytes = tmp.c_str();
if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK)
dstream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) // TODO this mught not be the right length
dstream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
int written = sqlite3_step(m_database_write);
if(written != SQLITE_DONE)
dstream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
<<sqlite3_errmsg(m_database)<<std::endl;
// Make ready for later reuse
sqlite3_reset(m_database_write);
// We just wrote it to the disk so clear modified flag
block->resetModified();
}
@@ -3258,6 +3397,9 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
if(version < SER_FMT_VER_HIGHEST || save_after_load)
{
saveBlock(block);
// Should be in database now, so delete the old file
fs::RecursiveDelete(fullpath);
}
// We just loaded it from the disk, so it's up-to-date.
@@ -3278,12 +3420,111 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
}
}
void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load)
{
DSTACK(__FUNCTION_NAME);
try {
std::istringstream is(*blob, std::ios_base::binary);
u8 version = SER_FMT_VER_INVALID;
is.read((char*)&version, 1);
if(is.fail())
throw SerializationError("ServerMap::loadBlock(): Failed"
" to read MapBlock version");
/*u32 block_size = MapBlock::serializedLength(version);
SharedBuffer<u8> data(block_size);
is.read((char*)*data, block_size);*/
// This will always return a sector because we're the server
//MapSector *sector = emergeSector(p2d);
MapBlock *block = NULL;
bool created_new = false;
block = sector->getBlockNoCreateNoEx(p3d.Y);
if(block == NULL)
{
block = sector->createBlankBlockNoInsert(p3d.Y);
created_new = true;
}
// Read basic data
block->deSerialize(is, version);
// Read extra data stored on disk
block->deSerializeDiskExtra(is, version);
// If it's a new block, insert it to the map
if(created_new)
sector->insertBlock(block);
/*
Save blocks loaded in old format in new format
*/
if(version < SER_FMT_VER_HIGHEST || save_after_load)
{
saveBlock(block);
}
// We just loaded it from, so it's up-to-date.
block->resetModified();
}
catch(SerializationError &e)
{
dstream<<"WARNING: Invalid block data in database "
<<" (SerializationError). "
<<"what()="<<e.what()
<<std::endl;
//" Ignoring. A new one will be generated.
assert(0);
// TODO: Copy to a backup database.
}
}
MapBlock* ServerMap::loadBlock(v3s16 blockpos)
{
DSTACK(__FUNCTION_NAME);
v2s16 p2d(blockpos.X, blockpos.Z);
if(!loadFromFolders()) {
verifyDatabase();
if(sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK)
dstream<<"WARNING: Could not bind block position for load: "
<<sqlite3_errmsg(m_database)<<std::endl;
if(sqlite3_step(m_database_read) == SQLITE_ROW) {
/*
Make sure sector is loaded
*/
MapSector *sector = createSector(p2d);
/*
Load block
*/
const char * data = (const char *)sqlite3_column_blob(m_database_read, 0);
size_t len = sqlite3_column_bytes(m_database_read, 0);
std::string datastr(data, len);
loadBlock(&datastr, blockpos, sector, false);
sqlite3_step(m_database_read);
// We should never get more than 1 row, so ok to reset
sqlite3_reset(m_database_read);
return getBlockNoCreateNoEx(blockpos);
}
sqlite3_reset(m_database_read);
// Not found in database, try the files
}
// The directory layout we're going to load from.
// 1 - original sectors/xxxxzzzz/
// 2 - new sectors2/xxx/zzz/
@@ -3334,9 +3575,9 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
return NULL;
/*
Load block
Load block and save it to the database
*/
loadBlock(sectordir, blockfilename, sector, loadlayout != 2);
loadBlock(sectordir, blockfilename, sector, true);
return getBlockNoCreateNoEx(blockpos);
}

View File

@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <jmutexautolock.h>
#include <jthread.h>
#include <iostream>
#include <sstream>
#include "common_irrlicht.h"
#include "mapnode.h"
@@ -31,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "voxel.h"
extern "C" {
#include "sqlite3.h"
}
class MapSector;
class ServerMapSector;
class ClientMapSector;
@@ -220,6 +225,10 @@ class Map /*: public NodeContainer*/
//core::aabbox3d<s16> getDisplayedBlockArea();
//bool updateChangedVisibleArea();
// Call these before and after saving of many blocks
virtual void beginSave() {return;};
virtual void endSave() {return;};
virtual void save(bool only_changed){assert(0);};
@@ -361,6 +370,23 @@ class ServerMap : public Map
v3s16 getBlockPos(std::string sectordir, std::string blockfile);
static std::string getBlockFilename(v3s16 p);
/*
Database functions
*/
// Create the database structure
void createDatabase();
// Verify we can read/write to the database
void verifyDatabase();
// Get an integer suitable for a block
static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
// Returns true if the database file does not exist
bool loadFromFolders();
// Call these before and after saving of blocks
void beginSave();
void endSave();
void save(bool only_changed);
//void loadAll();
@@ -391,6 +417,8 @@ class ServerMap : public Map
// This will generate a sector with getSector if not found.
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
MapBlock* loadBlock(v3s16 p);
// Database version
void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
// For debug printing
virtual void PrintInfo(std::ostream &out);
@@ -419,6 +447,13 @@ class ServerMap : public Map
This is reset to false when written on disk.
*/
bool m_map_metadata_changed;
/*
SQLite database and statements
*/
sqlite3 *m_database;
sqlite3_stmt *m_database_read;
sqlite3_stmt *m_database_write;
};
/*

View File

@@ -80,11 +80,12 @@ static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d)
}
#endif
static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
static void make_tree(VoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree)
{
MapNode treenode(CONTENT_TREE);
MapNode leavesnode(CONTENT_LEAVES);
MapNode applenode(CONTENT_APPLE);
s16 trunk_h = myrand_range(4, 5);
v3s16 p1 = p0;
for(s16 ii=0; ii<trunk_h; ii++)
@@ -147,8 +148,14 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;
u32 i = leaves_a.index(x,y,z);
if(leaves_d[i] == 1)
vmanip.m_data[vi] = leavesnode;
if(leaves_d[i] == 1) {
bool is_apple = myrand_range(0,99) < 10;
if(is_apple_tree && is_apple) {
vmanip.m_data[vi] = applenode;
} else {
vmanip.m_data[vi] = leavesnode;
}
}
}
}
@@ -1552,7 +1559,7 @@ void make_block(BlockMakeData *data)
/*
Create a block-specific seed
*/
u32 blockseed = (u32)(data->seed%0x100000000) + full_node_min.Z*38134234
u32 blockseed = (u32)(data->seed%0x100000000ULL) + full_node_min.Z*38134234
+ full_node_min.Y*42123 + full_node_min.X*23;
/*
@@ -1817,6 +1824,16 @@ void make_block(BlockMakeData *data)
if(noisebuf_ground_wetness.get(x,y,z) < -0.6)
vmanip.m_data[i] = MapNode(CONTENT_GRAVEL);
}
else if(noisebuf_ground_crumbleness.get(x,y,z) <
-3.0 + MYMIN(0.1 * sqrt((float)MYMAX(0, -y)), 1.5))
{
vmanip.m_data[i] = MapNode(CONTENT_LAVASOURCE);
for(s16 x1=-1; x1<=1; x1++)
for(s16 y1=-1; y1<=1; y1++)
for(s16 z1=-1; z1<=1; z1++)
data->transforming_liquid.push_back(
v3s16(p2d.X+x1, y+y1, p2d.Y+z1));
}
}
data->vmanip->m_area.add_y(em, i, -1);
@@ -2119,7 +2136,16 @@ void make_block(BlockMakeData *data)
p.Y++;
//if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5)
if(is_jungle == false)
make_tree(vmanip, p);
{
bool is_apple_tree;
if(myrand_range(0,4) != 0)
is_apple_tree = false;
else
is_apple_tree = noise2d_perlin(
0.5+(float)p.X/100, 0.5+(float)p.Z/100,
data->seed+342902, 3, 0.45) > 0.2;
make_tree(vmanip, p, is_apple_tree);
}
else
make_jungletree(vmanip, p);
}

View File

@@ -30,8 +30,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
ContentFeatures::~ContentFeatures()
{
if(initial_metadata)
delete initial_metadata;
delete initial_metadata;
delete special_material;
delete special_atlas;
}
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)

View File

@@ -96,7 +96,7 @@ enum LiquidType
LIQUID_SOURCE
};
class MapNode;
struct MapNode;
class NodeMetadata;
struct ContentFeatures
@@ -121,6 +121,7 @@ struct ContentFeatures
bool light_propagates;
bool sunlight_propagates;
u8 solidness; // Used when choosing which face is drawn
u8 visual_solidness; // When solidness=0, this tells how it looks like
// This is used for collision detection.
// Also for general solidness queries.
bool walkable;
@@ -128,6 +129,8 @@ struct ContentFeatures
bool pointable;
// Player can dig these
bool diggable;
// Player can climb these
bool climbable;
// Player can build on these
bool buildable_to;
// Whether the node has no liquid, source liquid or flowing liquid
@@ -151,12 +154,23 @@ struct ContentFeatures
content_t liquid_alternative_flowing;
// If the content is liquid, this is the source version of the liquid.
content_t liquid_alternative_source;
// Viscosity for fluid flow, ranging from 1 to 7, with
// 1 giving almost instantaneous propagation and 7 being
// the slowest possible
u8 liquid_viscosity;
// Used currently for flowing liquids
u8 vertex_alpha;
// Special irrlicht material, used sometimes
video::SMaterial *special_material;
AtlasPointer *special_atlas;
// Amount of light the node emits
u8 light_source;
// Digging properties for different tools
DiggingPropertiesList digging_properties;
u32 damage_per_second;
// NOTE: Move relevant properties to here from elsewhere
@@ -168,9 +182,11 @@ struct ContentFeatures
light_propagates = false;
sunlight_propagates = false;
solidness = 2;
visual_solidness = 0;
walkable = true;
pointable = true;
diggable = true;
climbable = false;
buildable_to = false;
liquid_type = LIQUID_NONE;
wall_mounted = false;
@@ -178,8 +194,14 @@ struct ContentFeatures
dug_item = "";
initial_metadata = NULL;
liquid_alternative_flowing = CONTENT_IGNORE;
liquid_alternative_source = CONTENT_IGNORE;
liquid_viscosity = 0;
vertex_alpha = 255;
special_material = NULL;
special_atlas = NULL;
light_source = 0;
digging_properties.clear();
damage_per_second = 0;
}
ContentFeatures()
@@ -403,10 +425,21 @@ enum LightBank
LIGHTBANK_NIGHT
};
/*
Masks for MapNode.param2 of flowing liquids
*/
#define LIQUID_LEVEL_MASK 0x07
#define LIQUID_FLOW_DOWN_MASK 0x08
/* maximum amount of liquid in a block */
#define LIQUID_LEVEL_MAX LIQUID_LEVEL_MASK
#define LIQUID_LEVEL_SOURCE (LIQUID_LEVEL_MAX+1)
/*
This is the stuff what the whole world consists of.
*/
struct MapNode
{
/*

View File

@@ -33,6 +33,7 @@ Player::Player():
craftresult_is_preview(true),
hp(20),
peer_id(PEER_ID_INEXISTENT),
m_selected_item(0),
m_pitch(0),
m_yaw(0),
m_speed(0,0,0),
@@ -47,6 +48,11 @@ Player::~Player()
delete inventory_backup;
}
void Player::wieldItem(u16 item)
{
m_selected_item = item;
}
void Player::resetInventory()
{
inventory.clear();
@@ -324,7 +330,18 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
/*
Calculate new position
*/
position += m_speed * dtime;
if(is_frozen) {
// Still move very slowly so as not to feel all completely stuck
position += m_speed * dtime * 0.001;
}
else {
position += m_speed * dtime;
}
/*
If the player enters an unloaded chunk this is set to true.
*/
is_frozen = false;
// Skip collision detection if a special movement mode is used
bool free_move = g_settings.getBool("free_move");
@@ -375,6 +392,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
in_water_stable = false;
}
/*
Check if player is climbing
*/
try {
v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
is_climbing = ((content_features(map.getNode(pp).getContent()).climbable ||
content_features(map.getNode(pp2).getContent()).climbable) && !free_move);
}
catch(InvalidPositionException &e)
{
is_climbing = false;
}
/*
Collision uncertainty radius
Make it a bit larger than the maximum distance of movement
@@ -461,7 +493,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
Player is allowed to jump when this is true.
*/
touching_ground = false;
/*std::cout<<"Checking collisions for ("
<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
<<") -> ("
@@ -482,8 +514,11 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
}
catch(InvalidPositionException &e)
{
// Doing nothing here will block the player from
// walking over map borders
if(!is_frozen) {
// freeze when entering unloaded areas
is_frozen = true;
}
continue;
}
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
@@ -723,7 +758,7 @@ void LocalPlayer::applyControl(float dtime)
bool fast_move = g_settings.getBool("fast_move");
bool continuous_forward = g_settings.getBool("continuous_forward");
if(free_move)
if(free_move || is_climbing)
{
v3f speed = getSpeed();
speed.Y = 0;
@@ -750,6 +785,12 @@ void LocalPlayer::applyControl(float dtime)
speed.Y = -walkspeed_max;
setSpeed(speed);
}
else if(is_climbing)
{
v3f speed = getSpeed();
speed.Y = -3*BS;
setSpeed(speed);
}
else
{
// If not free movement but fast is allowed, aux1 is
@@ -812,6 +853,12 @@ void LocalPlayer::applyControl(float dtime)
setSpeed(speed);
swimming_up = true;
}
else if(is_climbing)
{
v3f speed = getSpeed();
speed.Y = 3*BS;
setSpeed(speed);
}
}
// The speed of the player (Y is ignored)

View File

@@ -62,7 +62,20 @@ class Player
return m_position;
}
virtual void setPosition(v3f position)
v3s16 getLightPosition() const
{
return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
}
v3f getEyePosition()
{
// This is at the height of the eyes of the current figure
// return m_position + v3f(0, BS+BS/2, 0);
// This is more like in minecraft
return m_position + v3f(0,BS+(5*BS)/8,0);
}
virtual void setPosition(const v3f &position)
{
m_position = position;
}
@@ -92,6 +105,15 @@ class Player
snprintf(m_name, PLAYERNAME_SIZE, "%s", name);
}
virtual void wieldItem(u16 item);
virtual const InventoryItem *getWieldItem() const
{
const InventoryList *list = inventory.getList("main");
if (list)
return list->getItem(m_selected_item);
return NULL;
}
const char * getName()
{
return m_name;
@@ -118,7 +140,9 @@ class Player
bool in_water;
// This is more stable and defines the maximum speed of the player
bool in_water_stable;
bool is_climbing;
bool swimming_up;
bool is_frozen;
Inventory inventory;
// Actual inventory is backed up here when creative mode is used
@@ -132,6 +156,7 @@ class Player
protected:
char m_name[PLAYERNAME_SIZE];
u16 m_selected_item;
f32 m_pitch;
f32 m_yaw;
v3f m_speed;
@@ -205,7 +230,7 @@ class RemotePlayer : public Player, public scene::ISceneNode
return m_box;
}
void setPosition(v3f position)
void setPosition(const v3f &position)
{
m_oldpos = m_showpos;

View File

@@ -154,10 +154,10 @@ void initializePaths()
/*
OS X
*/
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
//TODO: Get path of executable. This assumes working directory is bin/
dstream<<"WARNING: Relative path not properly supported on OS X"
dstream<<"WARNING: Relative path not properly supported on OS X and FreeBSD"
<<std::endl;
path_data = std::string("../data");
path_userdata = std::string("../");
@@ -189,12 +189,12 @@ void initializePaths()
// Use "./bin/../data"
path_data = std::string(buf) + "/../data";
//path_data = std::string(buf) + "/../share/" + APPNAME;
//path_data = std::string(buf) + "/../share/" + PROJECT_NAME;
// Use "C:\Documents and Settings\user\Application Data\<APPNAME>"
// Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
len = GetEnvironmentVariable("APPDATA", buf, buflen);
assert(len < buflen);
path_userdata = std::string(buf) + "/" + APPNAME;
path_userdata = std::string(buf) + "/" + PROJECT_NAME;
/*
Linux
@@ -209,15 +209,15 @@ void initializePaths()
pathRemoveFile(buf, '/');
path_data = std::string(buf) + "/../share/" + APPNAME;
//path_data = std::string(INSTALL_PREFIX) + "/share/" + APPNAME;
path_data = std::string(buf) + "/../share/" + PROJECT_NAME;
//path_data = std::string(INSTALL_PREFIX) + "/share/" + PROJECT_NAME;
if (!fs::PathExists(path_data)) {
dstream<<"WARNING: data path " << path_data << " not found!";
path_data = std::string(buf) + "/../data";
dstream<<" Trying " << path_data << std::endl;
}
path_userdata = std::string(getenv("HOME")) + "/." + APPNAME;
path_userdata = std::string(getenv("HOME")) + "/." + PROJECT_NAME;
/*
OS X
@@ -243,7 +243,12 @@ void initializePaths()
}
CFRelease(resources_url);
path_userdata = std::string(getenv("HOME")) + "/Library/Application Support/" + APPNAME;
path_userdata = std::string(getenv("HOME")) + "/Library/Application Support/" + PROJECT_NAME;
#elif defined(__FreeBSD__)
path_data = std::string(INSTALL_PREFIX) + "/share/" + PROJECT_NAME;
path_userdata = std::string(getenv("HOME")) + "/." + PROJECT_NAME;
#endif

View File

@@ -63,9 +63,9 @@ extern std::string path_data;
/*
Directory for storing user data. Examples:
Windows: "C:\Documents and Settings\user\Application Data\<APPNAME>"
Linux: "~/.<APPNAME>"
Mac: "~/Library/Application Support/<APPNAME>"
Windows: "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
Linux: "~/.<PROJECT_NAME>"
Mac: "~/Library/Application Support/<PROJECT_NAME>"
*/
extern std::string path_userdata;

View File

@@ -27,28 +27,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/* report a zlib or i/o error */
void zerr(int ret)
{
fputs("zerr: ", stderr);
dstream<<"zerr: ";
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
dstream<<"error reading stdin"<<std::endl;
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
dstream<<"error writing stdout"<<std::endl;
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
dstream<<"invalid compression level"<<std::endl;
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
dstream<<"invalid or incomplete deflate data"<<std::endl;
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
dstream<<"out of memory"<<std::endl;
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
dstream<<"zlib version mismatch!"<<std::endl;
break;
default:
dstream<<"return value = "<<ret<<"\n";
dstream<<"return value = "<<ret<<std::endl;
}
}

View File

@@ -380,8 +380,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
v3s16 center = getNodeBlockPos(center_nodepos);
// Camera position and direction
v3f camera_pos =
playerpos + v3f(0, BS+BS/2, 0);
v3f camera_pos = player->getEyePosition();
v3f camera_dir = v3f(0,0,1);
camera_dir.rotateYZBy(player->getPitch());
camera_dir.rotateXZBy(player->getYaw());
@@ -775,6 +774,7 @@ void RemoteClient::SendObjectData(
u16 command
u16 number of player positions
for each player:
u16 peer_id
v3s32 position*100
v3s32 speed*100
s32 pitch*100
@@ -1064,6 +1064,7 @@ Server::Server(
m_env(new ServerMap(mapsavedir), this),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_authmanager(mapsavedir+"/auth.txt"),
m_banmanager(mapsavedir+"/ipban.txt"),
m_thread(this),
m_emergethread(this),
m_time_counter(0),
@@ -1252,6 +1253,20 @@ void Server::AsyncRunStep()
m_uptime.set(m_uptime.get() + dtime);
}
{
// Process connection's timeouts
JMutexAutoLock lock2(m_con_mutex);
ScopeProfiler sp(&g_profiler, "Server: connection timeout processing");
m_con.RunTimeouts(dtime);
}
{
// This has to be called so that the client list gets synced
// with the peer list of the connection
ScopeProfiler sp(&g_profiler, "Server: peer change handling");
handlePeerChanges();
}
/*
Update m_time_of_day and overall game time
*/
@@ -1294,20 +1309,6 @@ void Server::AsyncRunStep()
}
}
{
// Process connection's timeouts
JMutexAutoLock lock2(m_con_mutex);
ScopeProfiler sp(&g_profiler, "Server: connection timeout processing");
m_con.RunTimeouts(dtime);
}
{
// This has to be called so that the client list gets synced
// with the peer list of the connection
ScopeProfiler sp(&g_profiler, "Server: peer change handling");
handlePeerChanges();
}
{
JMutexAutoLock lock(m_env_mutex);
// Step environment
@@ -1732,9 +1733,15 @@ void Server::AsyncRunStep()
}
else if(event->type == MEET_OTHER)
{
dstream<<"Server: MEET_OTHER"<<std::endl;
prof.add("MEET_OTHER", 1);
dstream<<"WARNING: Server: MEET_OTHER not implemented"
<<std::endl;
for(core::map<v3s16, bool>::Iterator
i = event->modified_blocks.getIterator();
i.atEnd()==false; i++)
{
v3s16 p = i.getNode()->getKey();
setBlockNotSent(p);
}
}
else
{
@@ -1835,6 +1842,10 @@ void Server::AsyncRunStep()
// Auth stuff
if(m_authmanager.isModified())
m_authmanager.save();
//Bann stuff
if(m_banmanager.isModified())
m_banmanager.save();
// Map
JMutexAutoLock lock(m_env_mutex);
@@ -1924,6 +1935,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<peer_id<<" not found"<<std::endl;
return;
}
// drop player if is ip is banned
if(m_banmanager.isIpBanned(peer->address.serializeString())){
SendAccessDenied(m_con, peer_id,
L"Your ip is banned. Banned name was "
+narrow_to_wide(m_banmanager.getBanName(
peer->address.serializeString())));
m_con.deletePeer(peer_id, false);
return;
}
u8 peer_ser_ver = getClient(peer->id)->serialization_version;
@@ -1960,7 +1981,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
//peer->serialization_version = deployed;
getClient(peer->id)->pending_serialization_version = deployed;
if(deployed == SER_FMT_VER_INVALID)
{
derr_server<<DTIME<<"Server: Cannot negotiate "
@@ -1989,6 +2010,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
L"Your client is too old. Please upgrade.");
return;
}
/* Uhh... this should actually be a warning but let's do it like this */
if(net_proto_version < 2)
{
SendAccessDenied(m_con, peer_id,
L"Your client is too old. Please upgrade.");
return;
}
/*
Set up player
@@ -2158,6 +2187,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
UpdateCrafting(peer->id);
SendInventory(peer->id);
// Send player items to all players
SendPlayerItems();
// Send HP
{
Player *player = m_env.getPlayer(peer_id);
@@ -2422,7 +2454,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(g_settings.getBool("creative_mode") == false)
{
// Skip if inventory has no free space
if(ilist->getUsedSlots() == ilist->getSize())
if(ilist->roomForItem(item) == false)
{
dout_server<<"Player inventory has no free space"<<std::endl;
return;
@@ -2899,6 +2931,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return;
}
/*
If in creative mode, item dropping is disabled unless
player has build privileges
*/
if(g_settings.getBool("creative_mode") &&
(getPlayerPrivs(player) & PRIV_BUILD) == 0)
{
derr_server<<"Not allowing player to drop item: "
"creative mode and no build privs"<<std::endl;
return;
}
dout_server<<"Placing a miscellaneous item on map"
<<std::endl;
@@ -3162,6 +3206,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
mlist->addItem(item1);
}
}
// Disallow moving items if not allowed to build
else if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
return;
}
if(disable_action == false)
@@ -3222,13 +3269,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
u64 privs = getPlayerPrivs(player);
// Parse commands
std::wstring commandprefix = L"/#";
if(message.substr(0, commandprefix.size()) == commandprefix)
if(message[0] == L'/')
{
line += L"Server: ";
size_t strip_size = 1;
if (message[1] == L'#') // support old-style commans
++strip_size;
message = message.substr(strip_size);
message = message.substr(commandprefix.size());
WStrfnd f1(message);
f1.next(L" "); // Skip over /#whatever
std::wstring paramstring = f1.next(L"");
@@ -3241,9 +3288,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
player,
privs);
line += processServerCommand(ctx);
send_to_sender = ctx->flags & 1;
send_to_others = ctx->flags & 2;
std::wstring reply(processServerCommand(ctx));
send_to_sender = ctx->flags & SEND_TO_SENDER;
send_to_others = ctx->flags & SEND_TO_OTHERS;
if (ctx->flags & SEND_NO_PREFIX)
line += reply;
else
line += L"Server: " + reply;
delete ctx;
}
@@ -3382,6 +3435,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<std::endl;
SendChatMessage(peer_id, L"Password change successful");
}
else if (command == TOSERVER_PLAYERITEM)
{
if (datasize < 2+2)
return;
u16 item = readU16(&data[2]);
player->wieldItem(item);
SendWieldedItem(player);
}
else
{
derr_server<<"WARNING: Server::ProcessData(): Ignoring "
@@ -3666,6 +3728,60 @@ void Server::SendInventory(u16 peer_id)
m_con.Send(peer_id, 0, data, true);
}
std::string getWieldedItemString(const Player *player)
{
const InventoryItem *item = player->getWieldItem();
if (item == NULL)
return std::string("");
std::ostringstream os(std::ios_base::binary);
item->serialize(os);
return os.str();
}
void Server::SendWieldedItem(const Player* player)
{
DSTACK(__FUNCTION_NAME);
assert(player);
std::ostringstream os(std::ios_base::binary);
writeU16(os, TOCLIENT_PLAYERITEM);
writeU16(os, 1);
writeU16(os, player->peer_id);
os<<serializeString(getWieldedItemString(player));
// Make data buffer
std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
m_con.SendToAll(0, data, true);
}
void Server::SendPlayerItems()
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
core::list<Player *> players = m_env.getPlayers(true);
writeU16(os, TOCLIENT_PLAYERITEM);
writeU16(os, players.size());
core::list<Player *>::Iterator i;
for(i = players.begin(); i != players.end(); ++i)
{
Player *p = *i;
writeU16(os, p->peer_id);
os<<serializeString(getWieldedItemString(p));
}
// Make data buffer
std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
m_con.SendToAll(0, data, true);
}
void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
{
DSTACK(__FUNCTION_NAME);

View File

@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h"
#include "inventory.h"
#include "auth.h"
#include "ban.h"
/*
Some random functions
@@ -455,6 +456,28 @@ class Server : public con::PeerHandler, public MapEventReceiver,
g_settings.updateConfigFile(m_configpath.c_str());
}
void setIpBanned(const std::string &ip, const std::string &name)
{
m_banmanager.add(ip, name);
return;
}
void unsetIpBanned(const std::string &ip_or_name)
{
m_banmanager.remove(ip_or_name);
return;
}
std::string getBanDescription(const std::string &ip_or_name)
{
return m_banmanager.getBanDescription(ip_or_name);
}
con::Peer* getPeerNoEx(u16 peer_id)
{
return m_con.GetPeerNoEx(peer_id);
}
private:
// con::PeerHandler implementation.
@@ -479,6 +502,10 @@ class Server : public con::PeerHandler, public MapEventReceiver,
void SendObjectData(float dtime);
void SendPlayerInfos();
void SendInventory(u16 peer_id);
// send wielded item info about player to all
void SendWieldedItem(const Player *player);
// send wielded item info about all players to all players
void SendPlayerItems();
void SendChatMessage(u16 peer_id, const std::wstring &message);
void BroadcastChatMessage(const std::wstring &message);
void SendPlayerHP(Player *player);
@@ -562,6 +589,9 @@ class Server : public con::PeerHandler, public MapEventReceiver,
// User authentication
AuthManager m_authmanager;
// Bann checking
BanManager m_banmanager;
/*
Threads

View File

@@ -25,6 +25,14 @@ void cmd_status(std::wostringstream &os,
os<<ctx->server->getStatusString();
}
void cmd_me(std::wostringstream &os,
ServerCommandContext *ctx)
{
std::wstring name = narrow_to_wide(ctx->player->getName());
os << L"* " << name << L" " << ctx->paramstring;
ctx->flags |= SEND_TO_OTHERS | SEND_NO_PREFIX;
}
void cmd_privs(std::wostringstream &os,
ServerCommandContext *ctx)
{
@@ -130,7 +138,7 @@ void cmd_shutdown(std::wostringstream &os,
ctx->server->requestShutdown();
os<<L"*** Server shutting down (operator request)";
ctx->flags |= 2;
ctx->flags |= SEND_TO_OTHERS;
}
void cmd_setting(std::wostringstream &os,
@@ -183,12 +191,56 @@ void cmd_teleport(std::wostringstream &os,
os<< L"-!- Teleported.";
}
void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
{
if((ctx->privs & PRIV_BAN) == 0)
{
os<<L"-!- You don't have permission to do that";
return;
}
if(ctx->parms.size() < 2)
{
std::string desc = ctx->server->getBanDescription("");
os<<L"-!- Ban list: "<<narrow_to_wide(desc);
return;
}
if(ctx->parms[0] == L"ban")
{
Player *player = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
if(player == NULL)
{
os<<L"-!- No such player";
return;
}
con::Peer *peer = ctx->server->getPeerNoEx(player->peer_id);
if(peer == NULL)
{
dstream<<__FUNCTION_NAME<<": peer was not found"<<std::endl;
return;
}
std::string ip_string = peer->address.serializeString();
ctx->server->setIpBanned(ip_string, player->getName());
os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
<<narrow_to_wide(player->getName());
}
else
{
std::string ip_or_name = wide_to_narrow(ctx->parms[1]);
std::string desc = ctx->server->getBanDescription(ip_or_name);
ctx->server->unsetIpBanned(ip_or_name);
os<<L"-!- Unbanned "<<narrow_to_wide(desc);
}
}
std::wstring processServerCommand(ServerCommandContext *ctx)
{
std::wostringstream os(std::ios_base::binary);
ctx->flags = 1; // Default, unless we change it.
ctx->flags = SEND_TO_SENDER; // Default, unless we change it.
u64 privs = ctx->privs;
@@ -204,6 +256,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
os<<L" teleport";
if(privs & PRIV_PRIVS)
os<<L" grant revoke";
if(privs & PRIV_BAN)
os<<L" ban unban";
}
else if(ctx->parms[0] == L"status")
{
@@ -233,6 +287,14 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
{
cmd_teleport(os, ctx);
}
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
{
cmd_banunban(os, ctx);
}
else if(ctx->parms[0] == L"me")
{
cmd_me(os, ctx);
}
else
{
os<<L"-!- Invalid command: " + ctx->parms[0];

View File

@@ -25,9 +25,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "player.h"
#include "server.h"
#define SEND_TO_SENDER (1<<0)
#define SEND_TO_OTHERS (1<<1)
#define SEND_NO_PREFIX (1<<2)
struct ServerCommandContext
{
std::vector<std::wstring> parms;
std::wstring paramstring;
Server* server;

View File

@@ -162,7 +162,7 @@ int main(int argc, char *argv[])
BEGIN_DEBUG_EXCEPTION_HANDLER
// Print startup message
dstream<<DTIME<<"minetest-c55"
dstream<<DTIME<<PROJECT_NAME <<
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
<<", "<<BUILD_INFO
<<std::endl;

View File

@@ -97,6 +97,16 @@ void Address::Resolve(const char *name)
freeaddrinfo(resolved);
}
std::string Address::serializeString()
{
unsigned int a, b, c, d;
a = (m_address & 0xFF000000)>>24;
b = (m_address & 0x00FF0000)>>16;
c = (m_address & 0x0000FF00)>>8;
d = (m_address & 0x000000FF);
return itos(a)+"."+itos(b)+"."+itos(c)+"."+itos(d);
}
unsigned int Address::getAddress() const
{
return m_address;

View File

@@ -97,6 +97,7 @@ class Address
void setPort(unsigned short port);
void print(std::ostream *s) const;
void print() const;
std::string serializeString();
private:
unsigned int m_address;
unsigned short m_port;

File diff suppressed because it is too large Load Diff

View File

@@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.7.6.3"
#define SQLITE_VERSION_NUMBER 3007006
#define SQLITE_SOURCE_ID "2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e"
#define SQLITE_VERSION "3.7.7.1"
#define SQLITE_VERSION_NUMBER 3007007
#define SQLITE_SOURCE_ID "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -310,7 +310,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** argument. ^If the callback function of the 3rd argument to
** sqlite3_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements. ^The 4th argument to
** to sqlite3_exec() is relayed through to the 1st argument of each
** sqlite3_exec() is relayed through to the 1st argument of each
** callback invocation. ^If the callback pointer to sqlite3_exec()
** is NULL, then no callback is ever invoked and result rows are
** ignored.
@@ -375,7 +375,8 @@ SQLITE_API int sqlite3_exec(
**
** New error codes may be added in future versions of SQLite.
**
** See also: [SQLITE_IOERR_READ | extended result codes]
** See also: [SQLITE_IOERR_READ | extended result codes],
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
*/
#define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */
@@ -452,17 +453,21 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the xOpen method of the
** [sqlite3_vfs] object.
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
*/
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
@@ -470,6 +475,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
@@ -580,17 +586,18 @@ struct sqlite3_file {
/*
** CAPI3REF: OS Interface File Virtual Methods Object
**
** Every file opened by the [sqlite3_vfs] xOpen method populates an
** Every file opened by the [sqlite3_vfs.xOpen] method populates an
** [sqlite3_file] object (or, more commonly, a subclass of the
** [sqlite3_file] object) with a pointer to an instance of this object.
** This object defines the methods used to perform various operations
** against the open file represented by the [sqlite3_file] object.
**
** If the xOpen method sets the sqlite3_file.pMethods element
** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
** may be invoked even if the xOpen reported that it failed. The
** only way to prevent a call to xClose following a failed xOpen
** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
** to NULL.
**
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
@@ -762,7 +769,8 @@ typedef struct sqlite3_mutex sqlite3_mutex;
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system. The "vfs"
** in the name of the object stands for "virtual file system".
** in the name of the object stands for "virtual file system". See
** the [VFS | VFS documentation] for further information.
**
** The value of the iVersion field is initially 1 but may be larger in
** future versions of SQLite. Additional fields may be appended to this
@@ -791,6 +799,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** The zName field holds the name of the VFS module. The name must
** be unique across all VFS modules.
**
** [[sqlite3_vfs.xOpen]]
** ^SQLite guarantees that the zFilename parameter to xOpen
** is either a NULL pointer or string obtained
** from xFullPathname() with an optional suffix added.
@@ -868,6 +877,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** element will be valid after xOpen returns regardless of the success
** or failure of the xOpen call.
**
** [[sqlite3_vfs.xAccess]]
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
@@ -892,7 +902,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** method returns a Julian Day Number for the current date and time as
** a floating point value.
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
** Day Number multipled by 86400000 (the number of milliseconds in
** Day Number multiplied by 86400000 (the number of milliseconds in
** a 24-hour day).
** ^SQLite will use the xCurrentTimeInt64() method to get the current
** date and time if that method is available (if iVersion is 2 or
@@ -1114,9 +1124,9 @@ SQLITE_API int sqlite3_os_end(void);
** implementation of an application-defined [sqlite3_os_init()].
**
** The first argument to sqlite3_config() is an integer
** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
** [configuration option] that determines
** what property of SQLite is to be configured. Subsequent arguments
** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
** vary depending on the [configuration option]
** in the first argument.
**
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
@@ -1226,6 +1236,7 @@ struct sqlite3_mem_methods {
/*
** CAPI3REF: Configuration Options
** KEYWORDS: {configuration option}
**
** These constants are the available integer configuration options that
** can be passed as the first argument to the [sqlite3_config()] interface.
@@ -1238,7 +1249,7 @@ struct sqlite3_mem_methods {
** is invoked.
**
** <dl>
** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
** <dd>There are no arguments to this option. ^This option sets the
** [threading mode] to Single-thread. In other words, it disables
** all mutexing and puts SQLite into a mode where it can only be used
@@ -1249,7 +1260,7 @@ struct sqlite3_mem_methods {
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
** configuration option.</dd>
**
** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
** <dd>There are no arguments to this option. ^This option sets the
** [threading mode] to Multi-thread. In other words, it disables
** mutexing on [database connection] and [prepared statement] objects.
@@ -1263,7 +1274,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
**
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option. ^This option sets the
** [threading mode] to Serialized. In other words, this option enables
** all mutexes including the recursive
@@ -1279,7 +1290,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
**
** <dt>SQLITE_CONFIG_MALLOC</dt>
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mem_methods] structure. The argument specifies
** alternative low-level memory allocation routines to be used in place of
@@ -1287,7 +1298,7 @@ struct sqlite3_mem_methods {
** its own private copy of the content of the [sqlite3_mem_methods] structure
** before the [sqlite3_config()] call returns.</dd>
**
** <dt>SQLITE_CONFIG_GETMALLOC</dt>
** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
** structure is filled with the currently defined memory allocation routines.)^
@@ -1295,7 +1306,7 @@ struct sqlite3_mem_methods {
** routines with a wrapper that simulations memory allocation failure or
** tracks memory usage, for example. </dd>
**
** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^This option takes single argument of type int, interpreted as a
** boolean, which enables or disables the collection of memory allocation
** statistics. ^(When memory allocation statistics are disabled, the
@@ -1311,7 +1322,7 @@ struct sqlite3_mem_methods {
** allocation statistics are disabled by default.
** </dd>
**
** <dt>SQLITE_CONFIG_SCRATCH</dt>
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
** scratch memory. There are three arguments: A pointer an 8-byte
** aligned memory buffer from which the scratch allocations will be
@@ -1327,9 +1338,9 @@ struct sqlite3_mem_methods {
** scratch memory beyond what is provided by this configuration option, then
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
**
** <dt>SQLITE_CONFIG_PAGECACHE</dt>
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
** the database page cache with the default page cache implemenation.
** the database page cache with the default page cache implementation.
** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1348,7 +1359,7 @@ struct sqlite3_mem_methods {
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
** will be undefined.</dd>
**
** <dt>SQLITE_CONFIG_HEAP</dt>
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
** <dd> ^This option specifies a static memory buffer that SQLite will use
** for all of its dynamic memory allocation needs beyond those provided
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
@@ -1365,7 +1376,7 @@ struct sqlite3_mem_methods {
** The minimum allocation size is capped at 2^12. Reasonable values
** for the minimum allocation size are 2^5 through 2^8.</dd>
**
** <dt>SQLITE_CONFIG_MUTEX</dt>
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure. The argument specifies
** alternative low-level mutex routines to be used in place
@@ -1377,7 +1388,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
** return [SQLITE_ERROR].</dd>
**
** <dt>SQLITE_CONFIG_GETMUTEX</dt>
** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure. The
** [sqlite3_mutex_methods]
@@ -1390,7 +1401,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
** return [SQLITE_ERROR].</dd>
**
** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
** <dd> ^(This option takes two arguments that determine the default
** memory allocation for the lookaside memory allocator on each
** [database connection]. The first argument is the
@@ -1400,18 +1411,18 @@ struct sqlite3_mem_methods {
** verb to [sqlite3_db_config()] can be used to change the lookaside
** configuration on individual connections.)^ </dd>
**
** <dt>SQLITE_CONFIG_PCACHE</dt>
** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
** <dd> ^(This option takes a single argument which is a pointer to
** an [sqlite3_pcache_methods] object. This object specifies the interface
** to a custom page cache implementation.)^ ^SQLite makes a copy of the
** object and uses it for page cache memory allocations.</dd>
**
** <dt>SQLITE_CONFIG_GETPCACHE</dt>
** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** [sqlite3_pcache_methods] object. SQLite copies of the current
** page cache implementation into that object.)^ </dd>
**
** <dt>SQLITE_CONFIG_LOG</dt>
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
** function with a call signature of void(*)(void*,int,const char*),
** and a pointer to void. ^If the function pointer is not NULL, it is
@@ -1429,6 +1440,18 @@ struct sqlite3_mem_methods {
** In a multi-threaded application, the application-defined logger
** function must be threadsafe. </dd>
**
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
** <dd> This option takes a single argument of type int. If non-zero, then
** URI handling is globally enabled. If the parameter is zero, then URI handling
** is globally disabled. If URI handling is globally enabled, all filenames
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
** connection is opened. If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1447,6 +1470,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
#define SQLITE_CONFIG_URI 17 /* int */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -1532,13 +1556,17 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
**
** ^This routine returns the [rowid] of the most recent
** successful [INSERT] into the database from the [database connection]
** in the first argument. ^If no successful [INSERT]s
** in the first argument. ^As of SQLite version 3.7.7, this routines
** records the last insert rowid of both ordinary tables and [virtual tables].
** ^If no successful [INSERT]s
** have ever occurred on that database connection, zero is returned.
**
** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
** row is returned by this routine as long as the trigger is running.
** But once the trigger terminates, the value returned by this routine
** reverts to the last value inserted before the trigger fired.)^
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
** row as long as the trigger or virtual table method is running.
** But once the trigger or virtual table method ends, the value returned
** by this routine reverts to what it was before the trigger or virtual
** table method began.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
@@ -2201,6 +2229,9 @@ SQLITE_API int sqlite3_set_authorizer(
** to signal SQLite whether or not the action is permitted. See the
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
**
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
** from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
@@ -2323,7 +2354,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
** CAPI3REF: Opening A New Database Connection
**
** ^These routines open an SQLite database file whose name is given by the
** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
@@ -2350,7 +2381,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** sqlite3_open_v2() can take one of
** the following three values, optionally combined with the
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
**
** <dl>
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
@@ -2369,9 +2400,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** </dl>
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
** combinations shown above or one of the combinations shown above combined
** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
** combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined.
**
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
@@ -2386,6 +2416,11 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use. ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.
**
** ^If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. ^This in-memory database will vanish when
** the database connection is closed. Future versions of SQLite might
@@ -2398,10 +2433,111 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** on-disk database will be created. ^This private database will be
** automatically deleted as soon as the database connection is closed.
**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use. ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
**
** ^If [URI filename] interpretation is enabled, and the filename argument
** begins with "file:", then the filename is interpreted as a URI. ^URI
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
** set in the fourth argument to sqlite3_open_v2(), or if it has
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
** As of SQLite version 3.7.7, URI filename interpretation is turned off
** by default, but future releases of SQLite might enable URI filename
** interpretation by default. See "[URI filenames]" for additional
** information.
**
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
** authority, then it must be either an empty string or the string
** "localhost". ^If the authority is not an empty string or "localhost", an
** error is returned to the caller. ^The fragment component of a URI, if
** present, is ignored.
**
** ^SQLite uses the path component of the URI as the name of the disk file
** which contains the database. ^If the path begins with a '/' character,
** then it is interpreted as an absolute path. ^If the path does not begin
** with a '/' (meaning that the authority section is omitted from the URI)
** then the path is interpreted as a relative path.
** ^On windows, the first component of an absolute path
** is a drive specification (e.g. "C:").
**
** [[core URI query parameters]]
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [VFS | custom VFS implementation].
** SQLite interprets the following three query parameters:
**
** <ul>
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
** a VFS object that provides the operating system interface that should
** be used to access the database file on disk. ^If this option is set to
** an empty string the default VFS object is used. ^Specifying an unknown
** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
** present, then the VFS specified by the option takes precedence over
** the value passed as the fourth parameter to sqlite3_open_v2().
**
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
** "rwc". Attempting to set it to any other value is an error)^.
** ^If "ro" is specified, then the database is opened for read-only
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
** "rw", then the database is opened for read-write (but not create)
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
** been set. ^Value "rwc" is equivalent to setting both
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
** used, it is an error to specify a value for the mode parameter that is
** less restrictive than that specified by the flags passed as the third
** parameter.
**
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
** "private". ^Setting it to "shared" is equivalent to setting the
** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behaviour requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
** error. Future versions of SQLite might understand additional query
** parameters. See "[query parameters with special meaning to SQLite]" for
** additional information.
**
** [[URI filename examples]] <h3>URI filename examples</h3>
**
** <table border="1" align=center cellpadding=5>
** <tr><th> URI filenames <th> Results
** <tr><td> file:data.db <td>
** Open the file "data.db" in the current directory.
** <tr><td> file:/home/fred/data.db<br>
** file:///home/fred/data.db <br>
** file://localhost/home/fred/data.db <br> <td>
** Open the database file "/home/fred/data.db".
** <tr><td> file://darkstar/home/fred/data.db <td>
** An error. "darkstar" is not a recognized authority.
** <tr><td style="white-space:nowrap">
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
** <td> Windows only: Open the file "data.db" on fred's desktop on drive
** C:. Note that the %20 escaping in this example is not strictly
** necessary - space characters can be used literally
** in URI filenames.
** <tr><td> file:data.db?mode=ro&cache=private <td>
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
** query components of a URI. A hexadecimal escape sequence consists of a
** percent sign - "%" - followed by exactly two hexadecimal digits
** specifying an octet value. ^Before the path or query components of a
** URI filename are interpreted, they are encoded using UTF-8 and all
** hexadecimal escape sequences replaced by a single byte containing the
** corresponding octet. If this process generates an invalid UTF-8 encoding,
** the results are undefined.
**
** <b>Note to Windows users:</b> The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
@@ -2424,6 +2560,26 @@ SQLITE_API int sqlite3_open_v2(
const char *zVfs /* Name of VFS module to use */
);
/*
** CAPI3REF: Obtain Values For URI Parameters
**
** This is a utility routine, useful to VFS implementations, that checks
** to see if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of the query parameter.
**
** The zFilename argument is the filename pointer passed into the xOpen()
** method of a VFS implementation. The zParam argument is the name of the
** query parameter we seek. This routine returns the value of the zParam
** parameter if it exists. If the parameter does not exist, this routine
** returns a NULL pointer.
**
** If the zFilename argument to this function is not a pointer that SQLite
** passed into the xOpen VFS method, then the behavior of this routine
** is undefined and probably undesirable.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
/*
** CAPI3REF: Error Codes And Messages
**
@@ -2539,43 +2695,45 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** Additional information is available at [limits | Limits in SQLite].
**
** <dl>
** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
**
** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
**
** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
** <dd>The maximum number of columns in a table definition or in the
** result set of a [SELECT] or the maximum number of columns in an index
** or in an ORDER BY or GROUP BY clause.</dd>)^
**
** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
**
** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
**
** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
** <dd>The maximum number of instructions in a virtual machine program
** used to implement an SQL statement. This limit is not currently
** enforced, though that might be added in some future release of
** SQLite.</dd>)^
**
** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
** <dd>The maximum number of arguments on a function.</dd>)^
**
** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
**
** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
** <dd>The maximum length of the pattern argument to the [LIKE] or
** [GLOB] operators.</dd>)^
**
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^
** </dl>
*/
@@ -3104,7 +3262,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
** database locks it needs to do its job. ^If the statement is a [COMMIT]
** or occurs outside of an explicit transaction, then you can retry the
** statement. If the statement is not a [COMMIT] and occurs within a
** statement. If the statement is not a [COMMIT] and occurs within an
** explicit transaction then you should rollback the transaction before
** continuing.
**
@@ -3383,7 +3541,7 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
** CAPI3REF: Destroy A Prepared Statement Object
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors or
** ^If the most recent evaluation of the statement encountered no errors
** or if the statement is never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
@@ -4610,6 +4768,11 @@ struct sqlite3_module {
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
/* The methods above are in version 1 of the sqlite_module object. Those
** below are for version 2 and greater. */
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};
/*
@@ -5292,7 +5455,7 @@ struct sqlite3_mutex_methods {
**
** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
** the routine should return 1. This seems counter-intuitive since
** clearly the mutex cannot be held if it does not exist. But the
** clearly the mutex cannot be held if it does not exist. But
** the reason the mutex does not exist is because the build is not
** using mutexes. And we do not want the assert() containing the
** call to sqlite3_mutex_held() to fail, so a non-zero return is
@@ -5415,7 +5578,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISKEYWORD 16
#define SQLITE_TESTCTRL_PGHDRSZ 17
#define SQLITE_TESTCTRL_SCRATCHMALLOC 18
#define SQLITE_TESTCTRL_LAST 18
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 19
#define SQLITE_TESTCTRL_LAST 19
/*
** CAPI3REF: SQLite Runtime Status
@@ -5424,7 +5588,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
** about the performance of SQLite, and optionally to reset various
** highwater marks. ^The first argument is an integer code for
** the specific parameter to measure. ^(Recognized integer codes
** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
** are of the form [status parameters | SQLITE_STATUS_...].)^
** ^The current value of the parameter is returned into *pCurrent.
** ^The highest recorded value is returned in *pHighwater. ^If the
** resetFlag is true, then the highest record value is reset after
@@ -5451,12 +5615,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
/*
** CAPI3REF: Status Parameters
** KEYWORDS: {status parameters}
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite3_status()].
**
** <dl>
** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
** <dd>This parameter is the current amount of memory checked out
** using [sqlite3_malloc()], either directly or indirectly. The
** figure includes calls made to [sqlite3_malloc()] by the application
@@ -5466,23 +5631,24 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** this parameter. The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
**
** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
** internal equivalents). Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
** <dd>This parameter records the number of separate memory allocations
** currently checked out.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
** [pagecache memory allocator] that was configured using
** [SQLITE_CONFIG_PAGECACHE]. The
** value returned is in pages, not in bytes.</dd>)^
**
** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of page cache
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
@@ -5492,13 +5658,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [pagecache memory allocator]. Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
** <dd>This parameter returns the number of allocations used out of the
** [scratch memory allocator] configured using
** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
@@ -5506,7 +5672,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** outstanding at time, this parameter also reports the number of threads
** using scratch memory at the same time.</dd>)^
**
** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of scratch memory
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
** buffer and where forced to overflow to [sqlite3_malloc()]. The values
@@ -5516,13 +5682,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** slots were available.
** </dd>)^
**
** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [scratch memory allocator]. Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
** <dd>This parameter records the deepest parser stack. It is only
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
** </dl>
@@ -5547,9 +5713,9 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** about a single [database connection]. ^The first argument is the
** database connection object to be interrogated. ^The second argument
** is an integer constant, taken from the set of
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
** [SQLITE_DBSTATUS options], that
** determines the parameter to interrogate. The set of
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
** [SQLITE_DBSTATUS options] is likely
** to grow in future releases of SQLite.
**
** ^The current value of the requested parameter is written into *pCur
@@ -5566,6 +5732,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
/*
** CAPI3REF: Status Parameters for database connections
** KEYWORDS: {SQLITE_DBSTATUS options}
**
** These constants are the available integer "verbs" that can be passed as
** the second argument to the [sqlite3_db_status()] interface.
@@ -5577,15 +5744,16 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** if a discontinued or unsupported verb is invoked.
**
** <dl>
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
@@ -5593,6 +5761,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
@@ -5600,12 +5769,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
@@ -5614,7 +5783,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
@@ -5636,7 +5805,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** CAPI3REF: Prepared Statement Status
**
** ^(Each prepared statement maintains various
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
** [SQLITE_STMTSTATUS counters] that measure the number
** of times it has performed specific operations.)^ These counters can
** be used to monitor the performance characteristics of the prepared
** statements. For example, if the number of table steps greatly exceeds
@@ -5647,7 +5816,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** ^(This interface is used to retrieve and reset counter values from
** a [prepared statement]. The first argument is the prepared statement
** object to be interrogated. The second argument
** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
** is an integer code for a specific [SQLITE_STMTSTATUS counter]
** to be interrogated.)^
** ^The current value of the requested counter is returned.
** ^If the resetFlg is true, then the counter is reset to zero after this
@@ -5659,24 +5828,25 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
/*
** CAPI3REF: Status Parameters for prepared statements
** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite3_stmt_status()] interface.
** The meanings of the various counters are as follows:
**
** <dl>
** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan. Large numbers for this counter
** may indicate opportunities for performance improvement through
** careful use of indices.</dd>
**
** <dt>SQLITE_STMTSTATUS_SORT</dt>
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
** improvement performance through careful use of indices.</dd>
**
** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
** <dd>^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
@@ -5727,6 +5897,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** the application may discard the parameter after the call to
** [sqlite3_config()] returns.)^
**
** [[the xInit() page cache method]]
** ^(The xInit() method is called once for each effective
** call to [sqlite3_initialize()])^
** (usually only once during the lifetime of the process). ^(The xInit()
@@ -5737,6 +5908,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** built-in default page cache is used instead of the application defined
** page cache.)^
**
** [[the xShutdown() page cache method]]
** ^The xShutdown() method is called by [sqlite3_shutdown()].
** It can be used to clean up
** any outstanding resources before process shutdown, if required.
@@ -5751,6 +5923,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^SQLite will never invoke xInit() more than once without an intervening
** call to xShutdown().
**
** [[the xCreate() page cache methods]]
** ^SQLite invokes the xCreate() method to construct a new cache instance.
** SQLite will typically create one cache instance for each open database file,
** though this is not guaranteed. ^The
@@ -5775,6 +5948,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^Hence, a cache created with bPurgeable false will
** never contain any unpinned pages.
**
** [[the xCachesize() page cache method]]
** ^(The xCachesize() method may be called at any time by SQLite to set the
** suggested maximum cache-size (number of pages stored by) the cache
** instance passed as the first argument. This is the value configured using
@@ -5782,14 +5956,16 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** parameter, the implementation is not required to do anything with this
** value; it is advisory only.
**
** [[the xPagecount() page cache methods]]
** The xPagecount() method must return the number of pages currently
** stored in the cache, both pinned and unpinned.
**
** [[the xFetch() page cache methods]]
** The xFetch() method locates a page in the cache and returns a pointer to
** the page, or a NULL pointer.
** A "page", in this context, means a buffer of szPage bytes aligned at an
** 8-byte boundary. The page to be fetched is determined by the key. ^The
** mimimum key value is 1. After it has been retrieved using xFetch, the page
** minimum key value is 1. After it has been retrieved using xFetch, the page
** is considered to be "pinned".
**
** If the requested page is already in the page cache, then the page cache
@@ -5813,6 +5989,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
** [[the xUnpin() page cache method]]
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument. If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
@@ -5825,6 +6002,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** call to xUnpin() unpins the page regardless of the number of prior calls
** to xFetch().
**
** [[the xRekey() page cache methods]]
** The xRekey() method is used to change the key value associated with the
** page passed as the second argument. If the cache
** previously contains an entry associated with newKey, it must be
@@ -5837,6 +6015,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** of these pages are pinned, they are implicitly unpinned, meaning that
** they can be safely discarded.
**
** [[the xDestroy() page cache method]]
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
** All resources associated with the specified cache should be freed. ^After
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
@@ -5899,7 +6078,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** There should be exactly one call to sqlite3_backup_finish() for each
** successful call to sqlite3_backup_init().
**
** <b>sqlite3_backup_init()</b>
** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
**
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
** [database connection] associated with the destination database
@@ -5926,7 +6105,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** sqlite3_backup_finish() functions to perform the specified backup
** operation.
**
** <b>sqlite3_backup_step()</b>
** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
**
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
** the source and destination databases specified by [sqlite3_backup] object B.
@@ -5983,7 +6162,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
** <b>sqlite3_backup_finish()</b>
** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
**
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
** application wishes to abandon the backup operation, the application
@@ -6006,7 +6185,8 @@ typedef struct sqlite3_backup sqlite3_backup;
** is not a permanent error and does not affect the return value of
** sqlite3_backup_finish().
**
** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
**
** ^Each call to sqlite3_backup_step() sets two values inside
** the [sqlite3_backup] object: the number of pages still to be backed
@@ -6392,6 +6572,93 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
#define SQLITE_CHECKPOINT_FULL 1
#define SQLITE_CHECKPOINT_RESTART 2
/*
** CAPI3REF: Virtual Table Interface Configuration
**
** This function may be called by either the [xConnect] or [xCreate] method
** of a [virtual table] implementation to configure
** various facets of the virtual table interface.
**
** If this interface is invoked outside the context of an xConnect or
** xCreate virtual table method then the behavior is undefined.
**
** At present, there is only one option that may be configured using
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
** may be added in the future.
*/
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
** can use to customize and optimize their behavior.
**
** <dl>
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer. If X is zero, then the [virtual table] whose
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
** support constraints. In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
** specified as part of the users SQL statement, regardless of the actual
** ON CONFLICT mode specified.
**
** If X is non-zero, then the virtual table implementation guarantees
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
** any modifications to internal or persistent data structures have been made.
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
** is able to roll back a statement or database transaction, and abandon
** or continue processing the current SQL statement as appropriate.
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
** had been ABORT.
**
** Virtual table implementations that are required to handle OR REPLACE
** must do so within the [xUpdate] method. If a call to the
** [sqlite3_vtab_on_conflict()] function indicates that the current ON
** CONFLICT policy is REPLACE, the virtual table implementation should
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
** </dl>
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Conflict resolution modes
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
** is for the SQL statement being evaluated.
**
** Note that the [SQLITE_IGNORE] constant is also used as a potential
** return value from the [sqlite3_set_authorizer()] callback and that
** [SQLITE_ABORT] is also a [result code].
*/
#define SQLITE_ROLLBACK 1
/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
#define SQLITE_FAIL 3
/* #define SQLITE_ABORT 4 // Also an error code */
#define SQLITE_REPLACE 5
/*
** Undo the hack that converts floating point types to integer for

View File

@@ -495,11 +495,25 @@ void TextureSource::buildMainAtlas()
core::dimension2d<u32> atlas_dim(1024,1024);
video::IImage *atlas_img =
driver->createImage(video::ECF_A8R8G8B8, atlas_dim);
assert(atlas_img);
//assert(atlas_img);
if(atlas_img == NULL)
{
dstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
"image; not building texture atlas."<<std::endl;
return;
}
/*
A list of stuff to add. This should contain as much of the
stuff shown in game as possible, to minimize texture changes.
A list of stuff to include in the texture atlas.
It is a single-dimensional texture atlas due to the need to tile
textures.
It should contain as much of the stuff shown in game as possible,
to minimize texture changes.
It fills up quickly, so do not add anything that isn't contained
in most MapBlocks. E.g. mese isn't suitable but stone is.
*/
core::array<std::string> sourcelist;
@@ -518,7 +532,6 @@ void TextureSource::buildMainAtlas()
sourcelist.push_back("cobble.png");
sourcelist.push_back("mossycobble.png");
sourcelist.push_back("gravel.png");
sourcelist.push_back("cactus.png");
sourcelist.push_back("jungletree.png");
sourcelist.push_back("stone.png^mineral_coal.png");

View File

@@ -236,17 +236,14 @@ inline u16 readU32(std::istream &is)
inline void writeF1000(std::ostream &os, f32 p)
{
char buf[2];
char buf[4];
writeF1000((u8*)buf, p);
os.write(buf, 2);
os.write(buf, 4);
}
inline f32 readF1000(std::istream &is)
{
char buf[2];
is.read(buf, 2);
// TODO: verify if this gets rid of the valgrind warning
//if(is.gcount() != 2)
// return 0;
char buf[4];
is.read(buf, 4);
return readF1000((u8*)buf);
}
@@ -1264,6 +1261,14 @@ class Settings
m_settings[name] = value;
}
void set(std::string name, const char *value)
{
JMutexAutoLock lock(m_mutex);
m_settings[name] = value;
}
void setDefault(std::string name, std::string value)
{
JMutexAutoLock lock(m_mutex);
@@ -1456,6 +1461,8 @@ class Settings
i.getNode()->getValue());
}
return *this;
}
Settings & operator=(Settings &other)

View File

@@ -453,12 +453,14 @@ class VoxelManipulator /*: public NodeContainer*/
if(m_area.contains(p) == false)
return false;
m_data[m_area.index(p)] = n;
return true;
}
bool setNodeNoEmerge(s32 i, MapNode n)
{
if(m_area.contains(i) == false)
return false;
m_data[i] = n;
return true;
}
/*bool setContentNoEmerge(v3s16 p, u8 c)
{

View File

@@ -1,21 +1,36 @@
0 128 128 128
1 107 134 51
2 39 66 106
3 255 255 0
4 86 58 31
5 48 95 8
6 102 129 38
7 178 178 0
8 101 84 36
9 39 66 106
12 104 78 42
13 210 194 156
14 117 86 41
15 128 79 0
16 118 118 118
18 123 123 123
19 199 199 199
20 183 183 222
21 103 78 42
22 108 138 108
23 90 90 90
0 128 128 128 # CONTENT_STONE
2 39 66 106 # CONTENT_WATER
3 255 255 0 # CONTENT_TORCH
9 39 66 106 # CONTENT_WATERSOURCE
e 117 86 41 # CONTENT_SIGN_WALL
f 128 79 0 # CONTENT_CHEST
10 118 118 118 # CONTENT_FURNACE
15 103 78 42 # CONTENT_FENCE
1e 162 119 53 # CONTENT_RAIL
1f 154 110 40 # CONTENT_LADDER
20 255 204 0 # CONTENT_LAVA
21 255 204 0 # CONTENT_LAVASOURCE
800 107 134 51 # CONTENT_GRASS
801 86 58 31 # CONTENT_TREE
802 48 95 8 # CONTENT_LEAVES
803 102 129 38 # CONTENT_GRASS_FOOTSTEPS
804 178 178 0 # CONTENT_MESE
805 101 84 36 # CONTENT_MUD
808 104 78 42 # CONTENT_WOOD
809 210 194 156 # CONTENT_SAND
80a 123 123 123 # CONTENT_COBBLE
80b 199 199 199 # CONTENT_STEEL
80c 183 183 222 # CONTENT_GLASS
80d 219 202 178 # CONTENT_MOSSYCOBBLE
80e 78 154 6 # CONTENT_GRAVEL
80f 204 0 0 # CONTENT_SANDSTONE
810 0 215 0 # CONTENT_CACTUS
811 170 50 25 # CONTENT_BRICK
812 104 78 42 # CONTENT_CLAY
813 58 105 18 # CONTENT_PAPYRUS
814 196 160 0 # CONTENT_BOOKSHELF
815 205 190 121 # CONTENT_JUNGLETREE
816 62 101 25 # CONTENT_JUNGLEGRASS
817 255 153 255 # CONTENT_NC
818 102 50 255 # CONTENT_NC_RB
819 200 0 0 # CONTENT_APPLE

785
util/minetestmapper.py Executable file → Normal file
View File

@@ -1,5 +1,5 @@
#!/usr/bin/python2
# -*- coding: windows-1252 -*-
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
@@ -9,68 +9,121 @@
# Made by Jogge, modified by celeron55
# 2011-05-29: j0gge: initial release
# 2011-05-30: celeron55: simultaneous support for sectors/sectors2, removed
# 2011-05-30: celeron55: simultaneous support for sectors/sectors2, removed
# 2011-06-02: j0gge: command line parameters, coordinates, players, ...
# 2011-06-04: celeron55: added #!/usr/bin/python2 and converted \r\n to \n
# to make it easily executable on Linux
# 2011-07-30: WF: Support for content types extension, refactoring
# 2011-07-30: erlehmann: PEP 8 compliance.
# Requires Python Imaging Library: http://www.pythonware.com/products/pil/
# Some speed-up: ...lol, actually it slows it down.
#import psyco ; psyco.full()
#import psyco ; psyco.full()
#from psyco.classes import *
import zlib
import Image, ImageDraw, ImageFont, ImageColor
import os
import string
import time
import getopt
import sys
import array
import cStringIO
from PIL import Image, ImageDraw, ImageFont, ImageColor
TRANSLATION_TABLE = {
1: 0x800, # CONTENT_GRASS
4: 0x801, # CONTENT_TREE
5: 0x802, # CONTENT_LEAVES
6: 0x803, # CONTENT_GRASS_FOOTSTEPS
7: 0x804, # CONTENT_MESE
8: 0x805, # CONTENT_MUD
10: 0x806, # CONTENT_CLOUD
11: 0x807, # CONTENT_COALSTONE
12: 0x808, # CONTENT_WOOD
13: 0x809, # CONTENT_SAND
18: 0x80a, # CONTENT_COBBLE
19: 0x80b, # CONTENT_STEEL
20: 0x80c, # CONTENT_GLASS
22: 0x80d, # CONTENT_MOSSYCOBBLE
23: 0x80e, # CONTENT_GRAVEL
24: 0x80f, # CONTENT_SANDSTONE
25: 0x810, # CONTENT_CACTUS
26: 0x811, # CONTENT_BRICK
27: 0x812, # CONTENT_CLAY
28: 0x813, # CONTENT_PAPYRUS
29: 0x814} # CONTENT_BOOKSHELF
def hex_to_int(h):
i = int(h, 16)
if(i > 2047):
i -= 4096
return i
i = int(h, 16)
if(i > 2047):
i -= 4096
return i
def hex4_to_int(h):
i = int(h, 16)
if(i > 32767):
i -= 65536
return i
i = int(h, 16)
if(i > 32767):
i -= 65536
return i
def int_to_hex3(i):
if(i < 0):
return "%03X" % (i + 4096)
else:
return "%03X" % i
if(i < 0):
return "%03X" % (i + 4096)
else:
return "%03X" % i
def int_to_hex4(i):
if(i < 0):
return "%04X" % (i + 65536)
else:
return "%04X" % i
if(i < 0):
return "%04X" % (i + 65536)
else:
return "%04X" % i
def getBlockAsInteger(p):
return p[2]*16777216 + p[1]*4096 + p[0]
def unsignedToSigned(i, max_positive):
if i < max_positive:
return i
else:
return i - 2*max_positive
def getIntegerAsBlock(i):
x = unsignedToSigned(i % 4096, 2048)
i = int((i - x) / 4096)
y = unsignedToSigned(i % 4096, 2048)
i = int((i - y) / 4096)
z = unsignedToSigned(i % 4096, 2048)
return x,y,z
def limit(i, l, h):
if(i > h):
i = h
if(i < l):
i = l
return i
if(i > h):
i = h
if(i < l):
i = l
return i
def usage():
print "TODO: Help"
print("TODO: Help")
try:
opts, args = getopt.getopt(sys.argv[1:], "hi:o:", ["help", "input=", "output=", "bgcolor=", "scalecolor=", "origincolor=", "playercolor=", "draworigin", "drawplayers", "drawscale"])
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
opts, args = getopt.getopt(sys.argv[1:], "hi:o:", ["help", "input=",
"output=", "bgcolor=", "scalecolor=", "origincolor=",
"playercolor=", "draworigin", "drawplayers", "drawscale",
"drawunderground"])
except getopt.GetoptError as err:
# print help information and exit:
print(str(err)) # will print something like "option -a not recognized"
usage()
sys.exit(2)
path = "../world/"
output = "uloste.png"
output = "map.png"
border = 0
scalecolor = "black"
bgcolor = "white"
@@ -79,6 +132,7 @@ playercolor = "red"
drawscale = False
drawplayers = False
draworigin = False
drawunderground = False
sector_xmin = -1500 / 16
sector_xmax = 1500 / 16
@@ -86,71 +140,104 @@ sector_zmin = -1500 / 16
sector_zmax = 1500 / 16
for o, a in opts:
if o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-i", "--input"):
path = a
elif o in ("-o", "--output"):
output = a
elif o == "--bgcolor":
bgcolor = ImageColor.getrgb(a)
elif o == "--scalecolor":
scalecolor = ImageColor.getrgb(a)
elif o == "--playercolor":
playercolor = ImageColor.getrgb(a)
elif o == "--origincolor":
origincolor = ImageColor.getrgb(a)
elif o == "--drawscale":
drawscale = True
border = 40
elif o == "--drawplayers":
drawplayers = True
elif o == "--draworigin":
draworigin = True
else:
assert False, "unhandled option"
if path[-1:]!="/" and path[-1:]!="\\":
path = path + "/"
if o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-i", "--input"):
path = a
elif o in ("-o", "--output"):
output = a
elif o == "--bgcolor":
bgcolor = ImageColor.getrgb(a)
elif o == "--scalecolor":
scalecolor = ImageColor.getrgb(a)
elif o == "--playercolor":
playercolor = ImageColor.getrgb(a)
elif o == "--origincolor":
origincolor = ImageColor.getrgb(a)
elif o == "--drawscale":
drawscale = True
border = 40
elif o == "--drawplayers":
drawplayers = True
elif o == "--draworigin":
draworigin = True
elif o == "--drawunderground":
drawunderground = True
else:
assert False, "unhandled option"
if path[-1:] != "/" and path[-1:] != "\\":
path = path + "/"
# Load color information for the blocks.
colors = {}
f = file("colors.txt")
try:
f = file("colors.txt")
except IOError:
f = file(os.path.join(os.path.dirname(__file__), "colors.txt"))
for line in f:
values = string.split(line)
colors[int(values[0])] = (int(values[1]), int(values[2]), int(values[3]))
values = string.split(line)
colors[int(values[0], 16)] = (
int(values[1]),
int(values[2]),
int(values[3]))
f.close()
xlist = []
zlist = []
# List all sectors to memory and calculate the width and heigth of the resulting picture.
try:
for filename in os.listdir(path + "sectors2"):
for filename2 in os.listdir(path + "sectors2/" + filename):
x = hex_to_int(filename)
z = hex_to_int(filename2)
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
except OSError:
pass
try:
for filename in os.listdir(path + "sectors"):
x = hex4_to_int(filename[:4])
z = hex4_to_int(filename[-4:])
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
except OSError:
pass
# List all sectors to memory and calculate the width and heigth of the
# resulting picture.
conn = None
cur = None
if os.path.exists(path + "map.sqlite"):
import sqlite3
conn = sqlite3.connect(path + "map.sqlite")
cur = conn.cursor()
cur.execute("SELECT `pos` FROM `blocks`")
while True:
r = cur.fetchone()
if not r:
break
x, y, z = getIntegerAsBlock(r[0])
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
if os.path.exists(path + "sectors2"):
for filename in os.listdir(path + "sectors2"):
for filename2 in os.listdir(path + "sectors2/" + filename):
x = hex_to_int(filename)
z = hex_to_int(filename2)
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
if os.path.exists(path + "sectors"):
for filename in os.listdir(path + "sectors"):
x = hex4_to_int(filename[:4])
z = hex4_to_int(filename[-4:])
if x < sector_xmin or x > sector_xmax:
continue
if z < sector_zmin or z > sector_zmax:
continue
xlist.append(x)
zlist.append(z)
# Get rid of doubles
xlist, zlist = zip(*sorted(set(zip(xlist, zlist))))
minx = min(xlist)
minz = min(zlist)
@@ -160,7 +247,7 @@ maxz = max(zlist)
w = (maxx - minx) * 16 + 16
h = (maxz - minz) * 16 + 16
print "w="+str(w)+" h="+str(h)
print("w=" + str(w) + " h=" + str(h))
im = Image.new("RGB", (w + border, h + border), bgcolor)
draw = ImageDraw.Draw(im)
@@ -170,278 +257,304 @@ stuff = {}
starttime = time.time()
def data_is_air(d):
return (d == 254 or d == 126)
CONTENT_WATER = 2
def content_is_water(d):
return d in [2, 9]
def content_is_air(d):
return d in [126, 127, 254]
def read_content(mapdata, version, datapos):
if version == 20:
if mapdata[datapos] < 0x80:
return mapdata[datapos]
else:
return (mapdata[datapos] << 4) | (mapdata[datapos + 0x2000] >> 4)
elif 16 <= version < 20:
return TRANSLATION_TABLE.get(mapdata[datapos], mapdata[datapos])
else:
raise Exception("Unsupported map format: " + str(version))
def read_mapdata(f, version, pixellist, water, day_night_differs):
global stuff # oh my :-)
dec_o = zlib.decompressobj()
try:
mapdata = array.array("B", dec_o.decompress(f.read()))
except:
mapdata = []
f.close()
if(len(mapdata) < 4096):
print("bad: " + xhex + "/" + zhex + "/" + yhex + " " + \
str(len(mapdata)))
else:
chunkxpos = xpos * 16
chunkypos = ypos * 16
chunkzpos = zpos * 16
content = 0
datapos = 0
for (x, z) in reversed(pixellist):
for y in reversed(range(16)):
datapos = x + y * 16 + z * 256
content = read_content(mapdata, version, datapos)
if content_is_air(content):
pass
elif content_is_water(content):
water[(x, z)] += 1
# Add dummy stuff for drawing sea without seabed
stuff[(chunkxpos + x, chunkzpos + z)] = (
chunkypos + y, content, water[(x, z)], day_night_differs)
elif content in colors:
# Memorize information on the type and height of
# the block and for drawing the picture.
stuff[(chunkxpos + x, chunkzpos + z)] = (
chunkypos + y, content, water[(x, z)], day_night_differs)
pixellist.remove((x, z))
break
else:
print("strange block: %s/%s/%s x: %d y: %d z: %d \
block id: %x" % (xhex, zhex, yhex, x, y, z, content))
# Go through all sectors.
for n in range(len(xlist)):
#if n > 500:
# break
if n % 200 == 0:
nowtime = time.time()
dtime = nowtime - starttime
try:
n_per_second = 1.0 * n / dtime
except ZeroDivisionError:
n_per_second = 0
if n_per_second != 0:
seconds_per_n = 1.0 / n_per_second
time_guess = seconds_per_n * len(xlist)
remaining_s = time_guess - dtime
remaining_minutes = int(remaining_s / 60)
remaining_s -= remaining_minutes * 60;
print("Processing sector "+str(n)+" of "+str(len(xlist))
+" ("+str(round(100.0*n/len(xlist), 1))+"%)"
+" (ETA: "+str(remaining_minutes)+"m "
+str(int(remaining_s))+"s)")
#if n > 500:
# break
if n % 200 == 0:
nowtime = time.time()
dtime = nowtime - starttime
try:
n_per_second = 1.0 * n / dtime
except ZeroDivisionError:
n_per_second = 0
if n_per_second != 0:
seconds_per_n = 1.0 / n_per_second
time_guess = seconds_per_n * len(xlist)
remaining_s = time_guess - dtime
remaining_minutes = int(remaining_s / 60)
remaining_s -= remaining_minutes * 60
print("Processing sector " + str(n) + " of " + str(len(xlist))
+ " (" + str(round(100.0 * n / len(xlist), 1)) + "%)"
+ " (ETA: " + str(remaining_minutes) + "m "
+ str(int(remaining_s)) + "s)")
xpos = xlist[n]
zpos = zlist[n]
xhex = int_to_hex3(xpos)
zhex = int_to_hex3(zpos)
xhex4 = int_to_hex4(xpos)
zhex4 = int_to_hex4(zpos)
sector1 = xhex4.lower() + zhex4.lower()
sector2 = xhex.lower() + "/" + zhex.lower()
ylist = []
sectortype = ""
try:
for filename in os.listdir(path + "sectors/" + sector1):
if(filename != "meta"):
pos = int(filename, 16)
if(pos > 32767):
pos -= 65536
ylist.append(pos)
sectortype = "old"
except OSError:
pass
if sectortype != "old":
try:
for filename in os.listdir(path + "sectors2/" + sector2):
if(filename != "meta"):
pos = int(filename, 16)
if(pos > 32767):
pos -= 65536
ylist.append(pos)
sectortype = "new"
except OSError:
pass
if sectortype == "":
continue
xpos = xlist[n]
zpos = zlist[n]
ylist.sort()
# Make a list of pixels of the sector that are to be looked for.
pixellist = []
water = {}
for x in range(16):
for z in range(16):
pixellist.append((x, z))
water[(x, z)] = 0
# Go through the Y axis from top to bottom.
ylist2=[]
for ypos in reversed(ylist):
yhex = int_to_hex4(ypos)
xhex = int_to_hex3(xpos)
zhex = int_to_hex3(zpos)
xhex4 = int_to_hex4(xpos)
zhex4 = int_to_hex4(zpos)
filename = ""
if sectortype == "old":
filename = path + "sectors/" + sector1 + "/" + yhex.lower()
else:
filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
sector1 = xhex4.lower() + zhex4.lower()
sector2 = xhex.lower() + "/" + zhex.lower()
f = file(filename, "rb")
ylist = []
version = f.read(1)
flags = f.read(1)
# Checking day and night differs -flag
if not ord(flags) & 2:
ylist2.append((ypos,filename))
f.close()
continue
sectortype = ""
dec_o = zlib.decompressobj()
try:
mapdata = dec_o.decompress(f.read())
except:
mapdata = []
f.close()
if(len(mapdata) < 4096):
print "bad: " + xhex + "/" + zhex + "/" + yhex + " " + str(len(mapdata))
else:
chunkxpos = xpos * 16
chunkypos = ypos * 16
chunkzpos = zpos * 16
for (x, z) in reversed(pixellist):
for y in reversed(range(16)):
datapos = x + y * 16 + z * 256
if(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) in colors):
if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9):
water[(x, z)] += 1
# Add dummy stuff for drawing sea without seabed
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
else:
pixellist.remove((x, z))
# Memorize information on the type and height of the block and for drawing the picture.
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
break
elif(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) not in colors):
print "strange block: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos]))
# After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis.
if(len(pixellist) == 0):
break
if len(pixellist) > 0:
for (ypos, filename) in ylist2:
f = file(filename, "rb")
if cur:
psmin = getBlockAsInteger((xpos, -2048, zpos))
psmax = getBlockAsInteger((xpos, 2047, zpos))
cur.execute("SELECT `pos` FROM `blocks` WHERE `pos`>=? AND `pos`<=? AND (`pos` - ?) % 4096 = 0", (psmin, psmax, psmin))
while True:
r = cur.fetchone()
if not r:
break
pos = getIntegerAsBlock(r[0])[1]
ylist.append(pos)
sectortype = "sqlite"
try:
for filename in os.listdir(path + "sectors/" + sector1):
if(filename != "meta"):
pos = int(filename, 16)
if(pos > 32767):
pos -= 65536
ylist.append(pos)
sectortype = "old"
except OSError:
pass
version = f.read(1)
flags = f.read(1)
if sectortype == "":
try:
for filename in os.listdir(path + "sectors2/" + sector2):
if(filename != "meta"):
pos = int(filename, 16)
if(pos > 32767):
pos -= 65536
ylist.append(pos)
sectortype = "new"
except OSError:
pass
dec_o = zlib.decompressobj()
try:
mapdata = dec_o.decompress(f.read())
except:
mapdata = []
f.close()
if(len(mapdata) < 4096):
print "bad: " + xhex + "/" + zhex + "/" + yhex + " " + str(len(mapdata))
else:
chunkxpos = xpos * 16
chunkypos = ypos * 16
chunkzpos = zpos * 16
for (x, z) in reversed(pixellist):
for y in reversed(range(16)):
datapos = x + y * 16 + z * 256
if(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) in colors):
if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9):
water[(x, z)] += 1
# Add dummy stuff for drawing sea without seabed
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
else:
pixellist.remove((x, z))
# Memorize information on the type and height of the block and for drawing the picture.
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
break
elif(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) not in colors):
print "outo palikka: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos]))
# After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis.
if(len(pixellist) == 0):
break
if sectortype == "":
continue
print "Drawing image"
ylist.sort()
# Make a list of pixels of the sector that are to be looked for.
pixellist = []
water = {}
for x in range(16):
for z in range(16):
pixellist.append((x, z))
water[(x, z)] = 0
# Go through the Y axis from top to bottom.
for ypos in reversed(ylist):
yhex = int_to_hex4(ypos)
if sectortype == "sqlite":
ps = getBlockAsInteger((xpos, ypos, zpos))
cur.execute("SELECT `data` FROM `blocks` WHERE `pos`==? LIMIT 1", (ps,))
r = cur.fetchone()
if not r:
continue
f = cStringIO.StringIO(r[0])
else:
if sectortype == "old":
filename = path + "sectors/" + sector1 + "/" + yhex.lower()
else:
filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
f = file(filename, "rb")
# Let's just memorize these even though it's not really necessary.
version = ord(f.read(1))
flags = f.read(1)
# Checking day and night differs -flag
day_night_differs = ((ord(flags) & 2) != 0)
read_mapdata(f, version, pixellist, water, day_night_differs)
# After finding all the pixels in the sector, we can move on to
# the next sector without having to continue the Y axis.
if(len(pixellist) == 0):
break
print("Drawing image")
# Drawing the picture
starttime = time.time()
n = 0
for (x, z) in stuff.iterkeys():
if n % 500000 == 0:
nowtime = time.time()
dtime = nowtime - starttime
try:
n_per_second = 1.0 * n / dtime
except ZeroDivisionError:
n_per_second = 0
if n_per_second != 0:
listlen = len(stuff)
seconds_per_n = 1.0 / n_per_second
time_guess = seconds_per_n * listlen
remaining_s = time_guess - dtime
remaining_minutes = int(remaining_s / 60)
remaining_s -= remaining_minutes * 60;
print("Drawing pixel "+str(n)+" of "+str(listlen)
+" ("+str(round(100.0*n/listlen, 1))+"%)"
+" (ETA: "+str(remaining_minutes)+"m "
+str(int(remaining_s))+"s)")
n += 1
if n % 500000 == 0:
nowtime = time.time()
dtime = nowtime - starttime
try:
n_per_second = 1.0 * n / dtime
except ZeroDivisionError:
n_per_second = 0
if n_per_second != 0:
listlen = len(stuff)
seconds_per_n = 1.0 / n_per_second
time_guess = seconds_per_n * listlen
remaining_s = time_guess - dtime
remaining_minutes = int(remaining_s / 60)
remaining_s -= remaining_minutes * 60
print("Drawing pixel " + str(n) + " of " + str(listlen)
+ " (" + str(round(100.0 * n / listlen, 1)) + "%)"
+ " (ETA: " + str(remaining_minutes) + "m "
+ str(int(remaining_s)) + "s)")
n += 1
(r, g, b) = colors[stuff[(x,z)][1]]
# Comparing heights of a couple of adjacent blocks and changing brightness accordingly.
try:
c1 = stuff[(x - 1, z)][1]
c2 = stuff[(x, z + 1)][1]
c = stuff[(x, z)][1]
if c1 != 2 and c1 != 9 and c2 != 2 and c2 != 9 and c != 2 and c != 9:
y1 = stuff[(x - 1, z)][0]
y2 = stuff[(x, z + 1)][0]
y = stuff[(x, z)][0]
d = ((y - y1) + (y - y2)) * 12
else:
d = 0
if(d > 36):
d = 36
r = limit(r + d, 0, 255)
g = limit(g + d, 0, 255)
b = limit(b + d, 0, 255)
except:
pass
# Water
if(stuff[(x,z)][2] > 0):
r=int(r * .15 + colors[2][0] * .85)
g=int(g * .15 + colors[2][1] * .85)
b=int(b * .15 + colors[2][2] * .85)
impix[x - minx * 16 + border, h - 1 - (z - minz * 16) + border] = (r, g, b)
(r, g, b) = colors[stuff[(x, z)][1]]
dnd = stuff[(x, z)][3] # day/night differs?
if not dnd and not drawunderground:
if stuff[(x, z)][2] > 0: # water
(r, g, b) = colors[CONTENT_WATER]
else:
continue
# Comparing heights of a couple of adjacent blocks and changing
# brightness accordingly.
try:
c = stuff[(x, z)][1]
c1 = stuff[(x - 1, z)][1]
c2 = stuff[(x, z + 1)][1]
dnd1 = stuff[(x - 1, z)][3]
dnd2 = stuff[(x, z + 1)][3]
if not dnd:
d = -69
elif not content_is_water(c1) and not content_is_water(c2) and \
not content_is_water(c):
y = stuff[(x, z)][0]
y1 = stuff[(x - 1, z)][0] if dnd1 else y
y2 = stuff[(x, z + 1)][0] if dnd2 else y
d = ((y - y1) + (y - y2)) * 12
else:
d = 0
if(d > 36):
d = 36
r = limit(r + d, 0, 255)
g = limit(g + d, 0, 255)
b = limit(b + d, 0, 255)
except:
pass
# Water
if(stuff[(x, z)][2] > 0):
r = int(r * .15 + colors[2][0] * .85)
g = int(g * .15 + colors[2][1] * .85)
b = int(b * .15 + colors[2][2] * .85)
impix[x - minx * 16 + border, h - 1 - (z - minz * 16) + border] = (r, g, b)
if draworigin:
draw.ellipse((minx * -16 - 5 + border, h - minz * -16 - 6 + border, minx * -16 + 5 + border, h - minz * -16 + 4 + border), outline = origincolor)
draw.ellipse((minx * -16 - 5 + border, h - minz * -16 - 6 + border,
minx * -16 + 5 + border, h - minz * -16 + 4 + border),
outline=origincolor)
font = ImageFont.load_default()
if drawscale:
draw.text((24, 0), "X", font = font, fill = scalecolor)
draw.text((2, 24), "Z", font = font, fill = scalecolor)
draw.text((24, 0), "X", font=font, fill=scalecolor)
draw.text((2, 24), "Z", font=font, fill=scalecolor)
for n in range(int(minx / -4) * -4, maxx, 4):
draw.text((minx * -16 + n * 16 + 2 + border, 0), str(n * 16), font = font, fill = scalecolor)
draw.line((minx * -16 + n * 16 + border, 0, minx * -16 + n * 16 + border, border - 1), fill = scalecolor)
for n in range(int(minx / -4) * -4, maxx, 4):
draw.text((minx * -16 + n * 16 + 2 + border, 0), str(n * 16),
font=font, fill=scalecolor)
draw.line((minx * -16 + n * 16 + border, 0,
minx * -16 + n * 16 + border, border - 1), fill=scalecolor)
for n in range(int(maxz / 4) * 4, minz, -4):
draw.text((2, h - 1 - (n * 16 - minz * 16) + border), str(n * 16), font = font, fill = scalecolor)
draw.line((0, h - 1 - (n * 16 - minz * 16) + border, border - 1, h - 1 - (n * 16 - minz * 16) + border), fill = scalecolor)
for n in range(int(maxz / 4) * 4, minz, -4):
draw.text((2, h - 1 - (n * 16 - minz * 16) + border), str(n * 16),
font=font, fill=scalecolor)
draw.line((0, h - 1 - (n * 16 - minz * 16) + border, border - 1,
h - 1 - (n * 16 - minz * 16) + border), fill=scalecolor)
if drawplayers:
try:
for filename in os.listdir(path + "players"):
f = file(path + "players/" + filename)
lines = f.readlines()
name=""
position=[]
for line in lines:
p = string.split(line)
if p[0] == "name":
name = p[2]
print filename + ": name = " + name
if p[0] == "position":
position = string.split(p[2][1:-1], ",")
print filename + ": position = " + p[2]
if len(name) > 0 and len(position) == 3:
x=(int(float(position[0]) / 10 - minx * 16))
z=int(h - (float(position[2]) / 10 - minz * 16))
draw.ellipse((x - 2 + border, z - 2 + border, x + 2 + border, z + 2 + border), outline = playercolor)
draw.text((x + 2 + border, z + 2 + border), name, font = font, fill = playercolor)
f.close()
except OSError:
pass
try:
for filename in os.listdir(path + "players"):
f = file(path + "players/" + filename)
lines = f.readlines()
name = ""
position = []
for line in lines:
p = string.split(line)
if p[0] == "name":
name = p[2]
print(filename + ": name = " + name)
if p[0] == "position":
position = string.split(p[2][1:-1], ",")
print(filename + ": position = " + p[2])
if len(name) > 0 and len(position) == 3:
x = (int(float(position[0]) / 10 - minx * 16))
z = int(h - (float(position[2]) / 10 - minz * 16))
draw.ellipse((x - 2 + border, z - 2 + border,
x + 2 + border, z + 2 + border), outline=playercolor)
draw.text((x + 2 + border, z + 2 + border), name,
font=font, fill=playercolor)
f.close()
except OSError:
pass
print "Saving"
print("Saving")
im.save(output)

132
util/sectors2sqlite.py Executable file
View File

@@ -0,0 +1,132 @@
#!/usr/bin/python3
# Loads block files from sectors folders into map.sqlite database.
# The sectors folder should be safe to remove after this prints "Finished."
import time, os, sys
try:
import sqlite3
except:
exit('You need to have the Python sqlite3 module.')
path = "../world/"
paths = []
# sectors2 gets to try first
if os.path.isdir(path + 'sectors2/'):
paths.append('sectors2')
if os.path.isdir(path + 'sectors/'):
paths.append('sectors')
if not paths:
exit('Could not find sectors folder at ' + path + 'sectors2/ or ' + path + 'sectors/')
def parseSigned12bit(u):
u = int('0x'+u, 16)
return (u if u < 2**11 else u - 2**12)
def parseSigned16bit(u):
u = int('0x'+u, 16)
return (u if u < 2**15 else u - 2**16)
def int64(u):
while u >= 2**63:
u -= 2**64
while u <= -2**63:
u += 2**64
return u
# Convert sector folder(s) to integer
def getSectorPos(dirname):
if len(dirname) == 8:
# Old layout
x = parseSigned16bit(dirname[:4])
z = parseSigned16bit(dirname[4:])
elif len(dirname) == 7:
# New layout
x = parseSigned12bit(dirname[:3])
z = parseSigned12bit(dirname[4:])
else:
print('Terrible sector at ' + dirname)
return
return x, z
# Convert block file to integer position
def getBlockPos(sectordir, blockfile):
p2d = getSectorPos(sectordir)
if not p2d:
return
if len(blockfile) != 4:
print("Invalid block filename: " + blockfile)
y = parseSigned16bit(blockfile)
return p2d[0], y, p2d[1]
# Convert location to integer
def getBlockAsInteger(p):
return int64(p[2]*16777216 + p[1]*4096 + p[0])
# Init
create = False
if not os.path.isfile(path + 'map.sqlite'):
create = True
conn = sqlite3.connect(path + 'map.sqlite')
if not conn:
exit('Could not open database.')
cur = conn.cursor()
if create:
cur.execute("CREATE TABLE IF NOT EXISTS `blocks` (`pos` INT NOT NULL PRIMARY KEY, `data` BLOB);")
conn.commit()
print('Created database at ' + path + 'map.sqlite')
# Crawl the folders
count = 0
t = time.time()
for base in paths:
v = 0
if base == 'sectors':
v = 1
elif base == 'sectors2':
v= 2
else:
print('Ignoring base ' + base)
continue
for root, dirs, files in os.walk(path + base):
if files:
for block in files:
pos = getBlockAsInteger(getBlockPos(root[(-8 if v == 1 else -7 if v == 2 else 0):], block))
if pos is None:
print('Ignoring broken path ' + root + '/' + block)
continue
f = open(root+'/'+block, 'rb')
blob = f.read()
f.close()
if sys.version_info.major == 2:
blob = buffer(blob)
else:
blob = memoryview(blob)
cur.execute('INSERT OR IGNORE INTO `blocks` VALUES(?, ?)', (pos, blob))
count += 1
if(time.time() - t > 3):
t = time.time()
print(str(count)+' blocks processed...')
conn.commit()
print('Finished. (' + str(count) + ' blocks)')

65
util/updatepo.sh Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/sh
# Update/create minetest po files
# an auxiliary function to abort processing with an optional error
# message
abort() {
test -n "$1" && echo >&2 "$1"
exit 1
}
# The po/ directory is assumed to be parallel to the directory where
# this script is. Relative paths are fine for us so we can just
# use the following trick (works both for manual invocations and for
# script found from PATH)
scriptisin="$(dirname "$(which "$0")")"
# The script is executed from the parent of po/, which is also the
# parent of the script directory and of the src/ directory.
# We go through $scriptisin so that it can be executed from whatever
# directory and still work correctly
cd "$scriptisin/.."
test -e po || abort "po/ directory not found"
test -d po || abort "po/ is not a directory!"
# Get a list of the languages we have to update/create
cd po || abort "couldn't change directory to po!"
# This assumes that we won't have dirnames with space, which is
# the case for language codes, which are the only subdirs we expect to
# find in po/ anyway. If you put anything else there, you need to suffer
# the consequences of your actions, so we don't do sanity checks
langs=""
for lang in * ; do
if test ! -d $lang; then
continue
fi
langs="$langs $lang"
done
# go back
cd ..
# First thing first, update the .pot template. We place it in the po/
# directory at the top level. You a recent enough xgettext that supports
# --package-name
potfile=po/minetest.pot
xgettext --package-name=minetest -kN_ -kwgettext -F -n -o $potfile src/*.cpp src/*.h
# Now iterate on all languages and create the po file if missing, or update it
# if it exists already
for lang in $langs ; do # note the missing quotes around $langs
pofile=po/$lang/minetest.po
if test -e $pofile; then
echo "[$lang]: updating strings"
msgmerge -F -U $pofile $potfile
else
# This will ask for the translator identity
echo "[$lang]: NEW strings"
msginit -l $lang -o $pofile -i $potfile
fi
done

1285
util/wireshark/minetest.lua Normal file

File diff suppressed because it is too large Load Diff