Compare commits
339 Commits
0.2.201107
...
0.2.201109
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
960009d619 | ||
|
|
5ca877b836 | ||
|
|
b0c2c83861 | ||
|
|
1a63c6e016 | ||
|
|
fd7c8706ce | ||
|
|
aefa3b630b | ||
|
|
d5281eaa2e | ||
|
|
7504a748d0 | ||
|
|
bdf54908aa | ||
|
|
7244f09111 | ||
|
|
ca748ad44c | ||
|
|
ae6d83a41e | ||
|
|
b22cb69a15 | ||
|
|
40707e3c5b | ||
|
|
7f51bccf47 | ||
|
|
bfa5ad483f | ||
|
|
ae89aa55b9 | ||
|
|
88dc8c694e | ||
|
|
785a2fd23a | ||
|
|
4328a6442b | ||
|
|
6496b1cf1f | ||
|
|
c0caedc373 | ||
|
|
d28ea57083 | ||
|
|
8e26c5c066 | ||
|
|
5c1074aa7d | ||
|
|
bd72091150 | ||
|
|
faf3d7902a | ||
|
|
63f1ded167 | ||
|
|
3c30ab2807 | ||
|
|
310fa10035 | ||
|
|
bc847e8cc2 | ||
|
|
b82952bdba | ||
|
|
570a8dbf22 | ||
|
|
c68ea19e8d | ||
|
|
0c91d01866 | ||
|
|
e34cef312f | ||
|
|
d670c831c2 | ||
|
|
d1a16f24cf | ||
|
|
2d872ce3fa | ||
|
|
e3c58eff1c | ||
|
|
99de37ff94 | ||
|
|
5e3b9e3578 | ||
|
|
ad795c9f0c | ||
|
|
d6d479f94c | ||
|
|
6415528f96 | ||
|
|
4af1f2963c | ||
|
|
ba0322f353 | ||
|
|
1a705523c0 | ||
|
|
87b9e5467d | ||
|
|
625dac8d8c | ||
|
|
134e49cc8e | ||
|
|
cab426ffa3 | ||
|
|
3edf2bb417 | ||
|
|
9ebfbd150e | ||
|
|
e278742c5e | ||
|
|
ef08163c38 | ||
|
|
2e82268a67 | ||
|
|
00bdfad5f6 | ||
|
|
efd8dabd91 | ||
|
|
e4f443a57a | ||
|
|
d4df20a913 | ||
|
|
db495668ae | ||
|
|
996c653490 | ||
|
|
4acad897cf | ||
|
|
b37fffc2c5 | ||
|
|
a99450ab72 | ||
|
|
7776d6228e | ||
|
|
5415256a52 | ||
|
|
836e43db60 | ||
|
|
9c94538fb7 | ||
|
|
53eedd3ba4 | ||
|
|
42134bb49e | ||
|
|
0488bf54d3 | ||
|
|
da19aee307 | ||
|
|
d2c0b4905a | ||
|
|
153f07fdfb | ||
|
|
7e610aece5 | ||
|
|
16aedc0ef6 | ||
|
|
6596e585fe | ||
|
|
f98eda4d52 | ||
|
|
23717510c2 | ||
|
|
c51564ab5b | ||
|
|
1eb14c7743 | ||
|
|
56e9f97294 | ||
|
|
774faf4e85 | ||
|
|
d0711821f3 | ||
|
|
7024b45197 | ||
|
|
5fce673a56 | ||
|
|
29c9d3d5f4 | ||
|
|
708f1c336e | ||
|
|
dc4ac0b96f | ||
|
|
296748d32e | ||
|
|
ad408f269c | ||
|
|
e57754868f | ||
|
|
0c7e7f4998 | ||
|
|
136657bcc1 | ||
|
|
dc16820e02 | ||
|
|
4b85608e30 | ||
|
|
8ab77f4153 | ||
|
|
472585a7e8 | ||
|
|
8f42a8be0c | ||
|
|
c4b707bca2 | ||
|
|
9e35fe8c37 | ||
|
|
385904d75a | ||
|
|
b1e0b7728b | ||
|
|
eb255e6870 | ||
|
|
72e4c8f523 | ||
|
|
835d2e4b5f | ||
|
|
94b42a79d7 | ||
|
|
e40da2341c | ||
|
|
7aa72c56b6 | ||
|
|
5784c14ab7 | ||
|
|
3028bbb95b | ||
|
|
dfdc817db3 | ||
|
|
f4856a33c9 | ||
|
|
371af9c241 | ||
|
|
88a9bae160 | ||
|
|
ecd5c5f920 | ||
|
|
91d1186cbb | ||
|
|
467b3cf4c1 | ||
|
|
c007d8219e | ||
|
|
b318e82356 | ||
|
|
98fa00db12 | ||
|
|
69fca4f3cb | ||
|
|
f6ed45fc20 | ||
|
|
e81ff1e833 | ||
|
|
43b6ca0d14 | ||
|
|
34492ce480 | ||
|
|
163c38e175 | ||
|
|
11be390110 | ||
|
|
ea26a9f543 | ||
|
|
f9e1b0cd97 | ||
|
|
805564dcf2 | ||
|
|
76fb792544 | ||
|
|
ff35014eff | ||
|
|
de868d24c1 | ||
|
|
318a730c45 | ||
|
|
9017c51e7f | ||
|
|
bdb66aced7 | ||
|
|
ab83444cc3 | ||
|
|
64a6da3e45 | ||
|
|
dd9909a574 | ||
|
|
59c58f230e | ||
|
|
f79069f5b3 | ||
|
|
f5e0ba266e | ||
|
|
7361f29527 | ||
|
|
1d009a37df | ||
|
|
0fb208e63c | ||
|
|
dade01be29 | ||
|
|
45057667f1 | ||
|
|
4ab4e33450 | ||
|
|
0cfca69b42 | ||
|
|
1278a57afe | ||
|
|
071c0b5536 | ||
|
|
735fa8b652 | ||
|
|
0b37f98e16 | ||
|
|
5f8809e425 | ||
|
|
f143e269f4 | ||
|
|
1d1aec9631 | ||
|
|
817180bd55 | ||
|
|
60bd878f0a | ||
|
|
bbd8e645a2 | ||
|
|
97d659c9fd | ||
|
|
7b8227039f | ||
|
|
363487c97b | ||
|
|
f6bc662194 | ||
|
|
7bd9e53ae6 | ||
|
|
267744a568 | ||
|
|
8e67f4c4e6 | ||
|
|
1c59cff832 | ||
|
|
bc2819cab2 | ||
|
|
7ece67727d | ||
|
|
303351de6d | ||
|
|
831003156c | ||
|
|
54de4afd75 | ||
|
|
c01c487c62 | ||
|
|
2f6e931921 | ||
|
|
50dc2d8112 | ||
|
|
f4d7530587 | ||
|
|
185c0bd587 | ||
|
|
3c0090c0df | ||
|
|
6199252cda | ||
|
|
c08720bfba | ||
|
|
4882bda667 | ||
|
|
a817419fe4 | ||
|
|
37bf9a666a | ||
|
|
cd6d204a9d | ||
|
|
9baae3a701 | ||
|
|
92f504f98d | ||
|
|
75816150ec | ||
|
|
4681392bac | ||
|
|
17830c5894 | ||
|
|
edbcf7c039 | ||
|
|
96bee29e35 | ||
|
|
82ea534997 | ||
|
|
a4fe2a7c75 | ||
|
|
4ef9c7675a | ||
|
|
f69123050b | ||
|
|
a5a9c9f799 | ||
|
|
cce210f676 | ||
|
|
a8e493122e | ||
|
|
e00d7ee5be | ||
|
|
ad6b087353 | ||
|
|
3715e39e5d | ||
|
|
423109e64c | ||
|
|
71b7d92597 | ||
|
|
e034f8a2a3 | ||
|
|
47381bde3b | ||
|
|
c578efb32b | ||
|
|
5aa2679be7 | ||
|
|
d4e7faca21 | ||
|
|
4ffba76bb3 | ||
|
|
f4a08f7fb3 | ||
|
|
f6d9bcc9bb | ||
|
|
a7daf8e652 | ||
|
|
4771b4951d | ||
|
|
383698186f | ||
|
|
fb4c3ab4fb | ||
|
|
96ad0c8638 | ||
|
|
7985d746f9 | ||
|
|
a45f287ae1 | ||
|
|
7d9dd352cf | ||
|
|
a09660dc85 | ||
|
|
d78e5e7329 | ||
|
|
e61b2f99c1 | ||
|
|
d386f02893 | ||
|
|
5a3218e535 | ||
|
|
02653573d2 | ||
|
|
5c66664aef | ||
|
|
21b7a272c4 | ||
|
|
17a47b3335 | ||
|
|
89bbff18e5 | ||
|
|
fc95d00b2f | ||
|
|
3f4f844eeb | ||
|
|
6875ead7cf | ||
|
|
5388e8b124 | ||
|
|
02b14090c2 | ||
|
|
56a744599f | ||
|
|
9fa4b72a47 | ||
|
|
3e78b29cae | ||
|
|
d63c160bd6 | ||
|
|
2a6c0fc17f | ||
|
|
1340da7b54 | ||
|
|
89af509d10 | ||
|
|
89b8b792c1 | ||
|
|
a19491dbd2 | ||
|
|
f5c6e3973c | ||
|
|
e7beaac6f5 | ||
|
|
84684e53ed | ||
|
|
4c0e36a5e9 | ||
|
|
8ed83250d7 | ||
|
|
360a8918dd | ||
|
|
4d43a67419 | ||
|
|
33e80dae7f | ||
|
|
4f53619a15 | ||
|
|
3fb5b7a3bd | ||
|
|
bcd3e1af2f | ||
|
|
cd45ae3d0f | ||
|
|
e5dc58e710 | ||
|
|
cef7bb0619 | ||
|
|
a006b828a6 | ||
|
|
052bb24c7f | ||
|
|
3c630c0d90 | ||
|
|
d0810b0156 | ||
|
|
ffd3cdf519 | ||
|
|
ac2e822ea1 | ||
|
|
0cd2972d60 | ||
|
|
821ff68f54 | ||
|
|
e8eb4d233b | ||
|
|
414d1ff9e2 | ||
|
|
7d92ce061d | ||
|
|
a1e2a8bec6 | ||
|
|
f34a9b6a71 | ||
|
|
def870953a | ||
|
|
f2c6330505 | ||
|
|
077ffa5231 | ||
|
|
0802edf582 | ||
|
|
8bfa56648d | ||
|
|
4d20f1283f | ||
|
|
0a38e542c1 | ||
|
|
96f551a287 | ||
|
|
af05e4b2de | ||
|
|
4415d95c50 | ||
|
|
1cdf210e4f | ||
|
|
b0ad5ce8e2 | ||
|
|
b2447393e4 | ||
|
|
63ce6eee5c | ||
|
|
858b2d7439 | ||
|
|
6103e59c19 | ||
|
|
a106c0dbdc | ||
|
|
f37a3a84fa | ||
|
|
13cf5425db | ||
|
|
fb6ac9a1a6 | ||
|
|
033ae0dcae | ||
|
|
e261cc9e8f | ||
|
|
2ec160454a | ||
|
|
51d308c666 | ||
|
|
b3c439fb16 | ||
|
|
15ae9ca8a2 | ||
|
|
c3cd89705d | ||
|
|
1bd25925cb | ||
|
|
17e17ceb59 | ||
|
|
8da4a4276f | ||
|
|
3bb1cfdf36 | ||
|
|
e627f023a0 | ||
|
|
bd5cdbf1a4 | ||
|
|
34e57da1ca | ||
|
|
de8996ac3b | ||
|
|
33264d0fb6 | ||
|
|
cc65bda2cc | ||
|
|
4b2b65df9f | ||
|
|
4800f1df97 | ||
|
|
9850df35ae | ||
|
|
7dfa3442fe | ||
|
|
58bc6f3a18 | ||
|
|
a75c31143a | ||
|
|
15b375827e | ||
|
|
60578e0950 | ||
|
|
09d7654f46 | ||
|
|
28234f6e54 | ||
|
|
63fe487d93 | ||
|
|
d2b2c7c09e | ||
|
|
c930a92b72 | ||
|
|
cffd40c5d6 | ||
|
|
fb78854e9b | ||
|
|
461f53945d | ||
|
|
6c3ca42e0e | ||
|
|
0f4c83eb98 | ||
|
|
880aa870a0 | ||
|
|
cf136f1935 | ||
|
|
ca26de72c9 | ||
|
|
af574e58fe | ||
|
|
ed81aa8aae | ||
|
|
9ab64658ba | ||
|
|
3504a66eda | ||
|
|
3f0ac7adce | ||
|
|
0076339914 | ||
|
|
2176f4d697 | ||
|
|
843ffba567 |
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.cpp diff=cpp
|
||||
*.h diff=cpp
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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
29
.hgtags
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
10
README.txt
10
README.txt
@@ -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
|
||||
|
||||
@@ -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
BIN
data/apple.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 203 B |
BIN
data/apple_iron.png
Normal file
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
BIN
data/ladder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 395 B |
BIN
data/lava.png
Normal file
BIN
data/lava.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 357 B |
@@ -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
|
||||
|
||||
|
||||
@@ -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
271
genmap.py
@@ -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
|
||||
@@ -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
BIN
minetest-icon-24x24.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 913 B |
@@ -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
|
||||
@@ -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
486
po/da/minetest.po
Normal 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 ""
|
||||
@@ -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"
|
||||
|
||||
@@ -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 ""
|
||||
@@ -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
499
po/it/minetest.po
Normal 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
487
po/minetest.pot
Normal 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 ""
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
163
src/ban.cpp
Normal 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
52
src/ban.h
Normal 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
|
||||
@@ -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()
|
||||
|
||||
16
src/client.h
16
src/client.h
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
13
src/config.h
13
src/config.h
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
180
src/game.cpp
180
src/game.cpp
@@ -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
|
||||
*/
|
||||
|
||||
67
src/game.h
67
src/game.h
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
128
src/keycode.cpp
128
src/keycode.cpp
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
69
src/main.cpp
69
src/main.cpp
@@ -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]");
|
||||
|
||||
|
||||
727
src/map.cpp
727
src/map.cpp
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
35
src/map.h
35
src/map.h
@@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
29
src/player.h
29
src/player.h
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
172
src/server.cpp
172
src/server.cpp
@@ -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);
|
||||
|
||||
30
src/server.h
30
src/server.h
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
7520
src/sqlite/sqlite3.c
7520
src/sqlite/sqlite3.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
21
src/tile.cpp
21
src/tile.cpp
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
785
util/minetestmapper.py
Executable file → Normal 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
132
util/sectors2sqlite.py
Executable 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
65
util/updatepo.sh
Executable 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
1285
util/wireshark/minetest.lua
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user