Compare commits
314 Commits
0.4.dev-20
...
0.4.2-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d38b465b7c | ||
|
|
fd7ec2da91 | ||
|
|
c9ed379e39 | ||
|
|
e64feefc61 | ||
|
|
3e754382af | ||
|
|
7ef0a13250 | ||
|
|
0de3fb786d | ||
|
|
1d44a98f2f | ||
|
|
98ff4eb4ee | ||
|
|
a9d8df83d2 | ||
|
|
508b7b5e51 | ||
|
|
f7dc72f8aa | ||
|
|
0190f9b077 | ||
|
|
0c91a0d59d | ||
|
|
a26a66a8c4 | ||
|
|
100345f1e4 | ||
|
|
4535166a3b | ||
|
|
0346e68deb | ||
|
|
db62c227c8 | ||
|
|
983e45ae92 | ||
|
|
0a18dda158 | ||
|
|
9eaf93d41d | ||
|
|
2ac20982e0 | ||
|
|
96eac87d47 | ||
|
|
0cf1ed544c | ||
|
|
558e284e25 | ||
|
|
5c31445117 | ||
|
|
717ae67995 | ||
|
|
e8331f0c1d | ||
|
|
c009aa3a22 | ||
|
|
9af9d8f5d0 | ||
|
|
2c027b03db | ||
|
|
aef1332e42 | ||
|
|
16fc8b5fc2 | ||
|
|
fd845f27f5 | ||
|
|
ea62ee4b61 | ||
|
|
cd6becd442 | ||
|
|
829f262c79 | ||
|
|
246520b5cb | ||
|
|
38bb649582 | ||
|
|
82855a04ec | ||
|
|
6dfefaf229 | ||
|
|
d44f8a854b | ||
|
|
acf3a43095 | ||
|
|
4cc98d7add | ||
|
|
506203345b | ||
|
|
c259f7c8bd | ||
|
|
c62a121cca | ||
|
|
136eb32389 | ||
|
|
e3ddbe8c6b | ||
|
|
d085139057 | ||
|
|
28e7443f9b | ||
|
|
e79ad21aeb | ||
|
|
0b61253931 | ||
|
|
a2738dec59 | ||
|
|
1788709e2d | ||
|
|
47d30d12cb | ||
|
|
43df78102c | ||
|
|
cc10eec6c6 | ||
|
|
15bf9a7026 | ||
|
|
2795f44f03 | ||
|
|
b0ba05c9ac | ||
|
|
71c6845a94 | ||
|
|
4b97023251 | ||
|
|
369046bbb4 | ||
|
|
38580fbee7 | ||
|
|
08e1d40d6e | ||
|
|
80f35467d8 | ||
|
|
1b19020bf4 | ||
|
|
61e58ee9b7 | ||
|
|
f21af8da9c | ||
|
|
dece3a3600 | ||
|
|
16ad10e62f | ||
|
|
02fb912a95 | ||
|
|
48790c0751 | ||
|
|
c57e5083e8 | ||
|
|
c9a2058361 | ||
|
|
7039dfafd6 | ||
|
|
22ae83a589 | ||
|
|
1575448b1a | ||
|
|
9f031a6759 | ||
|
|
d0ea6f9920 | ||
|
|
1bc37d576c | ||
|
|
d159591b9a | ||
|
|
57550b2b3d | ||
|
|
d15d6c4e6b | ||
|
|
6b598f61a6 | ||
|
|
9e21204f8b | ||
|
|
e6b86fa304 | ||
|
|
268e50dfbd | ||
|
|
07ccc15fc2 | ||
|
|
2b500d72e5 | ||
|
|
cd0014b24f | ||
|
|
b3786d84c5 | ||
|
|
fd1135c7af | ||
|
|
f0678979b1 | ||
|
|
f4a7e11bce | ||
|
|
6a0388bb4b | ||
|
|
7ba72f2763 | ||
|
|
f7147d9c0a | ||
|
|
523a5fd2e5 | ||
|
|
ff85e2343c | ||
|
|
e74668ef7f | ||
|
|
22502f80db | ||
|
|
4b2cc38aba | ||
|
|
a8eb68142e | ||
|
|
81554fbf72 | ||
|
|
a435cfcd82 | ||
|
|
7631918a12 | ||
|
|
e070f1e525 | ||
|
|
430d6e1cca | ||
|
|
3a0562bebc | ||
|
|
c3658e7c79 | ||
|
|
b0f81c3253 | ||
|
|
31c171fc1e | ||
|
|
e9c123b1b9 | ||
|
|
037b259197 | ||
|
|
a569961e0f | ||
|
|
7eabde6aee | ||
|
|
ed772da0cc | ||
|
|
f48882213e | ||
|
|
1cd2076d42 | ||
|
|
816b9c8d71 | ||
|
|
3bea1a944e | ||
|
|
3e419ffb38 | ||
|
|
a149c6ecde | ||
|
|
3f18e9a2da | ||
|
|
4b0494062e | ||
|
|
a09d86dd3c | ||
|
|
3ccb0f691b | ||
|
|
1709fd854a | ||
|
|
7bf446f671 | ||
|
|
e4bc76f55c | ||
|
|
81c5e5200b | ||
|
|
9c3830dd35 | ||
|
|
bf8cfce50e | ||
|
|
b235e4d290 | ||
|
|
b8cf6dee3e | ||
|
|
35df1ee253 | ||
|
|
353f9fd43c | ||
|
|
3899f83da8 | ||
|
|
5f3c70061d | ||
|
|
aba7134301 | ||
|
|
d7447cdf9e | ||
|
|
ff8d2bbc36 | ||
|
|
70c98c9972 | ||
|
|
45f32838b9 | ||
|
|
7d6e80a423 | ||
|
|
f3ec1452cd | ||
|
|
29f03756bd | ||
|
|
fe8c5546f0 | ||
|
|
c4315a7afa | ||
|
|
704782c95b | ||
|
|
67059e1932 | ||
|
|
e2ea711136 | ||
|
|
74aa598769 | ||
|
|
747ff7daf8 | ||
|
|
1f670fc688 | ||
|
|
388906ac70 | ||
|
|
49d9745dc4 | ||
|
|
7c15d793ac | ||
|
|
d90cb3511c | ||
|
|
5100272dc3 | ||
|
|
afda9810f1 | ||
|
|
22df8b81b3 | ||
|
|
7a427c9070 | ||
|
|
a35e4bdbda | ||
|
|
0aeb5adb8f | ||
|
|
9c5cc217bf | ||
|
|
24603d7ad3 | ||
|
|
1eac6ff8ff | ||
|
|
8742b3dab2 | ||
|
|
93cdc9b9dc | ||
|
|
8ed74a3429 | ||
|
|
07a5e59ae7 | ||
|
|
f8c2f1cf54 | ||
|
|
b1f043d010 | ||
|
|
251c0c8508 | ||
|
|
3214daca4c | ||
|
|
e4485f5412 | ||
|
|
4eaaa0ec53 | ||
|
|
42323014ea | ||
|
|
c59d139eeb | ||
|
|
2b4d21160f | ||
|
|
e29a5b11e4 | ||
|
|
b58ee690a3 | ||
|
|
d8edd3d0c8 | ||
|
|
1b078efd5f | ||
|
|
e8e73d37fb | ||
|
|
2eec788544 | ||
|
|
dca28b9e12 | ||
|
|
e879c92596 | ||
|
|
7281c68b27 | ||
|
|
d228f1b658 | ||
|
|
2e60593c5b | ||
|
|
531fe10f51 | ||
|
|
454b07455a | ||
|
|
a4dc6f2c76 | ||
|
|
5608f12f9b | ||
|
|
18d8e3acec | ||
|
|
578fc5bb44 | ||
|
|
e8660cfd8e | ||
|
|
6a57eabb14 | ||
|
|
a67540807a | ||
|
|
20c377ca65 | ||
|
|
5436f1c7d5 | ||
|
|
4107390337 | ||
|
|
e74da72b82 | ||
|
|
24953ba974 | ||
|
|
22a5a1fa43 | ||
|
|
7bac62ee7f | ||
|
|
fcda11c6b0 | ||
|
|
66e1cb324c | ||
|
|
a869d23451 | ||
|
|
41f4941b74 | ||
|
|
b22168d3da | ||
|
|
b9b56bac6b | ||
|
|
fa670fa4b5 | ||
|
|
b131a0cf0c | ||
|
|
d7cef8d762 | ||
|
|
4483fc7df3 | ||
|
|
2cd5addc0c | ||
|
|
5bf06efb2a | ||
|
|
5196e309b8 | ||
|
|
bee1adc651 | ||
|
|
f0e7da8a63 | ||
|
|
5bd32eca0f | ||
|
|
491287c0af | ||
|
|
8ecfd88d92 | ||
|
|
b54178bbbd | ||
|
|
67547f74fc | ||
|
|
56ba193c77 | ||
|
|
d5594e431c | ||
|
|
7bfa2d4da6 | ||
|
|
4cf00f5698 | ||
|
|
a18326e97a | ||
|
|
36c9463467 | ||
|
|
13159c1a48 | ||
|
|
0fbef74f31 | ||
|
|
52122c342d | ||
|
|
96ee73f790 | ||
|
|
dc70f50b59 | ||
|
|
e297c73913 | ||
|
|
280e1a2512 | ||
|
|
1518b8f753 | ||
|
|
5403b1cf6d | ||
|
|
29110d5428 | ||
|
|
462003363f | ||
|
|
b494324ec3 | ||
|
|
4cee9a86ac | ||
|
|
7cad0a2dcd | ||
|
|
ed1ff06867 | ||
|
|
80a64341f0 | ||
|
|
bbf3eebb1a | ||
|
|
6b20ea0752 | ||
|
|
3241ad3ae8 | ||
|
|
9e7ccedba4 | ||
|
|
b9ffb5f30d | ||
|
|
9d456ca87a | ||
|
|
18350ad37f | ||
|
|
0983f65da7 | ||
|
|
42bbd5c9ae | ||
|
|
92ae11bd3b | ||
|
|
443f45eca1 | ||
|
|
a9ddbb4beb | ||
|
|
f8c3743991 | ||
|
|
072c265c30 | ||
|
|
440e9cdbef | ||
|
|
ace005bf7c | ||
|
|
75821c6889 | ||
|
|
d376148ca1 | ||
|
|
582ca33507 | ||
|
|
a6ca7eb29d | ||
|
|
02c035c548 | ||
|
|
418041d906 | ||
|
|
a3a400992e | ||
|
|
68625b047f | ||
|
|
9a1df7bf38 | ||
|
|
81b9cfdfa4 | ||
|
|
ae7aa65069 | ||
|
|
9e0f969b8b | ||
|
|
14a8fa4d68 | ||
|
|
07e5c9bd5f | ||
|
|
49c2ca0216 | ||
|
|
04172e3dd0 | ||
|
|
2c56a9f588 | ||
|
|
20e025b3d8 | ||
|
|
10591d2080 | ||
|
|
af29c0ade5 | ||
|
|
4c876ac62e | ||
|
|
66bf7b0b01 | ||
|
|
17d51a1609 | ||
|
|
0a59605e05 | ||
|
|
202658678d | ||
|
|
4f01db256f | ||
|
|
c04f4a7d73 | ||
|
|
f5e46ba7fc | ||
|
|
8609af54fc | ||
|
|
9a4ef87859 | ||
|
|
a57f4c23d8 | ||
|
|
d629f4d2fb | ||
|
|
6f20a73782 | ||
|
|
8cb7badd63 | ||
|
|
0f3c2f6541 | ||
|
|
56496ad5d8 | ||
|
|
e15dca2a9f | ||
|
|
a32706bc26 | ||
|
|
bdcca4767c | ||
|
|
38f4dbfb51 | ||
|
|
a374b1a6a3 | ||
|
|
0ff94978f5 | ||
|
|
fa24e6b995 | ||
|
|
37b64ff616 | ||
|
|
a2fd8d1db1 |
@@ -7,10 +7,15 @@ endif(${CMAKE_VERSION} STREQUAL "2.8.2")
|
||||
# This can be read from ${PROJECT_NAME} after project() is called
|
||||
project(minetest)
|
||||
|
||||
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||
|
||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 4)
|
||||
set(VERSION_PATCH dev-20120326)
|
||||
set(VERSION_PATCH 2-rc1)
|
||||
if(VERSION_EXTRA)
|
||||
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
|
||||
endif()
|
||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
|
||||
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
||||
@@ -57,7 +62,7 @@ if(WIN32)
|
||||
elseif(APPLE)
|
||||
# Random placeholders; this isn't usually used and may not work
|
||||
# See https://github.com/toabi/minetest-mac/
|
||||
set(SHAREDIR "share/${PROJECT_NAME}")
|
||||
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}")
|
||||
set(BINDIR "bin")
|
||||
set(DOCDIR "share/doc/${PROJECT_NAME}")
|
||||
set(EXAMPLE_CONF_DIR ${DOCDIR})
|
||||
@@ -73,25 +78,73 @@ elseif(UNIX) # Linux, BSD etc
|
||||
set(ICONDIR "unix/icons")
|
||||
set(LOCALEDIR "locale")
|
||||
else()
|
||||
set(SHAREDIR "share/${PROJECT_NAME}")
|
||||
set(BINDIR "bin")
|
||||
set(DOCDIR "share/doc/${PROJECT_NAME}")
|
||||
set(MANDIR "share/man")
|
||||
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}")
|
||||
set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
|
||||
set(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}")
|
||||
set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man")
|
||||
set(EXAMPLE_CONF_DIR ${DOCDIR})
|
||||
set(XDG_APPS_DIR "share/applications")
|
||||
set(ICONDIR "share/icons")
|
||||
set(LOCALEDIR "share/locale")
|
||||
set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/share/applications")
|
||||
set(ICONDIR "${CMAKE_INSTALL_PREFIX}/share/icons")
|
||||
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/share/locale")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CUSTOM_SHAREDIR "" CACHE STRING "Directory to install data files into")
|
||||
if(NOT CUSTOM_SHAREDIR STREQUAL "")
|
||||
set(SHAREDIR "${CUSTOM_SHAREDIR}")
|
||||
message(STATUS "Using SHAREDIR=${SHAREDIR}")
|
||||
endif()
|
||||
set(CUSTOM_BINDIR "" CACHE STRING "Directory to install binaries into")
|
||||
if(NOT CUSTOM_BINDIR STREQUAL "")
|
||||
set(BINDIR "${CUSTOM_BINDIR}")
|
||||
message(STATUS "Using BINDIR=${BINDIR}")
|
||||
endif()
|
||||
set(CUSTOM_DOCDIR "" CACHE STRING "Directory to install documentation into")
|
||||
if(NOT CUSTOM_DOCDIR STREQUAL "")
|
||||
set(DOCDIR "${CUSTOM_DOCDIR}")
|
||||
message(STATUS "Using DOCDIR=${DOCDIR}")
|
||||
endif()
|
||||
set(CUSTOM_MANDIR "" CACHE STRING "Directory to install manpages into")
|
||||
if(NOT CUSTOM_MANDIR STREQUAL "")
|
||||
set(MANDIR "${CUSTOM_MANDIR}")
|
||||
message(STATUS "Using MANDIR=${MANDIR}")
|
||||
endif()
|
||||
set(CUSTOM_EXAMPLE_CONF_DIR "" CACHE STRING "Directory to install example config file into")
|
||||
if(NOT CUSTOM_EXAMPLE_CONF_DIR STREQUAL "")
|
||||
set(EXAMPLE_CONF_DIR "${CUSTOM_EXAMPLE_CONF_DIR}")
|
||||
message(STATUS "Using EXAMPLE_CONF_DIR=${EXAMPLE_CONF_DIR}")
|
||||
endif()
|
||||
set(CUSTOM_XDG_APPS_DIR "" CACHE STRING "Directory to install .desktop files into")
|
||||
if(NOT CUSTOM_XDG_APPS_DIR STREQUAL "")
|
||||
set(XDG_APPS_DIR "${CUSTOM_XDG_APPS_DIR}")
|
||||
message(STATUS "Using XDG_APPS_DIR=${XDG_APPS_DIR}")
|
||||
endif()
|
||||
set(CUSTOM_ICONDIR "" CACHE STRING "Directory to install icons into")
|
||||
if(NOT CUSTOM_ICONDIR STREQUAL "")
|
||||
set(ICONDIR "${CUSTOM_ICONDIR}")
|
||||
message(STATUS "Using ICONDIR=${ICONDIR}")
|
||||
endif()
|
||||
set(CUSTOM_LOCALEDIR "" CACHE STRING "Directory to install l10n files into")
|
||||
if(NOT CUSTOM_LOCALEDIR STREQUAL "")
|
||||
set(LOCALEDIR "${CUSTOM_LOCALEDIR}")
|
||||
message(STATUS "Using LOCALEDIR=${LOCALEDIR}")
|
||||
endif()
|
||||
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest" DESTINATION "${SHAREDIR}/games")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games")
|
||||
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
|
||||
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
|
||||
install(FILES ${MINETEST_GAME_SOURCE}/game.conf DESTINATION "${SHAREDIR}/games/minetest_game/")
|
||||
install(FILES ${MINETEST_GAME_SOURCE}/README.txt DESTINATION "${SHAREDIR}/games/minetest_game/")
|
||||
install(DIRECTORY ${MINETEST_GAME_SOURCE}/mods DESTINATION "${SHAREDIR}/games/minetest_game")
|
||||
endif()
|
||||
if(BUILD_CLIENT)
|
||||
#install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/sounds/base/pack" DESTINATION "${SHAREDIR}/sounds/base")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base")
|
||||
endif()
|
||||
if(RUN_IN_PLACE)
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/mods/minetest/mods_here.txt" DESTINATION "${SHAREDIR}/mods/minetest")
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/all/textures_here.txt" DESTINATION "${SHAREDIR}/textures/all")
|
||||
endif()
|
||||
|
||||
install(FILES "README.txt" DESTINATION "${DOCDIR}")
|
||||
|
||||
46
README.txt
@@ -79,13 +79,20 @@ Compiling on GNU/Linux:
|
||||
-----------------------
|
||||
|
||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev
|
||||
|
||||
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
||||
$ wget https://github.com/celeron55/minetest/tarball/master -O master.tar.gz
|
||||
$ tar xf master.tar.gz
|
||||
$ cd celeron55-minetest-286edd4 (or similar)
|
||||
|
||||
Download minetest_game (otherwise only the "Minimal development test" game is available)
|
||||
$ cd games/
|
||||
$ wget https://github.com/celeron55/minetest_game/tarball/master -O master.tar.gz
|
||||
$ tar xf master.tar.gz
|
||||
$ mv celeron55-minetest_game-* minetest_game
|
||||
$ cd ..
|
||||
|
||||
Build a version that runs directly from the source directory:
|
||||
$ cmake . -DRUN_IN_PLACE=1
|
||||
$ make -j2
|
||||
@@ -102,6 +109,9 @@ $ ./minetest
|
||||
|
||||
Compiling on Windows:
|
||||
---------------------
|
||||
- This section is outdated. In addition to what is described here:
|
||||
- In addition to minetest, you need to download minetest_game.
|
||||
- If you wish to have sound support, you need libogg, libvorbis and libopenal
|
||||
|
||||
- You need:
|
||||
* CMake:
|
||||
@@ -250,8 +260,8 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
@@ -259,7 +269,7 @@ 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
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
@@ -315,6 +325,34 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
Lua
|
||||
---------------
|
||||
|
||||
Lua is licensed under the terms of the MIT license reproduced below.
|
||||
This means that Lua is free software and can be used for both academic
|
||||
and commercial purposes at absolutely no cost.
|
||||
|
||||
For details and rationale, see http://www.lua.org/license.html .
|
||||
|
||||
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Fonts
|
||||
---------------
|
||||
|
||||
188
builtin/auth.lua
Normal file
@@ -0,0 +1,188 @@
|
||||
-- Minetest: builtin/auth.lua
|
||||
|
||||
--
|
||||
-- Authentication handler
|
||||
--
|
||||
|
||||
function minetest.string_to_privs(str, delim)
|
||||
assert(type(str) == "string")
|
||||
delim = delim or ','
|
||||
privs = {}
|
||||
for _, priv in pairs(string.split(str, delim)) do
|
||||
privs[priv:trim()] = true
|
||||
end
|
||||
return privs
|
||||
end
|
||||
|
||||
function minetest.privs_to_string(privs, delim)
|
||||
assert(type(privs) == "table")
|
||||
delim = delim or ','
|
||||
list = {}
|
||||
for priv, bool in pairs(privs) do
|
||||
if bool then
|
||||
table.insert(list, priv)
|
||||
end
|
||||
end
|
||||
return table.concat(list, delim)
|
||||
end
|
||||
|
||||
assert(minetest.string_to_privs("a,b").b == true)
|
||||
assert(minetest.privs_to_string({a=true,b=true}) == "a,b")
|
||||
|
||||
minetest.auth_file_path = minetest.get_worldpath().."/auth.txt"
|
||||
minetest.auth_table = {}
|
||||
|
||||
local function read_auth_file()
|
||||
local newtable = {}
|
||||
local file, errmsg = io.open(minetest.auth_file_path, 'rb')
|
||||
if not file then
|
||||
minetest.log("info", minetest.auth_file_path.." could not be opened for reading ("..errmsg.."); assuming new world")
|
||||
return
|
||||
end
|
||||
for line in file:lines() do
|
||||
if line ~= "" then
|
||||
local name, password, privilegestring = string.match(line, "([^:]*):([^:]*):([^:]*)")
|
||||
if not name or not password or not privilegestring then
|
||||
error("Invalid line in auth.txt: "..dump(line))
|
||||
end
|
||||
local privileges = minetest.string_to_privs(privilegestring)
|
||||
newtable[name] = {password=password, privileges=privileges}
|
||||
end
|
||||
end
|
||||
io.close(file)
|
||||
minetest.auth_table = newtable
|
||||
minetest.notify_authentication_modified()
|
||||
end
|
||||
|
||||
local function save_auth_file()
|
||||
local newtable = {}
|
||||
-- Check table for validness before attempting to save
|
||||
for name, stuff in pairs(minetest.auth_table) do
|
||||
assert(type(name) == "string")
|
||||
assert(name ~= "")
|
||||
assert(type(stuff) == "table")
|
||||
assert(type(stuff.password) == "string")
|
||||
assert(type(stuff.privileges) == "table")
|
||||
end
|
||||
local file, errmsg = io.open(minetest.auth_file_path, 'w+b')
|
||||
if not file then
|
||||
error(minetest.auth_file_path.." could not be opened for writing: "..errmsg)
|
||||
end
|
||||
for name, stuff in pairs(minetest.auth_table) do
|
||||
local privstring = minetest.privs_to_string(stuff.privileges)
|
||||
file:write(name..":"..stuff.password..":"..privstring..'\n')
|
||||
end
|
||||
io.close(file)
|
||||
end
|
||||
|
||||
read_auth_file()
|
||||
|
||||
minetest.builtin_auth_handler = {
|
||||
get_auth = function(name)
|
||||
assert(type(name) == "string")
|
||||
-- Figure out what password to use for a new player (singleplayer
|
||||
-- always has an empty password, otherwise use default, which is
|
||||
-- usually empty too)
|
||||
local new_password_hash = ""
|
||||
-- If not in authentication table, return nil
|
||||
if not minetest.auth_table[name] then
|
||||
return nil
|
||||
end
|
||||
-- Figure out what privileges the player should have.
|
||||
-- Take a copy of the privilege table
|
||||
local privileges = {}
|
||||
for priv, _ in pairs(minetest.auth_table[name].privileges) do
|
||||
privileges[priv] = true
|
||||
end
|
||||
-- If singleplayer, give all privileges except those marked as give_to_singleplayer = false
|
||||
if minetest.is_singleplayer() then
|
||||
for priv, def in pairs(minetest.registered_privileges) do
|
||||
if def.give_to_singleplayer then
|
||||
privileges[priv] = true
|
||||
end
|
||||
end
|
||||
-- For the admin, give everything
|
||||
elseif name == minetest.setting_get("name") then
|
||||
for priv, def in pairs(minetest.registered_privileges) do
|
||||
privileges[priv] = true
|
||||
end
|
||||
end
|
||||
-- All done
|
||||
return {
|
||||
password = minetest.auth_table[name].password,
|
||||
privileges = privileges,
|
||||
}
|
||||
end,
|
||||
create_auth = function(name, password)
|
||||
assert(type(name) == "string")
|
||||
assert(type(password) == "string")
|
||||
minetest.log('info', "Built-in authentication handler adding player '"..name.."'")
|
||||
minetest.auth_table[name] = {
|
||||
password = password,
|
||||
privileges = minetest.string_to_privs(minetest.setting_get("default_privs")),
|
||||
}
|
||||
save_auth_file()
|
||||
end,
|
||||
set_password = function(name, password)
|
||||
assert(type(name) == "string")
|
||||
assert(type(password) == "string")
|
||||
if not minetest.auth_table[name] then
|
||||
minetest.builtin_auth_handler.create_auth(name, password)
|
||||
else
|
||||
minetest.log('info', "Built-in authentication handler setting password of player '"..name.."'")
|
||||
minetest.auth_table[name].password = password
|
||||
save_auth_file()
|
||||
end
|
||||
return true
|
||||
end,
|
||||
set_privileges = function(name, privileges)
|
||||
assert(type(name) == "string")
|
||||
assert(type(privileges) == "table")
|
||||
if not minetest.auth_table[name] then
|
||||
minetest.builtin_auth_handler.create_auth(name, minetest.get_password_hash(name, minetest.setting_get("default_password")))
|
||||
end
|
||||
minetest.auth_table[name].privileges = privileges
|
||||
minetest.notify_authentication_modified(name)
|
||||
save_auth_file()
|
||||
end,
|
||||
reload = function()
|
||||
read_auth_file()
|
||||
return true
|
||||
end,
|
||||
}
|
||||
|
||||
function minetest.register_authentication_handler(handler)
|
||||
if minetest.registered_auth_handler then
|
||||
error("Add-on authentication handler already registered by "..minetest.registered_auth_handler_modname)
|
||||
end
|
||||
minetest.registered_auth_handler = handler
|
||||
minetest.registered_auth_handler_modname = minetest.get_current_modname()
|
||||
end
|
||||
|
||||
function minetest.get_auth_handler()
|
||||
if minetest.registered_auth_handler then
|
||||
return minetest.registered_auth_handler
|
||||
end
|
||||
return minetest.builtin_auth_handler
|
||||
end
|
||||
|
||||
function minetest.set_player_password(name, password)
|
||||
if minetest.get_auth_handler().set_password then
|
||||
minetest.get_auth_handler().set_password(name, password)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.set_player_privs(name, privs)
|
||||
if minetest.get_auth_handler().set_privileges then
|
||||
minetest.get_auth_handler().set_privileges(name, privs)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.auth_reload()
|
||||
if minetest.get_auth_handler().reload then
|
||||
return minetest.get_auth_handler().reload()
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
@@ -5,800 +5,21 @@
|
||||
-- before loading and running any mods.
|
||||
--
|
||||
|
||||
--
|
||||
-- Override some Lua library functions
|
||||
--
|
||||
|
||||
-- Initialize some very basic things
|
||||
print = minetest.debug
|
||||
|
||||
--
|
||||
--
|
||||
--
|
||||
|
||||
function basic_dump2(o)
|
||||
if type(o) == "number" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "string" then
|
||||
return string.format("%q", o)
|
||||
elseif type(o) == "boolean" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "function" then
|
||||
return "<function>"
|
||||
elseif type(o) == "userdata" then
|
||||
return "<userdata>"
|
||||
elseif type(o) == "nil" then
|
||||
return "nil"
|
||||
else
|
||||
error("cannot dump a " .. type(o))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dump2(o, name, dumped)
|
||||
name = name or "_"
|
||||
dumped = dumped or {}
|
||||
io.write(name, " = ")
|
||||
if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
|
||||
or type(o) == "function" or type(o) == "nil"
|
||||
or type(o) == "userdata" then
|
||||
io.write(basic_dump2(o), "\n")
|
||||
elseif type(o) == "table" then
|
||||
if dumped[o] then
|
||||
io.write(dumped[o], "\n")
|
||||
else
|
||||
dumped[o] = name
|
||||
io.write("{}\n") -- new table
|
||||
for k,v in pairs(o) do
|
||||
local fieldname = string.format("%s[%s]", name, basic_dump2(k))
|
||||
dump2(v, fieldname, dumped)
|
||||
end
|
||||
end
|
||||
else
|
||||
error("cannot dump a " .. type(o))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dump(o, dumped)
|
||||
dumped = dumped or {}
|
||||
if type(o) == "number" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "string" then
|
||||
return string.format("%q", o)
|
||||
elseif type(o) == "table" then
|
||||
if dumped[o] then
|
||||
return "<circular reference>"
|
||||
end
|
||||
dumped[o] = true
|
||||
local t = {}
|
||||
for k,v in pairs(o) do
|
||||
t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
|
||||
end
|
||||
return "{" .. table.concat(t, ", ") .. "}"
|
||||
elseif type(o) == "boolean" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "function" then
|
||||
return "<function>"
|
||||
elseif type(o) == "userdata" then
|
||||
return "<userdata>"
|
||||
elseif type(o) == "nil" then
|
||||
return "nil"
|
||||
else
|
||||
error("cannot dump a " .. type(o))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Item definition helpers
|
||||
--
|
||||
|
||||
function minetest.inventorycube(img1, img2, img3)
|
||||
img2 = img2 or img1
|
||||
img3 = img3 or img1
|
||||
return "[inventorycube"
|
||||
.. "{" .. img1:gsub("%^", "&")
|
||||
.. "{" .. img2:gsub("%^", "&")
|
||||
.. "{" .. img3:gsub("%^", "&")
|
||||
end
|
||||
|
||||
function minetest.pos_to_string(pos)
|
||||
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
|
||||
end
|
||||
|
||||
function minetest.get_pointed_thing_position(pointed_thing, above)
|
||||
if pointed_thing.type == "node" then
|
||||
if above then
|
||||
-- The position where a node would be placed
|
||||
return pointed_thing.above
|
||||
else
|
||||
-- The position where a node would be dug
|
||||
return pointed_thing.under
|
||||
end
|
||||
elseif pointed_thing.type == "object" then
|
||||
obj = pointed_thing.ref
|
||||
if obj ~= nil then
|
||||
return obj:getpos()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.dir_to_facedir(dir)
|
||||
if math.abs(dir.x) > math.abs(dir.z) then
|
||||
if dir.x < 0 then
|
||||
return 3
|
||||
else
|
||||
return 1
|
||||
end
|
||||
else
|
||||
if dir.z < 0 then
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.dir_to_wallmounted(dir)
|
||||
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
|
||||
if dir.y < 0 then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
elseif math.abs(dir.x) > math.abs(dir.z) then
|
||||
if dir.x < 0 then
|
||||
return 3
|
||||
else
|
||||
return 2
|
||||
end
|
||||
else
|
||||
if dir.z < 0 then
|
||||
return 5
|
||||
else
|
||||
return 4
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.get_node_drops(nodename, toolname)
|
||||
local drop = ItemStack({name=nodename}):get_definition().drop
|
||||
if drop == nil then
|
||||
-- default drop
|
||||
return {ItemStack({name=nodename})}
|
||||
elseif type(drop) == "string" then
|
||||
-- itemstring drop
|
||||
return {ItemStack(drop)}
|
||||
elseif drop.items == nil then
|
||||
-- drop = {} to disable default drop
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Extended drop table
|
||||
local got_items = {}
|
||||
local got_count = 0
|
||||
local _, item, tool
|
||||
for _, item in ipairs(drop.items) do
|
||||
local good_rarity = true
|
||||
local good_tool = true
|
||||
if item.rarity ~= nil then
|
||||
good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
|
||||
end
|
||||
if item.tools ~= nil then
|
||||
good_tool = false
|
||||
for _, tool in ipairs(item.tools) do
|
||||
if tool:sub(1, 1) == '~' then
|
||||
good_tool = toolname:find(tool:sub(2)) ~= nil
|
||||
else
|
||||
good_tool = toolname == tool
|
||||
end
|
||||
if good_tool then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if good_rarity and good_tool then
|
||||
got_count = got_count + 1
|
||||
for _, add_item in ipairs(item.items) do
|
||||
got_items[#got_items+1] = add_item
|
||||
end
|
||||
if drop.max_items ~= nil and got_count == drop.max_items then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return got_items
|
||||
end
|
||||
|
||||
function minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
local item = itemstack:peek_item()
|
||||
local def = itemstack:get_definition()
|
||||
if def.type == "node" and pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
local oldnode = minetest.env:get_node(pos)
|
||||
local olddef = ItemStack({name=oldnode.name}):get_definition()
|
||||
|
||||
if not olddef.buildable_to then
|
||||
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||
.. " node in invalid position " .. minetest.pos_to_string(pos)
|
||||
.. ", replacing " .. oldnode.name)
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action", placer:get_player_name() .. " places node "
|
||||
.. def.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
local newnode = {name = def.name, param1 = 0, param2 = 0}
|
||||
|
||||
-- Calculate direction for wall mounted stuff like torches and signs
|
||||
if def.paramtype2 == 'wallmounted' then
|
||||
local under = pointed_thing.under
|
||||
local above = pointed_thing.above
|
||||
local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
|
||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif def.paramtype2 == 'facedir' then
|
||||
local playerpos = placer:getpos()
|
||||
local dir = {x = pos.x - playerpos.x, y = pos.y - playerpos.y, z = pos.z - playerpos.z}
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
minetest.log("action", "facedir: " .. newnode.param2)
|
||||
end
|
||||
|
||||
-- Add node and update
|
||||
minetest.env:add_node(pos, newnode)
|
||||
|
||||
-- Set metadata owner
|
||||
if def.metadata_name ~= "" then
|
||||
minetest.env:get_meta(pos):set_owner(placer:get_player_name())
|
||||
end
|
||||
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
||||
callback(pos, newnode, placer)
|
||||
end
|
||||
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
||||
if pos ~= nil then
|
||||
local item = itemstack:take_item()
|
||||
minetest.env:add_item(pos, item)
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_place(itemstack, placer, pointed_thing)
|
||||
if itemstack:get_definition().type == "node" then
|
||||
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
else
|
||||
return minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.item_drop(itemstack, dropper, pos)
|
||||
minetest.env:add_item(pos, itemstack)
|
||||
return ""
|
||||
end
|
||||
|
||||
function minetest.item_eat(hp_change, replace_with_item)
|
||||
return function(itemstack, user, pointed_thing) -- closure
|
||||
if itemstack:take_item() ~= nil then
|
||||
user:set_hp(user:get_hp() + hp_change)
|
||||
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.node_punch(pos, node, puncher)
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_punchnodes) do
|
||||
callback(pos, node, puncher)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function minetest.node_dig(pos, node, digger)
|
||||
minetest.debug("node_dig")
|
||||
|
||||
local def = ItemStack({name=node.name}):get_definition()
|
||||
if not def.diggable then
|
||||
minetest.debug("not diggable")
|
||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
||||
.. node.name .. " which is not diggable "
|
||||
.. minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
if meta ~= nil and not meta:get_allow_removal() then
|
||||
minetest.debug("dig prevented by metadata")
|
||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
||||
.. node.name .. ", but removal is disabled by metadata "
|
||||
.. minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log('action', digger:get_player_name() .. " digs "
|
||||
.. node.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
local wielded = digger:get_wielded_item()
|
||||
local drops = minetest.get_node_drops(node.name, wielded:get_name())
|
||||
|
||||
-- Wear out tool
|
||||
tp = wielded:get_tool_capabilities()
|
||||
dp = minetest.get_dig_params(def.groups, tp)
|
||||
wielded:add_wear(dp.wear)
|
||||
digger:set_wielded_item(wielded)
|
||||
|
||||
-- Add dropped items
|
||||
local _, dropped_item
|
||||
for _, dropped_item in ipairs(drops) do
|
||||
digger:get_inventory():add_item("main", dropped_item)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove node and update
|
||||
minetest.env:remove_node(pos)
|
||||
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_dignodes) do
|
||||
callback(pos, node, digger)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Item definition defaults
|
||||
--
|
||||
|
||||
minetest.nodedef_default = {
|
||||
-- Item properties
|
||||
type="node",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
usable = false,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
|
||||
on_punch = minetest.node_punch,
|
||||
on_dig = minetest.node_dig,
|
||||
|
||||
-- Node properties
|
||||
drawtype = "normal",
|
||||
visual_scale = 1.0,
|
||||
tile_images = {""},
|
||||
special_materials = {
|
||||
{image="", backface_culling=true},
|
||||
{image="", backface_culling=true},
|
||||
},
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
paramtype = "none",
|
||||
paramtype2 = "none",
|
||||
is_ground_content = false,
|
||||
sunlight_propagates = false,
|
||||
walkable = true,
|
||||
pointable = true,
|
||||
diggable = true,
|
||||
climbable = false,
|
||||
buildable_to = false,
|
||||
metadata_name = "",
|
||||
liquidtype = "none",
|
||||
liquid_alternative_flowing = "",
|
||||
liquid_alternative_source = "",
|
||||
liquid_viscosity = 0,
|
||||
light_source = 0,
|
||||
damage_per_second = 0,
|
||||
selection_box = {type="regular"},
|
||||
legacy_facedir_simple = false,
|
||||
legacy_wallmounted = false,
|
||||
}
|
||||
|
||||
minetest.craftitemdef_default = {
|
||||
type="craft",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
minetest.tooldef_default = {
|
||||
type="tool",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 1,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
minetest.noneitemdef_default = { -- This is used for the hand and unknown items
|
||||
type="none",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = nil,
|
||||
on_drop = nil,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
--
|
||||
-- Make raw registration functions inaccessible to anyone except builtin.lua
|
||||
--
|
||||
|
||||
local register_item_raw = minetest.register_item_raw
|
||||
minetest.register_item_raw = nil
|
||||
|
||||
local register_alias_raw = minetest.register_alias_raw
|
||||
minetest.register_item_raw = nil
|
||||
|
||||
--
|
||||
-- Item / entity / ABM registration functions
|
||||
--
|
||||
|
||||
minetest.registered_abms = {}
|
||||
minetest.registered_entities = {}
|
||||
minetest.registered_items = {}
|
||||
minetest.registered_nodes = {}
|
||||
minetest.registered_craftitems = {}
|
||||
minetest.registered_tools = {}
|
||||
minetest.registered_aliases = {}
|
||||
|
||||
-- For tables that are indexed by item name:
|
||||
-- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
|
||||
local function set_alias_metatable(table)
|
||||
setmetatable(table, {
|
||||
__index = function(name)
|
||||
return rawget(table, minetest.registered_aliases[name])
|
||||
end
|
||||
})
|
||||
end
|
||||
set_alias_metatable(minetest.registered_items)
|
||||
set_alias_metatable(minetest.registered_nodes)
|
||||
set_alias_metatable(minetest.registered_craftitems)
|
||||
set_alias_metatable(minetest.registered_tools)
|
||||
|
||||
-- These item names may not be used because they would interfere
|
||||
-- with legacy itemstrings
|
||||
local forbidden_item_names = {
|
||||
MaterialItem = true,
|
||||
MaterialItem2 = true,
|
||||
MaterialItem3 = true,
|
||||
NodeItem = true,
|
||||
node = true,
|
||||
CraftItem = true,
|
||||
craft = true,
|
||||
MBOItem = true,
|
||||
ToolItem = true,
|
||||
tool = true,
|
||||
}
|
||||
|
||||
local function check_modname_prefix(name)
|
||||
if name:sub(1,1) == ":" then
|
||||
-- Escape the modname prefix enforcement mechanism
|
||||
return name:sub(2)
|
||||
else
|
||||
-- Modname prefix enforcement
|
||||
local expected_prefix = minetest.get_current_modname() .. ":"
|
||||
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||
"\"modname:\" or \":\" prefix required")
|
||||
end
|
||||
local subname = name:sub(#expected_prefix+1)
|
||||
if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then
|
||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||
"contains unallowed characters")
|
||||
end
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.register_abm(spec)
|
||||
-- Add to minetest.registered_abms
|
||||
minetest.registered_abms[#minetest.registered_abms+1] = spec
|
||||
end
|
||||
|
||||
function minetest.register_entity(name, prototype)
|
||||
-- Check name
|
||||
if name == nil then
|
||||
error("Unable to register entity: Name is nil")
|
||||
end
|
||||
name = check_modname_prefix(tostring(name))
|
||||
|
||||
prototype.name = name
|
||||
prototype.__index = prototype -- so that it can be used as a metatable
|
||||
|
||||
-- Add to minetest.registered_entities
|
||||
minetest.registered_entities[name] = prototype
|
||||
end
|
||||
|
||||
function minetest.register_item(name, itemdef)
|
||||
-- Check name
|
||||
if name == nil then
|
||||
error("Unable to register item: Name is nil")
|
||||
end
|
||||
name = check_modname_prefix(tostring(name))
|
||||
if forbidden_item_names[name] then
|
||||
error("Unable to register item: Name is forbidden: " .. name)
|
||||
end
|
||||
itemdef.name = name
|
||||
|
||||
-- Apply defaults and add to registered_* table
|
||||
if itemdef.type == "node" then
|
||||
setmetatable(itemdef, {__index = minetest.nodedef_default})
|
||||
minetest.registered_nodes[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "craft" then
|
||||
setmetatable(itemdef, {__index = minetest.craftitemdef_default})
|
||||
minetest.registered_craftitems[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "tool" then
|
||||
setmetatable(itemdef, {__index = minetest.tooldef_default})
|
||||
minetest.registered_tools[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "none" then
|
||||
setmetatable(itemdef, {__index = minetest.noneitemdef_default})
|
||||
else
|
||||
error("Unable to register item: Type is invalid: " .. dump(itemdef))
|
||||
end
|
||||
|
||||
-- Flowing liquid uses param2
|
||||
if itemdef.type == "node" and itemdef.liquidtype == "flowing" then
|
||||
itemdef.paramtype2 = "flowingliquid"
|
||||
end
|
||||
|
||||
-- BEGIN Legacy stuff
|
||||
if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
|
||||
minetest.register_craft({
|
||||
type="cooking",
|
||||
output=itemdef.cookresult_itemstring,
|
||||
recipe=itemdef.name,
|
||||
cooktime=itemdef.furnace_cooktime
|
||||
})
|
||||
end
|
||||
if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then
|
||||
minetest.register_craft({
|
||||
type="fuel",
|
||||
recipe=itemdef.name,
|
||||
burntime=itemdef.furnace_burntime
|
||||
})
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
-- Disable all further modifications
|
||||
getmetatable(itemdef).__newindex = {}
|
||||
|
||||
--minetest.log("Registering item: " .. itemdef.name)
|
||||
minetest.registered_items[itemdef.name] = itemdef
|
||||
minetest.registered_aliases[itemdef.name] = nil
|
||||
register_item_raw(itemdef)
|
||||
end
|
||||
|
||||
function minetest.register_node(name, nodedef)
|
||||
nodedef.type = "node"
|
||||
minetest.register_item(name, nodedef)
|
||||
end
|
||||
|
||||
function minetest.register_craftitem(name, craftitemdef)
|
||||
craftitemdef.type = "craft"
|
||||
|
||||
-- BEGIN Legacy stuff
|
||||
if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
|
||||
craftitemdef.inventory_image = craftitemdef.image
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
minetest.register_item(name, craftitemdef)
|
||||
end
|
||||
|
||||
function minetest.register_tool(name, tooldef)
|
||||
tooldef.type = "tool"
|
||||
tooldef.stack_max = 1
|
||||
|
||||
-- BEGIN Legacy stuff
|
||||
if tooldef.inventory_image == nil and tooldef.image ~= nil then
|
||||
tooldef.inventory_image = tooldef.image
|
||||
end
|
||||
if tooldef.tool_capabilities == nil and
|
||||
(tooldef.full_punch_interval ~= nil or
|
||||
tooldef.basetime ~= nil or
|
||||
tooldef.dt_weight ~= nil or
|
||||
tooldef.dt_crackiness ~= nil or
|
||||
tooldef.dt_crumbliness ~= nil or
|
||||
tooldef.dt_cuttability ~= nil or
|
||||
tooldef.basedurability ~= nil or
|
||||
tooldef.dd_weight ~= nil or
|
||||
tooldef.dd_crackiness ~= nil or
|
||||
tooldef.dd_crumbliness ~= nil or
|
||||
tooldef.dd_cuttability ~= nil) then
|
||||
tooldef.tool_capabilities = {
|
||||
full_punch_interval = tooldef.full_punch_interval,
|
||||
basetime = tooldef.basetime,
|
||||
dt_weight = tooldef.dt_weight,
|
||||
dt_crackiness = tooldef.dt_crackiness,
|
||||
dt_crumbliness = tooldef.dt_crumbliness,
|
||||
dt_cuttability = tooldef.dt_cuttability,
|
||||
basedurability = tooldef.basedurability,
|
||||
dd_weight = tooldef.dd_weight,
|
||||
dd_crackiness = tooldef.dd_crackiness,
|
||||
dd_crumbliness = tooldef.dd_crumbliness,
|
||||
dd_cuttability = tooldef.dd_cuttability,
|
||||
}
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
minetest.register_item(name, tooldef)
|
||||
end
|
||||
|
||||
function minetest.register_alias(name, convert_to)
|
||||
if forbidden_item_names[name] then
|
||||
error("Unable to register alias: Name is forbidden: " .. name)
|
||||
end
|
||||
if minetest.registered_items[name] ~= nil then
|
||||
minetest.log("WARNING: Not registering alias, item with same name" ..
|
||||
" is already defined: " .. name .. " -> " .. convert_to)
|
||||
else
|
||||
--minetest.log("Registering alias: " .. name .. " -> " .. convert_to)
|
||||
minetest.registered_aliases[name] = convert_to
|
||||
register_alias_raw(name, convert_to)
|
||||
end
|
||||
end
|
||||
|
||||
-- Alias the forbidden item names to "" so they can't be
|
||||
-- created via itemstrings (e.g. /give)
|
||||
local name
|
||||
for name in pairs(forbidden_item_names) do
|
||||
minetest.registered_aliases[name] = ""
|
||||
register_alias_raw(name, "")
|
||||
end
|
||||
|
||||
|
||||
-- Deprecated:
|
||||
-- Aliases for minetest.register_alias (how ironic...)
|
||||
--minetest.alias_node = minetest.register_alias
|
||||
--minetest.alias_tool = minetest.register_alias
|
||||
--minetest.alias_craftitem = minetest.register_alias
|
||||
|
||||
--
|
||||
-- Built-in node definitions. Also defined in C.
|
||||
--
|
||||
|
||||
minetest.register_item(":unknown", {
|
||||
type = "none",
|
||||
description = "Unknown Item",
|
||||
inventory_image = "unknown_item.png",
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
})
|
||||
|
||||
minetest.register_node(":air", {
|
||||
description = "Air (you hacker you!)",
|
||||
inventory_image = "unknown_block.png",
|
||||
wield_image = "unknown_block.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
buildable_to = true,
|
||||
air_equivalent = true,
|
||||
})
|
||||
|
||||
minetest.register_node(":ignore", {
|
||||
description = "Ignore (you hacker you!)",
|
||||
inventory_image = "unknown_block.png",
|
||||
wield_image = "unknown_block.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "none",
|
||||
sunlight_propagates = false,
|
||||
walkable = false,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
buildable_to = true, -- A way to remove accidentally placed ignores
|
||||
air_equivalent = true,
|
||||
})
|
||||
|
||||
-- The hand (bare definition)
|
||||
minetest.register_item(":", {
|
||||
type = "none",
|
||||
})
|
||||
|
||||
--
|
||||
-- Default material types
|
||||
--
|
||||
function digprop_err()
|
||||
minetest.log("info", debug.traceback())
|
||||
minetest.log("info", "WARNING: The minetest.digprop_* functions are obsolete and need to be replaced by item groups.")
|
||||
end
|
||||
|
||||
minetest.digprop_constanttime = digprop_err
|
||||
minetest.digprop_stonelike = digprop_err
|
||||
minetest.digprop_dirtlike = digprop_err
|
||||
minetest.digprop_gravellike = digprop_err
|
||||
minetest.digprop_woodlike = digprop_err
|
||||
minetest.digprop_leaveslike = digprop_err
|
||||
minetest.digprop_glasslike = digprop_err
|
||||
|
||||
--
|
||||
-- Creative inventory
|
||||
--
|
||||
|
||||
minetest.creative_inventory = {}
|
||||
|
||||
minetest.add_to_creative_inventory = function(itemstring)
|
||||
table.insert(minetest.creative_inventory, itemstring)
|
||||
end
|
||||
|
||||
--
|
||||
-- Callback registration
|
||||
--
|
||||
|
||||
local function make_registration()
|
||||
local t = {}
|
||||
local registerfunc = function(func) table.insert(t, func) end
|
||||
return t, registerfunc
|
||||
end
|
||||
|
||||
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
|
||||
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
|
||||
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
|
||||
minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
|
||||
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
|
||||
minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
|
||||
minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
|
||||
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
|
||||
minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
|
||||
|
||||
--
|
||||
-- Set random seed
|
||||
--
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
-- END
|
||||
-- Load other files
|
||||
dofile(minetest.get_modpath("__builtin").."/serialize.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/misc_helpers.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/item.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/misc_register.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/item_entity.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/deprecated.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/misc.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/privileges.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/auth.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/chatcommands.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/static_spawn.lua")
|
||||
dofile(minetest.get_modpath("__builtin").."/detached_inventory.lua")
|
||||
|
||||
|
||||
577
builtin/chatcommands.lua
Normal file
@@ -0,0 +1,577 @@
|
||||
-- Minetest: builtin/chatcommands.lua
|
||||
|
||||
--
|
||||
-- Chat command handler
|
||||
--
|
||||
|
||||
minetest.chatcommands = {}
|
||||
function minetest.register_chatcommand(cmd, def)
|
||||
def = def or {}
|
||||
def.params = def.params or ""
|
||||
def.description = def.description or ""
|
||||
def.privs = def.privs or {}
|
||||
minetest.chatcommands[cmd] = def
|
||||
end
|
||||
|
||||
minetest.register_on_chat_message(function(name, message)
|
||||
local cmd, param = string.match(message, "^/([^ ]+) *(.*)")
|
||||
if not param then
|
||||
param = ""
|
||||
end
|
||||
local cmd_def = minetest.chatcommands[cmd]
|
||||
if cmd_def then
|
||||
if not cmd_def.func then
|
||||
-- This is a C++ command
|
||||
return false
|
||||
else
|
||||
local has_privs, missing_privs = minetest.check_player_privs(name, cmd_def.privs)
|
||||
if has_privs then
|
||||
cmd_def.func(name, param)
|
||||
else
|
||||
minetest.chat_send_player(name, "You don't have permission to run this command (missing privileges: "..table.concat(missing_privs, ", ")..")")
|
||||
end
|
||||
return true -- handled chat message
|
||||
end
|
||||
end
|
||||
return false
|
||||
end)
|
||||
|
||||
--
|
||||
-- Chat commands
|
||||
--
|
||||
|
||||
-- Register C++ commands without functions
|
||||
minetest.register_chatcommand("me", {params = nil, description = "chat action (eg. /me orders a pizza)", privs = {shout=true}})
|
||||
minetest.register_chatcommand("status", {description = "print server status line"})
|
||||
minetest.register_chatcommand("shutdown", {params = "", description = "shutdown server", privs = {server=true}})
|
||||
minetest.register_chatcommand("clearobjects", {params = "", description = "clear all objects in world", privs = {server=true}})
|
||||
minetest.register_chatcommand("time", {params = "<0...24000>", description = "set time of day", privs = {settime=true}})
|
||||
minetest.register_chatcommand("ban", {params = "<name>", description = "ban IP of player", privs = {ban=true}})
|
||||
minetest.register_chatcommand("unban", {params = "<name/ip>", description = "remove IP ban", privs = {ban=true}})
|
||||
|
||||
-- Register other commands
|
||||
minetest.register_chatcommand("help", {
|
||||
privs = {},
|
||||
params = "(nothing)/all/privs/<cmd>",
|
||||
description = "Get help for commands or list privileges",
|
||||
func = function(name, param)
|
||||
local format_help_line = function(cmd, def)
|
||||
local msg = "/"..cmd
|
||||
if def.params and def.params ~= "" then msg = msg .. " " .. def.params end
|
||||
if def.description and def.description ~= "" then msg = msg .. ": " .. def.description end
|
||||
return msg
|
||||
end
|
||||
if param == "" then
|
||||
local msg = ""
|
||||
cmds = {}
|
||||
for cmd, def in pairs(minetest.chatcommands) do
|
||||
if minetest.check_player_privs(name, def.privs) then
|
||||
table.insert(cmds, cmd)
|
||||
end
|
||||
end
|
||||
minetest.chat_send_player(name, "Available commands: "..table.concat(cmds, " "))
|
||||
minetest.chat_send_player(name, "Use '/help <cmd>' to get more information, or '/help all' to list everything.")
|
||||
elseif param == "all" then
|
||||
minetest.chat_send_player(name, "Available commands:")
|
||||
for cmd, def in pairs(minetest.chatcommands) do
|
||||
if minetest.check_player_privs(name, def.privs) then
|
||||
minetest.chat_send_player(name, format_help_line(cmd, def))
|
||||
end
|
||||
end
|
||||
elseif param == "privs" then
|
||||
minetest.chat_send_player(name, "Available privileges:")
|
||||
for priv, def in pairs(minetest.registered_privileges) do
|
||||
minetest.chat_send_player(name, priv..": "..def.description)
|
||||
end
|
||||
else
|
||||
local cmd = param
|
||||
def = minetest.chatcommands[cmd]
|
||||
if not def then
|
||||
minetest.chat_send_player(name, "Command not available: "..cmd)
|
||||
else
|
||||
minetest.chat_send_player(name, format_help_line(cmd, def))
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("privs", {
|
||||
params = "<name>",
|
||||
description = "print out privileges of player",
|
||||
func = function(name, param)
|
||||
if param == "" then
|
||||
param = name
|
||||
else
|
||||
--[[if not minetest.check_player_privs(name, {privs=true}) then
|
||||
minetest.chat_send_player(name, "Privileges of "..param.." are hidden from you.")
|
||||
return
|
||||
end]]
|
||||
end
|
||||
minetest.chat_send_player(name, "Privileges of "..param..": "..minetest.privs_to_string(minetest.get_player_privs(param), ' '))
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("grant", {
|
||||
params = "<name> <privilege>|all",
|
||||
description = "Give privilege to player",
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
if not minetest.check_player_privs(name, {privs=true}) and
|
||||
not minetest.check_player_privs(name, {basic_privs=true}) then
|
||||
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||
return
|
||||
end
|
||||
local grantname, grantprivstr = string.match(param, "([^ ]+) (.+)")
|
||||
if not grantname or not grantprivstr then
|
||||
minetest.chat_send_player(name, "Invalid parameters (see /help grant)")
|
||||
return
|
||||
end
|
||||
local grantprivs = minetest.string_to_privs(grantprivstr)
|
||||
if grantprivstr == "all" then
|
||||
grantprivs = minetest.registered_privileges
|
||||
end
|
||||
local privs = minetest.get_player_privs(grantname)
|
||||
local privs_known = true
|
||||
for priv, _ in pairs(grantprivs) do
|
||||
if priv ~= "interact" and priv ~= "shout" and priv ~= "interact_extra" and not minetest.check_player_privs(name, {privs=true}) then
|
||||
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||
return
|
||||
end
|
||||
if not minetest.registered_privileges[priv] then
|
||||
minetest.chat_send_player(name, "Unknown privilege: "..priv)
|
||||
privs_known = false
|
||||
end
|
||||
privs[priv] = true
|
||||
end
|
||||
if not privs_known then
|
||||
return
|
||||
end
|
||||
minetest.set_player_privs(grantname, privs)
|
||||
minetest.chat_send_player(name, "Privileges of "..grantname..": "..minetest.privs_to_string(minetest.get_player_privs(grantname), ' '))
|
||||
if grantname ~= name then
|
||||
minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' '))
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("revoke", {
|
||||
params = "<name> <privilege>|all",
|
||||
description = "Remove privilege from player",
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
if not minetest.check_player_privs(name, {privs=true}) and
|
||||
not minetest.check_player_privs(name, {basic_privs=true}) then
|
||||
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||
return
|
||||
end
|
||||
local revokename, revokeprivstr = string.match(param, "([^ ]+) (.+)")
|
||||
if not revokename or not revokeprivstr then
|
||||
minetest.chat_send_player(name, "Invalid parameters (see /help revoke)")
|
||||
return
|
||||
end
|
||||
local revokeprivs = minetest.string_to_privs(revokeprivstr)
|
||||
local privs = minetest.get_player_privs(revokename)
|
||||
for priv, _ in pairs(revokeprivs) do
|
||||
if priv ~= "interact" and priv ~= "shout" and priv ~= "interact_extra" and not minetest.check_player_privs(name, {privs=true}) then
|
||||
minetest.chat_send_player(name, "Your privileges are insufficient.")
|
||||
return
|
||||
end
|
||||
end
|
||||
if revokeprivstr == "all" then
|
||||
privs = {}
|
||||
else
|
||||
for priv, _ in pairs(revokeprivs) do
|
||||
privs[priv] = nil
|
||||
end
|
||||
end
|
||||
minetest.set_player_privs(revokename, privs)
|
||||
minetest.chat_send_player(name, "Privileges of "..revokename..": "..minetest.privs_to_string(minetest.get_player_privs(revokename), ' '))
|
||||
if revokename ~= name then
|
||||
minetest.chat_send_player(revokename, name.." revoked privileges from you: "..minetest.privs_to_string(revokeprivs, ' '))
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("setpassword", {
|
||||
params = "<name> <password>",
|
||||
description = "set given password",
|
||||
privs = {password=true},
|
||||
func = function(name, param)
|
||||
local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$")
|
||||
if not toname then
|
||||
toname = string.match(param, "^([^ ]+) *$")
|
||||
raw_password = nil
|
||||
end
|
||||
if not toname then
|
||||
minetest.chat_send_player(name, "Name field required")
|
||||
return
|
||||
end
|
||||
local actstr = "?"
|
||||
if not raw_password then
|
||||
minetest.set_player_password(toname, "")
|
||||
actstr = "cleared"
|
||||
else
|
||||
minetest.set_player_password(toname, minetest.get_password_hash(toname, raw_password))
|
||||
actstr = "set"
|
||||
end
|
||||
minetest.chat_send_player(name, "Password of player \""..toname.."\" "..actstr)
|
||||
if toname ~= name then
|
||||
minetest.chat_send_player(toname, "Your password was "..actstr.." by "..name)
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("clearpassword", {
|
||||
params = "<name>",
|
||||
description = "set empty password",
|
||||
privs = {password=true},
|
||||
func = function(name, param)
|
||||
toname = param
|
||||
if not toname then
|
||||
minetest.chat_send_player(toname, "Name field required")
|
||||
return
|
||||
end
|
||||
minetest.set_player_password(toname, '')
|
||||
minetest.chat_send_player(name, "Password of player \""..toname.."\" cleared")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("auth_reload", {
|
||||
params = "",
|
||||
description = "reload authentication data",
|
||||
privs = {server=true},
|
||||
func = function(name, param)
|
||||
local done = minetest.auth_reload()
|
||||
if done then
|
||||
minetest.chat_send_player(name, "Done.")
|
||||
else
|
||||
minetest.chat_send_player(name, "Failed.")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("teleport", {
|
||||
params = "<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>",
|
||||
description = "teleport to given position",
|
||||
privs = {teleport=true},
|
||||
func = function(name, param)
|
||||
-- Returns (pos, true) if found, otherwise (pos, false)
|
||||
local function find_free_position_near(pos)
|
||||
local tries = {
|
||||
{x=1,y=0,z=0},
|
||||
{x=-1,y=0,z=0},
|
||||
{x=0,y=0,z=1},
|
||||
{x=0,y=0,z=-1},
|
||||
}
|
||||
for _, d in ipairs(tries) do
|
||||
local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
|
||||
local n = minetest.env:get_node(p)
|
||||
if not minetest.registered_nodes[n.name].walkable then
|
||||
return p, true
|
||||
end
|
||||
end
|
||||
return pos, false
|
||||
end
|
||||
|
||||
local teleportee = nil
|
||||
local p = {}
|
||||
p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
|
||||
teleportee = minetest.env:get_player_by_name(name)
|
||||
if teleportee and p.x and p.y and p.z then
|
||||
minetest.chat_send_player(name, "Teleporting to ("..p.x..", "..p.y..", "..p.z..")")
|
||||
teleportee:setpos(p)
|
||||
return
|
||||
end
|
||||
|
||||
local teleportee = nil
|
||||
local p = nil
|
||||
local target_name = nil
|
||||
target_name = string.match(param, "^([^ ]+)$")
|
||||
teleportee = minetest.env:get_player_by_name(name)
|
||||
if target_name then
|
||||
local target = minetest.env:get_player_by_name(target_name)
|
||||
if target then
|
||||
p = target:getpos()
|
||||
end
|
||||
end
|
||||
if teleportee and p then
|
||||
p = find_free_position_near(p)
|
||||
minetest.chat_send_player(name, "Teleporting to "..target_name.." at ("..p.x..", "..p.y..", "..p.z..")")
|
||||
teleportee:setpos(p)
|
||||
return
|
||||
end
|
||||
|
||||
if minetest.check_player_privs(name, {bring=true}) then
|
||||
local teleportee = nil
|
||||
local p = {}
|
||||
local teleportee_name = nil
|
||||
teleportee_name, p.x, p.y, p.z = string.match(param, "^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
|
||||
if teleportee_name then
|
||||
teleportee = minetest.env:get_player_by_name(teleportee_name)
|
||||
end
|
||||
if teleportee and p.x and p.y and p.z then
|
||||
minetest.chat_send_player(name, "Teleporting "..teleportee_name.." to ("..p.x..", "..p.y..", "..p.z..")")
|
||||
teleportee:setpos(p)
|
||||
return
|
||||
end
|
||||
|
||||
local teleportee = nil
|
||||
local p = nil
|
||||
local teleportee_name = nil
|
||||
local target_name = nil
|
||||
teleportee_name, target_name = string.match(param, "^([^ ]+) +([^ ]+)$")
|
||||
if teleportee_name then
|
||||
teleportee = minetest.env:get_player_by_name(teleportee_name)
|
||||
end
|
||||
if target_name then
|
||||
local target = minetest.env:get_player_by_name(target_name)
|
||||
if target then
|
||||
p = target:getpos()
|
||||
end
|
||||
end
|
||||
if teleportee and p then
|
||||
p = find_free_position_near(p)
|
||||
minetest.chat_send_player(name, "Teleporting "..teleportee_name.." to "..target_name.." at ("..p.x..", "..p.y..", "..p.z..")")
|
||||
teleportee:setpos(p)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
minetest.chat_send_player(name, "Invalid parameters (\""..param.."\") or player not found (see /help teleport)")
|
||||
return
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("set", {
|
||||
params = "[-n] <name> <value> | <name>",
|
||||
description = "set or read server configuration setting",
|
||||
privs = {server=true},
|
||||
func = function(name, param)
|
||||
local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)")
|
||||
if arg and arg == "-n" and setname and setvalue then
|
||||
minetest.setting_set(setname, setvalue)
|
||||
minetest.chat_send_player(name, setname.." = "..setvalue)
|
||||
return
|
||||
end
|
||||
local setname, setvalue = string.match(param, "([^ ]+) (.+)")
|
||||
if setname and setvalue then
|
||||
if not minetest.setting_get(setname) then
|
||||
minetest.chat_send_player(name, "Failed. Use '/set -n <name> <value>' to create a new setting.")
|
||||
return
|
||||
end
|
||||
minetest.setting_set(setname, setvalue)
|
||||
minetest.chat_send_player(name, setname.." = "..setvalue)
|
||||
return
|
||||
end
|
||||
local setname = string.match(param, "([^ ]+)")
|
||||
if setname then
|
||||
local setvalue = minetest.setting_get(setname)
|
||||
if not setvalue then
|
||||
setvalue = "<not set>"
|
||||
end
|
||||
minetest.chat_send_player(name, setname.." = "..setvalue)
|
||||
return
|
||||
end
|
||||
minetest.chat_send_player(name, "Invalid parameters (see /help set)")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("mods", {
|
||||
params = "",
|
||||
description = "lists mods installed on the server",
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
local response = ""
|
||||
local modnames = minetest.get_modnames()
|
||||
for i, mod in ipairs(modnames) do
|
||||
response = response .. mod
|
||||
-- Add space if not at the end
|
||||
if i ~= #modnames then
|
||||
response = response .. " "
|
||||
end
|
||||
end
|
||||
minetest.chat_send_player(name, response)
|
||||
end,
|
||||
})
|
||||
|
||||
local function handle_give_command(cmd, giver, receiver, stackstring)
|
||||
minetest.log("action", giver.." invoked "..cmd..', stackstring="'
|
||||
..stackstring..'"')
|
||||
minetest.log(cmd..' invoked, stackstring="'..stackstring..'"')
|
||||
local itemstack = ItemStack(stackstring)
|
||||
if itemstack:is_empty() then
|
||||
minetest.chat_send_player(giver, 'error: cannot give an empty item')
|
||||
return
|
||||
elseif not itemstack:is_known() then
|
||||
minetest.chat_send_player(giver, 'error: cannot give an unknown item')
|
||||
return
|
||||
end
|
||||
local receiverref = minetest.env:get_player_by_name(receiver)
|
||||
if receiverref == nil then
|
||||
minetest.chat_send_player(giver, receiver..' is not a known player')
|
||||
return
|
||||
end
|
||||
local leftover = receiverref:get_inventory():add_item("main", itemstack)
|
||||
if leftover:is_empty() then
|
||||
partiality = ""
|
||||
elseif leftover:get_count() == itemstack:get_count() then
|
||||
partiality = "could not be "
|
||||
else
|
||||
partiality = "partially "
|
||||
end
|
||||
-- The actual item stack string may be different from what the "giver"
|
||||
-- entered (e.g. big numbers are always interpreted as 2^16-1).
|
||||
stackstring = itemstack:to_string()
|
||||
if giver == receiver then
|
||||
minetest.chat_send_player(giver, '"'..stackstring
|
||||
..'" '..partiality..'added to inventory.');
|
||||
else
|
||||
minetest.chat_send_player(giver, '"'..stackstring
|
||||
..'" '..partiality..'added to '..receiver..'\'s inventory.');
|
||||
minetest.chat_send_player(receiver, '"'..stackstring
|
||||
..'" '..partiality..'added to inventory.');
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("give", {
|
||||
params = "<name> <itemstring>",
|
||||
description = "give item to player",
|
||||
privs = {give=true},
|
||||
func = function(name, param)
|
||||
local toname, itemstring = string.match(param, "^([^ ]+) +(.+)$")
|
||||
if not toname or not itemstring then
|
||||
minetest.chat_send_player(name, "name and itemstring required")
|
||||
return
|
||||
end
|
||||
handle_give_command("/give", name, toname, itemstring)
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("giveme", {
|
||||
params = "<itemstring>",
|
||||
description = "give item to yourself",
|
||||
privs = {give=true},
|
||||
func = function(name, param)
|
||||
local itemstring = string.match(param, "(.+)$")
|
||||
if not itemstring then
|
||||
minetest.chat_send_player(name, "itemstring required")
|
||||
return
|
||||
end
|
||||
handle_give_command("/giveme", name, name, itemstring)
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("spawnentity", {
|
||||
params = "<entityname>",
|
||||
description = "spawn entity at your position",
|
||||
privs = {give=true, interact=true},
|
||||
func = function(name, param)
|
||||
local entityname = string.match(param, "(.+)$")
|
||||
if not entityname then
|
||||
minetest.chat_send_player(name, "entityname required")
|
||||
return
|
||||
end
|
||||
print('/spawnentity invoked, entityname="'..entityname..'"')
|
||||
local player = minetest.env:get_player_by_name(name)
|
||||
if player == nil then
|
||||
print("Unable to spawn entity, player is nil")
|
||||
return true -- Handled chat message
|
||||
end
|
||||
local p = player:getpos()
|
||||
p.y = p.y + 1
|
||||
minetest.env:add_entity(p, entityname)
|
||||
minetest.chat_send_player(name, '"'..entityname
|
||||
..'" spawned.');
|
||||
end,
|
||||
})
|
||||
minetest.register_chatcommand("pulverize", {
|
||||
params = "",
|
||||
description = "delete item in hand",
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
local player = minetest.env:get_player_by_name(name)
|
||||
if player == nil then
|
||||
print("Unable to pulverize, player is nil")
|
||||
return true -- Handled chat message
|
||||
end
|
||||
if player:get_wielded_item():is_empty() then
|
||||
minetest.chat_send_player(name, 'Unable to pulverize, no item in hand.')
|
||||
else
|
||||
player:set_wielded_item(nil)
|
||||
minetest.chat_send_player(name, 'An item was pulverized.')
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Key = player name
|
||||
minetest.rollback_punch_callbacks = {}
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node, puncher)
|
||||
local name = puncher:get_player_name()
|
||||
if minetest.rollback_punch_callbacks[name] then
|
||||
minetest.rollback_punch_callbacks[name](pos, node, puncher)
|
||||
minetest.rollback_punch_callbacks[name] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("rollback_check", {
|
||||
params = "[<range>] [<seconds>]",
|
||||
description = "check who has last touched a node or near it, "..
|
||||
"max. <seconds> ago (default range=0, seconds=86400=24h)",
|
||||
privs = {rollback=true},
|
||||
func = function(name, param)
|
||||
local range, seconds = string.match(param, "(%d+) *(%d*)")
|
||||
range = tonumber(range) or 0
|
||||
seconds = tonumber(seconds) or 86400
|
||||
minetest.chat_send_player(name, "Punch a node (limits set: range="..
|
||||
dump(range).." seconds="..dump(seconds).."s)")
|
||||
minetest.rollback_punch_callbacks[name] = function(pos, node, puncher)
|
||||
local name = puncher:get_player_name()
|
||||
minetest.chat_send_player(name, "Checking...")
|
||||
local actor, act_p, act_seconds =
|
||||
minetest.rollback_get_last_node_actor(pos, range, seconds)
|
||||
if actor == "" then
|
||||
minetest.chat_send_player(name, "Nobody has touched the "..
|
||||
"specified location in "..dump(seconds).." seconds")
|
||||
return
|
||||
end
|
||||
local nodedesc = "this node"
|
||||
if act_p.x ~= pos.x or act_p.y ~= pos.y or act_p.z ~= pos.z then
|
||||
nodedesc = minetest.pos_to_string(act_p)
|
||||
end
|
||||
local nodename = minetest.env:get_node(act_p).name
|
||||
minetest.chat_send_player(name, "Last actor on "..nodedesc..
|
||||
" was "..actor..", "..dump(act_seconds)..
|
||||
"s ago (node is now "..nodename..")")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("rollback", {
|
||||
params = "<player name> [<seconds>] | :<actor> [<seconds>]",
|
||||
description = "revert actions of a player; default for <seconds> is 60",
|
||||
privs = {rollback=true},
|
||||
func = function(name, param)
|
||||
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
|
||||
if not target_name then
|
||||
local player_name = nil;
|
||||
player_name, seconds = string.match(param, "([^ ]+) *(%d*)")
|
||||
if not player_name then
|
||||
minetest.chat_send_player(name, "Invalid parameters. See /help rollback and /help rollback_check")
|
||||
return
|
||||
end
|
||||
target_name = "player:"..player_name
|
||||
end
|
||||
seconds = tonumber(seconds) or 60
|
||||
minetest.chat_send_player(name, "Reverting actions of "..
|
||||
dump(target_name).." since "..dump(seconds).." seconds.")
|
||||
local success, log = minetest.rollback_revert_actions_by(
|
||||
target_name, seconds)
|
||||
if #log > 10 then
|
||||
minetest.chat_send_player(name, "(log is too long to show)")
|
||||
else
|
||||
for _,line in ipairs(log) do
|
||||
minetest.chat_send_player(name, line)
|
||||
end
|
||||
end
|
||||
if success then
|
||||
minetest.chat_send_player(name, "Reverting actions succeeded.")
|
||||
else
|
||||
minetest.chat_send_player(name, "Reverting actions FAILED.")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
26
builtin/deprecated.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
-- Minetest: builtin/deprecated.lua
|
||||
|
||||
--
|
||||
-- Default material types
|
||||
--
|
||||
function digprop_err()
|
||||
minetest.log("info", debug.traceback())
|
||||
minetest.log("info", "WARNING: The minetest.digprop_* functions are obsolete and need to be replaced by item groups.")
|
||||
end
|
||||
|
||||
minetest.digprop_constanttime = digprop_err
|
||||
minetest.digprop_stonelike = digprop_err
|
||||
minetest.digprop_dirtlike = digprop_err
|
||||
minetest.digprop_gravellike = digprop_err
|
||||
minetest.digprop_woodlike = digprop_err
|
||||
minetest.digprop_leaveslike = digprop_err
|
||||
minetest.digprop_glasslike = digprop_err
|
||||
|
||||
minetest.node_metadata_inventory_move_allow_all = function()
|
||||
minetest.log("info", "WARNING: minetest.node_metadata_inventory_move_allow_all is obsolete and does nothing.")
|
||||
end
|
||||
|
||||
minetest.add_to_creative_inventory = function(itemstring)
|
||||
minetest.log('info', "WARNING: minetest.add_to_creative_inventory: This function is deprecated and does nothing.")
|
||||
end
|
||||
|
||||
19
builtin/detached_inventory.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
-- Minetest: builtin/detached_inventory.lua
|
||||
|
||||
minetest.detached_inventories = {}
|
||||
|
||||
function minetest.create_detached_inventory(name, callbacks)
|
||||
local stuff = {}
|
||||
stuff.name = name
|
||||
if callbacks then
|
||||
stuff.allow_move = callbacks.allow_move
|
||||
stuff.allow_put = callbacks.allow_put
|
||||
stuff.allow_take = callbacks.allow_take
|
||||
stuff.on_move = callbacks.on_move
|
||||
stuff.on_put = callbacks.on_put
|
||||
stuff.on_take = callbacks.on_take
|
||||
end
|
||||
minetest.detached_inventories[name] = stuff
|
||||
return minetest.create_detached_inventory_raw(name)
|
||||
end
|
||||
|
||||
447
builtin/item.lua
Normal file
@@ -0,0 +1,447 @@
|
||||
-- Minetest: builtin/item.lua
|
||||
|
||||
--
|
||||
-- Item definition helpers
|
||||
--
|
||||
|
||||
function minetest.inventorycube(img1, img2, img3)
|
||||
img2 = img2 or img1
|
||||
img3 = img3 or img1
|
||||
return "[inventorycube"
|
||||
.. "{" .. img1:gsub("%^", "&")
|
||||
.. "{" .. img2:gsub("%^", "&")
|
||||
.. "{" .. img3:gsub("%^", "&")
|
||||
end
|
||||
|
||||
function minetest.get_pointed_thing_position(pointed_thing, above)
|
||||
if pointed_thing.type == "node" then
|
||||
if above then
|
||||
-- The position where a node would be placed
|
||||
return pointed_thing.above
|
||||
else
|
||||
-- The position where a node would be dug
|
||||
return pointed_thing.under
|
||||
end
|
||||
elseif pointed_thing.type == "object" then
|
||||
obj = pointed_thing.ref
|
||||
if obj ~= nil then
|
||||
return obj:getpos()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.dir_to_facedir(dir)
|
||||
if math.abs(dir.x) > math.abs(dir.z) then
|
||||
if dir.x < 0 then
|
||||
return 3
|
||||
else
|
||||
return 1
|
||||
end
|
||||
else
|
||||
if dir.z < 0 then
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.dir_to_wallmounted(dir)
|
||||
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
|
||||
if dir.y < 0 then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
elseif math.abs(dir.x) > math.abs(dir.z) then
|
||||
if dir.x < 0 then
|
||||
return 3
|
||||
else
|
||||
return 2
|
||||
end
|
||||
else
|
||||
if dir.z < 0 then
|
||||
return 5
|
||||
else
|
||||
return 4
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.get_node_drops(nodename, toolname)
|
||||
local drop = ItemStack({name=nodename}):get_definition().drop
|
||||
if drop == nil then
|
||||
-- default drop
|
||||
return {ItemStack({name=nodename})}
|
||||
elseif type(drop) == "string" then
|
||||
-- itemstring drop
|
||||
return {ItemStack(drop)}
|
||||
elseif drop.items == nil then
|
||||
-- drop = {} to disable default drop
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Extended drop table
|
||||
local got_items = {}
|
||||
local got_count = 0
|
||||
local _, item, tool
|
||||
for _, item in ipairs(drop.items) do
|
||||
local good_rarity = true
|
||||
local good_tool = true
|
||||
if item.rarity ~= nil then
|
||||
good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
|
||||
end
|
||||
if item.tools ~= nil then
|
||||
good_tool = false
|
||||
for _, tool in ipairs(item.tools) do
|
||||
if tool:sub(1, 1) == '~' then
|
||||
good_tool = toolname:find(tool:sub(2)) ~= nil
|
||||
else
|
||||
good_tool = toolname == tool
|
||||
end
|
||||
if good_tool then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if good_rarity and good_tool then
|
||||
got_count = got_count + 1
|
||||
for _, add_item in ipairs(item.items) do
|
||||
got_items[#got_items+1] = add_item
|
||||
end
|
||||
if drop.max_items ~= nil and got_count == drop.max_items then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return got_items
|
||||
end
|
||||
|
||||
function minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
local item = itemstack:peek_item()
|
||||
local def = itemstack:get_definition()
|
||||
if def.type ~= "node" or pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local under = pointed_thing.under
|
||||
local oldnode_under = minetest.env:get_node(under)
|
||||
local olddef_under = ItemStack({name=oldnode_under.name}):get_definition()
|
||||
olddef_under = olddef_under or minetest.nodedef_default
|
||||
local above = pointed_thing.above
|
||||
local oldnode_above = minetest.env:get_node(above)
|
||||
local olddef_above = ItemStack({name=oldnode_above.name}):get_definition()
|
||||
olddef_above = olddef_above or minetest.nodedef_default
|
||||
|
||||
if not olddef_above.buildable_to and not olddef_under.buildable_to then
|
||||
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||
.. " node in invalid position " .. minetest.pos_to_string(above)
|
||||
.. ", replacing " .. oldnode_above.name)
|
||||
return
|
||||
end
|
||||
|
||||
-- Place above pointed node
|
||||
local place_to = {x = above.x, y = above.y, z = above.z}
|
||||
|
||||
-- If node under is buildable_to, place into it instead (eg. snow)
|
||||
if olddef_under.buildable_to then
|
||||
minetest.log("info", "node under is buildable to")
|
||||
place_to = {x = under.x, y = under.y, z = under.z}
|
||||
end
|
||||
|
||||
minetest.log("action", placer:get_player_name() .. " places node "
|
||||
.. def.name .. " at " .. minetest.pos_to_string(place_to))
|
||||
|
||||
local oldnode = minetest.env:get_node(place_to)
|
||||
local newnode = {name = def.name, param1 = 0, param2 = 0}
|
||||
|
||||
-- Calculate direction for wall mounted stuff like torches and signs
|
||||
if def.paramtype2 == 'wallmounted' then
|
||||
local dir = {
|
||||
x = under.x - above.x,
|
||||
y = under.y - above.y,
|
||||
z = under.z - above.z
|
||||
}
|
||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif def.paramtype2 == 'facedir' then
|
||||
local placer_pos = placer:getpos()
|
||||
if placer_pos then
|
||||
local dir = {
|
||||
x = above.x - placer_pos.x,
|
||||
y = above.y - placer_pos.y,
|
||||
z = above.z - placer_pos.z
|
||||
}
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
minetest.log("action", "facedir: " .. newnode.param2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add node and update
|
||||
minetest.env:add_node(place_to, newnode)
|
||||
|
||||
-- Run callback
|
||||
if def.after_place_node then
|
||||
-- Copy place_to because callback can modify it
|
||||
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
|
||||
def.after_place_node(place_to_copy, placer)
|
||||
end
|
||||
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
||||
-- Copy pos and node because callback can modify them
|
||||
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
|
||||
local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
|
||||
local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
|
||||
callback(place_to_copy, newnode_copy, placer, oldnode_copy)
|
||||
end
|
||||
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
||||
if pos ~= nil then
|
||||
local item = itemstack:take_item()
|
||||
minetest.env:add_item(pos, item)
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_place(itemstack, placer, pointed_thing)
|
||||
if itemstack:get_definition().type == "node" then
|
||||
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
else
|
||||
return minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.item_drop(itemstack, dropper, pos)
|
||||
if dropper.get_player_name then
|
||||
local v = dropper:get_look_dir()
|
||||
local p = {x=pos.x+v.x, y=pos.y+1.5+v.y, z=pos.z+v.z}
|
||||
local obj = minetest.env:add_item(p, itemstack)
|
||||
v.x = v.x*2
|
||||
v.y = v.y*2 + 1
|
||||
v.z = v.z*2
|
||||
obj:setvelocity(v)
|
||||
else
|
||||
minetest.env:add_item(pos, itemstack)
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
function minetest.item_eat(hp_change, replace_with_item)
|
||||
return function(itemstack, user, pointed_thing) -- closure
|
||||
if itemstack:take_item() ~= nil then
|
||||
user:set_hp(user:get_hp() + hp_change)
|
||||
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.node_punch(pos, node, puncher)
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_punchnodes) do
|
||||
-- Copy pos and node because callback can modify them
|
||||
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
||||
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||
callback(pos_copy, node_copy, puncher)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.node_dig(pos, node, digger)
|
||||
minetest.debug("node_dig")
|
||||
|
||||
local def = ItemStack({name=node.name}):get_definition()
|
||||
if not def.diggable or (def.can_dig and not def.can_dig(pos,digger)) then
|
||||
minetest.debug("not diggable")
|
||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
||||
.. node.name .. " which is not diggable "
|
||||
.. minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log('action', digger:get_player_name() .. " digs "
|
||||
.. node.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
local wielded = digger:get_wielded_item()
|
||||
local drops = minetest.get_node_drops(node.name, wielded:get_name())
|
||||
|
||||
-- Wear out tool
|
||||
local tp = wielded:get_tool_capabilities()
|
||||
local dp = minetest.get_dig_params(def.groups, tp)
|
||||
wielded:add_wear(dp.wear)
|
||||
digger:set_wielded_item(wielded)
|
||||
|
||||
-- Add dropped items to object's inventory
|
||||
if digger:get_inventory() then
|
||||
local _, dropped_item
|
||||
for _, dropped_item in ipairs(drops) do
|
||||
digger:get_inventory():add_item("main", dropped_item)
|
||||
end
|
||||
end
|
||||
|
||||
local oldmetadata = nil
|
||||
if def.after_dig_node then
|
||||
oldmetadata = minetest.env:get_meta(pos):to_table()
|
||||
end
|
||||
|
||||
-- Remove node and update
|
||||
minetest.env:remove_node(pos)
|
||||
|
||||
-- Run callback
|
||||
if def.after_dig_node then
|
||||
-- Copy pos and node because callback can modify them
|
||||
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
||||
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||
def.after_dig_node(pos_copy, node_copy, oldmetadata, digger)
|
||||
end
|
||||
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_dignodes) do
|
||||
-- Copy pos and node because callback can modify them
|
||||
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
||||
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||
callback(pos_copy, node_copy, digger)
|
||||
end
|
||||
end
|
||||
|
||||
-- This is used to allow mods to redefine minetest.item_place and so on
|
||||
-- NOTE: This is not the preferred way. Preferred way is to provide enough
|
||||
-- callbacks to not require redefining global functions. -celeron55
|
||||
local function redef_wrapper(table, name)
|
||||
return function(...)
|
||||
return table[name](...)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Item definition defaults
|
||||
--
|
||||
|
||||
minetest.nodedef_default = {
|
||||
-- Item properties
|
||||
type="node",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
usable = false,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
node_placement_prediction = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||
on_drop = redef_wrapper(minetest, 'item_drop'), -- minetest.item_drop
|
||||
on_use = nil,
|
||||
can_dig = nil,
|
||||
|
||||
on_punch = redef_wrapper(minetest, 'node_punch'), -- minetest.node_punch
|
||||
on_dig = redef_wrapper(minetest, 'node_dig'), -- minetest.node_dig
|
||||
|
||||
on_receive_fields = nil,
|
||||
|
||||
on_metadata_inventory_move = minetest.node_metadata_inventory_move_allow_all,
|
||||
on_metadata_inventory_offer = minetest.node_metadata_inventory_offer_allow_all,
|
||||
on_metadata_inventory_take = minetest.node_metadata_inventory_take_allow_all,
|
||||
|
||||
-- Node properties
|
||||
drawtype = "normal",
|
||||
visual_scale = 1.0,
|
||||
-- Don't define these because otherwise the old tile_images and
|
||||
-- special_materials wouldn't be read
|
||||
--tiles ={""},
|
||||
--special_tiles = {
|
||||
-- {name="", backface_culling=true},
|
||||
-- {name="", backface_culling=true},
|
||||
--},
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
paramtype = "none",
|
||||
paramtype2 = "none",
|
||||
is_ground_content = false,
|
||||
sunlight_propagates = false,
|
||||
walkable = true,
|
||||
pointable = true,
|
||||
diggable = true,
|
||||
climbable = false,
|
||||
buildable_to = false,
|
||||
liquidtype = "none",
|
||||
liquid_alternative_flowing = "",
|
||||
liquid_alternative_source = "",
|
||||
liquid_viscosity = 0,
|
||||
light_source = 0,
|
||||
damage_per_second = 0,
|
||||
selection_box = {type="regular"},
|
||||
legacy_facedir_simple = false,
|
||||
legacy_wallmounted = false,
|
||||
}
|
||||
|
||||
minetest.craftitemdef_default = {
|
||||
type="craft",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||
on_drop = redef_wrapper(minetest, 'item_drop'), -- minetest.item_drop
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
minetest.tooldef_default = {
|
||||
type="tool",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 1,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = redef_wrapper(minetest, 'item_place'), -- minetest.item_place
|
||||
on_drop = redef_wrapper(minetest, 'item_drop'), -- minetest.item_drop
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
minetest.noneitemdef_default = { -- This is used for the hand and unknown items
|
||||
type="none",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
groups = {},
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
liquids_pointable = false,
|
||||
tool_capabilities = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = nil,
|
||||
on_drop = nil,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
104
builtin/item_entity.lua
Normal file
@@ -0,0 +1,104 @@
|
||||
-- Minetest: builtin/item_entity.lua
|
||||
|
||||
function minetest.spawn_item(pos, item)
|
||||
-- Take item in any format
|
||||
local stack = ItemStack(item)
|
||||
local obj = minetest.env:add_entity(pos, "__builtin:item")
|
||||
obj:get_luaentity():set_item(stack:to_string())
|
||||
return obj
|
||||
end
|
||||
|
||||
minetest.register_entity("__builtin:item", {
|
||||
initial_properties = {
|
||||
hp_max = 1,
|
||||
physical = true,
|
||||
collisionbox = {-0.17,-0.17,-0.17, 0.17,0.17,0.17},
|
||||
visual = "sprite",
|
||||
visual_size = {x=0.5, y=0.5},
|
||||
textures = {""},
|
||||
spritediv = {x=1, y=1},
|
||||
initial_sprite_basepos = {x=0, y=0},
|
||||
is_visible = false,
|
||||
},
|
||||
|
||||
itemstring = '',
|
||||
physical_state = true,
|
||||
|
||||
set_item = function(self, itemstring)
|
||||
self.itemstring = itemstring
|
||||
local stack = ItemStack(itemstring)
|
||||
local itemtable = stack:to_table()
|
||||
local itemname = nil
|
||||
if itemtable then
|
||||
itemname = stack:to_table().name
|
||||
end
|
||||
local item_texture = nil
|
||||
local item_type = ""
|
||||
if minetest.registered_items[itemname] then
|
||||
item_texture = minetest.registered_items[itemname].inventory_image
|
||||
item_type = minetest.registered_items[itemname].type
|
||||
end
|
||||
prop = {
|
||||
is_visible = true,
|
||||
visual = "sprite",
|
||||
textures = {"unknown_item.png"}
|
||||
}
|
||||
if item_texture and item_texture ~= "" then
|
||||
prop.visual = "sprite"
|
||||
prop.textures = {item_texture}
|
||||
prop.visual_size = {x=0.50, y=0.50}
|
||||
else
|
||||
prop.visual = "wielditem"
|
||||
prop.textures = {itemname}
|
||||
prop.visual_size = {x=0.20, y=0.20}
|
||||
prop.automatic_rotate = math.pi * 0.25
|
||||
end
|
||||
self.object:set_properties(prop)
|
||||
end,
|
||||
|
||||
get_staticdata = function(self)
|
||||
return self.itemstring
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
self.itemstring = staticdata
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
self.object:setvelocity({x=0, y=2, z=0})
|
||||
self.object:setacceleration({x=0, y=-10, z=0})
|
||||
self:set_item(self.itemstring)
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
local p = self.object:getpos()
|
||||
p.y = p.y - 0.3
|
||||
local nn = minetest.env:get_node(p).name
|
||||
-- If node is not registered or node is walkably solid
|
||||
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable then
|
||||
if self.physical_state then
|
||||
self.object:setvelocity({x=0,y=0,z=0})
|
||||
self.object:setacceleration({x=0, y=0, z=0})
|
||||
self.physical_state = false
|
||||
self.object:set_properties({
|
||||
physical = false
|
||||
})
|
||||
end
|
||||
else
|
||||
if not self.physical_state then
|
||||
self.object:setvelocity({x=0,y=0,z=0})
|
||||
self.object:setacceleration({x=0, y=-10, z=0})
|
||||
self.physical_state = true
|
||||
self.object:set_properties({
|
||||
physical = true
|
||||
})
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function(self, hitter)
|
||||
if self.itemstring ~= '' then
|
||||
hitter:get_inventory():add_item("main", self.itemstring)
|
||||
end
|
||||
self.object:remove()
|
||||
end,
|
||||
})
|
||||
|
||||
101
builtin/misc.lua
Normal file
@@ -0,0 +1,101 @@
|
||||
-- Minetest: builtin/misc.lua
|
||||
|
||||
--
|
||||
-- Misc. API functions
|
||||
--
|
||||
|
||||
minetest.timers_to_add = {}
|
||||
minetest.timers = {}
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, timer in ipairs(minetest.timers_to_add) do
|
||||
table.insert(minetest.timers, timer)
|
||||
end
|
||||
minetest.timers_to_add = {}
|
||||
for index, timer in ipairs(minetest.timers) do
|
||||
timer.time = timer.time - dtime
|
||||
if timer.time <= 0 then
|
||||
timer.func(timer.param)
|
||||
table.remove(minetest.timers,index)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function minetest.after(time, func, param)
|
||||
table.insert(minetest.timers_to_add, {time=time, func=func, param=param})
|
||||
end
|
||||
|
||||
function minetest.check_player_privs(name, privs)
|
||||
local player_privs = minetest.get_player_privs(name)
|
||||
local missing_privileges = {}
|
||||
for priv, val in pairs(privs) do
|
||||
if val then
|
||||
if not player_privs[priv] then
|
||||
table.insert(missing_privileges, priv)
|
||||
end
|
||||
end
|
||||
end
|
||||
if #missing_privileges > 0 then
|
||||
return false, missing_privileges
|
||||
end
|
||||
return true, ""
|
||||
end
|
||||
|
||||
function minetest.get_connected_players()
|
||||
-- This could be optimized a bit, but leave that for later
|
||||
local list = {}
|
||||
for _, obj in pairs(minetest.env:get_objects_inside_radius({x=0,y=0,z=0}, 1000000)) do
|
||||
if obj:is_player() then
|
||||
table.insert(list, obj)
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function minetest.hash_node_position(pos)
|
||||
return (pos.z+32768)*65536*65536 + (pos.y+32768)*65536 + pos.x+32768
|
||||
end
|
||||
|
||||
function minetest.get_item_group(name, group)
|
||||
if not minetest.registered_items[name] or not
|
||||
minetest.registered_items[name].groups[group] then
|
||||
return 0
|
||||
end
|
||||
return minetest.registered_items[name].groups[group]
|
||||
end
|
||||
|
||||
function minetest.get_node_group(name, group)
|
||||
return minetest.get_item_group(name, group)
|
||||
end
|
||||
|
||||
function minetest.string_to_pos(value)
|
||||
local p = {}
|
||||
p.x, p.y, p.z = string.match(value, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
|
||||
if p.x and p.y and p.z then
|
||||
p.x = tonumber(p.x)
|
||||
p.y = tonumber(p.y)
|
||||
p.z = tonumber(p.z)
|
||||
return p
|
||||
end
|
||||
local p = {}
|
||||
p.x, p.y, p.z = string.match(value, "^%( *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+) *%)$")
|
||||
if p.x and p.y and p.z then
|
||||
p.x = tonumber(p.x)
|
||||
p.y = tonumber(p.y)
|
||||
p.z = tonumber(p.z)
|
||||
return p
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
assert(minetest.string_to_pos("10.0, 5, -2").x == 10)
|
||||
assert(minetest.string_to_pos("( 10.0, 5, -2)").z == -2)
|
||||
assert(minetest.string_to_pos("asd, 5, -2)") == nil)
|
||||
|
||||
function minetest.setting_get_pos(name)
|
||||
local value = minetest.setting_get(name)
|
||||
if not value then
|
||||
return nil
|
||||
end
|
||||
return minetest.string_to_pos(value)
|
||||
end
|
||||
|
||||
94
builtin/misc_helpers.lua
Normal file
@@ -0,0 +1,94 @@
|
||||
-- Minetest: builtin/misc_helpers.lua
|
||||
|
||||
function basic_dump2(o)
|
||||
if type(o) == "number" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "string" then
|
||||
return string.format("%q", o)
|
||||
elseif type(o) == "boolean" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "function" then
|
||||
return "<function>"
|
||||
elseif type(o) == "userdata" then
|
||||
return "<userdata>"
|
||||
elseif type(o) == "nil" then
|
||||
return "nil"
|
||||
else
|
||||
error("cannot dump a " .. type(o))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dump2(o, name, dumped)
|
||||
name = name or "_"
|
||||
dumped = dumped or {}
|
||||
io.write(name, " = ")
|
||||
if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
|
||||
or type(o) == "function" or type(o) == "nil"
|
||||
or type(o) == "userdata" then
|
||||
io.write(basic_dump2(o), "\n")
|
||||
elseif type(o) == "table" then
|
||||
if dumped[o] then
|
||||
io.write(dumped[o], "\n")
|
||||
else
|
||||
dumped[o] = name
|
||||
io.write("{}\n") -- new table
|
||||
for k,v in pairs(o) do
|
||||
local fieldname = string.format("%s[%s]", name, basic_dump2(k))
|
||||
dump2(v, fieldname, dumped)
|
||||
end
|
||||
end
|
||||
else
|
||||
error("cannot dump a " .. type(o))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dump(o, dumped)
|
||||
dumped = dumped or {}
|
||||
if type(o) == "number" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "string" then
|
||||
return string.format("%q", o)
|
||||
elseif type(o) == "table" then
|
||||
if dumped[o] then
|
||||
return "<circular reference>"
|
||||
end
|
||||
dumped[o] = true
|
||||
local t = {}
|
||||
for k,v in pairs(o) do
|
||||
t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
|
||||
end
|
||||
return "{" .. table.concat(t, ", ") .. "}"
|
||||
elseif type(o) == "boolean" then
|
||||
return tostring(o)
|
||||
elseif type(o) == "function" then
|
||||
return "<function>"
|
||||
elseif type(o) == "userdata" then
|
||||
return "<userdata>"
|
||||
elseif type(o) == "nil" then
|
||||
return "nil"
|
||||
else
|
||||
error("cannot dump a " .. type(o))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function string:split(sep)
|
||||
local sep, fields = sep or ",", {}
|
||||
local pattern = string.format("([^%s]+)", sep)
|
||||
self:gsub(pattern, function(c) fields[#fields+1] = c end)
|
||||
return fields
|
||||
end
|
||||
|
||||
function string:trim()
|
||||
return (self:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
assert(string.trim("\n \t\tfoo bar\t ") == "foo bar")
|
||||
|
||||
function minetest.pos_to_string(pos)
|
||||
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
|
||||
end
|
||||
|
||||
|
||||
314
builtin/misc_register.lua
Normal file
@@ -0,0 +1,314 @@
|
||||
-- Minetest: builtin/misc_register.lua
|
||||
|
||||
--
|
||||
-- Make raw registration functions inaccessible to anyone except this file
|
||||
--
|
||||
|
||||
local register_item_raw = minetest.register_item_raw
|
||||
minetest.register_item_raw = nil
|
||||
|
||||
local register_alias_raw = minetest.register_alias_raw
|
||||
minetest.register_item_raw = nil
|
||||
|
||||
--
|
||||
-- Item / entity / ABM registration functions
|
||||
--
|
||||
|
||||
minetest.registered_abms = {}
|
||||
minetest.registered_entities = {}
|
||||
minetest.registered_items = {}
|
||||
minetest.registered_nodes = {}
|
||||
minetest.registered_craftitems = {}
|
||||
minetest.registered_tools = {}
|
||||
minetest.registered_aliases = {}
|
||||
|
||||
-- For tables that are indexed by item name:
|
||||
-- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
|
||||
local function set_alias_metatable(table)
|
||||
setmetatable(table, {
|
||||
__index = function(name)
|
||||
return rawget(table, minetest.registered_aliases[name])
|
||||
end
|
||||
})
|
||||
end
|
||||
set_alias_metatable(minetest.registered_items)
|
||||
set_alias_metatable(minetest.registered_nodes)
|
||||
set_alias_metatable(minetest.registered_craftitems)
|
||||
set_alias_metatable(minetest.registered_tools)
|
||||
|
||||
-- These item names may not be used because they would interfere
|
||||
-- with legacy itemstrings
|
||||
local forbidden_item_names = {
|
||||
MaterialItem = true,
|
||||
MaterialItem2 = true,
|
||||
MaterialItem3 = true,
|
||||
NodeItem = true,
|
||||
node = true,
|
||||
CraftItem = true,
|
||||
craft = true,
|
||||
MBOItem = true,
|
||||
ToolItem = true,
|
||||
tool = true,
|
||||
}
|
||||
|
||||
local function check_modname_prefix(name)
|
||||
if name:sub(1,1) == ":" then
|
||||
-- Escape the modname prefix enforcement mechanism
|
||||
return name:sub(2)
|
||||
else
|
||||
-- Modname prefix enforcement
|
||||
local expected_prefix = minetest.get_current_modname() .. ":"
|
||||
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||
"\"modname:\" or \":\" prefix required")
|
||||
end
|
||||
local subname = name:sub(#expected_prefix+1)
|
||||
if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then
|
||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||
"contains unallowed characters")
|
||||
end
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.register_abm(spec)
|
||||
-- Add to minetest.registered_abms
|
||||
minetest.registered_abms[#minetest.registered_abms+1] = spec
|
||||
end
|
||||
|
||||
function minetest.register_entity(name, prototype)
|
||||
-- Check name
|
||||
if name == nil then
|
||||
error("Unable to register entity: Name is nil")
|
||||
end
|
||||
name = check_modname_prefix(tostring(name))
|
||||
|
||||
prototype.name = name
|
||||
prototype.__index = prototype -- so that it can be used as a metatable
|
||||
|
||||
-- Add to minetest.registered_entities
|
||||
minetest.registered_entities[name] = prototype
|
||||
end
|
||||
|
||||
function minetest.register_item(name, itemdef)
|
||||
-- Check name
|
||||
if name == nil then
|
||||
error("Unable to register item: Name is nil")
|
||||
end
|
||||
name = check_modname_prefix(tostring(name))
|
||||
if forbidden_item_names[name] then
|
||||
error("Unable to register item: Name is forbidden: " .. name)
|
||||
end
|
||||
itemdef.name = name
|
||||
|
||||
-- Apply defaults and add to registered_* table
|
||||
if itemdef.type == "node" then
|
||||
setmetatable(itemdef, {__index = minetest.nodedef_default})
|
||||
minetest.registered_nodes[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "craft" then
|
||||
setmetatable(itemdef, {__index = minetest.craftitemdef_default})
|
||||
minetest.registered_craftitems[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "tool" then
|
||||
setmetatable(itemdef, {__index = minetest.tooldef_default})
|
||||
minetest.registered_tools[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "none" then
|
||||
setmetatable(itemdef, {__index = minetest.noneitemdef_default})
|
||||
else
|
||||
error("Unable to register item: Type is invalid: " .. dump(itemdef))
|
||||
end
|
||||
|
||||
-- Flowing liquid uses param2
|
||||
if itemdef.type == "node" and itemdef.liquidtype == "flowing" then
|
||||
itemdef.paramtype2 = "flowingliquid"
|
||||
end
|
||||
|
||||
-- BEGIN Legacy stuff
|
||||
if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
|
||||
minetest.register_craft({
|
||||
type="cooking",
|
||||
output=itemdef.cookresult_itemstring,
|
||||
recipe=itemdef.name,
|
||||
cooktime=itemdef.furnace_cooktime
|
||||
})
|
||||
end
|
||||
if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then
|
||||
minetest.register_craft({
|
||||
type="fuel",
|
||||
recipe=itemdef.name,
|
||||
burntime=itemdef.furnace_burntime
|
||||
})
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
-- Disable all further modifications
|
||||
getmetatable(itemdef).__newindex = {}
|
||||
|
||||
--minetest.log("Registering item: " .. itemdef.name)
|
||||
minetest.registered_items[itemdef.name] = itemdef
|
||||
minetest.registered_aliases[itemdef.name] = nil
|
||||
register_item_raw(itemdef)
|
||||
end
|
||||
|
||||
function minetest.register_node(name, nodedef)
|
||||
nodedef.type = "node"
|
||||
minetest.register_item(name, nodedef)
|
||||
end
|
||||
|
||||
function minetest.register_craftitem(name, craftitemdef)
|
||||
craftitemdef.type = "craft"
|
||||
|
||||
-- BEGIN Legacy stuff
|
||||
if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
|
||||
craftitemdef.inventory_image = craftitemdef.image
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
minetest.register_item(name, craftitemdef)
|
||||
end
|
||||
|
||||
function minetest.register_tool(name, tooldef)
|
||||
tooldef.type = "tool"
|
||||
tooldef.stack_max = 1
|
||||
|
||||
-- BEGIN Legacy stuff
|
||||
if tooldef.inventory_image == nil and tooldef.image ~= nil then
|
||||
tooldef.inventory_image = tooldef.image
|
||||
end
|
||||
if tooldef.tool_capabilities == nil and
|
||||
(tooldef.full_punch_interval ~= nil or
|
||||
tooldef.basetime ~= nil or
|
||||
tooldef.dt_weight ~= nil or
|
||||
tooldef.dt_crackiness ~= nil or
|
||||
tooldef.dt_crumbliness ~= nil or
|
||||
tooldef.dt_cuttability ~= nil or
|
||||
tooldef.basedurability ~= nil or
|
||||
tooldef.dd_weight ~= nil or
|
||||
tooldef.dd_crackiness ~= nil or
|
||||
tooldef.dd_crumbliness ~= nil or
|
||||
tooldef.dd_cuttability ~= nil) then
|
||||
tooldef.tool_capabilities = {
|
||||
full_punch_interval = tooldef.full_punch_interval,
|
||||
basetime = tooldef.basetime,
|
||||
dt_weight = tooldef.dt_weight,
|
||||
dt_crackiness = tooldef.dt_crackiness,
|
||||
dt_crumbliness = tooldef.dt_crumbliness,
|
||||
dt_cuttability = tooldef.dt_cuttability,
|
||||
basedurability = tooldef.basedurability,
|
||||
dd_weight = tooldef.dd_weight,
|
||||
dd_crackiness = tooldef.dd_crackiness,
|
||||
dd_crumbliness = tooldef.dd_crumbliness,
|
||||
dd_cuttability = tooldef.dd_cuttability,
|
||||
}
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
minetest.register_item(name, tooldef)
|
||||
end
|
||||
|
||||
function minetest.register_alias(name, convert_to)
|
||||
if forbidden_item_names[name] then
|
||||
error("Unable to register alias: Name is forbidden: " .. name)
|
||||
end
|
||||
if minetest.registered_items[name] ~= nil then
|
||||
minetest.log("WARNING: Not registering alias, item with same name" ..
|
||||
" is already defined: " .. name .. " -> " .. convert_to)
|
||||
else
|
||||
--minetest.log("Registering alias: " .. name .. " -> " .. convert_to)
|
||||
minetest.registered_aliases[name] = convert_to
|
||||
register_alias_raw(name, convert_to)
|
||||
end
|
||||
end
|
||||
|
||||
-- Alias the forbidden item names to "" so they can't be
|
||||
-- created via itemstrings (e.g. /give)
|
||||
local name
|
||||
for name in pairs(forbidden_item_names) do
|
||||
minetest.registered_aliases[name] = ""
|
||||
register_alias_raw(name, "")
|
||||
end
|
||||
|
||||
|
||||
-- Deprecated:
|
||||
-- Aliases for minetest.register_alias (how ironic...)
|
||||
--minetest.alias_node = minetest.register_alias
|
||||
--minetest.alias_tool = minetest.register_alias
|
||||
--minetest.alias_craftitem = minetest.register_alias
|
||||
|
||||
--
|
||||
-- Built-in node definitions. Also defined in C.
|
||||
--
|
||||
|
||||
minetest.register_item(":unknown", {
|
||||
type = "none",
|
||||
description = "Unknown Item",
|
||||
inventory_image = "unknown_item.png",
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node(":air", {
|
||||
description = "Air (you hacker you!)",
|
||||
inventory_image = "unknown_block.png",
|
||||
wield_image = "unknown_block.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
buildable_to = true,
|
||||
air_equivalent = true,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node(":ignore", {
|
||||
description = "Ignore (you hacker you!)",
|
||||
inventory_image = "unknown_block.png",
|
||||
wield_image = "unknown_block.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "none",
|
||||
sunlight_propagates = false,
|
||||
walkable = false,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
buildable_to = true, -- A way to remove accidentally placed ignores
|
||||
air_equivalent = true,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
-- The hand (bare definition)
|
||||
minetest.register_item(":", {
|
||||
type = "none",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
--
|
||||
-- Callback registration
|
||||
--
|
||||
|
||||
local function make_registration()
|
||||
local t = {}
|
||||
local registerfunc = function(func) table.insert(t, func) end
|
||||
return t, registerfunc
|
||||
end
|
||||
|
||||
local function make_registration_reverse()
|
||||
local t = {}
|
||||
local registerfunc = function(func) table.insert(t, 1, func) end
|
||||
return t, registerfunc
|
||||
end
|
||||
|
||||
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
|
||||
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
|
||||
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
|
||||
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
|
||||
minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
|
||||
minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
|
||||
minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
|
||||
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
|
||||
minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
|
||||
minetest.registered_on_joinplayers, minetest.register_on_joinplayer = make_registration()
|
||||
minetest.registered_on_leaveplayers, minetest.register_on_leaveplayer = make_registration()
|
||||
minetest.registered_on_player_receive_fields, minetest.register_on_player_receive_fields = make_registration_reverse()
|
||||
|
||||
48
builtin/privileges.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
-- Minetest: builtin/privileges.lua
|
||||
|
||||
--
|
||||
-- Privileges
|
||||
--
|
||||
|
||||
minetest.registered_privileges = {}
|
||||
|
||||
function minetest.register_privilege(name, param)
|
||||
local function fill_defaults(def)
|
||||
if def.give_to_singleplayer == nil then
|
||||
def.give_to_singleplayer = true
|
||||
end
|
||||
if def.description == nil then
|
||||
def.description = "(no description)"
|
||||
end
|
||||
end
|
||||
local def = {}
|
||||
if type(param) == "table" then
|
||||
def = param
|
||||
else
|
||||
def = {description = param}
|
||||
end
|
||||
fill_defaults(def)
|
||||
minetest.registered_privileges[name] = def
|
||||
end
|
||||
|
||||
minetest.register_privilege("interact", "Can interact with things and modify the world")
|
||||
minetest.register_privilege("teleport", "Can use /teleport command")
|
||||
minetest.register_privilege("bring", "Can teleport other players")
|
||||
minetest.register_privilege("settime", "Can use /time")
|
||||
minetest.register_privilege("privs", "Can modify privileges")
|
||||
minetest.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges")
|
||||
minetest.register_privilege("server", "Can do server maintenance stuff")
|
||||
minetest.register_privilege("shout", "Can speak in chat")
|
||||
minetest.register_privilege("ban", "Can ban and unban players")
|
||||
minetest.register_privilege("give", "Can use /give and /giveme")
|
||||
minetest.register_privilege("password", "Can use /setpassword and /clearpassword")
|
||||
minetest.register_privilege("fly", {
|
||||
description = "Can fly using the free_move mode",
|
||||
give_to_singleplayer = false,
|
||||
})
|
||||
minetest.register_privilege("fast", {
|
||||
description = "Can walk fast using the fast_move mode",
|
||||
give_to_singleplayer = false,
|
||||
})
|
||||
minetest.register_privilege("rollback", "Can use the rollback functionality")
|
||||
|
||||
207
builtin/serialize.lua
Normal file
@@ -0,0 +1,207 @@
|
||||
-- Minetest: builtin/serialize.lua
|
||||
|
||||
-- https://github.com/fab13n/metalua/blob/no-dll/src/lib/serialize.lua
|
||||
-- Copyright (c) 2006-2997 Fabien Fleutot <metalua@gmail.com>
|
||||
-- License: MIT
|
||||
--------------------------------------------------------------------------------
|
||||
-- Serialize an object into a source code string. This string, when passed as
|
||||
-- an argument to deserialize(), returns an object structurally identical
|
||||
-- to the original one. The following are currently supported:
|
||||
-- * strings, numbers, booleans, nil
|
||||
-- * tables thereof. Tables can have shared part, but can't be recursive yet.
|
||||
-- Caveat: metatables and environments aren't saved.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local no_identity = { number=1, boolean=1, string=1, ['nil']=1 }
|
||||
|
||||
function minetest.serialize(x)
|
||||
|
||||
local gensym_max = 0 -- index of the gensym() symbol generator
|
||||
local seen_once = { } -- element->true set of elements seen exactly once in the table
|
||||
local multiple = { } -- element->varname set of elements seen more than once
|
||||
local nested = { } -- transient, set of elements currently being traversed
|
||||
local nest_points = { }
|
||||
local nest_patches = { }
|
||||
|
||||
local function gensym()
|
||||
gensym_max = gensym_max + 1 ; return gensym_max
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- nest_points are places where a table appears within itself, directly or not.
|
||||
-- for instance, all of these chunks create nest points in table x:
|
||||
-- "x = { }; x[x] = 1", "x = { }; x[1] = x", "x = { }; x[1] = { y = { x } }".
|
||||
-- To handle those, two tables are created by mark_nest_point:
|
||||
-- * nest_points [parent] associates all keys and values in table parent which
|
||||
-- create a nest_point with boolean `true'
|
||||
-- * nest_patches contain a list of { parent, key, value } tuples creating
|
||||
-- a nest point. They're all dumped after all the other table operations
|
||||
-- have been performed.
|
||||
--
|
||||
-- mark_nest_point (p, k, v) fills tables nest_points and nest_patches with
|
||||
-- informations required to remember that key/value (k,v) create a nest point
|
||||
-- in table parent. It also marks `parent' as occuring multiple times, since
|
||||
-- several references to it will be required in order to patch the nest
|
||||
-- points.
|
||||
-----------------------------------------------------------------------------
|
||||
local function mark_nest_point (parent, k, v)
|
||||
local nk, nv = nested[k], nested[v]
|
||||
assert (not nk or seen_once[k] or multiple[k])
|
||||
assert (not nv or seen_once[v] or multiple[v])
|
||||
local mode = (nk and nv and "kv") or (nk and "k") or ("v")
|
||||
local parent_np = nest_points [parent]
|
||||
local pair = { k, v }
|
||||
if not parent_np then parent_np = { }; nest_points [parent] = parent_np end
|
||||
parent_np [k], parent_np [v] = nk, nv
|
||||
table.insert (nest_patches, { parent, k, v })
|
||||
seen_once [parent], multiple [parent] = nil, true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- First pass, list the tables and functions which appear more than once in x
|
||||
-----------------------------------------------------------------------------
|
||||
local function mark_multiple_occurences (x)
|
||||
if no_identity [type(x)] then return end
|
||||
if seen_once [x] then seen_once [x], multiple [x] = nil, true
|
||||
elseif multiple [x] then -- pass
|
||||
else seen_once [x] = true end
|
||||
|
||||
if type (x) == 'table' then
|
||||
nested [x] = true
|
||||
for k, v in pairs (x) do
|
||||
if nested[k] or nested[v] then mark_nest_point (x, k, v) else
|
||||
mark_multiple_occurences (k)
|
||||
mark_multiple_occurences (v)
|
||||
end
|
||||
end
|
||||
nested [x] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local dumped = { } -- multiply occuring values already dumped in localdefs
|
||||
local localdefs = { } -- already dumped local definitions as source code lines
|
||||
|
||||
-- mutually recursive functions:
|
||||
local dump_val, dump_or_ref_val
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- if x occurs multiple times, dump the local var rather than the
|
||||
-- value. If it's the first time it's dumped, also dump the content
|
||||
-- in localdefs.
|
||||
--------------------------------------------------------------------
|
||||
function dump_or_ref_val (x)
|
||||
if nested[x] then return 'false' end -- placeholder for recursive reference
|
||||
if not multiple[x] then return dump_val (x) end
|
||||
local var = dumped [x]
|
||||
if var then return "_[" .. var .. "]" end -- already referenced
|
||||
local val = dump_val(x) -- first occurence, create and register reference
|
||||
var = gensym()
|
||||
table.insert(localdefs, "_["..var.."]="..val)
|
||||
dumped [x] = var
|
||||
return "_[" .. var .. "]"
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Second pass, dump the object; subparts occuring multiple times are dumped
|
||||
-- in local variables which can be referenced multiple times;
|
||||
-- care is taken to dump locla vars in asensible order.
|
||||
-----------------------------------------------------------------------------
|
||||
function dump_val(x)
|
||||
local t = type(x)
|
||||
if x==nil then return 'nil'
|
||||
elseif t=="number" then return tostring(x)
|
||||
elseif t=="string" then return string.format("%q", x)
|
||||
elseif t=="boolean" then return x and "true" or "false"
|
||||
elseif t=="table" then
|
||||
local acc = { }
|
||||
local idx_dumped = { }
|
||||
local np = nest_points [x]
|
||||
for i, v in ipairs(x) do
|
||||
if np and np[v] then
|
||||
table.insert (acc, 'false') -- placeholder
|
||||
else
|
||||
table.insert (acc, dump_or_ref_val(v))
|
||||
end
|
||||
idx_dumped[i] = true
|
||||
end
|
||||
for k, v in pairs(x) do
|
||||
if np and (np[k] or np[v]) then
|
||||
--check_multiple(k); check_multiple(v) -- force dumps in localdefs
|
||||
elseif not idx_dumped[k] then
|
||||
table.insert (acc, "[" .. dump_or_ref_val(k) .. "] = " .. dump_or_ref_val(v))
|
||||
end
|
||||
end
|
||||
return "{ "..table.concat(acc,", ").." }"
|
||||
else
|
||||
error ("Can't serialize data of type "..t)
|
||||
end
|
||||
end
|
||||
|
||||
local function dump_nest_patches()
|
||||
for _, entry in ipairs(nest_patches) do
|
||||
local p, k, v = unpack (entry)
|
||||
assert (multiple[p])
|
||||
local set = dump_or_ref_val (p) .. "[" .. dump_or_ref_val (k) .. "] = " ..
|
||||
dump_or_ref_val (v) .. " -- rec "
|
||||
table.insert (localdefs, set)
|
||||
end
|
||||
end
|
||||
|
||||
mark_multiple_occurences (x)
|
||||
local toplevel = dump_or_ref_val (x)
|
||||
dump_nest_patches()
|
||||
|
||||
if next (localdefs) then
|
||||
return "local _={ }\n" ..
|
||||
table.concat (localdefs, "\n") ..
|
||||
"\nreturn " .. toplevel
|
||||
else
|
||||
return "return " .. toplevel
|
||||
end
|
||||
end
|
||||
|
||||
-- Deserialization.
|
||||
-- http://stackoverflow.com/questions/5958818/loading-serialized-data-into-a-table
|
||||
--
|
||||
|
||||
local function stringtotable(sdata)
|
||||
if sdata:byte(1) == 27 then return nil, "binary bytecode prohibited" end
|
||||
local f, message = assert(loadstring(sdata))
|
||||
if not f then return nil, message end
|
||||
setfenv(f, table)
|
||||
return f()
|
||||
end
|
||||
|
||||
function minetest.deserialize(sdata)
|
||||
local table = {}
|
||||
local okay,results = pcall(stringtotable, sdata)
|
||||
if okay then
|
||||
return results
|
||||
end
|
||||
print('error:'.. results)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Run some unit tests
|
||||
local function unit_test()
|
||||
function unitTest(name, success)
|
||||
if not success then
|
||||
error(name .. ': failed')
|
||||
end
|
||||
end
|
||||
|
||||
unittest_input = {cat={sound="nyan", speed=400}, dog={sound="woof"}}
|
||||
unittest_output = minetest.deserialize(minetest.serialize(unittest_input))
|
||||
|
||||
unitTest("test 1a", unittest_input.cat.sound == unittest_output.cat.sound)
|
||||
unitTest("test 1b", unittest_input.cat.speed == unittest_output.cat.speed)
|
||||
unitTest("test 1c", unittest_input.dog.sound == unittest_output.dog.sound)
|
||||
|
||||
unittest_input = {escapechars="\n\r\t\v\\\"\'\[\]", noneuropean="θשׁ٩∂"}
|
||||
unittest_output = minetest.deserialize(minetest.serialize(unittest_input))
|
||||
unitTest("test 3a", unittest_input.escapechars == unittest_output.escapechars)
|
||||
unitTest("test 3b", unittest_input.noneuropean == unittest_output.noneuropean)
|
||||
end
|
||||
unit_test() -- Run it
|
||||
unit_test = nil -- Hide it
|
||||
|
||||
33
builtin/static_spawn.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
-- Minetest: builtin/static_spawn.lua
|
||||
|
||||
local function warn_invalid_static_spawnpoint()
|
||||
if minetest.setting_get("static_spawnpoint") and
|
||||
not minetest.setting_get_pos("static_spawnpoint") then
|
||||
minetest.log('error', "The static_spawnpoint setting is invalid: \""..
|
||||
minetest.setting_get("static_spawnpoint").."\"")
|
||||
end
|
||||
end
|
||||
|
||||
warn_invalid_static_spawnpoint()
|
||||
|
||||
local function put_player_in_spawn(obj)
|
||||
warn_invalid_static_spawnpoint()
|
||||
local static_spawnpoint = minetest.setting_get_pos("static_spawnpoint")
|
||||
if not static_spawnpoint then
|
||||
return false
|
||||
end
|
||||
minetest.log('action', "Moving "..obj:get_player_name()..
|
||||
" to static spawnpoint at "..
|
||||
minetest.pos_to_string(static_spawnpoint))
|
||||
obj:setpos(static_spawnpoint)
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_on_newplayer(function(obj)
|
||||
put_player_in_spawn(obj)
|
||||
end)
|
||||
|
||||
minetest.register_on_respawnplayer(function(obj)
|
||||
return put_player_in_spawn(obj)
|
||||
end)
|
||||
|
||||
1008
doc/lua_api.txt
@@ -1,13 +1,16 @@
|
||||
=================================================
|
||||
Minetest World Format used as of 0.4.dev-20120322
|
||||
=================================================
|
||||
=============================
|
||||
Minetest World Format 22...25
|
||||
=============================
|
||||
|
||||
This applies to a world format carrying the block serialization version 22
|
||||
which is used at least in version 0.4.dev-20120322.
|
||||
This applies to a world format carrying the block serialization version
|
||||
22...25, used at least in
|
||||
- 0.4.dev-20120322 ... 0.4.dev-20120606 (22...23)
|
||||
- 0.4.0 (23)
|
||||
- 24 was never released as stable and existed for ~2 days
|
||||
|
||||
The block serialization version used is 22. It does not fully specify every
|
||||
aspect of this format; if compliance with this format is to be checked, it
|
||||
needs to be done by detecting if the files and data indeed follows it.
|
||||
The block serialization version does not fully specify every aspect of this
|
||||
format; if compliance with this format is to be checked, it needs to be
|
||||
done by detecting if the files and data indeed follows it.
|
||||
|
||||
Legacy stuff
|
||||
=============
|
||||
@@ -20,8 +23,8 @@ Files
|
||||
Everything is contained in a directory, the name of which is freeform, but
|
||||
often serves as the name of the world.
|
||||
|
||||
Currently the authentication and ban data is stored on a per-world basis. It
|
||||
can be copied over from an old world to a newly created world.
|
||||
Currently the authentication and ban data is stored on a per-world basis.
|
||||
It can be copied over from an old world to a newly created world.
|
||||
|
||||
World
|
||||
|-- auth.txt ----- Authentication data
|
||||
@@ -260,17 +263,26 @@ u8 flags
|
||||
|
||||
u8 content_width
|
||||
- Number of bytes in the content (param0) fields of nodes
|
||||
- Always 1
|
||||
if map format version <= 23:
|
||||
- Always 1
|
||||
if map format version >= 24:
|
||||
- Always 2
|
||||
|
||||
u8 params_width
|
||||
- Number of bytes used for parameters per node
|
||||
- Always 2
|
||||
|
||||
zlib-compressed node data:
|
||||
- content:
|
||||
u8[4096]: param0 fields
|
||||
u8[4096]: param1 fields
|
||||
u8[4096]: param2 fields
|
||||
if content_width == 1:
|
||||
- content:
|
||||
u8[4096]: param0 fields
|
||||
u8[4096]: param1 fields
|
||||
u8[4096]: param2 fields
|
||||
if content_width == 2:
|
||||
- content:
|
||||
u16[4096]: param0 fields
|
||||
u8[4096]: param1 fields
|
||||
u8[4096]: param2 fields
|
||||
- The location of a node in each of those arrays is (z*16*16 + y*16 + x).
|
||||
|
||||
zlib-compressed node metadata list
|
||||
@@ -283,9 +295,19 @@ zlib-compressed node metadata list
|
||||
u16 content_size
|
||||
u8[content_size] (content of metadata)
|
||||
|
||||
u16 mapblockobject_count
|
||||
- Always 0
|
||||
- Should be removed in version 23 (TODO)
|
||||
- Node timers
|
||||
if map format version == 23:
|
||||
u8 unused version (always 0)
|
||||
if map format version == 24: (NOTE: Not released as stable)
|
||||
u8 nodetimer_version
|
||||
if nodetimer_version == 0:
|
||||
(nothing else)
|
||||
if nodetimer_version == 1:
|
||||
u16 num_of_timers
|
||||
foreach num_of_timers:
|
||||
u16 timer position (z*16*16 + y*16 + x)
|
||||
s32 timeout*1000
|
||||
s32 elapsed*1000
|
||||
|
||||
u8 static object version:
|
||||
- Always 0
|
||||
@@ -315,17 +337,29 @@ foreach num_name_id_mappings
|
||||
u16 name_len
|
||||
u8[name_len] name
|
||||
|
||||
- Node timers
|
||||
if map format version == 25:
|
||||
u8 length of the data of a single timer (always 2+4+4=10)
|
||||
u16 num_of_timers
|
||||
foreach num_of_timers:
|
||||
u16 timer position (z*16*16 + y*16 + x)
|
||||
s32 timeout*1000
|
||||
s32 elapsed*1000
|
||||
|
||||
EOF.
|
||||
|
||||
Format of nodes
|
||||
----------------
|
||||
A node is composed of the u8 fields param0, param1 and param2.
|
||||
|
||||
The content id of a node is determined as so:
|
||||
- If param0 < 0x80,
|
||||
content_id = param0
|
||||
- Otherwise
|
||||
content_id = (param0<<4) + (param2>>4)
|
||||
if map format version <= 23:
|
||||
The content id of a node is determined as so:
|
||||
- If param0 < 0x80,
|
||||
content_id = param0
|
||||
- Otherwise
|
||||
content_id = (param0<<4) + (param2>>4)
|
||||
if map format version >= 24:
|
||||
The content id of a node is param0.
|
||||
|
||||
The purpose of param1 and param2 depend on the definition of the node.
|
||||
|
||||
|
||||
@@ -90,6 +90,6 @@ bucket.register_liquid(
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "default:bucket_lava",
|
||||
recipe = "bucket:bucket_lava",
|
||||
burntime = 60,
|
||||
})
|
||||
|
||||
114
games/minimal/mods/default/mapgen.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
-- minetest/default/mapgen.lua
|
||||
|
||||
--
|
||||
-- Aliases for map generator outputs
|
||||
--
|
||||
|
||||
minetest.register_alias("mapgen_air", "air")
|
||||
minetest.register_alias("mapgen_stone", "default:stone")
|
||||
minetest.register_alias("mapgen_tree", "default:tree")
|
||||
minetest.register_alias("mapgen_leaves", "default:leaves")
|
||||
minetest.register_alias("mapgen_apple", "default:apple")
|
||||
minetest.register_alias("mapgen_water_source", "default:water_source")
|
||||
minetest.register_alias("mapgen_dirt", "default:dirt")
|
||||
minetest.register_alias("mapgen_sand", "default:sand")
|
||||
minetest.register_alias("mapgen_gravel", "default:gravel")
|
||||
minetest.register_alias("mapgen_clay", "default:clay")
|
||||
minetest.register_alias("mapgen_lava_source", "default:lava_source")
|
||||
minetest.register_alias("mapgen_cobble", "default:cobble")
|
||||
minetest.register_alias("mapgen_mossycobble", "default:mossycobble")
|
||||
minetest.register_alias("mapgen_dirt_with_grass", "default:dirt_with_grass")
|
||||
minetest.register_alias("mapgen_junglegrass", "default:junglegrass")
|
||||
minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal")
|
||||
minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron")
|
||||
minetest.register_alias("mapgen_mese", "default:mese")
|
||||
|
||||
--
|
||||
-- Ore generation
|
||||
--
|
||||
|
||||
local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max)
|
||||
if maxp.y < height_min or minp.y > height_max then
|
||||
return
|
||||
end
|
||||
local y_min = math.max(minp.y, height_min)
|
||||
local y_max = math.min(maxp.y, height_max)
|
||||
local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1)
|
||||
local pr = PseudoRandom(seed)
|
||||
local num_chunks = math.floor(chunks_per_volume * volume)
|
||||
local chunk_size = 3
|
||||
if ore_per_chunk <= 4 then
|
||||
chunk_size = 2
|
||||
end
|
||||
local inverse_chance = math.floor(chunk_size*chunk_size*chunk_size / ore_per_chunk)
|
||||
--print("generate_ore num_chunks: "..dump(num_chunks))
|
||||
for i=1,num_chunks do
|
||||
local y0 = pr:next(y_min, y_max-chunk_size+1)
|
||||
if y0 >= height_min and y0 <= height_max then
|
||||
local x0 = pr:next(minp.x, maxp.x-chunk_size+1)
|
||||
local z0 = pr:next(minp.z, maxp.z-chunk_size+1)
|
||||
local p0 = {x=x0, y=y0, z=z0}
|
||||
for x1=0,chunk_size-1 do
|
||||
for y1=0,chunk_size-1 do
|
||||
for z1=0,chunk_size-1 do
|
||||
if pr:next(1,inverse_chance) == 1 then
|
||||
local x2 = x0+x1
|
||||
local y2 = y0+y1
|
||||
local z2 = z0+z1
|
||||
local p2 = {x=x2, y=y2, z=z2}
|
||||
if minetest.env:get_node(p2).name == wherein then
|
||||
minetest.env:set_node(p2, {name=name})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--print("generate_ore done")
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
generate_ore("default:stone_with_coal", "default:stone", minp, maxp, seed, 1/8/8/8, 5, -31000, 64)
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+1, 1/16/16/16, 5, -5, 7)
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+2, 1/12/12/12, 5, -16, -5)
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+3, 1/9/9/9, 5, -31000, -17)
|
||||
-- Generate clay
|
||||
if maxp.y >= 2 and minp.y <= 0 then
|
||||
-- Assume X and Z lengths are equal
|
||||
local divlen = 4
|
||||
local divs = (maxp.x-minp.x)/divlen+1;
|
||||
for divx=0+1,divs-1-1 do
|
||||
for divz=0+1,divs-1-1 do
|
||||
local cx = minp.x + math.floor((divx+0.5)*divlen)
|
||||
local cz = minp.z + math.floor((divz+0.5)*divlen)
|
||||
if minetest.env:get_node({x=cx,y=1,z=cz}).name == "default:water_source" and
|
||||
minetest.env:get_node({x=cx,y=0,z=cz}).name == "default:sand" then
|
||||
local is_shallow = true
|
||||
local num_water_around = 0
|
||||
if minetest.env:get_node({x=cx-divlen*2,y=1,z=cz+0}).name == "default:water_source" then
|
||||
num_water_around = num_water_around + 1 end
|
||||
if minetest.env:get_node({x=cx+divlen*2,y=1,z=cz+0}).name == "default:water_source" then
|
||||
num_water_around = num_water_around + 1 end
|
||||
if minetest.env:get_node({x=cx+0,y=1,z=cz-divlen*2}).name == "default:water_source" then
|
||||
num_water_around = num_water_around + 1 end
|
||||
if minetest.env:get_node({x=cx+0,y=1,z=cz+divlen*2}).name == "default:water_source" then
|
||||
num_water_around = num_water_around + 1 end
|
||||
if num_water_around >= 2 then
|
||||
is_shallow = false
|
||||
end
|
||||
if is_shallow then
|
||||
for x1=-divlen,divlen do
|
||||
for z1=-divlen,divlen do
|
||||
if minetest.env:get_node({x=cx+x1,y=0,z=cz+z1}).name == "default:sand" then
|
||||
minetest.env:set_node({x=cx+x1,y=0,z=cz+z1}, {name="default:clay"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
BIN
games/minimal/mods/default/sounds/default_grass_footstep.1.ogg
Normal file
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
games/minimal/mods/default/textures/crack_anylength.png
Normal file
|
After Width: | Height: | Size: 367 B |
BIN
games/minimal/mods/default/textures/default_furnace_fire_bg.png
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
games/minimal/mods/default/textures/default_furnace_fire_fg.png
Normal file
|
After Width: | Height: | Size: 865 B |
|
After Width: | Height: | Size: 376 B |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
@@ -6,38 +6,59 @@
|
||||
|
||||
experimental = {}
|
||||
|
||||
timers_to_add = {}
|
||||
timers = {}
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for indes, timer in ipairs(timers_to_add) do
|
||||
table.insert(timers, timer)
|
||||
end
|
||||
timers_to_add = {}
|
||||
for index, timer in ipairs(timers) do
|
||||
timer.time = timer.time - dtime
|
||||
if timer.time <= 0 then
|
||||
timer.func()
|
||||
timers[index] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
after = function(time, func)
|
||||
table.insert(timers_to_add, {time=time, func=func})
|
||||
function experimental.print_to_everything(msg)
|
||||
minetest.log("action", msg)
|
||||
minetest.chat_send_all(msg)
|
||||
end
|
||||
|
||||
--[[
|
||||
experimental.player_visual_index = 0
|
||||
function switch_player_visual()
|
||||
for _, obj in pairs(minetest.get_connected_players()) do
|
||||
if experimental.player_visual_index == 0 then
|
||||
obj:set_properties({visual="upright_sprite"})
|
||||
else
|
||||
obj:set_properties({visual="cube"})
|
||||
end
|
||||
end
|
||||
experimental.player_visual_index = (experimental.player_visual_index + 1) % 2
|
||||
minetest.after(1.0, switch_player_visual)
|
||||
end
|
||||
minetest.after(1.0, switch_player_visual)
|
||||
]]
|
||||
|
||||
minetest.register_node("experimental:soundblock", {
|
||||
tile_images = {"unknown_block.png", "default_tnt_bottom.png",
|
||||
"default_tnt_side.png", "default_tnt_side.png",
|
||||
"default_tnt_side.png", "default_tnt_side.png"},
|
||||
inventory_image = minetest.inventorycube("unknown_block.png",
|
||||
"default_tnt_side.png", "default_tnt_side.png"),
|
||||
groups = {dig_immediate=3},
|
||||
})
|
||||
|
||||
minetest.register_alias("sb", "experimental:soundblock")
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"experimental:soundblock"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(p0, node, _, _)
|
||||
minetest.sound_play("default_grass_footstep", {pos=p0, gain=0.5})
|
||||
end,
|
||||
})
|
||||
|
||||
--[[
|
||||
stepsound = -1
|
||||
function test_sound()
|
||||
print("test_sound")
|
||||
stepsound = minetest.sound_play("default_grass_footstep", {gain=1.0})
|
||||
after(2.0, test_sound)
|
||||
--after(0.1, test_sound_stop)
|
||||
minetest.after(2.0, test_sound)
|
||||
--minetest.after(0.1, test_sound_stop)
|
||||
end
|
||||
function test_sound_stop()
|
||||
print("test_sound_stop")
|
||||
minetest.sound_stop(stepsound)
|
||||
after(2.0, test_sound)
|
||||
minetest.after(2.0, test_sound)
|
||||
end
|
||||
test_sound()
|
||||
--]]
|
||||
@@ -81,235 +102,10 @@ function on_step(dtime)
|
||||
end
|
||||
minetest.register_globalstep(on_step)
|
||||
|
||||
-- An example furnace-thing implemented in Lua
|
||||
|
||||
--[[
|
||||
minetest.register_node("experimental:luafurnace", {
|
||||
tile_images = {"default_lava.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_front.png"},
|
||||
--inventory_image = "furnace_front.png",
|
||||
inventory_image = minetest.inventorycube("default_furnace_front.png"),
|
||||
paramtype = "facedir_simple",
|
||||
metadata_name = "generic",
|
||||
material = minetest.digprop_stonelike(3.0),
|
||||
})
|
||||
|
||||
minetest.register_on_placenode(function(pos, newnode, placer)
|
||||
if newnode.name == "experimental:luafurnace" then
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
meta:inventory_set_list("fuel", {""})
|
||||
meta:inventory_set_list("src", {""})
|
||||
meta:inventory_set_list("dst", {"","","",""})
|
||||
meta:set_inventory_draw_spec(
|
||||
"invsize[8,9;]"
|
||||
.."list[current_name;fuel;2,3;1,1;]"
|
||||
.."list[current_name;src;2,1;1,1;]"
|
||||
.."list[current_name;dst;5,1;2,2;]"
|
||||
.."list[current_player;main;0,5;8,4;]"
|
||||
)
|
||||
|
||||
local total_cooked = 0;
|
||||
meta:set_string("total_cooked", total_cooked)
|
||||
meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"experimental:luafurnace"},
|
||||
interval = 1.0,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
for i, name in ipairs({
|
||||
"fuel_totaltime",
|
||||
"fuel_time",
|
||||
"src_totaltime",
|
||||
"src_time"
|
||||
}) do
|
||||
if not meta:get_string(name) then
|
||||
meta:set_string(name, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
local fuelitem = inv:get_stack("fuel", 1):peek_item()
|
||||
local srcitem = inv:get_stack("src", 1):peek_item()
|
||||
--print("fuelitem="..dump(fuelitem))
|
||||
--print("srcitem="..dump(srcitem))
|
||||
|
||||
local was_active = false
|
||||
|
||||
local src_cooktime = -1
|
||||
local result_stackstring = nil
|
||||
|
||||
if srcitem then
|
||||
local prop = get_item_definition(srcitem)
|
||||
if prop and prop.cookresult_itemstring ~= "" then
|
||||
result_stackstring = prop.cookresult_itemstring
|
||||
src_cooktime = prop.furnace_cooktime or 3
|
||||
end
|
||||
end
|
||||
|
||||
print("src_cooktime="..dump(src_cooktime))
|
||||
print("result_stackstring="..dump(result_stackstring))
|
||||
|
||||
if tonumber(meta:get_string("fuel_time")) < tonumber(meta:get_string("fuel_totaltime")) then
|
||||
was_active = true
|
||||
meta:set_string("fuel_time", tonumber(meta:get_string("fuel_time")) + 1)
|
||||
meta:set_string("src_time", tonumber(meta:get_string("src_time")) + 1)
|
||||
--print("result_stackstring="..dump(result_stackstring))
|
||||
--print('tonumber(meta:get_string("src_time"))='..dump(tonumber(meta:get_string("src_time"))))
|
||||
--print("src_cooktime="..dump(src_cooktime))
|
||||
if result_stackstring and tonumber(meta:get_string("src_time")) >= src_cooktime and src_cooktime >= 0 then
|
||||
-- Put result in "dst" list
|
||||
success = inv:autoinsert_stackstring("dst", result_stackstring)
|
||||
if not success then
|
||||
print("Could not autoinsert '"..result_stackstring.."'")
|
||||
end
|
||||
-- If succeeded, take stuff from "src" list
|
||||
if success then
|
||||
srcstack = inv:get_stack("src", 1)
|
||||
srcstack:take_item()
|
||||
inv:set_stack("src", 1, srcstack)
|
||||
end
|
||||
meta:set_string("src_time", 0)
|
||||
end
|
||||
end
|
||||
|
||||
if tonumber(meta:get_string("fuel_time")) < tonumber(meta:get_string("fuel_totaltime")) then
|
||||
meta:set_infotext("Furnace active: "..(tonumber(meta:get_string("fuel_time"))/tonumber(meta:get_string("fuel_totaltime"))*100).."%")
|
||||
return
|
||||
end
|
||||
|
||||
local srcitem = inv:get_stack("src", 1):peek_item()
|
||||
|
||||
local src_cooktime = 0
|
||||
local result_stackstring = nil
|
||||
|
||||
if srcitem then
|
||||
local prop = get_item_definition(srcitem)
|
||||
if prop and prop.cookresult_itemstring ~= "" then
|
||||
result_stackstring = prop.cookresult_itemstring
|
||||
src_cooktime = prop.furnace_cooktime or 3
|
||||
end
|
||||
end
|
||||
|
||||
local fuelitem = inv:get_stack("fuel", 1):peek_item()
|
||||
|
||||
if not result_stackstring or not fuelitem then
|
||||
if was_active then
|
||||
meta:set_infotext("Furnace is empty")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local burntime = -1
|
||||
if fuelitem then
|
||||
local prop = get_item_definition(fuelitem)
|
||||
if prop then
|
||||
burntime = prop.furnace_burntime or -1
|
||||
end
|
||||
end
|
||||
|
||||
if burntime <= 0 then
|
||||
meta:set_infotext("Furnace out of fuel")
|
||||
return
|
||||
end
|
||||
|
||||
meta:set_string("fuel_totaltime", burntime)
|
||||
meta:set_string("fuel_time", 0)
|
||||
|
||||
local stack = inv:get_stack("fuel", 1)
|
||||
stack:take_item()
|
||||
inv:set_stack("fuel", 1, stack)
|
||||
end,
|
||||
})
|
||||
minetest.register_abm({
|
||||
nodenames = {"experimental:luafurnace"},
|
||||
interval = 1.0,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
local fuellist = meta:inventory_get_list("fuel")
|
||||
local srclist = meta:inventory_get_list("src")
|
||||
local dstlist = meta:inventory_get_list("dst")
|
||||
if fuellist == nil or srclist == nil or dstlist == nil then
|
||||
return
|
||||
end
|
||||
_, srcitem = stackstring_take_item(srclist[1])
|
||||
_, fuelitem = stackstring_take_item(fuellist[1])
|
||||
if not srcitem or not fuelitem then return end
|
||||
if fuelitem.type == "node" then
|
||||
local prop = minetest.registered_nodes[fuelitem.name]
|
||||
if prop == nil then return end
|
||||
if prop.furnace_burntime < 0 then return end
|
||||
else
|
||||
return
|
||||
end
|
||||
local resultstack = nil
|
||||
if srcitem.type == "node" then
|
||||
local prop = minetest.registered_nodes[srcitem.name]
|
||||
if prop == nil then return end
|
||||
if prop.cookresult_item == "" then return end
|
||||
resultstack = prop.cookresult_item
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
if resultstack == nil then
|
||||
return
|
||||
end
|
||||
|
||||
dstlist[1], success = stackstring_put_stackstring(dstlist[1], resultstack)
|
||||
if not success then
|
||||
return
|
||||
end
|
||||
|
||||
fuellist[1], _ = stackstring_take_item(fuellist[1])
|
||||
srclist[1], _ = stackstring_take_item(srclist[1])
|
||||
|
||||
meta:inventory_set_list("fuel", fuellist)
|
||||
meta:inventory_set_list("src", srclist)
|
||||
meta:inventory_set_list("dst", dstlist)
|
||||
|
||||
local total_cooked = meta:get_string("total_cooked")
|
||||
total_cooked = tonumber(total_cooked) + 1
|
||||
meta:set_string("total_cooked", total_cooked)
|
||||
meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
|
||||
end,
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = 'node "experimental:luafurnace" 1',
|
||||
recipe = {
|
||||
{'node "default:cobble"', 'node "default:cobble"', 'node "default:cobble"'},
|
||||
{'node "default:cobble"', 'node "default:steel_ingot"', 'node "default:cobble"'},
|
||||
{'node "default:cobble"', 'node "default:cobble"', 'node "default:cobble"'},
|
||||
}
|
||||
})
|
||||
--]]
|
||||
|
||||
--
|
||||
-- Random stuff
|
||||
--
|
||||
|
||||
--[[
|
||||
minetest.register_tool("experimental:horribletool", {
|
||||
image = "default_lava.png",
|
||||
basetime = 2.0
|
||||
dt_weight = 0.2
|
||||
dt_crackiness = 0.2
|
||||
dt_crumbliness = 0.2
|
||||
dt_cuttability = 0.2
|
||||
basedurability = 50
|
||||
dd_weight = -5
|
||||
dd_crackiness = -5
|
||||
dd_crumbliness = -5
|
||||
dd_cuttability = -5
|
||||
})
|
||||
--]]
|
||||
|
||||
--
|
||||
-- TNT (not functional)
|
||||
--
|
||||
@@ -415,16 +211,17 @@ minetest.register_alias("TNT", "experimental:tnt")
|
||||
--
|
||||
|
||||
minetest.register_entity("experimental:dummyball", {
|
||||
-- Static definition
|
||||
hp_max = 20,
|
||||
physical = false,
|
||||
collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4},
|
||||
visual = "sprite",
|
||||
visual_size = {x=1, y=1},
|
||||
textures = {"experimental_dummyball.png"},
|
||||
spritediv = {x=1, y=3},
|
||||
initial_sprite_basepos = {x=0, y=0},
|
||||
-- Dynamic variables
|
||||
initial_properties = {
|
||||
hp_max = 20,
|
||||
physical = false,
|
||||
collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4},
|
||||
visual = "sprite",
|
||||
visual_size = {x=1, y=1},
|
||||
textures = {"experimental_dummyball.png"},
|
||||
spritediv = {x=1, y=3},
|
||||
initial_sprite_basepos = {x=0, y=0},
|
||||
},
|
||||
|
||||
phase = 0,
|
||||
phasetimer = 0,
|
||||
|
||||
@@ -645,6 +442,149 @@ minetest.register_abm({
|
||||
end,
|
||||
})--]]
|
||||
|
||||
minetest.register_node("experimental:tester_node_1", {
|
||||
description = "Tester Node 1 (construct/destruct/timer)",
|
||||
tile_images = {"wieldhand.png"},
|
||||
groups = {oddly_breakable_by_hand=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
-- This was known to cause a bug in minetest.item_place_node() when used
|
||||
-- via minetest.env:place_node(), causing a placer with no position
|
||||
paramtype2 = "facedir",
|
||||
|
||||
on_construct = function(pos)
|
||||
experimental.print_to_everything("experimental:tester_node_1:on_construct("..minetest.pos_to_string(pos)..")")
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
meta:set_string("mine", "test")
|
||||
local timer = minetest.env:get_node_timer(pos)
|
||||
timer:start(4, 3)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
experimental.print_to_everything("experimental:tester_node_1:after_place_node("..minetest.pos_to_string(pos)..")")
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
if meta:get_string("mine") == "test" then
|
||||
experimental.print_to_everything("correct metadata found")
|
||||
else
|
||||
experimental.print_to_everything("incorrect metadata found")
|
||||
end
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
experimental.print_to_everything("experimental:tester_node_1:on_destruct("..minetest.pos_to_string(pos)..")")
|
||||
end,
|
||||
|
||||
after_destruct = function(pos)
|
||||
experimental.print_to_everything("experimental:tester_node_1:after_destruct("..minetest.pos_to_string(pos)..")")
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
experimental.print_to_everything("experimental:tester_node_1:after_dig_node("..minetest.pos_to_string(pos)..")")
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
experimental.print_to_everything("on_timer(): elapsed="..dump(elapsed))
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("experimental:tester_tool_1", {
|
||||
description = "Tester Tool 1",
|
||||
inventory_image = "experimental_tester_tool_1.png",
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
--print(dump(pointed_thing))
|
||||
if pointed_thing.type == "node" then
|
||||
if minetest.env:get_node(pointed_thing.under).name == "experimental:tester_node_1" then
|
||||
local p = pointed_thing.under
|
||||
minetest.log("action", "Tester tool used at "..minetest.pos_to_string(p))
|
||||
minetest.env:dig_node(p)
|
||||
else
|
||||
local p = pointed_thing.above
|
||||
minetest.log("action", "Tester tool used at "..minetest.pos_to_string(p))
|
||||
minetest.env:place_node(p, {name="experimental:tester_node_1"})
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'experimental:tester_tool_1',
|
||||
recipe = {
|
||||
{'group:crumbly'},
|
||||
{'group:crumbly'},
|
||||
}
|
||||
})
|
||||
|
||||
--[[minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(3, function()
|
||||
player:set_inventory_formspec("size[8,7.5]"..
|
||||
"image[1,0.6;1,2;player.png]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"list[current_player;craft;3,0;3,3;]"..
|
||||
"list[current_player;craftpreview;7,1;1,1;]")
|
||||
end)
|
||||
end)]]
|
||||
|
||||
-- Create a detached inventory
|
||||
local inv = minetest.create_detached_inventory("test_inventory", {
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
experimental.print_to_everything("allow move asked")
|
||||
return count -- Allow all
|
||||
end,
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
experimental.print_to_everything("allow put asked")
|
||||
return 1 -- Allow only 1
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
experimental.print_to_everything("allow take asked")
|
||||
return 4 -- Allow 4 at max
|
||||
end,
|
||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
experimental.print_to_everything(player:get_player_name().." moved items")
|
||||
end,
|
||||
on_put = function(inv, listname, index, stack, player)
|
||||
experimental.print_to_everything(player:get_player_name().." put items")
|
||||
end,
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
experimental.print_to_everything(player:get_player_name().." took items")
|
||||
end,
|
||||
})
|
||||
inv:set_size("main", 4*6)
|
||||
inv:add_item("main", "experimental:tester_tool_1")
|
||||
inv:add_item("main", "experimental:tnt 5")
|
||||
|
||||
minetest.register_chatcommand("test1", {
|
||||
params = "",
|
||||
description = "Test 1: Modify player's inventory view",
|
||||
func = function(name, param)
|
||||
local player = minetest.env:get_player_by_name(name)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
player:set_inventory_formspec(
|
||||
"size[13,7.5]"..
|
||||
"image[6,0.6;1,2;player.png]"..
|
||||
"list[current_player;main;5,3.5;8,4;]"..
|
||||
"list[current_player;craft;8,0;3,3;]"..
|
||||
"list[current_player;craftpreview;12,1;1,1;]"..
|
||||
"list[detached:test_inventory;main;0,0;4,6;0]"..
|
||||
"button[0.5,7;2,1;button1;Button 1]"..
|
||||
"button_exit[2.5,7;2,1;button2;Exit Button]"
|
||||
)
|
||||
minetest.chat_send_player(name, "Done.");
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
experimental.print_to_everything("Inventory fields 1: player="..player:get_player_name()..", fields="..dump(fields))
|
||||
end)
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
experimental.print_to_everything("Inventory fields 2: player="..player:get_player_name()..", fields="..dump(fields))
|
||||
return true -- Disable the first callback
|
||||
end)
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
experimental.print_to_everything("Inventory fields 3: player="..player:get_player_name()..", fields="..dump(fields))
|
||||
end)
|
||||
|
||||
minetest.log("experimental modname="..dump(minetest.get_current_modname()))
|
||||
minetest.log("experimental modpath="..dump(minetest.get_modpath("experimental")))
|
||||
minetest.log("experimental worldpath="..dump(minetest.get_worldpath()))
|
||||
|
||||
|
After Width: | Height: | Size: 209 B |
@@ -1,12 +1,16 @@
|
||||
minetest.register_on_newplayer(function(player)
|
||||
print("on_newplayer")
|
||||
if minetest.setting_getbool("give_initial_stuff") then
|
||||
print("giving give_initial_stuff to player")
|
||||
player:get_inventory():add_item('main', 'default:pick_steel')
|
||||
player:get_inventory():add_item('main', 'default:torch 99')
|
||||
player:get_inventory():add_item('main', 'default:axe_steel')
|
||||
player:get_inventory():add_item('main', 'default:shovel_steel')
|
||||
player:get_inventory():add_item('main', 'default:cobble 99')
|
||||
end
|
||||
print("[minimal] giving initial stuff to player")
|
||||
player:get_inventory():add_item('main', 'default:pick_stone')
|
||||
player:get_inventory():add_item('main', 'default:torch 99')
|
||||
player:get_inventory():add_item('main', 'default:cobble 99')
|
||||
player:get_inventory():add_item('main', 'default:wood 99')
|
||||
player:get_inventory():add_item('main', 'default:axe_steel')
|
||||
player:get_inventory():add_item('main', 'default:shovel_steel')
|
||||
player:get_inventory():add_item('main', 'default:pick_wood')
|
||||
player:get_inventory():add_item('main', 'default:pick_steel')
|
||||
player:get_inventory():add_item('main', 'default:pick_mese')
|
||||
player:get_inventory():add_item('main', 'default:mese 99')
|
||||
player:get_inventory():add_item('main', 'default:water_source 99')
|
||||
player:get_inventory():add_item('main', 'experimental:tester_tool_1')
|
||||
end)
|
||||
|
||||
|
||||
1
games/minimal/mods/stairs/depends.txt
Normal file
@@ -0,0 +1 @@
|
||||
default
|
||||
93
games/minimal/mods/stairs/init.lua
Normal file
@@ -0,0 +1,93 @@
|
||||
stairs = {}
|
||||
|
||||
-- Node will be called stairs:stair_<subname>
|
||||
function stairs.register_stair(subname, recipeitem, groups, images, description)
|
||||
minetest.register_node("stairs:stair_" .. subname, {
|
||||
description = description,
|
||||
drawtype = "nodebox",
|
||||
tile_images = images,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = true,
|
||||
groups = groups,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
{-0.5, 0, 0, 0.5, 0.5, 0.5},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'stairs:stair_' .. subname .. ' 4',
|
||||
recipe = {
|
||||
{recipeitem, "", ""},
|
||||
{recipeitem, recipeitem, ""},
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Node will be called stairs:slab_<subname>
|
||||
function stairs.register_slab(subname, recipeitem, groups, images, description)
|
||||
minetest.register_node("stairs:slab_" .. subname, {
|
||||
description = description,
|
||||
drawtype = "nodebox",
|
||||
tile_images = images,
|
||||
paramtype = "light",
|
||||
is_ground_content = true,
|
||||
groups = groups,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'stairs:slab_' .. subname .. ' 3',
|
||||
recipe = {
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Nodes will be called stairs:{stair,slab}_<subname>
|
||||
function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab)
|
||||
stairs.register_stair(subname, recipeitem, groups, images, desc_stair)
|
||||
stairs.register_slab(subname, recipeitem, groups, images, desc_slab)
|
||||
end
|
||||
|
||||
stairs.register_stair_and_slab("wood", "default:wood",
|
||||
{snappy=2,choppy=2,oddly_breakable_by_hand=2},
|
||||
{"default_wood.png"},
|
||||
"Wooden stair",
|
||||
"Wooden slab")
|
||||
|
||||
stairs.register_stair_and_slab("stone", "default:stone",
|
||||
{cracky=3},
|
||||
{"default_stone.png"},
|
||||
"Stone stair",
|
||||
"Stone slab")
|
||||
|
||||
stairs.register_stair_and_slab("cobble", "default:cobble",
|
||||
{cracky=3},
|
||||
{"default_cobble.png"},
|
||||
"Cobble stair",
|
||||
"Cobble slab")
|
||||
|
||||
stairs.register_stair_and_slab("brick", "default:brick",
|
||||
{cracky=3},
|
||||
{"default_brick.png"},
|
||||
"Brick stair",
|
||||
"Brick slab")
|
||||
|
||||
stairs.register_stair_and_slab("sandstone", "default:sandstone",
|
||||
{crumbly=2,cracky=2},
|
||||
{"default_sandstone.png"},
|
||||
"Sandstone stair",
|
||||
"Sandstone slab")
|
||||
11
games/minimal/mods/test/init.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
--
|
||||
-- Minimal Development Test
|
||||
-- Mod: test
|
||||
--
|
||||
|
||||
-- Try out PseudoRandom
|
||||
pseudo = PseudoRandom(13)
|
||||
assert(pseudo:next() == 22290)
|
||||
assert(pseudo:next() == 13854)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# Uncomment settings by removing the preceding #.
|
||||
#
|
||||
# Further documentation:
|
||||
# http://celeron.55.lt/~celeron55/minetest/wiki/doku.php
|
||||
# http://c55.me/minetest/wiki/doku.php
|
||||
#
|
||||
# NOTE: This file might not be up-to-date, refer to the
|
||||
# defaultsettings.cpp file for an up-to-date list:
|
||||
@@ -16,6 +16,7 @@
|
||||
#
|
||||
# A vim command to convert most of defaultsettings.cpp to conf file format:
|
||||
# :'<,'>s/\tg_settings\.setDefault("\([^"]*\)", "\([^"]*\)");.*/#\1 = \2/g
|
||||
# Note: Some of the settings are implemented in Lua
|
||||
|
||||
#
|
||||
# Client and server
|
||||
@@ -47,22 +48,28 @@
|
||||
#keymap_rangeselect = KEY_KEY_R
|
||||
#keymap_freemove = KEY_KEY_K
|
||||
#keymap_fastmove = KEY_KEY_J
|
||||
#keymap_frametime_graph = KEY_F1
|
||||
#keymap_screenshot = KEY_F12
|
||||
# Some (temporary) keys for debugging
|
||||
#keymap_print_debug_stacks = KEY_KEY_P
|
||||
|
||||
# The desired FPS
|
||||
# Minimum FPS
|
||||
# The amount of rendered stuff is dynamically set according to this
|
||||
#wanted_fps = 30
|
||||
# If FPS would go higher than this, limit it by sleeping
|
||||
# (to not waste CPU power for no benefit)
|
||||
#fps_max = 60
|
||||
# The allowed adjustment range for the automatic rendering range adjustment
|
||||
#viewing_range_nodes_max = 300
|
||||
#viewing_range_nodes_min = 25
|
||||
#viewing_range_nodes_max = 160
|
||||
#viewing_range_nodes_min = 35
|
||||
# Initial window size
|
||||
#screenW = 800
|
||||
#screenH = 600
|
||||
#fullscreen = false
|
||||
#fullscreen_bpp = 24
|
||||
# Experimental option, might cause visible spaces between blocks
|
||||
# when set to higher number than 0
|
||||
#fsaa = 0
|
||||
#vsync = false
|
||||
# Address to connect to (#blank = start local server)
|
||||
#address =
|
||||
# Enable random user input, for testing
|
||||
@@ -78,8 +85,6 @@
|
||||
# Enable smooth lighting with simple ambient occlusion;
|
||||
# disable for speed or for different looks.
|
||||
#smooth_lighting = true
|
||||
# Whether to draw a frametime graph (for debugging frametime)
|
||||
#frametime_graph = false
|
||||
# Enable combining mainly used textures to a bigger one for improved speed
|
||||
# disable if it causes graphics glitches.
|
||||
#enable_texture_atlas = true
|
||||
@@ -110,19 +115,24 @@
|
||||
#console_color = (0,0,0)
|
||||
# In-game chat console background alpha (opaqueness, between 0 and 255)
|
||||
#console_alpha = 200
|
||||
# Sound settings
|
||||
#enable_sound = true
|
||||
#sound_volume = 0.7
|
||||
# Whether node texture animations should be desynchronized per MapBlock
|
||||
#desynchronize_mapblock_texture_animation = true
|
||||
|
||||
#
|
||||
# Server stuff
|
||||
#
|
||||
|
||||
# Default game (default when creating a new world)
|
||||
#default_game = mesetint
|
||||
# Map directory (everything in the world is stored here)
|
||||
#map-dir = /custom/map
|
||||
#default_game = minetest
|
||||
# World directory (everything in the world is stored here)
|
||||
#map-dir = /custom/world
|
||||
# Message of the Day
|
||||
#motd = Welcome to this awesome Minetest server!
|
||||
# Maximum number of players connected simultaneously
|
||||
#max_users = 20
|
||||
#max_users = 100
|
||||
# Set to false to allow old clients to connect
|
||||
#strict_protocol_version_checking = true
|
||||
# Set to true to enable creative mode (unlimited inventory)
|
||||
@@ -137,12 +147,21 @@
|
||||
#give_initial_stuff = false
|
||||
# New users need to input this password
|
||||
#default_password =
|
||||
# Available privileges: build, teleport, settime, privs, shout
|
||||
#default_privs = build, shout
|
||||
# Whether players are transferred to client without any range limit
|
||||
# Available privileges: interact, shout, teleport, settime, privs, ...
|
||||
# See /privs in game for a full list on your server and mod configuration.
|
||||
#default_privs = interact, shout
|
||||
# Whether players are shown to clients without any range limit
|
||||
#unlimited_player_transfer_distance = true
|
||||
# Whether to enable players killing each other
|
||||
#enable_pvp = true
|
||||
# If this is set, players will always (re)spawn at the given position
|
||||
#static_spawnpoint = 0, 10, 0
|
||||
# If true, new players cannot join with an empty password
|
||||
#disallow_empty_password = false
|
||||
# If true, disable cheat prevention in multiplayer
|
||||
#disable_anticheat = false
|
||||
# If true, actions are recorded for rollback
|
||||
#enable_rollback_recording = false
|
||||
|
||||
# Profiler data print interval. #0 = disable.
|
||||
#profiler_print_interval = 0
|
||||
@@ -155,17 +174,21 @@
|
||||
#max_simultaneous_block_sends_per_client = 2
|
||||
# how many blocks are flying in the wire simultaneously per server
|
||||
#max_simultaneous_block_sends_server_total = 8
|
||||
#max_block_send_distance = 7
|
||||
#max_block_generate_distance = 5
|
||||
#time_send_interval = 20
|
||||
# From how far blocks are sent to clients (value * 16 nodes)
|
||||
#max_block_send_distance = 10
|
||||
# From how far blocks are generated for clients (value * 16 nodes)
|
||||
#max_block_generate_distance = 6
|
||||
# Interval of sending time of day to clients
|
||||
#time_send_interval = 5
|
||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour, 0=day/night/whatever stays unchanged
|
||||
#time_speed = 72
|
||||
#time_speed = 96
|
||||
#server_unload_unused_data_timeout = 29
|
||||
# Interval of saving important changes in the world
|
||||
#server_map_save_interval = 5.3
|
||||
# To reduce lag, block transfers are slowed down when a player is building something.
|
||||
# This determines how long they are slowed down after placing or removing a node.
|
||||
#full_block_send_enable_min_time_from_building = 2.0
|
||||
# Set to true to enable experimental features or stuff that is tested
|
||||
# (varies from version to version, usually not useful at all)
|
||||
#enable_experimental = false
|
||||
|
||||
# Length of a server tick in dedicated server
|
||||
#dedicated_server_step = 0.05
|
||||
# Can be set to true to disable shutting down on invalid world data
|
||||
#ignore_world_load_errors = false
|
||||
|
||||
5
misc/winresource.rc
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <richedit.h>
|
||||
LANGUAGE 0, SUBLANG_NEUTRAL
|
||||
130 ICON "minetest-icon.ico"
|
||||
901
po/minetest.pot
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: minetest\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-08-02 12:36+0200\n"
|
||||
"POT-Creation-Date: 2012-06-04 23:25+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"
|
||||
@@ -17,461 +17,278 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:84
|
||||
msgid "KEYBINDINGS"
|
||||
#: src/guiConfirmMenu.cpp:120
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:94
|
||||
msgid "Forward"
|
||||
#: src/guiConfirmMenu.cpp:126
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:111
|
||||
msgid "Backward"
|
||||
#: src/guiCreateWorld.cpp:116
|
||||
msgid "World name"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:127 src/guiKeyChangeMenu.h:38
|
||||
msgid "Left"
|
||||
#: src/guiCreateWorld.cpp:135
|
||||
msgid "Game"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:142 src/guiKeyChangeMenu.h:38
|
||||
msgid "Right"
|
||||
#: src/guiCreateWorld.cpp:159
|
||||
msgid "Create"
|
||||
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
|
||||
#: src/guiCreateWorld.cpp:165 src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:221
|
||||
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
|
||||
#: src/guiDeathScreen.cpp:96
|
||||
msgid "You died."
|
||||
msgstr ""
|
||||
|
||||
#: src/guiDeathScreen.cpp:104
|
||||
msgid "Respawn"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:111
|
||||
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:121
|
||||
msgid "Forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:138
|
||||
msgid "Backward"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:154 src/keycode.cpp:226
|
||||
msgid "Left"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:169 src/keycode.cpp:226
|
||||
msgid "Right"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:185
|
||||
msgid "Use"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:200
|
||||
msgid "Sneak"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:216
|
||||
msgid "Jump"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:231
|
||||
msgid "Drop"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:246
|
||||
msgid "Inventory"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:262
|
||||
msgid "Chat"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:276
|
||||
msgid "Command"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:290
|
||||
msgid "Console"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:306
|
||||
msgid "Toggle fly"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:321
|
||||
msgid "Toggle fast"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:336
|
||||
msgid "Range select"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:353
|
||||
msgid "Print stacks"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:368
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.cpp:626 src/guiKeyChangeMenu.cpp:631
|
||||
#: src/guiKeyChangeMenu.cpp:636 src/guiKeyChangeMenu.cpp:641
|
||||
#: src/guiKeyChangeMenu.cpp:646 src/guiKeyChangeMenu.cpp:651
|
||||
#: src/guiKeyChangeMenu.cpp:656 src/guiKeyChangeMenu.cpp:661
|
||||
#: src/guiKeyChangeMenu.cpp:666 src/guiKeyChangeMenu.cpp:671
|
||||
#: src/guiKeyChangeMenu.cpp:676 src/guiKeyChangeMenu.cpp:681
|
||||
#: src/guiKeyChangeMenu.cpp:686 src/guiKeyChangeMenu.cpp:691
|
||||
#: src/guiKeyChangeMenu.cpp:696 src/guiKeyChangeMenu.cpp:701
|
||||
msgid "press Key"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:33
|
||||
msgid "Left Button"
|
||||
#: src/guiMainMenu.cpp:217
|
||||
msgid "Singleplayer"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:33
|
||||
msgid "Middle Button"
|
||||
#: src/guiMainMenu.cpp:218
|
||||
msgid "Multiplayer"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:33
|
||||
msgid "Right Button"
|
||||
#: src/guiMainMenu.cpp:219
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:33
|
||||
msgid "X Button 1"
|
||||
#: src/guiMainMenu.cpp:220
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:34
|
||||
msgid "Back"
|
||||
#: src/guiMainMenu.cpp:221
|
||||
msgid "Credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:34
|
||||
msgid "Clear"
|
||||
#: src/guiMainMenu.cpp:252
|
||||
msgid "Select World:"
|
||||
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
|
||||
#: src/guiMainMenu.cpp:274 src/keycode.cpp:227
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:39
|
||||
msgid "Help"
|
||||
#: src/guiMainMenu.cpp:281
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiKeyChangeMenu.h:39
|
||||
msgid "Insert"
|
||||
#: src/guiMainMenu.cpp:289
|
||||
msgid "Configure"
|
||||
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
|
||||
#: src/guiMainMenu.cpp:304 src/keycode.cpp:246
|
||||
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
|
||||
#: src/guiMainMenu.cpp:315 src/guiMainMenu.cpp:492
|
||||
msgid "Creative Mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:287
|
||||
#: src/guiMainMenu.cpp:321 src/guiMainMenu.cpp:498
|
||||
msgid "Enable Damage"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:295
|
||||
msgid "Delete map"
|
||||
#: src/guiMainMenu.cpp:341 src/guiMainMenu.cpp:414
|
||||
msgid "Name/Password"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMessageMenu.cpp:94 src/guiTextInputMenu.cpp:112
|
||||
#: src/guiMainMenu.cpp:368 src/guiMainMenu.cpp:441
|
||||
msgid "Address/Port"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:394 src/guiMainMenu.cpp:473
|
||||
msgid "Start Game / Connect"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:464
|
||||
msgid "Leave address blank to start a local server."
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:505 src/guiMainMenu.cpp:833
|
||||
msgid "Delete world"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:512
|
||||
msgid "Create world"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:546
|
||||
msgid "Fancy trees"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:552
|
||||
msgid "Smooth Lighting"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:558
|
||||
msgid "3D Clouds"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:564
|
||||
msgid "Opaque water"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:573
|
||||
msgid "Change keys"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:804
|
||||
msgid "Address required."
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:822
|
||||
msgid "Cannot delete world: Nothing selected"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:837
|
||||
msgid "Files to be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:853
|
||||
msgid "Cannot create world: No games found"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:866
|
||||
msgid "Nothing here"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMainMenu.cpp:915
|
||||
msgid "Failed to delete all world files"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiMessageMenu.cpp:109 src/guiTextInputMenu.cpp:123
|
||||
msgid "Proceed"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPasswordChange.cpp:103
|
||||
#: src/guiPasswordChange.cpp:108
|
||||
msgid "Old Password"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPasswordChange.cpp:120
|
||||
#: src/guiPasswordChange.cpp:125
|
||||
msgid "New Password"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPasswordChange.cpp:136
|
||||
#: src/guiPasswordChange.cpp:141
|
||||
msgid "Confirm Password"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPasswordChange.cpp:153
|
||||
#: src/guiPasswordChange.cpp:158
|
||||
msgid "Change"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPasswordChange.cpp:162
|
||||
#: src/guiPasswordChange.cpp:167
|
||||
msgid "Passwords do not match!"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPauseMenu.cpp:111
|
||||
#: src/guiPauseMenu.cpp:118
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPauseMenu.cpp:118
|
||||
#: src/guiPauseMenu.cpp:127
|
||||
msgid "Change Password"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPauseMenu.cpp:125
|
||||
msgid "Disconnect"
|
||||
#: src/guiPauseMenu.cpp:135
|
||||
msgid "Exit to Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPauseMenu.cpp:132
|
||||
#: src/guiPauseMenu.cpp:142
|
||||
msgid "Exit to OS"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiPauseMenu.cpp:139
|
||||
#: src/guiPauseMenu.cpp:149
|
||||
msgid ""
|
||||
"Default Controls:\n"
|
||||
"- WASD: Walk\n"
|
||||
@@ -485,3 +302,325 @@ msgid ""
|
||||
"- ESC: This menu\n"
|
||||
"- T: Chat\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:221
|
||||
msgid "Left Button"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:221
|
||||
msgid "Middle Button"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:221
|
||||
msgid "Right Button"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:221
|
||||
msgid "X Button 1"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:222
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:222
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:222
|
||||
msgid "Return"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:222
|
||||
msgid "Tab"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:222
|
||||
msgid "X Button 2"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:223
|
||||
msgid "Capital"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:223
|
||||
msgid "Control"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:223
|
||||
msgid "Kana"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:223
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:223
|
||||
msgid "Pause"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:223
|
||||
msgid "Shift"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:224
|
||||
msgid "Convert"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:224
|
||||
msgid "Escape"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:224
|
||||
msgid "Final"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:224
|
||||
msgid "Junja"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:224
|
||||
msgid "Kanji"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:224
|
||||
msgid "Nonconvert"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "Accept"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "End"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "Mode Change"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "Next"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "Prior"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:225
|
||||
msgid "Space"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:226
|
||||
msgid "Down"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:226
|
||||
msgid "Execute"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:226
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:226
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:226
|
||||
msgid "Up"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:227
|
||||
msgid "Help"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:227
|
||||
msgid "Insert"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:227
|
||||
msgid "Snapshot"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:230
|
||||
msgid "Left Windows"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:231
|
||||
msgid "Apps"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:231
|
||||
msgid "Numpad 0"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:231
|
||||
msgid "Numpad 1"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:231
|
||||
msgid "Right Windows"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:231
|
||||
msgid "Sleep"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:232
|
||||
msgid "Numpad 2"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:232
|
||||
msgid "Numpad 3"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:232
|
||||
msgid "Numpad 4"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:232
|
||||
msgid "Numpad 5"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:232
|
||||
msgid "Numpad 6"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:232
|
||||
msgid "Numpad 7"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:233
|
||||
msgid "Numpad *"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:233
|
||||
msgid "Numpad +"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:233
|
||||
msgid "Numpad -"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:233
|
||||
msgid "Numpad /"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:233
|
||||
msgid "Numpad 8"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:233
|
||||
msgid "Numpad 9"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:237
|
||||
msgid "Num Lock"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:237
|
||||
msgid "Scroll Lock"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:238
|
||||
msgid "Left Shift"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:238
|
||||
msgid "Right Shift"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:239
|
||||
msgid "Left Control"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:239
|
||||
msgid "Left Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:239
|
||||
msgid "Right Control"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:239
|
||||
msgid "Right Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:241
|
||||
msgid "Comma"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:241
|
||||
msgid "Minus"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:241
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:241
|
||||
msgid "Plus"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:245
|
||||
msgid "Attn"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:245
|
||||
msgid "CrSel"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:246
|
||||
msgid "Erase OEF"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:246
|
||||
msgid "ExSel"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:246
|
||||
msgid "OEM Clear"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:246
|
||||
msgid "PA1"
|
||||
msgstr ""
|
||||
|
||||
#: src/keycode.cpp:246
|
||||
msgid "Zoom"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1379
|
||||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1601
|
||||
msgid "Failed to initialize world"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1613
|
||||
msgid "No world selected and no address provided. Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1621
|
||||
msgid "Could not find or load game \""
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1635
|
||||
msgid "Invalid gamespec."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1675
|
||||
msgid "Connection error (timed out?)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1686
|
||||
msgid ""
|
||||
"\n"
|
||||
"Check debug.txt for details."
|
||||
msgstr ""
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
project(minetest)
|
||||
cmake_minimum_required( VERSION 2.6 )
|
||||
|
||||
if(RUN_IN_PLACE)
|
||||
add_definitions ( -DRUN_IN_PLACE )
|
||||
endif(RUN_IN_PLACE)
|
||||
|
||||
# Set some random things default to not being visible in the GUI
|
||||
mark_as_advanced(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
|
||||
mark_as_advanced(JTHREAD_INCLUDE_DIR JTHREAD_LIBRARY)
|
||||
@@ -67,7 +63,7 @@ endif(ENABLE_SOUND AND BUILD_CLIENT)
|
||||
|
||||
if(SOUND_PROBLEM)
|
||||
message(FATAL_ERROR "Sound enabled, but cannot be used.\n"
|
||||
"To continue, either fill in the required paths or disable sound.")
|
||||
"To continue, either fill in the required paths or disable sound. (-DENABLE_SOUND=0)")
|
||||
endif()
|
||||
if(USE_SOUND)
|
||||
set(sound_SRCS sound_openal.cpp)
|
||||
@@ -106,6 +102,8 @@ if(WIN32)
|
||||
CACHE FILEPATH "Path to zlibwapi.dll (for installation)")
|
||||
set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2"
|
||||
CACHE PATH "irrlicht dir")
|
||||
set(MINGWM10_DLL ""
|
||||
CACHE FILEPATH "Path to mingwm10.dll (for installation)")
|
||||
if(ENABLE_SOUND)
|
||||
set(OPENAL_DLL "" CACHE FILEPATH "Path to OpenAL32.dll for installation (optional)")
|
||||
set(OGG_DLL "" CACHE FILEPATH "Path to libogg.dll for installation (optional)")
|
||||
@@ -137,13 +135,15 @@ else()
|
||||
#set(CLIENT_PLATFORM_LIBS -lXxf86vm)
|
||||
# This way Xxf86vm is found on OpenBSD too
|
||||
find_library(XXF86VM_LIBRARY Xxf86vm)
|
||||
mark_as_advanced(XXF86VM_LIBRARY)
|
||||
set(CLIENT_PLATFORM_LIBS ${CLIENT_PLATFORM_LIBS} ${XXF86VM_LIBRARY})
|
||||
endif()
|
||||
|
||||
find_package(Jthread REQUIRED)
|
||||
find_package(Sqlite3 REQUIRED)
|
||||
|
||||
# TODO: Create proper find script for Lua
|
||||
# Do not use system-wide installation of Lua, because it'll likely be a
|
||||
# different version and/or has different build options.
|
||||
set(LUA_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lua/src")
|
||||
set(LUA_LIBRARY "lua")
|
||||
|
||||
@@ -153,18 +153,21 @@ configure_file(
|
||||
)
|
||||
|
||||
set(common_SRCS
|
||||
rollback_interface.cpp
|
||||
rollback.cpp
|
||||
genericobject.cpp
|
||||
voxelalgorithms.cpp
|
||||
sound.cpp
|
||||
quicktune.cpp
|
||||
subgame.cpp
|
||||
inventorymanager.cpp
|
||||
mods.cpp
|
||||
serverremoteplayer.cpp
|
||||
content_abm.cpp
|
||||
craftdef.cpp
|
||||
nameidmapping.cpp
|
||||
itemdef.cpp
|
||||
nodedef.cpp
|
||||
luaentity_common.cpp
|
||||
object_properties.cpp
|
||||
scriptapi.cpp
|
||||
script.cpp
|
||||
log.cpp
|
||||
@@ -172,9 +175,9 @@ set(common_SRCS
|
||||
mapgen.cpp
|
||||
content_nodemeta.cpp
|
||||
content_mapnode.cpp
|
||||
auth.cpp
|
||||
collision.cpp
|
||||
nodemetadata.cpp
|
||||
nodetimer.cpp
|
||||
serverobject.cpp
|
||||
noise.cpp
|
||||
porting.cpp
|
||||
@@ -196,23 +199,33 @@ set(common_SRCS
|
||||
mapsector.cpp
|
||||
map.cpp
|
||||
player.cpp
|
||||
utility.cpp
|
||||
test.cpp
|
||||
sha1.cpp
|
||||
base64.cpp
|
||||
ban.cpp
|
||||
util/serialize.cpp
|
||||
util/directiontables.cpp
|
||||
util/numeric.cpp
|
||||
util/pointedthing.cpp
|
||||
util/string.cpp
|
||||
util/timetaker.cpp
|
||||
)
|
||||
|
||||
# This gives us the icon
|
||||
if(WIN32)
|
||||
set(WINRESOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../misc/winresource.rc)
|
||||
if(MINGW)
|
||||
if(NOT CMAKE_RC_COMPILER)
|
||||
set(CMAKE_RC_COMPILER "windres.exe")
|
||||
endif()
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
||||
COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-i${CMAKE_CURRENT_SOURCE_DIR}/winresource.rc
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
|
||||
COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-i${WINRESOURCE_FILE}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
SET(common_SRCS ${common_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
|
||||
else(MINGW) # Probably MSVC
|
||||
set(common_SRCS ${common_SRCS} winresource.rc)
|
||||
set(common_SRCS ${common_SRCS} ${WINRESOURCE_FILE})
|
||||
endif(MINGW)
|
||||
endif()
|
||||
|
||||
@@ -220,6 +233,7 @@ endif()
|
||||
set(minetest_SRCS
|
||||
${common_SRCS}
|
||||
${sound_SRCS}
|
||||
localplayer.cpp
|
||||
sky.cpp
|
||||
clientmap.cpp
|
||||
content_cso.cpp
|
||||
@@ -237,7 +251,7 @@ set(minetest_SRCS
|
||||
guiKeyChangeMenu.cpp
|
||||
guiMessageMenu.cpp
|
||||
guiTextInputMenu.cpp
|
||||
guiInventoryMenu.cpp
|
||||
guiFormSpecMenu.cpp
|
||||
guiPauseMenu.cpp
|
||||
guiPasswordChange.cpp
|
||||
guiDeathScreen.cpp
|
||||
@@ -347,14 +361,18 @@ else()
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-but-set-variable")
|
||||
endif(HAS_UNUSED_BUT_SET_VARIABLE_WARNING)
|
||||
endif()
|
||||
|
||||
|
||||
if(MINGW)
|
||||
set(OTHER_FLAGS "-mthreads -fexceptions")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES i386 CACHE STRING "do not build for 64-bit" FORCE)
|
||||
set(ARCH i386)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS} ${OTHER_FLAGS}")
|
||||
|
||||
if(USE_GPROF)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
|
||||
@@ -374,6 +392,9 @@ endif()
|
||||
# Installation
|
||||
#
|
||||
if(WIN32)
|
||||
if(MINGWM10_DLL)
|
||||
install(FILES ${MINGWM10_DLL} DESTINATION ${BINDIR})
|
||||
endif()
|
||||
if(DEFINED ZLIB_DLL)
|
||||
install(FILES ${ZLIB_DLL} DESTINATION ${BINDIR})
|
||||
endif()
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef ACTIVEOBJECT_HEADER
|
||||
#define ACTIVEOBJECT_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
|
||||
#define ACTIVEOBJECT_TYPE_INVALID 0
|
||||
|
||||
300
src/auth.cpp
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
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 "auth.h"
|
||||
#include <fstream>
|
||||
#include <jmutexautolock.h>
|
||||
//#include "main.h" // for g_settings
|
||||
#include <sstream>
|
||||
#include "strfnd.h"
|
||||
#include "log.h"
|
||||
|
||||
std::set<std::string> privsToSet(u64 privs)
|
||||
{
|
||||
std::set<std::string> s;
|
||||
if(privs & PRIV_INTERACT)
|
||||
s.insert("interact");
|
||||
if(privs & PRIV_TELEPORT)
|
||||
s.insert("teleport");
|
||||
if(privs & PRIV_SETTIME)
|
||||
s.insert("settime");
|
||||
if(privs & PRIV_PRIVS)
|
||||
s.insert("privs");
|
||||
if(privs & PRIV_SHOUT)
|
||||
s.insert("shout");
|
||||
if(privs & PRIV_BAN)
|
||||
s.insert("ban");
|
||||
if(privs & PRIV_GIVE)
|
||||
s.insert("give");
|
||||
if(privs & PRIV_PASSWORD)
|
||||
s.insert("password");
|
||||
return s;
|
||||
}
|
||||
|
||||
// Convert a privileges value into a human-readable string,
|
||||
// with each component separated by a comma.
|
||||
std::string privsToString(u64 privs)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
if(privs & PRIV_INTERACT)
|
||||
os<<"interact,";
|
||||
if(privs & PRIV_TELEPORT)
|
||||
os<<"teleport,";
|
||||
if(privs & PRIV_SETTIME)
|
||||
os<<"settime,";
|
||||
if(privs & PRIV_PRIVS)
|
||||
os<<"privs,";
|
||||
if(privs & PRIV_SHOUT)
|
||||
os<<"shout,";
|
||||
if(privs & PRIV_BAN)
|
||||
os<<"ban,";
|
||||
if(privs & PRIV_GIVE)
|
||||
os<<"give,";
|
||||
if(privs & PRIV_PASSWORD)
|
||||
os<<"password,";
|
||||
if(os.tellp())
|
||||
{
|
||||
// Drop the trailing comma. (Why on earth can't
|
||||
// you truncate a C++ stream anyway???)
|
||||
std::string tmp = os.str();
|
||||
return tmp.substr(0, tmp.length() -1);
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// Converts a comma-seperated list of privilege values into a
|
||||
// privileges value. The reverse of privsToString(). Returns
|
||||
// PRIV_INVALID if there is anything wrong with the input.
|
||||
u64 stringToPrivs(std::string str)
|
||||
{
|
||||
u64 privs=0;
|
||||
Strfnd f(str);
|
||||
while(f.atend() == false)
|
||||
{
|
||||
std::string s = trim(f.next(","));
|
||||
if(s == "build")
|
||||
privs |= PRIV_INTERACT;
|
||||
else if(s == "interact")
|
||||
privs |= PRIV_INTERACT;
|
||||
else if(s == "teleport")
|
||||
privs |= PRIV_TELEPORT;
|
||||
else if(s == "settime")
|
||||
privs |= PRIV_SETTIME;
|
||||
else if(s == "privs")
|
||||
privs |= PRIV_PRIVS;
|
||||
else if(s == "shout")
|
||||
privs |= PRIV_SHOUT;
|
||||
else if(s == "ban")
|
||||
privs |= PRIV_BAN;
|
||||
else if(s == "give")
|
||||
privs |= PRIV_GIVE;
|
||||
else if(s == "password")
|
||||
privs |= PRIV_PASSWORD;
|
||||
else
|
||||
return PRIV_INVALID;
|
||||
}
|
||||
return privs;
|
||||
}
|
||||
|
||||
AuthManager::AuthManager(const std::string &authfilepath):
|
||||
m_authfilepath(authfilepath),
|
||||
m_modified(false)
|
||||
{
|
||||
m_mutex.Init();
|
||||
|
||||
try{
|
||||
load();
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<"WARNING: AuthManager: creating "
|
||||
<<m_authfilepath<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
AuthManager::~AuthManager()
|
||||
{
|
||||
save();
|
||||
}
|
||||
|
||||
void AuthManager::load()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
infostream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
|
||||
std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
infostream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
|
||||
throw SerializationError("AuthManager::load(): Couldn't open file");
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(is.eof() || is.good() == false)
|
||||
break;
|
||||
|
||||
// Read a line
|
||||
std::string line;
|
||||
std::getline(is, line, '\n');
|
||||
|
||||
std::istringstream iss(line);
|
||||
|
||||
// Read name
|
||||
std::string name;
|
||||
std::getline(iss, name, ':');
|
||||
|
||||
// Read password
|
||||
std::string pwd;
|
||||
std::getline(iss, pwd, ':');
|
||||
|
||||
// Read privileges
|
||||
std::string stringprivs;
|
||||
std::getline(iss, stringprivs, ':');
|
||||
u64 privs = stringToPrivs(stringprivs);
|
||||
|
||||
// Store it
|
||||
AuthData ad;
|
||||
ad.pwd = pwd;
|
||||
ad.privs = privs;
|
||||
m_authdata[name] = ad;
|
||||
}
|
||||
|
||||
m_modified = false;
|
||||
}
|
||||
|
||||
void AuthManager::save()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
infostream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
|
||||
std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
|
||||
if(os.good() == false)
|
||||
{
|
||||
infostream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
|
||||
throw SerializationError("AuthManager::save(): Couldn't open file");
|
||||
}
|
||||
|
||||
for(core::map<std::string, AuthData>::Iterator
|
||||
i = m_authdata.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
if(name == "")
|
||||
continue;
|
||||
AuthData ad = i.getNode()->getValue();
|
||||
os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
|
||||
}
|
||||
|
||||
m_modified = false;
|
||||
}
|
||||
|
||||
bool AuthManager::exists(const std::string &username)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, AuthData>::Node *n;
|
||||
n = m_authdata.find(username);
|
||||
if(n == NULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthManager::set(const std::string &username, AuthData ad)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_authdata[username] = ad;
|
||||
|
||||
m_modified = true;
|
||||
}
|
||||
|
||||
void AuthManager::add(const std::string &username)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_authdata[username] = AuthData();
|
||||
|
||||
m_modified = true;
|
||||
}
|
||||
|
||||
std::string AuthManager::getPassword(const std::string &username)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, AuthData>::Node *n;
|
||||
n = m_authdata.find(username);
|
||||
if(n == NULL)
|
||||
throw AuthNotFoundException("");
|
||||
|
||||
return n->getValue().pwd;
|
||||
}
|
||||
|
||||
void AuthManager::setPassword(const std::string &username,
|
||||
const std::string &password)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, AuthData>::Node *n;
|
||||
n = m_authdata.find(username);
|
||||
if(n == NULL)
|
||||
throw AuthNotFoundException("");
|
||||
|
||||
AuthData ad = n->getValue();
|
||||
ad.pwd = password;
|
||||
n->setValue(ad);
|
||||
|
||||
m_modified = true;
|
||||
}
|
||||
|
||||
u64 AuthManager::getPrivs(const std::string &username)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, AuthData>::Node *n;
|
||||
n = m_authdata.find(username);
|
||||
if(n == NULL)
|
||||
throw AuthNotFoundException("");
|
||||
|
||||
return n->getValue().privs;
|
||||
}
|
||||
|
||||
void AuthManager::setPrivs(const std::string &username, u64 privs)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, AuthData>::Node *n;
|
||||
n = m_authdata.find(username);
|
||||
if(n == NULL)
|
||||
throw AuthNotFoundException("");
|
||||
|
||||
AuthData ad = n->getValue();
|
||||
ad.privs = privs;
|
||||
n->setValue(ad);
|
||||
|
||||
m_modified = true;
|
||||
}
|
||||
|
||||
bool AuthManager::isModified()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
return m_modified;
|
||||
}
|
||||
|
||||
|
||||
107
src/auth.h
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
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 AUTH_HEADER
|
||||
#define AUTH_HEADER
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include "irrlichttypes.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
// Player privileges. These form a bitmask stored in the privs field
|
||||
// of the player, and define things they're allowed to do. See also
|
||||
// the static methods Player::privsToString and stringToPrivs that
|
||||
// convert these to human-readable form.
|
||||
const u64 PRIV_INTERACT = 1; // Can interact
|
||||
const u64 PRIV_TELEPORT = 2; // Can teleport
|
||||
const u64 PRIV_SETTIME = 4; // Can set the time
|
||||
const u64 PRIV_PRIVS = 8; // Can grant and revoke privileges
|
||||
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
|
||||
const u64 PRIV_GIVE = 128; // Can give stuff
|
||||
const u64 PRIV_PASSWORD = 256; // Can set other players' passwords
|
||||
|
||||
// Default privileges - these can be overriden for new players using the
|
||||
// config option "default_privs" - however, this value still applies for
|
||||
// players that existed before the privileges system was added.
|
||||
const u64 PRIV_DEFAULT = PRIV_INTERACT|PRIV_SHOUT;
|
||||
const u64 PRIV_ALL = 0x7FFFFFFFFFFFFFFFULL;
|
||||
const u64 PRIV_INVALID = 0x8000000000000000ULL;
|
||||
|
||||
std::set<std::string> privsToSet(u64 privs);
|
||||
|
||||
// Convert a privileges value into a human-readable string,
|
||||
// with each component separated by a comma.
|
||||
std::string privsToString(u64 privs);
|
||||
|
||||
// Converts a comma-seperated list of privilege values into a
|
||||
// privileges value. The reverse of privsToString(). Returns
|
||||
// PRIV_INVALID if there is anything wrong with the input.
|
||||
u64 stringToPrivs(std::string str);
|
||||
|
||||
struct AuthData
|
||||
{
|
||||
std::string pwd;
|
||||
u64 privs;
|
||||
|
||||
AuthData():
|
||||
privs(PRIV_DEFAULT)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class AuthNotFoundException : public BaseException
|
||||
{
|
||||
public:
|
||||
AuthNotFoundException(const char *s):
|
||||
BaseException(s)
|
||||
{}
|
||||
};
|
||||
|
||||
class AuthManager
|
||||
{
|
||||
public:
|
||||
AuthManager(const std::string &authfilepath);
|
||||
~AuthManager();
|
||||
void load();
|
||||
void save();
|
||||
bool exists(const std::string &username);
|
||||
void set(const std::string &username, AuthData ad);
|
||||
void add(const std::string &username);
|
||||
std::string getPassword(const std::string &username);
|
||||
void setPassword(const std::string &username,
|
||||
const std::string &password);
|
||||
u64 getPrivs(const std::string &username);
|
||||
void setPrivs(const std::string &username, u64 privs);
|
||||
bool isModified();
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
std::string m_authfilepath;
|
||||
core::map<std::string, AuthData> m_authdata;
|
||||
bool m_modified;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <string>
|
||||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include "common_irrlicht.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
class BanManager
|
||||
|
||||
@@ -38,6 +38,13 @@ static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
bool base64_is_valid(std::string const& s)
|
||||
{
|
||||
for(size_t i=0; i<s.size(); i++)
|
||||
if(!is_base64(s[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <string>
|
||||
|
||||
bool base64_is_valid(std::string const& s);
|
||||
std::string base64_encode(unsigned char const* , unsigned int len);
|
||||
std::string base64_decode(std::string const& s);
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -33,6 +33,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gamedef.h"
|
||||
#include "sound.h"
|
||||
#include "event.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/mathconstants.h"
|
||||
|
||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
|
||||
IGameDef *gamedef):
|
||||
@@ -212,8 +214,22 @@ void Camera::step(f32 dtime)
|
||||
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
f32 tool_reload_ratio)
|
||||
{
|
||||
// Get player position
|
||||
// Smooth the movement when walking up stairs
|
||||
v3f old_player_position = m_playernode->getPosition();
|
||||
v3f player_position = player->getPosition();
|
||||
//if(player->touching_ground && player_position.Y > old_player_position.Y)
|
||||
if(player->touching_ground &&
|
||||
player_position.Y > old_player_position.Y)
|
||||
{
|
||||
f32 oldy = old_player_position.Y;
|
||||
f32 newy = player_position.Y;
|
||||
f32 t = exp(-23*frametime);
|
||||
player_position.Y = oldy * t + newy * (1-t);
|
||||
}
|
||||
|
||||
// Set player node transformation
|
||||
m_playernode->setPosition(player->getPosition());
|
||||
m_playernode->setPosition(player_position);
|
||||
m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
|
||||
m_playernode->updateAbsolutePosition();
|
||||
|
||||
@@ -234,17 +250,17 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
|
||||
#if 1
|
||||
f32 bobknob = 1.2;
|
||||
f32 bobtmp = sin(pow(bobfrac, bobknob) * PI);
|
||||
//f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI);
|
||||
f32 bobtmp = sin(pow(bobfrac, bobknob) * M_PI);
|
||||
//f32 bobtmp2 = cos(pow(bobfrac, bobknob) * M_PI);
|
||||
|
||||
v3f bobvec = v3f(
|
||||
0.3 * bobdir * sin(bobfrac * PI),
|
||||
0.3 * bobdir * sin(bobfrac * M_PI),
|
||||
-0.28 * bobtmp * bobtmp,
|
||||
0.);
|
||||
|
||||
//rel_cam_pos += 0.2 * bobvec;
|
||||
//rel_cam_target += 0.03 * bobvec;
|
||||
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI);
|
||||
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * M_PI);
|
||||
float f = 1.0;
|
||||
f *= g_settings->getFloat("view_bobbing_amount");
|
||||
rel_cam_pos += bobvec * f;
|
||||
@@ -253,10 +269,10 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
rel_cam_target.Z -= 0.005 * bobvec.Z * f;
|
||||
//rel_cam_target.X -= 0.005 * bobvec.X * f;
|
||||
//rel_cam_target.Y -= 0.005 * bobvec.Y * f;
|
||||
rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f);
|
||||
rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * M_PI * f);
|
||||
#else
|
||||
f32 angle_deg = 1 * bobdir * sin(bobfrac * PI);
|
||||
f32 angle_rad = angle_deg * PI / 180;
|
||||
f32 angle_deg = 1 * bobdir * sin(bobfrac * M_PI);
|
||||
f32 angle_rad = angle_deg * M_PI / 180;
|
||||
f32 r = 0.05;
|
||||
v3f off = v3f(
|
||||
r * sin(angle_rad),
|
||||
@@ -289,7 +305,10 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
|
||||
// FOV and aspect ratio
|
||||
m_aspect = (f32)screensize.X / (f32) screensize.Y;
|
||||
m_fov_y = fov_degrees * PI / 180.0;
|
||||
m_fov_y = fov_degrees * M_PI / 180.0;
|
||||
// Increase vertical FOV on lower aspect ratios (<16:10)
|
||||
m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect)));
|
||||
// WTF is this? It can't be right
|
||||
m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y));
|
||||
m_cameranode->setAspectRatio(m_aspect);
|
||||
m_cameranode->setFOV(m_fov_y);
|
||||
@@ -317,22 +336,22 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 digfrac = m_digging_anim;
|
||||
wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI);
|
||||
wield_position.Y += 15 * sin(digfrac * 2 * PI);
|
||||
wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * M_PI);
|
||||
wield_position.Y += 15 * sin(digfrac * 2 * M_PI);
|
||||
wield_position.Z += 5 * digfrac;
|
||||
|
||||
// Euler angles are PURE EVIL, so why not use quaternions?
|
||||
core::quaternion quat_begin(wield_rotation * core::DEGTORAD);
|
||||
core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD);
|
||||
core::quaternion quat_slerp;
|
||||
quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI));
|
||||
quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * M_PI));
|
||||
quat_slerp.toEuler(wield_rotation);
|
||||
wield_rotation *= core::RADTODEG;
|
||||
}
|
||||
else {
|
||||
f32 bobfrac = my_modf(m_view_bobbing_anim);
|
||||
wield_position.X -= sin(bobfrac*PI*2.0) * 3.0;
|
||||
wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0;
|
||||
wield_position.X -= sin(bobfrac*M_PI*2.0) * 3.0;
|
||||
wield_position.Y += sin(my_modf(bobfrac*2.0)*M_PI) * 3.0;
|
||||
}
|
||||
m_wieldnode->setPosition(wield_position);
|
||||
m_wieldnode->setRotation(wield_rotation);
|
||||
@@ -348,7 +367,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
|
||||
if ((hypot(speed.X, speed.Z) > BS) &&
|
||||
(player->touching_ground) &&
|
||||
(g_settings->getBool("view_bobbing") == true) &&
|
||||
(g_settings->getBool("free_move") == false))
|
||||
(g_settings->getBool("free_move") == false ||
|
||||
!m_gamedef->checkLocalPrivilege("fly")))
|
||||
{
|
||||
// Start animation
|
||||
m_view_bobbing_state = 1;
|
||||
@@ -534,7 +554,7 @@ void Camera::drawWieldedTool()
|
||||
// Draw the wielded node (in a separate scene manager)
|
||||
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
|
||||
cam->setAspectRatio(m_cameranode->getAspectRatio());
|
||||
cam->setFOV(72.0*PI/180.0);
|
||||
cam->setFOV(72.0*M_PI/180.0);
|
||||
cam->setNearValue(0.1);
|
||||
cam->setFarValue(100);
|
||||
m_wieldmgr->drawAll();
|
||||
|
||||
12
src/camera.h
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,11 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CAMERA_HEADER
|
||||
#define CAMERA_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "inventory.h"
|
||||
#include "mesh.h"
|
||||
#include "tile.h"
|
||||
#include "utility.h"
|
||||
#include "util/numeric.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
|
||||
class LocalPlayer;
|
||||
|
||||
11
src/chat.cpp
@@ -3,26 +3,27 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "chat.h"
|
||||
#include "debug.h"
|
||||
#include "utility.h"
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
#include "util/string.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
ChatBuffer::ChatBuffer(u32 scrollback):
|
||||
m_scrollback(scrollback),
|
||||
|
||||
10
src/chat.h
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CHAT_HEADER
|
||||
#define CHAT_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
|
||||
// Chat console related classes, only used by the client
|
||||
|
||||
184
src/client.cpp
@@ -3,22 +3,21 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "utility.h"
|
||||
#include <iostream>
|
||||
#include "clientserver.h"
|
||||
#include "jmutexautolock.h"
|
||||
@@ -40,7 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "clientmap.h"
|
||||
#include "filecache.h"
|
||||
#include "sound.h"
|
||||
#include "utility_string.h"
|
||||
#include "util/string.h"
|
||||
#include "hex.h"
|
||||
|
||||
static std::string getMediaCacheDir()
|
||||
@@ -305,6 +304,15 @@ Client::~Client()
|
||||
sleep_ms(100);
|
||||
|
||||
delete m_inventory_from_server;
|
||||
|
||||
// Delete detached inventories
|
||||
{
|
||||
for(std::map<std::string, Inventory*>::iterator
|
||||
i = m_detached_inventories.begin();
|
||||
i != m_detached_inventories.end(); i++){
|
||||
delete i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::connect(Address address)
|
||||
@@ -1397,45 +1405,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
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)
|
||||
{
|
||||
infostream<<"Client: ignoring player item "
|
||||
<< deSerializeString(is)
|
||||
<< " for non-existing peer id " << peer_id
|
||||
<< std::endl;
|
||||
continue;
|
||||
} else if (player->isLocal()) {
|
||||
infostream<<"Client: ignoring player item "
|
||||
<< deSerializeString(is)
|
||||
<< " for local player" << std::endl;
|
||||
continue;
|
||||
} else {
|
||||
InventoryList *inv = player->inventory.getList("main");
|
||||
std::string itemstring(deSerializeString(is));
|
||||
ItemStack item;
|
||||
item.deSerialize(itemstring, m_itemdef);
|
||||
inv->changeItem(0, item);
|
||||
if(itemstring.empty())
|
||||
{
|
||||
infostream<<"Client: empty player item for peer "
|
||||
<<peer_id<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: player item for peer "
|
||||
<<peer_id<<": "<<itemstring<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
infostream<<"Client: WARNING: Ignoring TOCLIENT_PLAYERITEM"<<std::endl;
|
||||
}
|
||||
else if(command == TOCLIENT_DEATHSCREEN)
|
||||
{
|
||||
@@ -1677,10 +1647,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
int client_id = -1;
|
||||
switch(type){
|
||||
case 0: // local
|
||||
client_id = m_sound->playSound(name, false, gain);
|
||||
client_id = m_sound->playSound(name, loop, gain);
|
||||
break;
|
||||
case 1: // positional
|
||||
client_id = m_sound->playSoundAt(name, false, gain, pos);
|
||||
client_id = m_sound->playSoundAt(name, loop, gain, pos);
|
||||
break;
|
||||
case 2: { // object
|
||||
ClientActiveObject *cao = m_env.getActiveObject(object_id);
|
||||
@@ -1712,6 +1682,49 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
m_sound->stopSound(client_id);
|
||||
}
|
||||
}
|
||||
else if(command == TOCLIENT_PRIVILEGES)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
m_privileges.clear();
|
||||
infostream<<"Client: Privileges updated: ";
|
||||
u16 num_privileges = readU16(is);
|
||||
for(u16 i=0; i<num_privileges; i++){
|
||||
std::string priv = deSerializeString(is);
|
||||
m_privileges.insert(priv);
|
||||
infostream<<priv<<" ";
|
||||
}
|
||||
infostream<<std::endl;
|
||||
}
|
||||
else if(command == TOCLIENT_INVENTORY_FORMSPEC)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
// Store formspec in LocalPlayer
|
||||
Player *player = m_env.getLocalPlayer();
|
||||
assert(player != NULL);
|
||||
player->inventory_formspec = deSerializeLongString(is);
|
||||
}
|
||||
else if(command == TOCLIENT_DETACHED_INVENTORY)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
std::string name = deSerializeString(is);
|
||||
|
||||
infostream<<"Client: Detached inventory update: \""<<name<<"\""<<std::endl;
|
||||
|
||||
Inventory *inv = NULL;
|
||||
if(m_detached_inventories.count(name) > 0)
|
||||
inv = m_detached_inventories[name];
|
||||
else{
|
||||
inv = new Inventory(m_itemdef);
|
||||
m_detached_inventories[name] = inv;
|
||||
}
|
||||
inv->deSerialize(is);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
@@ -1763,33 +1776,23 @@ void Client::interact(u8 action, const PointedThing& pointed)
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendSignNodeText(v3s16 p, std::string text)
|
||||
void Client::sendNodemetaFields(v3s16 p, const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields)
|
||||
{
|
||||
/*
|
||||
u16 command
|
||||
v3s16 p
|
||||
u16 textlen
|
||||
textdata
|
||||
*/
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
u8 buf[12];
|
||||
|
||||
// Write command
|
||||
writeU16(buf, TOSERVER_SIGNNODETEXT);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
// Write p
|
||||
writeV3S16(buf, p);
|
||||
os.write((char*)buf, 6);
|
||||
|
||||
u16 textlen = text.size();
|
||||
// Write text length
|
||||
writeS16(buf, textlen);
|
||||
os.write((char*)buf, 2);
|
||||
writeU16(os, TOSERVER_NODEMETA_FIELDS);
|
||||
writeV3S16(os, p);
|
||||
os<<serializeString(formname);
|
||||
writeU16(os, fields.size());
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = fields.begin(); i != fields.end(); i++){
|
||||
const std::string &name = i->first;
|
||||
const std::string &value = i->second;
|
||||
os<<serializeString(name);
|
||||
os<<serializeLongString(value);
|
||||
}
|
||||
|
||||
// Write text
|
||||
os.write((char*)text.c_str(), textlen);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
@@ -1797,6 +1800,29 @@ void Client::sendSignNodeText(v3s16 p, std::string text)
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendInventoryFields(const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
||||
writeU16(os, TOSERVER_INVENTORY_FIELDS);
|
||||
os<<serializeString(formname);
|
||||
writeU16(os, fields.size());
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = fields.begin(); i != fields.end(); i++){
|
||||
const std::string &name = i->first;
|
||||
const std::string &value = i->second;
|
||||
os<<serializeString(name);
|
||||
os<<serializeLongString(value);
|
||||
}
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendInventoryAction(InventoryAction *a)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
@@ -2091,6 +2117,13 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
|
||||
return meta->getInventory();
|
||||
}
|
||||
break;
|
||||
case InventoryLocation::DETACHED:
|
||||
{
|
||||
if(m_detached_inventories.count(loc.name) == 0)
|
||||
return NULL;
|
||||
return m_detached_inventories[loc.name];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -2371,32 +2404,41 @@ ClientEvent Client::getClientEvent()
|
||||
|
||||
void Client::afterContentReceived()
|
||||
{
|
||||
verbosestream<<"Client::afterContentReceived() started"<<std::endl;
|
||||
assert(m_itemdef_received);
|
||||
assert(m_nodedef_received);
|
||||
assert(m_media_received);
|
||||
|
||||
|
||||
// remove the information about which checksum each texture
|
||||
// ought to have
|
||||
m_media_name_sha1_map.clear();
|
||||
|
||||
// Rebuild inherited images and recreate textures
|
||||
verbosestream<<"Rebuilding images and textures"<<std::endl;
|
||||
m_tsrc->rebuildImagesAndTextures();
|
||||
|
||||
// Update texture atlas
|
||||
verbosestream<<"Updating texture atlas"<<std::endl;
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
m_tsrc->buildMainAtlas(this);
|
||||
|
||||
// Update node aliases
|
||||
verbosestream<<"Updating node aliases"<<std::endl;
|
||||
m_nodedef->updateAliases(m_itemdef);
|
||||
|
||||
// Update node textures
|
||||
verbosestream<<"Updating node textures"<<std::endl;
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
|
||||
// Update item textures and meshes
|
||||
verbosestream<<"Updating item textures and meshes"<<std::endl;
|
||||
m_itemdef->updateTexturesAndMeshes(this);
|
||||
|
||||
// Start mesh update thread after setting up content definitions
|
||||
verbosestream<<"Starting mesh update thread"<<std::endl;
|
||||
m_mesh_update_thread.Start();
|
||||
|
||||
verbosestream<<"Client::afterContentReceived() done"<<std::endl;
|
||||
}
|
||||
|
||||
float Client::getRTT(void)
|
||||
|
||||
43
src/client.h
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,21 +20,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENT_HEADER
|
||||
#define CLIENT_HEADER
|
||||
|
||||
#ifndef SERVER
|
||||
|
||||
#include "connection.h"
|
||||
#include "environment.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "jmutex.h"
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "clientobject.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
#include "gamedef.h"
|
||||
#include "inventorymanager.h"
|
||||
#include "filesys.h"
|
||||
#include "filecache.h"
|
||||
#include "localplayer.h"
|
||||
#include "util/pointedthing.h"
|
||||
|
||||
struct MeshMakeData;
|
||||
class MapBlockMesh;
|
||||
@@ -211,11 +210,14 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
|
||||
|
||||
void interact(u8 action, const PointedThing& pointed);
|
||||
|
||||
void sendSignNodeText(v3s16 p, std::string text);
|
||||
void sendNodemetaFields(v3s16 p, const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields);
|
||||
void sendInventoryFields(const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields);
|
||||
void sendInventoryAction(InventoryAction *a);
|
||||
void sendChatMessage(const std::wstring &message);
|
||||
void sendChangePassword(const std::wstring oldpassword,
|
||||
const std::wstring newpassword);
|
||||
const std::wstring newpassword);
|
||||
void sendDamage(u8 damage);
|
||||
void sendRespawn();
|
||||
|
||||
@@ -262,14 +264,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
|
||||
|
||||
u16 getHP();
|
||||
|
||||
float getAvgRtt()
|
||||
{
|
||||
try{
|
||||
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
||||
} catch(con::PeerNotFoundException){
|
||||
return 1337;
|
||||
}
|
||||
}
|
||||
bool checkPrivilege(const std::string &priv)
|
||||
{ return (m_privileges.count(priv) != 0); }
|
||||
|
||||
bool getChatMessage(std::wstring &message);
|
||||
void typeChatMessage(const std::wstring& message);
|
||||
@@ -312,6 +308,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
|
||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||
virtual ISoundManager* getSoundManager();
|
||||
virtual MtEventManager* getEventManager();
|
||||
virtual bool checkLocalPrivilege(const std::string &priv)
|
||||
{ return checkPrivilege(priv); }
|
||||
|
||||
private:
|
||||
|
||||
@@ -392,9 +390,14 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
|
||||
std::map<int, s32> m_sounds_client_to_server;
|
||||
// And relations to objects
|
||||
std::map<int, u16> m_sounds_to_objects;
|
||||
};
|
||||
|
||||
#endif // !SERVER
|
||||
// Privileges
|
||||
std::set<std::string> m_privileges;
|
||||
|
||||
// Detached inventories
|
||||
// key = name
|
||||
std::map<std::string, Inventory*> m_detached_inventories;
|
||||
};
|
||||
|
||||
#endif // !CLIENT_HEADER
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapblock.h"
|
||||
#include "profiler.h"
|
||||
#include "settings.h"
|
||||
#include "util/mathconstants.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@@ -46,7 +47,7 @@ ClientMap::ClientMap(
|
||||
m_control(control),
|
||||
m_camera_position(0,0,0),
|
||||
m_camera_direction(0,0,1),
|
||||
m_camera_fov(PI)
|
||||
m_camera_fov(M_PI)
|
||||
{
|
||||
m_camera_mutex.Init();
|
||||
assert(m_camera_mutex.IsInitialized());
|
||||
@@ -324,6 +325,16 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
Occlusion culling
|
||||
*/
|
||||
|
||||
// No occlusion culling when free_move is on and camera is
|
||||
// inside ground
|
||||
bool occlusion_culling_enabled = true;
|
||||
if(g_settings->getBool("free_move")){
|
||||
MapNode n = getNodeNoEx(cam_pos_nodes);
|
||||
if(n.getContent() == CONTENT_IGNORE ||
|
||||
nodemgr->get(n).solidness == 2)
|
||||
occlusion_culling_enabled = false;
|
||||
}
|
||||
|
||||
v3s16 cpn = block->getPos() * MAP_BLOCKSIZE;
|
||||
cpn += v3s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2);
|
||||
float step = BS*1;
|
||||
@@ -334,6 +345,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
s16 bs2 = MAP_BLOCKSIZE/2 + 1;
|
||||
u32 needed_count = 1;
|
||||
if(
|
||||
occlusion_culling_enabled &&
|
||||
isOccluded(this, spn, cpn + v3s16(0,0,0),
|
||||
step, stepfac, startoff, endoff, needed_count, nodemgr) &&
|
||||
isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2),
|
||||
@@ -598,9 +610,9 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
|
||||
if(z_directions[0].X < -99){
|
||||
for(u32 i=0; i<sizeof(z_directions)/sizeof(*z_directions); i++){
|
||||
z_directions[i] = v3f(
|
||||
0.01 * myrand_range(-80, 80),
|
||||
0.01 * myrand_range(-100, 100),
|
||||
1.0,
|
||||
0.01 * myrand_range(-80, 80)
|
||||
0.01 * myrand_range(-100, 100)
|
||||
);
|
||||
z_offsets[i] = 0.01 * myrand_range(0,100);
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTMAP_HEADER
|
||||
#define CLIENTMAP_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "map.h"
|
||||
|
||||
struct MapDrawControl
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTOBJECT_HEADER
|
||||
#define CLIENTOBJECT_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "activeobject.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTSERVER_HEADER
|
||||
#define CLIENTSERVER_HEADER
|
||||
|
||||
#include "utility.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
/*
|
||||
changes by PROTOCOL_VERSION:
|
||||
@@ -50,9 +50,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
PROTOCOL_VERSION 9:
|
||||
ContentFeatures and NodeDefManager use a different serialization
|
||||
format; better for future version cross-compatibility
|
||||
Many things
|
||||
PROTOCOL_VERSION 10:
|
||||
TOCLIENT_PRIVILEGES
|
||||
Version raised to force 'fly' and 'fast' privileges into effect.
|
||||
Node metadata change (came in later; somewhat incompatible)
|
||||
PROTOCOL_VERSION 11:
|
||||
TileDef in ContentFeatures
|
||||
Nodebox drawtype
|
||||
(some dev snapshot)
|
||||
TOCLIENT_INVENTORY_FORMSPEC
|
||||
(0.4.0, 0.4.1)
|
||||
PROTOCOL_VERSION 12:
|
||||
TOSERVER_INVENTORY_FIELDS
|
||||
16-bit node ids
|
||||
TOCLIENT_DETACHED_INVENTORY
|
||||
*/
|
||||
|
||||
#define PROTOCOL_VERSION 9
|
||||
#define PROTOCOL_VERSION 12
|
||||
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
@@ -200,7 +215,7 @@ enum ToClientCommand
|
||||
wstring reason
|
||||
*/
|
||||
|
||||
TOCLIENT_PLAYERITEM = 0x36,
|
||||
TOCLIENT_PLAYERITEM = 0x36, // Obsolete
|
||||
/*
|
||||
u16 command
|
||||
u16 count of player items
|
||||
@@ -291,6 +306,30 @@ enum ToClientCommand
|
||||
u16 command
|
||||
s32 sound_id
|
||||
*/
|
||||
|
||||
TOCLIENT_PRIVILEGES = 0x41,
|
||||
/*
|
||||
u16 command
|
||||
u16 number of privileges
|
||||
for each privilege
|
||||
u16 len
|
||||
u8[len] privilege
|
||||
*/
|
||||
|
||||
TOCLIENT_INVENTORY_FORMSPEC = 0x42,
|
||||
/*
|
||||
u16 command
|
||||
u32 len
|
||||
u8[len] formspec
|
||||
*/
|
||||
|
||||
TOCLIENT_DETACHED_INVENTORY = 0x43,
|
||||
/*
|
||||
[0] u16 command
|
||||
u16 len
|
||||
u8[len] name
|
||||
[2] serialized inventory
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
@@ -402,7 +441,7 @@ enum ToServerCommand
|
||||
wstring message
|
||||
*/
|
||||
|
||||
TOSERVER_SIGNNODETEXT = 0x33,
|
||||
TOSERVER_SIGNNODETEXT = 0x33, // obsolete
|
||||
/*
|
||||
u16 command
|
||||
v3s16 p
|
||||
@@ -471,6 +510,33 @@ enum ToServerCommand
|
||||
s32[len] sound_id
|
||||
*/
|
||||
|
||||
TOSERVER_NODEMETA_FIELDS = 0x3b,
|
||||
/*
|
||||
u16 command
|
||||
v3s16 p
|
||||
u16 len
|
||||
u8[len] form name (reserved for future use)
|
||||
u16 number of fields
|
||||
for each field:
|
||||
u16 len
|
||||
u8[len] field name
|
||||
u32 len
|
||||
u8[len] field value
|
||||
*/
|
||||
|
||||
TOSERVER_INVENTORY_FIELDS = 0x3c,
|
||||
/*
|
||||
u16 command
|
||||
u16 len
|
||||
u8[len] form name (reserved for future use)
|
||||
u16 number of fields
|
||||
for each field:
|
||||
u16 len
|
||||
u8[len] field name
|
||||
u32 len
|
||||
u8[len] field value
|
||||
*/
|
||||
|
||||
TOSERVER_REQUEST_MEDIA = 0x40,
|
||||
/*
|
||||
u16 command
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLIENTSIMPLEOBJECT_HEADER
|
||||
#define CLIENTSIMPLEOBJECT_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
class ClientEnvironment;
|
||||
|
||||
class ClientSimpleObject
|
||||
|
||||
171
src/clouds.cpp
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -213,8 +213,7 @@ void Clouds::render()
|
||||
|
||||
v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f;
|
||||
|
||||
video::S3DVertex v[4] =
|
||||
{
|
||||
video::S3DVertex v[4] = {
|
||||
video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1),
|
||||
video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1),
|
||||
video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0),
|
||||
@@ -236,88 +235,88 @@ void Clouds::render()
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: // top
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Normal = v3f(0,1,0);
|
||||
}
|
||||
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 1: // back
|
||||
if(CONTAINS(xi, zi-1, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi, zi-1, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color=c_side_1;
|
||||
v[j].Normal = v3f(0,0,-1);
|
||||
}
|
||||
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
|
||||
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
|
||||
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
|
||||
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 2: //right
|
||||
if(CONTAINS(xi+1, zi, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi+1, zi, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color=c_side_2;
|
||||
v[j].Normal = v3f(1,0,0);
|
||||
}
|
||||
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
|
||||
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 3: // front
|
||||
if(CONTAINS(xi, zi+1, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi, zi+1, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color=c_side_1;
|
||||
v[j].Normal = v3f(0,0,-1);
|
||||
}
|
||||
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
|
||||
break;
|
||||
case 4: // left
|
||||
if(CONTAINS(xi-1, zi, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi-1, zi, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color=c_side_2;
|
||||
v[j].Normal = v3f(-1,0,0);
|
||||
}
|
||||
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
|
||||
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
|
||||
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
|
||||
break;
|
||||
case 5: // bottom
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color=c_bottom;
|
||||
v[j].Normal = v3f(0,-1,0);
|
||||
}
|
||||
v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 0: // top
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Normal.set(0,1,0);
|
||||
}
|
||||
v[0].Pos.set(-rx, ry,-rz);
|
||||
v[1].Pos.set(-rx, ry, rz);
|
||||
v[2].Pos.set( rx, ry, rz);
|
||||
v[3].Pos.set( rx, ry,-rz);
|
||||
break;
|
||||
case 1: // back
|
||||
if(CONTAINS(xi, zi-1, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi, zi-1, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color = c_side_1;
|
||||
v[j].Normal.set(0,0,-1);
|
||||
}
|
||||
v[0].Pos.set(-rx, ry,-rz);
|
||||
v[1].Pos.set( rx, ry,-rz);
|
||||
v[2].Pos.set( rx,-ry,-rz);
|
||||
v[3].Pos.set(-rx,-ry,-rz);
|
||||
break;
|
||||
case 2: //right
|
||||
if(CONTAINS(xi+1, zi, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi+1, zi, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color = c_side_2;
|
||||
v[j].Normal.set(1,0,0);
|
||||
}
|
||||
v[0].Pos.set( rx, ry,-rz);
|
||||
v[1].Pos.set( rx, ry, rz);
|
||||
v[2].Pos.set( rx,-ry, rz);
|
||||
v[3].Pos.set( rx,-ry,-rz);
|
||||
break;
|
||||
case 3: // front
|
||||
if(CONTAINS(xi, zi+1, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi, zi+1, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color = c_side_1;
|
||||
v[j].Normal.set(0,0,-1);
|
||||
}
|
||||
v[0].Pos.set( rx, ry, rz);
|
||||
v[1].Pos.set(-rx, ry, rz);
|
||||
v[2].Pos.set(-rx,-ry, rz);
|
||||
v[3].Pos.set( rx,-ry, rz);
|
||||
break;
|
||||
case 4: // left
|
||||
if(CONTAINS(xi-1, zi, cloud_radius_i)){
|
||||
u32 j = GETINDEX(xi-1, zi, cloud_radius_i);
|
||||
if(grid[j])
|
||||
continue;
|
||||
}
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color = c_side_2;
|
||||
v[j].Normal.set(-1,0,0);
|
||||
}
|
||||
v[0].Pos.set(-rx, ry, rz);
|
||||
v[1].Pos.set(-rx, ry,-rz);
|
||||
v[2].Pos.set(-rx,-ry,-rz);
|
||||
v[3].Pos.set(-rx,-ry, rz);
|
||||
break;
|
||||
case 5: // bottom
|
||||
for(int j=0;j<4;j++){
|
||||
v[j].Color = c_bottom;
|
||||
v[j].Normal.set(0,-1,0);
|
||||
}
|
||||
v[0].Pos.set( rx,-ry, rz);
|
||||
v[1].Pos.set(-rx,-ry, rz);
|
||||
v[2].Pos.set(-rx,-ry,-rz);
|
||||
v[3].Pos.set( rx,-ry,-rz);
|
||||
break;
|
||||
}
|
||||
|
||||
v3f pos = v3f(p0.X,m_cloud_y,p0.Y);
|
||||
v3f pos(p0.X, m_cloud_y, p0.Y);
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
v[i].Pos += pos;
|
||||
|
||||
10
src/clouds.h
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CLOUDS_HEADER
|
||||
#define CLOUDS_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <iostream>
|
||||
|
||||
class Clouds : public scene::ISceneNode
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
#define CMAKE_CONFIG_H
|
||||
|
||||
#define CMAKE_PROJECT_NAME "@PROJECT_NAME@"
|
||||
#define CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
|
||||
#define CMAKE_VERSION_STRING "@VERSION_STRING@"
|
||||
#define CMAKE_RUN_IN_PLACE @RUN_IN_PLACE@
|
||||
#define CMAKE_USE_GETTEXT @USE_GETTEXT@
|
||||
#define CMAKE_USE_SOUND @USE_SOUND@
|
||||
#define CMAKE_STATIC_SHAREDIR "@SHAREDIR@"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define CMAKE_BUILD_TYPE "Release"
|
||||
#else
|
||||
#define CMAKE_BUILD_TYPE "Debug"
|
||||
#endif
|
||||
#define CMAKE_USE_GETTEXT @USE_GETTEXT@
|
||||
#define CMAKE_USE_SOUND @USE_SOUND@
|
||||
#define CMAKE_BUILD_INFO "VER=@VERSION_STRING@ BUILD_TYPE="CMAKE_BUILD_TYPE" RUN_IN_PLACE=@RUN_IN_PLACE@ USE_GETTEXT=@USE_GETTEXT@ USE_SOUND=@USE_SOUND@ INSTALL_PREFIX=@CMAKE_INSTALL_PREFIX@"
|
||||
#define CMAKE_BUILD_INFO "VER=@VERSION_STRING@ BUILD_TYPE="CMAKE_BUILD_TYPE" RUN_IN_PLACE=@RUN_IN_PLACE@ USE_GETTEXT=@USE_GETTEXT@ USE_SOUND=@USE_SOUND@ STATIC_SHAREDIR=@SHAREDIR@"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -22,28 +22,249 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "map.h"
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "log.h"
|
||||
#include <vector>
|
||||
#include "util/timetaker.h"
|
||||
#include "main.h" // g_profiler
|
||||
#include "profiler.h"
|
||||
|
||||
// Helper function:
|
||||
// Checks for collision of a moving aabbox with a static aabbox
|
||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||
// The time after which the collision occurs is stored in dtime.
|
||||
int axisAlignedCollision(
|
||||
const aabb3f &staticbox, const aabb3f &movingbox,
|
||||
const v3f &speed, f32 d, f32 &dtime)
|
||||
{
|
||||
//TimeTaker tt("axisAlignedCollision");
|
||||
|
||||
f32 xsize = (staticbox.MaxEdge.X - staticbox.MinEdge.X);
|
||||
f32 ysize = (staticbox.MaxEdge.Y - staticbox.MinEdge.Y);
|
||||
f32 zsize = (staticbox.MaxEdge.Z - staticbox.MinEdge.Z);
|
||||
|
||||
aabb3f relbox(
|
||||
movingbox.MinEdge.X - staticbox.MinEdge.X,
|
||||
movingbox.MinEdge.Y - staticbox.MinEdge.Y,
|
||||
movingbox.MinEdge.Z - staticbox.MinEdge.Z,
|
||||
movingbox.MaxEdge.X - staticbox.MinEdge.X,
|
||||
movingbox.MaxEdge.Y - staticbox.MinEdge.Y,
|
||||
movingbox.MaxEdge.Z - staticbox.MinEdge.Z
|
||||
);
|
||||
|
||||
if(speed.X > 0) // Check for collision with X- plane
|
||||
{
|
||||
if(relbox.MaxEdge.X <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.X / speed.X;
|
||||
if((relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 0;
|
||||
}
|
||||
else if(relbox.MinEdge.X > xsize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(speed.X < 0) // Check for collision with X+ plane
|
||||
{
|
||||
if(relbox.MinEdge.X >= xsize - d)
|
||||
{
|
||||
dtime = (xsize - relbox.MinEdge.X) / speed.X;
|
||||
if((relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 0;
|
||||
}
|
||||
else if(relbox.MaxEdge.X < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// NO else if here
|
||||
|
||||
if(speed.Y > 0) // Check for collision with Y- plane
|
||||
{
|
||||
if(relbox.MaxEdge.Y <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.Y / speed.Y;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 1;
|
||||
}
|
||||
else if(relbox.MinEdge.Y > ysize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(speed.Y < 0) // Check for collision with Y+ plane
|
||||
{
|
||||
if(relbox.MinEdge.Y >= ysize - d)
|
||||
{
|
||||
dtime = (ysize - relbox.MinEdge.Y) / speed.Y;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 1;
|
||||
}
|
||||
else if(relbox.MaxEdge.Y < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// NO else if here
|
||||
|
||||
if(speed.Z > 0) // Check for collision with Z- plane
|
||||
{
|
||||
if(relbox.MaxEdge.Z <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.Z / speed.Z;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0))
|
||||
return 2;
|
||||
}
|
||||
//else if(relbox.MinEdge.Z > zsize)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
else if(speed.Z < 0) // Check for collision with Z+ plane
|
||||
{
|
||||
if(relbox.MinEdge.Z >= zsize - d)
|
||||
{
|
||||
dtime = (zsize - relbox.MinEdge.Z) / speed.Z;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0))
|
||||
return 2;
|
||||
}
|
||||
//else if(relbox.MaxEdge.Z < 0)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Helper function:
|
||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||
bool wouldCollideWithCeiling(
|
||||
const std::vector<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d)
|
||||
{
|
||||
//TimeTaker tt("wouldCollideWithCeiling");
|
||||
|
||||
assert(y_increase >= 0);
|
||||
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = staticboxes.begin();
|
||||
i != staticboxes.end(); i++)
|
||||
{
|
||||
const aabb3f& staticbox = *i;
|
||||
if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
|
||||
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
|
||||
(movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
|
||||
(movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
|
||||
(movingbox.MinEdge.Z < staticbox.MaxEdge.Z) &&
|
||||
(movingbox.MaxEdge.Z > staticbox.MinEdge.Z))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f)
|
||||
{
|
||||
//TimeTaker tt("collisionMoveSimple");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
|
||||
|
||||
collisionMoveResult result;
|
||||
|
||||
v3f oldpos_f = pos_f;
|
||||
v3s16 oldpos_i = floatToInt(oldpos_f, BS);
|
||||
/*
|
||||
Calculate new velocity
|
||||
*/
|
||||
speed_f += accel_f * dtime;
|
||||
|
||||
// If there is no speed, there are no collisions
|
||||
if(speed_f.getLength() == 0)
|
||||
return result;
|
||||
|
||||
/*
|
||||
Calculate new position
|
||||
Collect node boxes in movement range
|
||||
*/
|
||||
pos_f += speed_f * dtime;
|
||||
std::vector<aabb3f> cboxes;
|
||||
std::vector<bool> is_unloaded;
|
||||
std::vector<bool> is_step_up;
|
||||
{
|
||||
//TimeTaker tt2("collisionMoveSimple collect boxes");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
|
||||
|
||||
v3s16 oldpos_i = floatToInt(pos_f, BS);
|
||||
v3s16 newpos_i = floatToInt(pos_f + speed_f * dtime, BS);
|
||||
s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1;
|
||||
s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1;
|
||||
s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1;
|
||||
s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1;
|
||||
s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1;
|
||||
s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1;
|
||||
|
||||
for(s16 x = min_x; x <= max_x; x++)
|
||||
for(s16 y = min_y; y <= max_y; y++)
|
||||
for(s16 z = min_z; z <= max_z; z++)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(v3s16(x,y,z));
|
||||
if(gamedef->getNodeDefManager()->get(n).walkable == false)
|
||||
continue;
|
||||
|
||||
std::vector<aabb3f> nodeboxes = n.getNodeBoxes(gamedef->ndef());
|
||||
for(std::vector<aabb3f>::iterator
|
||||
i = nodeboxes.begin();
|
||||
i != nodeboxes.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += v3f(x, y, z)*BS;
|
||||
box.MaxEdge += v3f(x, y, z)*BS;
|
||||
cboxes.push_back(box);
|
||||
is_unloaded.push_back(false);
|
||||
is_step_up.push_back(false);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Collide with unloaded nodes
|
||||
aabb3f box = getNodeBox(v3s16(x,y,z), BS);
|
||||
cboxes.push_back(box);
|
||||
is_unloaded.push_back(true);
|
||||
is_step_up.push_back(false);
|
||||
}
|
||||
}
|
||||
} // tt2
|
||||
|
||||
assert(cboxes.size() == is_unloaded.size());
|
||||
assert(cboxes.size() == is_step_up.size());
|
||||
|
||||
/*
|
||||
Collision detection
|
||||
*/
|
||||
|
||||
// position in nodes
|
||||
v3s16 pos_i = floatToInt(pos_f, BS);
|
||||
|
||||
|
||||
/*
|
||||
Collision uncertainty radius
|
||||
Make it a bit larger than the maximum distance of movement
|
||||
@@ -54,49 +275,129 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
|
||||
// This should always apply, otherwise there are glitches
|
||||
assert(d > pos_max_d);
|
||||
|
||||
/*
|
||||
Calculate collision box
|
||||
*/
|
||||
core::aabbox3d<f32> box = box_0;
|
||||
box.MaxEdge += pos_f;
|
||||
box.MinEdge += pos_f;
|
||||
core::aabbox3d<f32> oldbox = box_0;
|
||||
oldbox.MaxEdge += oldpos_f;
|
||||
oldbox.MinEdge += oldpos_f;
|
||||
|
||||
/*
|
||||
If the object lies on a walkable node, this is set to true.
|
||||
*/
|
||||
result.touching_ground = false;
|
||||
|
||||
/*
|
||||
Go through every node around the object
|
||||
*/
|
||||
s16 min_x = (box_0.MinEdge.X / BS) - 2;
|
||||
s16 min_y = (box_0.MinEdge.Y / BS) - 2;
|
||||
s16 min_z = (box_0.MinEdge.Z / BS) - 2;
|
||||
s16 max_x = (box_0.MaxEdge.X / BS) + 1;
|
||||
s16 max_y = (box_0.MaxEdge.Y / BS) + 1;
|
||||
s16 max_z = (box_0.MaxEdge.Z / BS) + 1;
|
||||
for(s16 y = oldpos_i.Y + min_y; y <= oldpos_i.Y + max_y; y++)
|
||||
for(s16 z = oldpos_i.Z + min_z; z <= oldpos_i.Z + max_z; z++)
|
||||
for(s16 x = oldpos_i.X + min_x; x <= oldpos_i.X + max_x; x++)
|
||||
int loopcount = 0;
|
||||
|
||||
while(dtime > BS*1e-10)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(v3s16(x,y,z));
|
||||
if(gamedef->getNodeDefManager()->get(n).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
//TimeTaker tt3("collisionMoveSimple dtime loop");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple dtime loop avg", SPT_AVG);
|
||||
|
||||
// Avoid infinite loop
|
||||
loopcount++;
|
||||
if(loopcount >= 100)
|
||||
{
|
||||
// Doing nothing here will block the object from
|
||||
// walking over map borders
|
||||
infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, aborting to avoid infiniite loop"<<std::endl;
|
||||
dtime = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
aabb3f movingbox = box_0;
|
||||
movingbox.MinEdge += pos_f;
|
||||
movingbox.MaxEdge += pos_f;
|
||||
|
||||
int nearest_collided = -1;
|
||||
f32 nearest_dtime = dtime;
|
||||
u32 nearest_boxindex = -1;
|
||||
|
||||
/*
|
||||
Go through every nodebox, find nearest collision
|
||||
*/
|
||||
for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++)
|
||||
{
|
||||
// Ignore if already stepped up this nodebox.
|
||||
if(is_step_up[boxindex])
|
||||
continue;
|
||||
|
||||
// Find nearest collision of the two boxes (raytracing-like)
|
||||
f32 dtime_tmp;
|
||||
int collided = axisAlignedCollision(
|
||||
cboxes[boxindex], movingbox, speed_f, d, dtime_tmp);
|
||||
|
||||
if(collided == -1 || dtime_tmp >= nearest_dtime)
|
||||
continue;
|
||||
|
||||
nearest_dtime = dtime_tmp;
|
||||
nearest_collided = collided;
|
||||
nearest_boxindex = boxindex;
|
||||
}
|
||||
|
||||
if(nearest_collided == -1)
|
||||
{
|
||||
// No collision with any collision box.
|
||||
pos_f += speed_f * dtime;
|
||||
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, a collision occurred.
|
||||
|
||||
const aabb3f& cbox = cboxes[nearest_boxindex];
|
||||
|
||||
// Check for stairs.
|
||||
bool step_up = (nearest_collided != 1) && // must not be Y direction
|
||||
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
||||
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
||||
(!wouldCollideWithCeiling(cboxes, movingbox,
|
||||
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
||||
d));
|
||||
|
||||
// Move to the point of collision and reduce dtime by nearest_dtime
|
||||
if(nearest_dtime < 0)
|
||||
{
|
||||
// Handle negative nearest_dtime (can be caused by the d allowance)
|
||||
if(!step_up)
|
||||
{
|
||||
if(nearest_collided == 0)
|
||||
pos_f.X += speed_f.X * nearest_dtime;
|
||||
if(nearest_collided == 1)
|
||||
pos_f.Y += speed_f.Y * nearest_dtime;
|
||||
if(nearest_collided == 2)
|
||||
pos_f.Z += speed_f.Z * nearest_dtime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pos_f += speed_f * nearest_dtime;
|
||||
dtime -= nearest_dtime;
|
||||
}
|
||||
|
||||
// Set the speed component that caused the collision to zero
|
||||
if(step_up)
|
||||
{
|
||||
// Special case: Handle stairs
|
||||
is_step_up[nearest_boxindex] = true;
|
||||
}
|
||||
else if(nearest_collided == 0) // X
|
||||
{
|
||||
speed_f.X = 0;
|
||||
result.collides = true;
|
||||
result.collides_xz = true;
|
||||
}
|
||||
else if(nearest_collided == 1) // Y
|
||||
{
|
||||
speed_f.Y = 0;
|
||||
result.collides = true;
|
||||
}
|
||||
else if(nearest_collided == 2) // Z
|
||||
{
|
||||
speed_f.Z = 0;
|
||||
result.collides = true;
|
||||
result.collides_xz = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Final touches: Check if standing on ground, step up stairs.
|
||||
*/
|
||||
aabb3f box = box_0;
|
||||
box.MinEdge += pos_f;
|
||||
box.MaxEdge += pos_f;
|
||||
for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++)
|
||||
{
|
||||
const aabb3f& cbox = cboxes[boxindex];
|
||||
|
||||
/*
|
||||
See if the object is touching ground.
|
||||
|
||||
@@ -107,108 +408,50 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
Use 0.15*BS so that it is easier to get on a node.
|
||||
*/
|
||||
if(
|
||||
//fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < d
|
||||
fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS
|
||||
&& nodebox.MaxEdge.X-d > box.MinEdge.X
|
||||
&& nodebox.MinEdge.X+d < box.MaxEdge.X
|
||||
&& nodebox.MaxEdge.Z-d > box.MinEdge.Z
|
||||
&& nodebox.MinEdge.Z+d < box.MaxEdge.Z
|
||||
cbox.MaxEdge.X-d > box.MinEdge.X &&
|
||||
cbox.MinEdge.X+d < box.MaxEdge.X &&
|
||||
cbox.MaxEdge.Z-d > box.MinEdge.Z &&
|
||||
cbox.MinEdge.Z+d < box.MaxEdge.Z
|
||||
){
|
||||
result.touching_ground = true;
|
||||
}
|
||||
|
||||
// If object doesn't intersect with node, ignore node.
|
||||
if(box.intersectsWithBox(nodebox) == false)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Go through every axis
|
||||
*/
|
||||
v3f dirs[3] = {
|
||||
v3f(0,0,1), // back-front
|
||||
v3f(0,1,0), // top-bottom
|
||||
v3f(1,0,0), // right-left
|
||||
};
|
||||
for(u16 i=0; i<3; i++)
|
||||
{
|
||||
/*
|
||||
Calculate values along the axis
|
||||
*/
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 objectmax = box.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 objectmin = box.MinEdge.dotProduct(dirs[i]);
|
||||
f32 objectmax_old = oldbox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 objectmin_old = oldbox.MinEdge.dotProduct(dirs[i]);
|
||||
|
||||
/*
|
||||
Check collision for the axis.
|
||||
Collision happens when object is going through a surface.
|
||||
*/
|
||||
bool negative_axis_collides =
|
||||
(nodemax > objectmin && nodemax <= objectmin_old + d
|
||||
&& speed_f.dotProduct(dirs[i]) < 0);
|
||||
bool positive_axis_collides =
|
||||
(nodemin < objectmax && nodemin >= objectmax_old - d
|
||||
&& speed_f.dotProduct(dirs[i]) > 0);
|
||||
bool main_axis_collides =
|
||||
negative_axis_collides || positive_axis_collides;
|
||||
|
||||
/*
|
||||
Check overlap of object and node in other axes
|
||||
*/
|
||||
bool other_axes_overlap = true;
|
||||
for(u16 j=0; j<3; j++)
|
||||
if(is_step_up[boxindex])
|
||||
{
|
||||
if(j == i)
|
||||
continue;
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
||||
f32 objectmax = box.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 objectmin = box.MinEdge.dotProduct(dirs[j]);
|
||||
if(!(nodemax - d > objectmin && nodemin + d < objectmax))
|
||||
{
|
||||
other_axes_overlap = false;
|
||||
break;
|
||||
}
|
||||
pos_f.Y += (cbox.MaxEdge.Y - box.MinEdge.Y);
|
||||
box = box_0;
|
||||
box.MinEdge += pos_f;
|
||||
box.MaxEdge += pos_f;
|
||||
}
|
||||
|
||||
/*
|
||||
If this is a collision, revert the pos_f in the main
|
||||
direction.
|
||||
*/
|
||||
if(other_axes_overlap && main_axis_collides)
|
||||
if(fabs(cbox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS)
|
||||
{
|
||||
speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i];
|
||||
pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i];
|
||||
pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i];
|
||||
result.collides = true;
|
||||
result.touching_ground = true;
|
||||
if(is_unloaded[boxindex])
|
||||
result.standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
}
|
||||
} // xyz
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This doesn't seem to work and isn't used
|
||||
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f)
|
||||
{
|
||||
//TimeTaker tt("collisionMovePrecise");
|
||||
ScopeProfiler sp(g_profiler, "collisionMovePrecise avg", SPT_AVG);
|
||||
|
||||
collisionMoveResult final_result;
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// time = distance / speed
|
||||
f32 dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||
|
||||
// Maximum time increment is 10ms or lower
|
||||
if(dtime_max_increment > 0.01)
|
||||
dtime_max_increment = 0.01;
|
||||
|
||||
// If there is no speed, there are no collisions
|
||||
if(speed_f.getLength() == 0)
|
||||
return final_result;
|
||||
|
||||
// Don't allow overly huge dtime
|
||||
if(dtime > 2.0)
|
||||
dtime = 2.0;
|
||||
|
||||
|
||||
f32 dtime_downcount = dtime;
|
||||
|
||||
u32 loopcount = 0;
|
||||
@@ -216,6 +459,16 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// time = distance / speed
|
||||
f32 dtime_max_increment = 1.0;
|
||||
if(speed_f.getLength() != 0)
|
||||
dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||
|
||||
// Maximum time increment is 10ms or lower
|
||||
if(dtime_max_increment > 0.01)
|
||||
dtime_max_increment = 0.01;
|
||||
|
||||
f32 dtime_part;
|
||||
if(dtime_downcount > dtime_max_increment)
|
||||
{
|
||||
@@ -234,17 +487,20 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
}
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(map, gamedef,
|
||||
pos_max_d, box_0, dtime_part, pos_f, speed_f);
|
||||
pos_max_d, box_0, stepheight, dtime_part,
|
||||
pos_f, speed_f, accel_f);
|
||||
|
||||
if(result.touching_ground)
|
||||
final_result.touching_ground = true;
|
||||
if(result.collides)
|
||||
final_result.collides = true;
|
||||
if(result.collides_xz)
|
||||
final_result.collides_xz = true;
|
||||
if(result.standing_on_unloaded)
|
||||
final_result.standing_on_unloaded = true;
|
||||
}
|
||||
while(dtime_downcount > 0.001);
|
||||
|
||||
|
||||
return final_result;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef COLLISION_HEADER
|
||||
#define COLLISION_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <vector>
|
||||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
@@ -29,22 +30,47 @@ struct collisionMoveResult
|
||||
{
|
||||
bool touching_ground;
|
||||
bool collides;
|
||||
bool collides_xz;
|
||||
bool standing_on_unloaded;
|
||||
|
||||
collisionMoveResult():
|
||||
touching_ground(false),
|
||||
collides(false)
|
||||
collides(false),
|
||||
collides_xz(false),
|
||||
standing_on_unloaded(false)
|
||||
{}
|
||||
};
|
||||
|
||||
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f);
|
||||
|
||||
#if 0
|
||||
// This doesn't seem to work and isn't used
|
||||
// Moves using as many iterations as needed
|
||||
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f);
|
||||
#endif
|
||||
|
||||
// Helper function:
|
||||
// Checks for collision of a moving aabbox with a static aabbox
|
||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||
// dtime receives time until first collision, invalid if -1 is returned
|
||||
int axisAlignedCollision(
|
||||
const aabb3f &staticbox, const aabb3f &movingbox,
|
||||
const v3f &speed, f32 d, f32 &dtime);
|
||||
|
||||
// Helper function:
|
||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||
bool wouldCollideWithCeiling(
|
||||
const std::vector<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d);
|
||||
|
||||
|
||||
enum CollisionType
|
||||
{
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
|
||||
#define PROJECT_NAME "Minetest"
|
||||
#define VERSION_STRING "unknown"
|
||||
#define BUILD_TYPE "unknown"
|
||||
#define RUN_IN_PLACE 0
|
||||
#define USE_GETTEXT 0
|
||||
#define USE_SOUND 0
|
||||
#define STATIC_SHAREDIR ""
|
||||
#define BUILD_INFO "non-cmake"
|
||||
|
||||
#ifdef USE_CMAKE_CONFIG_H
|
||||
@@ -19,12 +20,14 @@
|
||||
#define PROJECT_NAME CMAKE_PROJECT_NAME
|
||||
#undef VERSION_STRING
|
||||
#define VERSION_STRING CMAKE_VERSION_STRING
|
||||
#undef BUILD_INFO
|
||||
#define BUILD_INFO CMAKE_BUILD_INFO
|
||||
#undef RUN_IN_PLACE
|
||||
#define RUN_IN_PLACE CMAKE_RUN_IN_PLACE
|
||||
#undef USE_GETTEXT
|
||||
#define USE_GETTEXT CMAKE_USE_GETTEXT
|
||||
#undef USE_SOUND
|
||||
#define USE_SOUND CMAKE_USE_SOUND
|
||||
#undef STATIC_SHAREDIR
|
||||
#define STATIC_SHAREDIR CMAKE_STATIC_SHAREDIR
|
||||
#undef BUILD_INFO
|
||||
#define BUILD_INFO CMAKE_BUILD_INFO
|
||||
#endif
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -22,10 +22,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serialization.h"
|
||||
#include "log.h"
|
||||
#include "porting.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/string.h"
|
||||
|
||||
namespace con
|
||||
{
|
||||
|
||||
static u16 readPeerId(u8 *packetdata)
|
||||
{
|
||||
return readU16(&packetdata[4]);
|
||||
}
|
||||
static u8 readChannel(u8 *packetdata)
|
||||
{
|
||||
return readU8(&packetdata[6]);
|
||||
}
|
||||
|
||||
BufferedPacket makePacket(Address &address, u8 *data, u32 datasize,
|
||||
u32 protocol_id, u16 sender_peer_id, u8 channel)
|
||||
{
|
||||
@@ -353,9 +365,11 @@ SharedBuffer<u8> IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable)
|
||||
<<" != sp->reliable="<<sp->reliable
|
||||
<<std::endl;
|
||||
|
||||
// If chunk already exists, cancel
|
||||
// If chunk already exists, ignore it.
|
||||
// Sometimes two identical packets may arrive when there is network
|
||||
// lag and the server re-sends stuff.
|
||||
if(sp->chunks.find(chunk_num) != NULL)
|
||||
throw AlreadyExistsException("Chunk already in buffer");
|
||||
return SharedBuffer<u8>();
|
||||
|
||||
// Cut chunk data out of packet
|
||||
u32 chunkdatasize = p.data.getSize() - headersize;
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,14 +20,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CONNECTION_HEADER
|
||||
#define CONNECTION_HEADER
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "debug.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "socket.h"
|
||||
#include "utility.h"
|
||||
#include "exceptions.h"
|
||||
#include "constants.h"
|
||||
#include "util/pointer.h"
|
||||
#include "util/container.h"
|
||||
#include "util/thread.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace con
|
||||
{
|
||||
@@ -107,15 +108,6 @@ class ProcessedSilentlyException : public BaseException
|
||||
{}
|
||||
};
|
||||
|
||||
inline u16 readPeerId(u8 *packetdata)
|
||||
{
|
||||
return readU16(&packetdata[4]);
|
||||
}
|
||||
inline u8 readChannel(u8 *packetdata)
|
||||
{
|
||||
return readU8(&packetdata[6]);
|
||||
}
|
||||
|
||||
#define SEQNUM_MAX 65535
|
||||
inline bool seqnum_higher(u16 higher, u16 lower)
|
||||
{
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -24,11 +24,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
All kinds of constants.
|
||||
|
||||
Cross-platform compatibility crap should go in porting.h.
|
||||
|
||||
Some things here are legacy crap.
|
||||
*/
|
||||
|
||||
//#define HAXMODE 0
|
||||
|
||||
#define DEBUGFILE "debug.txt"
|
||||
/*
|
||||
Connection
|
||||
*/
|
||||
|
||||
// Define for simulating the quirks of sending through internet.
|
||||
// Causes the socket class to deliberately drop random packets.
|
||||
@@ -42,66 +44,52 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// resend_timeout = avg_rtt * this
|
||||
#define RESEND_TIMEOUT_FACTOR 4
|
||||
|
||||
#define PI 3.14159
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's
|
||||
// going near the limit or not, so this is lower.
|
||||
#define MAP_GENERATION_LIMIT (31000)
|
||||
|
||||
// Size of node in rendering units
|
||||
#define BS (10.0)
|
||||
|
||||
#define MAP_BLOCKSIZE 16
|
||||
/*
|
||||
This makes mesh updates too slow, as many meshes are updated during
|
||||
the main loop (related to TempMods and day/night)
|
||||
Server
|
||||
*/
|
||||
//#define MAP_BLOCKSIZE 32
|
||||
|
||||
// Sectors are split to SECTOR_HEIGHTMAP_SPLIT^2 heightmaps
|
||||
#define SECTOR_HEIGHTMAP_SPLIT (MAP_BLOCKSIZE/8)
|
||||
|
||||
// Time after building, during which the following limit
|
||||
// is in use
|
||||
//#define FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING 2.0
|
||||
// This many blocks are sent when player is building
|
||||
#define LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS 0
|
||||
// Override for the previous one when distance of block
|
||||
// is very low
|
||||
// Override for the previous one when distance of block is very low
|
||||
#define BLOCK_SEND_DISABLE_LIMITS_MAX_D 1
|
||||
|
||||
/*
|
||||
Map-related things
|
||||
*/
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's going near
|
||||
// the limit or not, so this is lower.
|
||||
#define MAP_GENERATION_LIMIT (31000)
|
||||
|
||||
// Size of node in floating-point units
|
||||
// The original idea behind this is to disallow plain casts between
|
||||
// floating-point and integer positions, which potentially give wrong
|
||||
// results. (negative coordinates, values between nodes, ...)
|
||||
// Use floatToInt(p, BS) and intToFloat(p, BS).
|
||||
#define BS (10.0)
|
||||
|
||||
// Dimension of a MapBlock
|
||||
#define MAP_BLOCKSIZE 16
|
||||
// This makes mesh updates too slow, as many meshes are updated during
|
||||
// the main loop (related to TempMods and day/night)
|
||||
//#define MAP_BLOCKSIZE 32
|
||||
|
||||
/*
|
||||
Old stuff that shouldn't be hardcoded
|
||||
*/
|
||||
|
||||
// Size of player's main inventory
|
||||
#define PLAYER_INVENTORY_SIZE (8*4)
|
||||
|
||||
#define SIGN_TEXT_MAX_LENGTH 50
|
||||
|
||||
// Whether to catch all std::exceptions.
|
||||
// Assert will be called on such an event.
|
||||
// In debug mode, leave these for the debugger and don't catch them.
|
||||
#ifdef NDEBUG
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
#else
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
Collecting active blocks is stopped after object data
|
||||
size reaches this
|
||||
*/
|
||||
#define MAX_OBJECTDATA_SIZE 450
|
||||
|
||||
/*
|
||||
This is good to be a bit different than 0 so that water level
|
||||
is not between two MapBlocks
|
||||
This is good to be a bit different than 0 so that water level is not
|
||||
between two MapBlocks
|
||||
*/
|
||||
#define WATER_LEVEL 1
|
||||
|
||||
// Length of cracking animation in count of images
|
||||
#define CRACK_ANIMATION_LENGTH 5
|
||||
|
||||
// Some stuff needed by old code moved to here from heightmap.h
|
||||
#define GROUNDHEIGHT_NOTFOUND_SETVALUE (-10e6)
|
||||
#define GROUNDHEIGHT_VALID_MINVALUE ( -9e6)
|
||||
// Maximum hit points of a player
|
||||
#define PLAYER_MAX_HP 20
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "mapblock.h" // For getNodeBlockPos
|
||||
#include "mapgen.h" // For mapgen::make_tree
|
||||
#include "map.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "environment.h"
|
||||
#include "gamedef.h"
|
||||
#include "log.h"
|
||||
#include "map.h"
|
||||
|
||||
static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
|
||||
float txs, float tys, int col, int row)
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CONTENT_CSO_HEADER
|
||||
#define CONTENT_CSO_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "clientsimpleobject.h"
|
||||
|
||||
ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr,
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -25,6 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
#include "tile.h"
|
||||
#include "gamedef.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/directiontables.h"
|
||||
|
||||
// Create a cuboid.
|
||||
// collector - the MeshCollector for the resulting polygons
|
||||
@@ -210,8 +213,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
top_is_same_liquid = true;
|
||||
|
||||
u16 l = 0;
|
||||
// If this liquid emits light and doesn't contain light, draw
|
||||
// it at what it emits, for an increased effect
|
||||
u8 light_source = nodedef->get(n).light_source;
|
||||
if(light_source != 0){
|
||||
//l = decode_light(undiminish_light(light_source));
|
||||
l = decode_light(light_source);
|
||||
l = l | (l<<8);
|
||||
}
|
||||
// Use the light of the node on top if possible
|
||||
if(nodedef->get(ntop).param_type == CPT_LIGHT)
|
||||
else if(nodedef->get(ntop).param_type == CPT_LIGHT)
|
||||
l = getInteriorLight(ntop, 0, data);
|
||||
// Otherwise use the light of this node (the liquid)
|
||||
else
|
||||
@@ -463,7 +474,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
pa_liquid.x0(), pa_liquid.y0()),
|
||||
};
|
||||
|
||||
// This fixes a strange bug
|
||||
// To get backface culling right, the vertices need to go
|
||||
// clockwise around the front of the face. And we happened to
|
||||
// calculate corner levels in exact reverse order.
|
||||
s32 corner_resolve[4] = {3,2,1,0};
|
||||
|
||||
for(s32 i=0; i<4; i++)
|
||||
@@ -474,6 +487,52 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
vertices[i].Pos.Y += corner_levels[j];
|
||||
vertices[i].Pos += intToFloat(p, BS);
|
||||
}
|
||||
|
||||
// Default downwards-flowing texture animation goes from
|
||||
// -Z towards +Z, thus the direction is +Z.
|
||||
// Rotate texture to make animation go in flow direction
|
||||
// Positive if liquid moves towards +Z
|
||||
int dz = (corner_levels[side_corners[2][0]] +
|
||||
corner_levels[side_corners[2][1]] <
|
||||
corner_levels[side_corners[3][0]] +
|
||||
corner_levels[side_corners[3][1]]);
|
||||
// Positive if liquid moves towards +X
|
||||
int dx = (corner_levels[side_corners[0][0]] +
|
||||
corner_levels[side_corners[0][1]] <
|
||||
corner_levels[side_corners[1][0]] +
|
||||
corner_levels[side_corners[1][1]]);
|
||||
// -X
|
||||
if(-dx >= abs(dz))
|
||||
{
|
||||
v2f t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = t;
|
||||
}
|
||||
// +X
|
||||
if(dx >= abs(dz))
|
||||
{
|
||||
v2f t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = t;
|
||||
}
|
||||
// -Z
|
||||
if(-dz >= abs(dx))
|
||||
{
|
||||
v2f t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = t;
|
||||
t = vertices[0].TCoords;
|
||||
vertices[0].TCoords = vertices[3].TCoords;
|
||||
vertices[3].TCoords = vertices[2].TCoords;
|
||||
vertices[2].TCoords = vertices[1].TCoords;
|
||||
vertices[1].TCoords = t;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
@@ -727,12 +786,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
|
||||
TileSpec tile_nocrack = tile;
|
||||
tile_nocrack.material_flags &= ~MATERIAL_FLAG_CRACK;
|
||||
|
||||
|
||||
// A hack to put wood the right way around in the posts
|
||||
ITextureSource *tsrc = data->m_gamedef->tsrc();
|
||||
TileSpec tile_rot = tile;
|
||||
tile_rot.texture = tsrc->getTexture(tsrc->getTextureName(
|
||||
tile.texture.id) + "^[transformR90");
|
||||
|
||||
u16 l = getInteriorLight(n, 1, data);
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
const f32 post_rad=(f32)BS/10;
|
||||
const f32 bar_rad=(f32)BS/20;
|
||||
const f32 post_rad=(f32)BS/8;
|
||||
const f32 bar_rad=(f32)BS/16;
|
||||
const f32 bar_len=(f32)(BS/2)-post_rad;
|
||||
|
||||
v3f pos = intToFloat(p, BS);
|
||||
@@ -742,13 +807,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
post.MinEdge += pos;
|
||||
post.MaxEdge += pos;
|
||||
f32 postuv[24]={
|
||||
0.4,0.4,0.6,0.6,
|
||||
0.4,0.4,0.6,0.6,
|
||||
0.35,0,0.65,1,
|
||||
0.35,0,0.65,1,
|
||||
0.35,0,0.65,1,
|
||||
0.35,0,0.65,1};
|
||||
makeCuboid(&collector, post, &tile, 1, c, postuv);
|
||||
6/16.,6/16.,10/16.,10/16.,
|
||||
6/16.,6/16.,10/16.,10/16.,
|
||||
0/16.,0,4/16.,1,
|
||||
4/16.,0,8/16.,1,
|
||||
8/16.,0,12/16.,1,
|
||||
12/16.,0,16/16.,1};
|
||||
makeCuboid(&collector, post, &tile_rot, 1, c, postuv);
|
||||
|
||||
// Now a section of fence, +X, if there's a post there
|
||||
v3s16 p2 = p;
|
||||
@@ -762,17 +827,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
bar.MinEdge += pos;
|
||||
bar.MaxEdge += pos;
|
||||
f32 xrailuv[24]={
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6};
|
||||
0/16.,2/16.,16/16.,4/16.,
|
||||
0/16.,4/16.,16/16.,6/16.,
|
||||
6/16.,6/16.,8/16.,8/16.,
|
||||
10/16.,10/16.,12/16.,12/16.,
|
||||
0/16.,8/16.,16/16.,10/16.,
|
||||
0/16.,14/16.,16/16.,16/16.};
|
||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||
c, xrailuv);
|
||||
bar.MinEdge.Y -= BS/2;
|
||||
bar.MaxEdge.Y -= BS/2;
|
||||
// TODO: no crack
|
||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||
c, xrailuv);
|
||||
}
|
||||
@@ -789,13 +853,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
bar.MinEdge += pos;
|
||||
bar.MaxEdge += pos;
|
||||
f32 zrailuv[24]={
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6};
|
||||
|
||||
3/16.,1/16.,5/16.,5/16., // cannot rotate; stretch
|
||||
4/16.,1/16.,6/16.,5/16., // for wood texture instead
|
||||
0/16.,9/16.,16/16.,11/16.,
|
||||
0/16.,6/16.,16/16.,8/16.,
|
||||
6/16.,6/16.,8/16.,8/16.,
|
||||
10/16.,10/16.,12/16.,12/16.};
|
||||
makeCuboid(&collector, bar, &tile_nocrack, 1,
|
||||
c, zrailuv);
|
||||
bar.MinEdge.Y -= BS/2;
|
||||
@@ -856,7 +919,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
if(n_plus_z_plus_y.getContent() == thiscontent)
|
||||
is_rail_z_plus_y[1] = true;
|
||||
|
||||
|
||||
bool is_rail_x_all[] = {false, false};
|
||||
bool is_rail_z_all[] = {false, false};
|
||||
is_rail_x_all[0]=is_rail_x[0] || is_rail_x_minus_y[0] || is_rail_x_plus_y[0];
|
||||
@@ -864,30 +926,69 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
is_rail_z_all[0]=is_rail_z[0] || is_rail_z_minus_y[0] || is_rail_z_plus_y[0];
|
||||
is_rail_z_all[1]=is_rail_z[1] || is_rail_z_minus_y[1] || is_rail_z_plus_y[1];
|
||||
|
||||
bool is_straight = (is_rail_x_all[0] && is_rail_x_all[1]) || (is_rail_z_all[0] && is_rail_z_all[1]);//is really straight, rails on both sides
|
||||
int adjacencies = is_rail_x_all[0] + is_rail_x_all[1] + is_rail_z_all[0] + is_rail_z_all[1];
|
||||
// reasonable default, flat straight unrotated rail
|
||||
bool is_straight = true;
|
||||
int adjacencies = 0;
|
||||
int angle = 0;
|
||||
u8 tileindex = 0;
|
||||
|
||||
if (is_rail_x_plus_y[0] || is_rail_x_plus_y[1] || is_rail_z_plus_y[0] || is_rail_z_plus_y[1]) //is straight because sloped
|
||||
// check for sloped rail
|
||||
if (is_rail_x_plus_y[0] || is_rail_x_plus_y[1] || is_rail_z_plus_y[0] || is_rail_z_plus_y[1])
|
||||
{
|
||||
adjacencies = 5; //5 means sloped
|
||||
is_straight = true;
|
||||
is_straight = true; // sloped is always straight
|
||||
}
|
||||
else
|
||||
{
|
||||
// is really straight, rails on both sides
|
||||
is_straight = (is_rail_x_all[0] && is_rail_x_all[1]) || (is_rail_z_all[0] && is_rail_z_all[1]);
|
||||
adjacencies = is_rail_x_all[0] + is_rail_x_all[1] + is_rail_z_all[0] + is_rail_z_all[1];
|
||||
}
|
||||
|
||||
// Assign textures
|
||||
u8 tileindex = 0; // straight
|
||||
if(adjacencies < 2)
|
||||
tileindex = 0; // straight
|
||||
else if(adjacencies == 2)
|
||||
{
|
||||
if(is_straight)
|
||||
tileindex = 0; // straight
|
||||
else
|
||||
switch (adjacencies) {
|
||||
case 1:
|
||||
if(is_rail_x_all[0] || is_rail_x_all[1])
|
||||
angle = 90;
|
||||
break;
|
||||
case 2:
|
||||
if(!is_straight)
|
||||
tileindex = 1; // curved
|
||||
}
|
||||
else if(adjacencies == 3)
|
||||
if(is_rail_x_all[0] && is_rail_x_all[1])
|
||||
angle = 90;
|
||||
if(is_rail_z_all[0] && is_rail_z_all[1]){
|
||||
if (n_minus_z_plus_y.getContent() == thiscontent) angle = 180;
|
||||
}
|
||||
else if(is_rail_x_all[0] && is_rail_z_all[0])
|
||||
angle = 270;
|
||||
else if(is_rail_x_all[0] && is_rail_z_all[1])
|
||||
angle = 180;
|
||||
else if(is_rail_x_all[1] && is_rail_z_all[1])
|
||||
angle = 90;
|
||||
break;
|
||||
case 3:
|
||||
// here is where the potential to 'switch' a junction is, but not implemented at present
|
||||
tileindex = 2; // t-junction
|
||||
else if(adjacencies == 4)
|
||||
if(!is_rail_x_all[1])
|
||||
angle=180;
|
||||
if(!is_rail_z_all[0])
|
||||
angle=90;
|
||||
if(!is_rail_z_all[1])
|
||||
angle=270;
|
||||
break;
|
||||
case 4:
|
||||
tileindex = 3; // crossing
|
||||
break;
|
||||
case 5: //sloped
|
||||
if(is_rail_z_plus_y[0])
|
||||
angle = 180;
|
||||
if(is_rail_x_plus_y[0])
|
||||
angle = 90;
|
||||
if(is_rail_x_plus_y[1])
|
||||
angle = -90;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TileSpec tile = getNodeTileN(n, p, tileindex, data);
|
||||
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
@@ -916,67 +1017,73 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
ap.x0(), ap.y0()),
|
||||
};
|
||||
|
||||
|
||||
// Rotate textures
|
||||
int angle = 0;
|
||||
|
||||
if(adjacencies == 1)
|
||||
{
|
||||
if(is_rail_x_all[0] || is_rail_x_all[1])
|
||||
angle = 90;
|
||||
}
|
||||
if(adjacencies == 2)
|
||||
{
|
||||
if(is_rail_x_all[0] && is_rail_x_all[1])
|
||||
{
|
||||
angle = 90;
|
||||
}
|
||||
if(is_rail_z_all[0] && is_rail_z_all[1])
|
||||
{
|
||||
if (n_minus_z_plus_y.getContent() == thiscontent) angle = 180;
|
||||
}
|
||||
else if(is_rail_x_all[0] && is_rail_z_all[0])
|
||||
angle = 270;
|
||||
else if(is_rail_x_all[0] && is_rail_z_all[1])
|
||||
angle = 180;
|
||||
else if(is_rail_x_all[1] && is_rail_z_all[1])
|
||||
angle = 90;
|
||||
}
|
||||
if(adjacencies == 3)
|
||||
{
|
||||
if(!is_rail_x_all[0])
|
||||
angle=0;
|
||||
if(!is_rail_x_all[1])
|
||||
angle=180;
|
||||
if(!is_rail_z_all[0])
|
||||
angle=90;
|
||||
if(!is_rail_z_all[1])
|
||||
angle=270;
|
||||
}
|
||||
//adjacencies 4: Crossing
|
||||
if(adjacencies == 5) //sloped
|
||||
{
|
||||
if(is_rail_z_plus_y[0])
|
||||
angle = 180;
|
||||
if(is_rail_x_plus_y[0])
|
||||
angle = 90;
|
||||
if(is_rail_x_plus_y[1])
|
||||
angle = -90;
|
||||
}
|
||||
|
||||
if(angle != 0) {
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(angle);
|
||||
}
|
||||
|
||||
for(s32 i=0; i<4; i++)
|
||||
{
|
||||
if(angle != 0)
|
||||
vertices[i].Pos.rotateXZBy(angle);
|
||||
vertices[i].Pos += intToFloat(p, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
collector.append(tile, vertices, 4, indices, 6);
|
||||
break;}
|
||||
case NDT_NODEBOX:
|
||||
{
|
||||
static const v3s16 tile_dirs[6] = {
|
||||
v3s16(0, 1, 0),
|
||||
v3s16(0, -1, 0),
|
||||
v3s16(1, 0, 0),
|
||||
v3s16(-1, 0, 0),
|
||||
v3s16(0, 0, 1),
|
||||
v3s16(0, 0, -1)
|
||||
};
|
||||
|
||||
TileSpec tiles[6];
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
// Handles facedir rotation for textures
|
||||
tiles[i] = getNodeTile(n, p, tile_dirs[i], data);
|
||||
}
|
||||
|
||||
u16 l = getInteriorLight(n, 0, data);
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
v3f pos = intToFloat(p, BS);
|
||||
|
||||
std::vector<aabb3f> boxes = n.getNodeBoxes(nodedef);
|
||||
for(std::vector<aabb3f>::iterator
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += pos;
|
||||
box.MaxEdge += pos;
|
||||
|
||||
// Compute texture coords
|
||||
f32 tx1 = (i->MinEdge.X/BS)+0.5;
|
||||
f32 ty1 = (i->MinEdge.Y/BS)+0.5;
|
||||
f32 tz1 = (i->MinEdge.Z/BS)+0.5;
|
||||
f32 tx2 = (i->MaxEdge.X/BS)+0.5;
|
||||
f32 ty2 = (i->MaxEdge.Y/BS)+0.5;
|
||||
f32 tz2 = (i->MaxEdge.Z/BS)+0.5;
|
||||
f32 txc[24] = {
|
||||
// up
|
||||
tx1, 1-tz2, tx2, 1-tz1,
|
||||
// down
|
||||
tx1, tz1, tx2, tz2,
|
||||
// right
|
||||
tz1, 1-ty2, tz2, 1-ty1,
|
||||
// left
|
||||
1-tz2, 1-ty2, 1-tz1, 1-ty1,
|
||||
// back
|
||||
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
||||
// front
|
||||
tx1, 1-ty2, tx2, 1-ty1,
|
||||
};
|
||||
|
||||
makeCuboid(&collector, box, tiles, 6, c, txc);
|
||||
}
|
||||
break;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,26 +3,25 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "content_mapnode.h"
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "mapnode.h"
|
||||
#include "nodedef.h"
|
||||
#include "utility.h"
|
||||
#include "nameidmapping.h"
|
||||
#include <map>
|
||||
|
||||
@@ -103,23 +102,6 @@ content_t trans_table_19[21][2] = {
|
||||
{CONTENT_BOOKSHELF, 29},
|
||||
};
|
||||
|
||||
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version)
|
||||
{
|
||||
MapNode result = n_from;
|
||||
if(version <= 19)
|
||||
{
|
||||
content_t c_from = n_from.getContent();
|
||||
for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++)
|
||||
{
|
||||
if(trans_table_19[i][0] == c_from)
|
||||
{
|
||||
result.setContent(trans_table_19[i][1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
|
||||
{
|
||||
MapNode result = n_from;
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
// Backwards compatibility for non-extended content types in v19
|
||||
extern content_t trans_table_19[21][2];
|
||||
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version);
|
||||
MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
|
||||
|
||||
// Get legacy node name mapping for loading old blocks
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2010-2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "content_nodemeta.h"
|
||||
|
||||
#include <map>
|
||||
#include "inventory.h"
|
||||
#include "log.h"
|
||||
#include "utility.h"
|
||||
#include "craftdef.h"
|
||||
#include "gamedef.h"
|
||||
|
||||
class Inventory;
|
||||
#include "util/serialize.h"
|
||||
#include "util/string.h"
|
||||
#include "constants.h" // MAP_BLOCKSIZE
|
||||
#include <sstream>
|
||||
|
||||
#define NODEMETA_GENERIC 1
|
||||
#define NODEMETA_SIGN 14
|
||||
@@ -34,809 +31,167 @@ class Inventory;
|
||||
#define NODEMETA_FURNACE 16
|
||||
#define NODEMETA_LOCKABLE_CHEST 17
|
||||
|
||||
core::map<u16, NodeMetadata::Factory> NodeMetadata::m_types;
|
||||
core::map<std::string, NodeMetadata::Factory2> NodeMetadata::m_names;
|
||||
// Returns true if node timer must be set
|
||||
static bool content_nodemeta_deserialize_legacy_body(
|
||||
std::istream &is, s16 id, NodeMetadata *meta)
|
||||
{
|
||||
meta->clear();
|
||||
|
||||
class SignNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
SignNodeMetadata(IGameDef *gamedef, std::string text);
|
||||
//~SignNodeMetadata();
|
||||
|
||||
virtual u16 typeId() const;
|
||||
virtual const char* typeName() const
|
||||
{ return "sign"; }
|
||||
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
|
||||
static NodeMetadata* create(IGameDef *gamedef);
|
||||
virtual NodeMetadata* clone(IGameDef *gamedef);
|
||||
virtual void serializeBody(std::ostream &os);
|
||||
virtual std::string infoText();
|
||||
|
||||
virtual bool allowsTextInput(){ return true; }
|
||||
virtual std::string getText(){ return m_text; }
|
||||
virtual void setText(const std::string &t){ m_text = t; }
|
||||
|
||||
private:
|
||||
std::string m_text;
|
||||
};
|
||||
|
||||
class ChestNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
ChestNodeMetadata(IGameDef *gamedef);
|
||||
~ChestNodeMetadata();
|
||||
|
||||
virtual u16 typeId() const;
|
||||
virtual const char* typeName() const
|
||||
{ return "chest"; }
|
||||
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
|
||||
static NodeMetadata* create(IGameDef *gamedef);
|
||||
virtual NodeMetadata* clone(IGameDef *gamedef);
|
||||
virtual void serializeBody(std::ostream &os);
|
||||
virtual std::string infoText();
|
||||
virtual Inventory* getInventory() {return m_inventory;}
|
||||
virtual bool nodeRemovalDisabled();
|
||||
virtual std::string getInventoryDrawSpecString();
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
};
|
||||
|
||||
class LockingChestNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
LockingChestNodeMetadata(IGameDef *gamedef);
|
||||
~LockingChestNodeMetadata();
|
||||
|
||||
virtual u16 typeId() const;
|
||||
virtual const char* typeName() const
|
||||
{ return "locked_chest"; }
|
||||
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
|
||||
static NodeMetadata* create(IGameDef *gamedef);
|
||||
virtual NodeMetadata* clone(IGameDef *gamedef);
|
||||
virtual void serializeBody(std::ostream &os);
|
||||
virtual std::string infoText();
|
||||
virtual Inventory* getInventory() {return m_inventory;}
|
||||
virtual bool nodeRemovalDisabled();
|
||||
virtual std::string getInventoryDrawSpecString();
|
||||
|
||||
virtual std::string getOwner(){ return m_text; }
|
||||
virtual void setOwner(std::string t){ m_text = t; }
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
std::string m_text;
|
||||
};
|
||||
|
||||
class FurnaceNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
FurnaceNodeMetadata(IGameDef *gamedef);
|
||||
~FurnaceNodeMetadata();
|
||||
|
||||
virtual u16 typeId() const;
|
||||
virtual const char* typeName() const
|
||||
{ return "furnace"; }
|
||||
virtual NodeMetadata* clone(IGameDef *gamedef);
|
||||
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
|
||||
static NodeMetadata* create(IGameDef *gamedef);
|
||||
virtual void serializeBody(std::ostream &os);
|
||||
virtual std::string infoText();
|
||||
virtual Inventory* getInventory() {return m_inventory;}
|
||||
virtual void inventoryModified();
|
||||
virtual bool step(float dtime);
|
||||
virtual bool nodeRemovalDisabled();
|
||||
virtual std::string getInventoryDrawSpecString();
|
||||
|
||||
protected:
|
||||
bool getCookResult(bool remove, std::string &cookresult, float &cooktime);
|
||||
bool getBurnResult(bool remove, float &burntime);
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
std::string m_infotext;
|
||||
float m_step_accumulator;
|
||||
float m_fuel_totaltime;
|
||||
float m_fuel_time;
|
||||
float m_src_totaltime;
|
||||
float m_src_time;
|
||||
};
|
||||
|
||||
/*
|
||||
SignNodeMetadata
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
SignNodeMetadata proto_SignNodeMetadata(NULL, "");
|
||||
|
||||
SignNodeMetadata::SignNodeMetadata(IGameDef *gamedef, std::string text):
|
||||
NodeMetadata(gamedef),
|
||||
m_text(text)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
}
|
||||
u16 SignNodeMetadata::typeId() const
|
||||
{
|
||||
return NODEMETA_SIGN;
|
||||
}
|
||||
NodeMetadata* SignNodeMetadata::create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
std::string text = deSerializeString(is);
|
||||
return new SignNodeMetadata(gamedef, text);
|
||||
}
|
||||
NodeMetadata* SignNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
return new SignNodeMetadata(gamedef, "");
|
||||
}
|
||||
NodeMetadata* SignNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
return new SignNodeMetadata(gamedef, m_text);
|
||||
}
|
||||
void SignNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
os<<serializeString(m_text);
|
||||
}
|
||||
std::string SignNodeMetadata::infoText()
|
||||
{
|
||||
return std::string("\"")+m_text+"\"";
|
||||
}
|
||||
|
||||
/*
|
||||
ChestNodeMetadata
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
ChestNodeMetadata proto_ChestNodeMetadata(NULL);
|
||||
|
||||
ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
m_inventory = NULL;
|
||||
}
|
||||
ChestNodeMetadata::~ChestNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
u16 ChestNodeMetadata::typeId() const
|
||||
{
|
||||
return NODEMETA_CHEST;
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->addList("0", 8*4);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
return d;
|
||||
}
|
||||
void ChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
m_inventory->serialize(os);
|
||||
}
|
||||
std::string ChestNodeMetadata::infoText()
|
||||
{
|
||||
return "Chest";
|
||||
}
|
||||
bool ChestNodeMetadata::nodeRemovalDisabled()
|
||||
{
|
||||
/*
|
||||
Disable removal if chest contains something
|
||||
*/
|
||||
InventoryList *list = m_inventory->getList("0");
|
||||
if(list == NULL)
|
||||
return false;
|
||||
if(list->getUsedSlots() == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string ChestNodeMetadata::getInventoryDrawSpecString()
|
||||
{
|
||||
return
|
||||
"invsize[8,9;]"
|
||||
"list[current_name;0;0,0;8,4;]"
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
|
||||
/*
|
||||
LockingChestNodeMetadata
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL);
|
||||
|
||||
LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
m_inventory = NULL;
|
||||
}
|
||||
LockingChestNodeMetadata::~LockingChestNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
u16 LockingChestNodeMetadata::typeId() const
|
||||
{
|
||||
return NODEMETA_LOCKABLE_CHEST;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
|
||||
d->setOwner(deSerializeString(is));
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->addList("0", 8*4);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
return d;
|
||||
}
|
||||
void LockingChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
os<<serializeString(m_text);
|
||||
m_inventory->serialize(os);
|
||||
}
|
||||
std::string LockingChestNodeMetadata::infoText()
|
||||
{
|
||||
return "Locking Chest";
|
||||
}
|
||||
bool LockingChestNodeMetadata::nodeRemovalDisabled()
|
||||
{
|
||||
/*
|
||||
Disable removal if chest contains something
|
||||
*/
|
||||
InventoryList *list = m_inventory->getList("0");
|
||||
if(list == NULL)
|
||||
return false;
|
||||
if(list->getUsedSlots() == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
|
||||
{
|
||||
return
|
||||
"invsize[8,9;]"
|
||||
"list[current_name;0;0,0;8,4;]"
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
|
||||
/*
|
||||
FurnaceNodeMetadata
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
FurnaceNodeMetadata proto_FurnaceNodeMetadata(NULL);
|
||||
|
||||
FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
|
||||
m_inventory = NULL;
|
||||
|
||||
m_infotext = "Furnace is inactive";
|
||||
|
||||
m_step_accumulator = 0;
|
||||
m_fuel_totaltime = 0;
|
||||
m_fuel_time = 0;
|
||||
m_src_totaltime = 0;
|
||||
m_src_time = 0;
|
||||
}
|
||||
FurnaceNodeMetadata::~FurnaceNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
u16 FurnaceNodeMetadata::typeId() const
|
||||
{
|
||||
return NODEMETA_FURNACE;
|
||||
}
|
||||
NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef);
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
|
||||
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
|
||||
int temp = 0;
|
||||
is>>temp;
|
||||
d->m_fuel_totaltime = (float)temp/10;
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
d->m_fuel_time = (float)temp/10;
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
d->m_src_totaltime = (float)temp/10;
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
d->m_src_time = (float)temp/10;
|
||||
|
||||
if(is.eof())
|
||||
if(id == NODEMETA_GENERIC) // GenericNodeMetadata (0.4-dev)
|
||||
{
|
||||
// Old furnaces didn't serialize src_totaltime and src_time
|
||||
d->m_src_totaltime = 0;
|
||||
d->m_src_time = 0;
|
||||
d->m_infotext = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
// New furnaces also serialize the infotext (so that the
|
||||
// client doesn't need to have the list of cooking recipes).
|
||||
d->m_infotext = deSerializeJsonString(is);
|
||||
}
|
||||
meta->getInventory()->deSerialize(is);
|
||||
deSerializeLongString(is); // m_text
|
||||
deSerializeString(is); // m_owner
|
||||
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* FurnaceNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->addList("fuel", 1);
|
||||
d->m_inventory->addList("src", 1);
|
||||
d->m_inventory->addList("dst", 4);
|
||||
return d;
|
||||
}
|
||||
void FurnaceNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
m_inventory->serialize(os);
|
||||
os<<itos(m_fuel_totaltime*10)<<" ";
|
||||
os<<itos(m_fuel_time*10)<<" ";
|
||||
os<<itos(m_src_totaltime*10)<<" ";
|
||||
os<<itos(m_src_time*10)<<" ";
|
||||
os<<serializeJsonString(m_infotext);
|
||||
}
|
||||
std::string FurnaceNodeMetadata::infoText()
|
||||
{
|
||||
return m_infotext;
|
||||
}
|
||||
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()
|
||||
{
|
||||
infostream<<"Furnace inventory modification callback"<<std::endl;
|
||||
}
|
||||
bool FurnaceNodeMetadata::step(float dtime)
|
||||
{
|
||||
if(dtime > 60.0)
|
||||
infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
|
||||
|
||||
InventoryList *dst_list = m_inventory->getList("dst");
|
||||
assert(dst_list);
|
||||
|
||||
// Update at a fixed frequency
|
||||
const float interval = 2.0;
|
||||
m_step_accumulator += dtime;
|
||||
bool changed = false;
|
||||
while(m_step_accumulator > interval)
|
||||
{
|
||||
m_step_accumulator -= interval;
|
||||
dtime = interval;
|
||||
|
||||
//infostream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||
|
||||
bool changed_this_loop = false;
|
||||
|
||||
// Check
|
||||
// 1. if the source item is cookable
|
||||
// 2. if there is room for the cooked item
|
||||
std::string cookresult;
|
||||
float cooktime;
|
||||
bool cookable = getCookResult(false, cookresult, cooktime);
|
||||
ItemStack cookresult_item;
|
||||
bool room_available = false;
|
||||
if(cookable)
|
||||
{
|
||||
cookresult_item.deSerialize(cookresult, m_gamedef->idef());
|
||||
room_available = dst_list->roomForItem(cookresult_item);
|
||||
}
|
||||
|
||||
// Step fuel time
|
||||
bool burning = (m_fuel_time < m_fuel_totaltime);
|
||||
if(burning)
|
||||
{
|
||||
changed_this_loop = true;
|
||||
m_fuel_time += dtime;
|
||||
}
|
||||
|
||||
std::string infotext;
|
||||
if(room_available)
|
||||
{
|
||||
float burntime;
|
||||
if(burning)
|
||||
{
|
||||
changed_this_loop = true;
|
||||
m_src_time += dtime;
|
||||
m_src_totaltime = cooktime;
|
||||
infotext = "Furnace is cooking";
|
||||
}
|
||||
else if(getBurnResult(true, burntime))
|
||||
{
|
||||
// Fuel inserted
|
||||
changed_this_loop = true;
|
||||
m_fuel_time = 0;
|
||||
m_fuel_totaltime = burntime;
|
||||
//m_src_time += dtime;
|
||||
//m_src_totaltime = cooktime;
|
||||
infotext = "Furnace is cooking";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_src_time = 0;
|
||||
m_src_totaltime = 0;
|
||||
infotext = "Furnace is out of fuel";
|
||||
}
|
||||
if(m_src_totaltime > 0.001 && m_src_time >= m_src_totaltime)
|
||||
{
|
||||
// One item fully cooked
|
||||
changed_this_loop = true;
|
||||
dst_list->addItem(cookresult_item);
|
||||
getCookResult(true, cookresult, cooktime); // decrement source
|
||||
m_src_totaltime = 0;
|
||||
m_src_time = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not cookable or no room available
|
||||
m_src_totaltime = 0;
|
||||
m_src_time = 0;
|
||||
if(cookable)
|
||||
infotext = "Furnace is overloaded";
|
||||
else if(burning)
|
||||
infotext = "Furnace is active";
|
||||
else
|
||||
{
|
||||
infotext = "Furnace is inactive";
|
||||
m_fuel_totaltime = 0;
|
||||
m_fuel_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Do this so it doesn't always show (0%) for weak fuel
|
||||
if(m_fuel_totaltime > 3) {
|
||||
infotext += " (";
|
||||
infotext += itos(m_fuel_time/m_fuel_totaltime*100);
|
||||
infotext += "%)";
|
||||
}
|
||||
|
||||
if(infotext != m_infotext)
|
||||
{
|
||||
m_infotext = infotext;
|
||||
changed_this_loop = true;
|
||||
}
|
||||
|
||||
if(burning && m_fuel_time >= m_fuel_totaltime)
|
||||
{
|
||||
m_fuel_time = 0;
|
||||
m_fuel_totaltime = 0;
|
||||
}
|
||||
|
||||
if(changed_this_loop)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_step_accumulator = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
|
||||
{
|
||||
return
|
||||
"invsize[8,9;]"
|
||||
"list[current_name;fuel;2,3;1,1;]"
|
||||
"list[current_name;src;2,1;1,1;]"
|
||||
"list[current_name;dst;5,1;2,2;]"
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
bool FurnaceNodeMetadata::getCookResult(bool remove,
|
||||
std::string &cookresult, float &cooktime)
|
||||
{
|
||||
std::vector<ItemStack> items;
|
||||
InventoryList *src_list = m_inventory->getList("src");
|
||||
assert(src_list);
|
||||
items.push_back(src_list->getItem(0));
|
||||
|
||||
CraftInput ci(CRAFT_METHOD_COOKING, 1, items);
|
||||
CraftOutput co;
|
||||
bool found = m_gamedef->getCraftDefManager()->getCraftResult(
|
||||
ci, co, remove, m_gamedef);
|
||||
if(remove)
|
||||
src_list->changeItem(0, ci.items[0]);
|
||||
|
||||
cookresult = co.item;
|
||||
cooktime = co.time;
|
||||
return found;
|
||||
}
|
||||
bool FurnaceNodeMetadata::getBurnResult(bool remove, float &burntime)
|
||||
{
|
||||
std::vector<ItemStack> items;
|
||||
InventoryList *fuel_list = m_inventory->getList("fuel");
|
||||
assert(fuel_list);
|
||||
items.push_back(fuel_list->getItem(0));
|
||||
|
||||
CraftInput ci(CRAFT_METHOD_FUEL, 1, items);
|
||||
CraftOutput co;
|
||||
bool found = m_gamedef->getCraftDefManager()->getCraftResult(
|
||||
ci, co, remove, m_gamedef);
|
||||
if(remove)
|
||||
fuel_list->changeItem(0, ci.items[0]);
|
||||
|
||||
burntime = co.time;
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
GenericNodeMetadata
|
||||
*/
|
||||
|
||||
class GenericNodeMetadata : public NodeMetadata
|
||||
{
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
std::string m_text;
|
||||
std::string m_owner;
|
||||
|
||||
std::string m_infotext;
|
||||
std::string m_inventorydrawspec;
|
||||
bool m_allow_text_input;
|
||||
bool m_removal_disabled;
|
||||
bool m_enforce_owner;
|
||||
|
||||
bool m_inventory_modified;
|
||||
bool m_text_modified;
|
||||
|
||||
std::map<std::string, std::string> m_stringvars;
|
||||
|
||||
public:
|
||||
u16 typeId() const
|
||||
{
|
||||
return NODEMETA_GENERIC;
|
||||
}
|
||||
const char* typeName() const
|
||||
{
|
||||
return "generic";
|
||||
}
|
||||
|
||||
GenericNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef),
|
||||
|
||||
m_inventory(NULL),
|
||||
m_text(""),
|
||||
m_owner(""),
|
||||
|
||||
m_infotext("GenericNodeMetadata"),
|
||||
m_inventorydrawspec(""),
|
||||
m_allow_text_input(false),
|
||||
m_removal_disabled(false),
|
||||
m_enforce_owner(false),
|
||||
|
||||
m_inventory_modified(false),
|
||||
m_text_modified(false)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
}
|
||||
virtual ~GenericNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
NodeMetadata* clone(IGameDef *gamedef)
|
||||
{
|
||||
GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
|
||||
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
d->m_text = m_text;
|
||||
d->m_owner = m_owner;
|
||||
|
||||
d->m_infotext = m_infotext;
|
||||
d->m_inventorydrawspec = m_inventorydrawspec;
|
||||
d->m_allow_text_input = m_allow_text_input;
|
||||
d->m_removal_disabled = m_removal_disabled;
|
||||
d->m_enforce_owner = m_enforce_owner;
|
||||
d->m_inventory_modified = m_inventory_modified;
|
||||
d->m_text_modified = m_text_modified;
|
||||
return d;
|
||||
}
|
||||
static NodeMetadata* create(IGameDef *gamedef)
|
||||
{
|
||||
GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
return d;
|
||||
}
|
||||
static NodeMetadata* create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
|
||||
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
d->m_text = deSerializeLongString(is);
|
||||
d->m_owner = deSerializeString(is);
|
||||
|
||||
d->m_infotext = deSerializeString(is);
|
||||
d->m_inventorydrawspec = deSerializeString(is);
|
||||
d->m_allow_text_input = readU8(is);
|
||||
d->m_removal_disabled = readU8(is);
|
||||
d->m_enforce_owner = readU8(is);
|
||||
meta->setString("infotext",deSerializeString(is));
|
||||
meta->setString("formspec",deSerializeString(is));
|
||||
readU8(is); // m_allow_text_input
|
||||
readU8(is); // m_allow_removal
|
||||
readU8(is); // m_enforce_owner
|
||||
|
||||
int num_vars = readU32(is);
|
||||
for(int i=0; i<num_vars; i++){
|
||||
std::string name = deSerializeString(is);
|
||||
std::string var = deSerializeLongString(is);
|
||||
d->m_stringvars[name] = var;
|
||||
meta->setString(name, var);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
void serializeBody(std::ostream &os)
|
||||
{
|
||||
m_inventory->serialize(os);
|
||||
os<<serializeLongString(m_text);
|
||||
os<<serializeString(m_owner);
|
||||
|
||||
os<<serializeString(m_infotext);
|
||||
os<<serializeString(m_inventorydrawspec);
|
||||
writeU8(os, m_allow_text_input);
|
||||
writeU8(os, m_removal_disabled);
|
||||
writeU8(os, m_enforce_owner);
|
||||
|
||||
int num_vars = m_stringvars.size();
|
||||
writeU32(os, num_vars);
|
||||
for(std::map<std::string, std::string>::iterator
|
||||
i = m_stringvars.begin(); i != m_stringvars.end(); i++){
|
||||
os<<serializeString(i->first);
|
||||
os<<serializeLongString(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
std::string infoText()
|
||||
{
|
||||
return m_infotext;
|
||||
}
|
||||
Inventory* getInventory()
|
||||
{
|
||||
return m_inventory;
|
||||
}
|
||||
void inventoryModified()
|
||||
{
|
||||
m_inventory_modified = true;
|
||||
}
|
||||
bool step(float dtime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool nodeRemovalDisabled()
|
||||
else if(id == NODEMETA_SIGN) // SignNodeMetadata
|
||||
{
|
||||
return m_removal_disabled;
|
||||
meta->setString("text", deSerializeString(is));
|
||||
//meta->setString("infotext","\"${text}\"");
|
||||
meta->setString("infotext",
|
||||
std::string("\"") + meta->getString("text") + "\"");
|
||||
meta->setString("formspec","field[text;;${text}]");
|
||||
return false;
|
||||
}
|
||||
std::string getInventoryDrawSpecString()
|
||||
else if(id == NODEMETA_CHEST) // ChestNodeMetadata
|
||||
{
|
||||
return m_inventorydrawspec;
|
||||
}
|
||||
bool allowsTextInput()
|
||||
{
|
||||
return m_allow_text_input;
|
||||
}
|
||||
std::string getText()
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
void setText(const std::string &t)
|
||||
{
|
||||
m_text = t;
|
||||
m_text_modified = true;
|
||||
}
|
||||
std::string getOwner()
|
||||
{
|
||||
if(m_enforce_owner)
|
||||
return m_owner;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
void setOwner(std::string t)
|
||||
{
|
||||
m_owner = t;
|
||||
}
|
||||
|
||||
/* Interface for GenericNodeMetadata */
|
||||
meta->getInventory()->deSerialize(is);
|
||||
|
||||
void setInfoText(const std::string &text)
|
||||
{
|
||||
infostream<<"GenericNodeMetadata::setInfoText(\""
|
||||
<<text<<"\")"<<std::endl;
|
||||
m_infotext = text;
|
||||
// Rename inventory list "0" to "main"
|
||||
Inventory *inv = meta->getInventory();
|
||||
if(!inv->getList("main") && inv->getList("0")){
|
||||
inv->getList("0")->setName("main");
|
||||
}
|
||||
assert(inv->getList("main") && !inv->getList("0"));
|
||||
|
||||
meta->setString("formspec","size[8,9]"
|
||||
"list[current_name;main;0,0;8,4;]"
|
||||
"list[current_player;main;0,5;8,4;]");
|
||||
return false;
|
||||
}
|
||||
void setInventoryDrawSpec(const std::string &text)
|
||||
else if(id == NODEMETA_LOCKABLE_CHEST) // LockingChestNodeMetadata
|
||||
{
|
||||
m_inventorydrawspec = text;
|
||||
}
|
||||
void setAllowTextInput(bool b)
|
||||
{
|
||||
m_allow_text_input = b;
|
||||
}
|
||||
void setRemovalDisabled(bool b)
|
||||
{
|
||||
m_removal_disabled = b;
|
||||
}
|
||||
void setEnforceOwner(bool b)
|
||||
{
|
||||
m_enforce_owner = b;
|
||||
}
|
||||
bool isInventoryModified()
|
||||
{
|
||||
return m_inventory_modified;
|
||||
}
|
||||
void resetInventoryModified()
|
||||
{
|
||||
m_inventory_modified = false;
|
||||
}
|
||||
bool isTextModified()
|
||||
{
|
||||
return m_text_modified;
|
||||
}
|
||||
void resetTextModified()
|
||||
{
|
||||
m_text_modified = false;
|
||||
}
|
||||
void setString(const std::string &name, const std::string &var)
|
||||
{
|
||||
m_stringvars[name] = var;
|
||||
}
|
||||
std::string getString(const std::string &name)
|
||||
{
|
||||
std::map<std::string, std::string>::iterator i;
|
||||
i = m_stringvars.find(name);
|
||||
if(i == m_stringvars.end())
|
||||
return "";
|
||||
return i->second;
|
||||
}
|
||||
};
|
||||
meta->setString("owner", deSerializeString(is));
|
||||
meta->getInventory()->deSerialize(is);
|
||||
|
||||
// Prototype
|
||||
GenericNodeMetadata proto_GenericNodeMetadata(NULL);
|
||||
// Rename inventory list "0" to "main"
|
||||
Inventory *inv = meta->getInventory();
|
||||
if(!inv->getList("main") && inv->getList("0")){
|
||||
inv->getList("0")->setName("main");
|
||||
}
|
||||
assert(inv->getList("main") && !inv->getList("0"));
|
||||
|
||||
meta->setString("formspec","size[8,9]"
|
||||
"list[current_name;main;0,0;8,4;]"
|
||||
"list[current_player;main;0,5;8,4;]");
|
||||
return false;
|
||||
}
|
||||
else if(id == NODEMETA_FURNACE) // FurnaceNodeMetadata
|
||||
{
|
||||
meta->getInventory()->deSerialize(is);
|
||||
int temp = 0;
|
||||
is>>temp;
|
||||
meta->setString("fuel_totaltime", ftos((float)temp/10));
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
meta->setString("fuel_time", ftos((float)temp/10));
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
//meta->setString("src_totaltime", ftos((float)temp/10));
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
meta->setString("src_time", ftos((float)temp/10));
|
||||
|
||||
meta->setString("formspec","size[8,9]"
|
||||
"list[current_name;fuel;2,3;1,1;]"
|
||||
"list[current_name;src;2,1;1,1;]"
|
||||
"list[current_name;dst;5,1;2,2;]"
|
||||
"list[current_player;main;0,5;8,4;]");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SerializationError("Unknown legacy node metadata");
|
||||
}
|
||||
}
|
||||
|
||||
static bool content_nodemeta_deserialize_legacy_meta(
|
||||
std::istream &is, NodeMetadata *meta)
|
||||
{
|
||||
// Read id
|
||||
s16 id = readS16(is);
|
||||
|
||||
// Read data
|
||||
std::string data = deSerializeString(is);
|
||||
std::istringstream tmp_is(data, std::ios::binary);
|
||||
return content_nodemeta_deserialize_legacy_body(tmp_is, id, meta);
|
||||
}
|
||||
|
||||
void content_nodemeta_deserialize_legacy(std::istream &is,
|
||||
NodeMetadataList *meta, NodeTimerList *timers,
|
||||
IGameDef *gamedef)
|
||||
{
|
||||
meta->clear();
|
||||
timers->clear();
|
||||
|
||||
u16 version = readU16(is);
|
||||
|
||||
if(version > 1)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
|
||||
<<std::endl;
|
||||
throw SerializationError(__FUNCTION_NAME);
|
||||
}
|
||||
|
||||
u16 count = readU16(is);
|
||||
|
||||
for(u16 i=0; i<count; i++)
|
||||
{
|
||||
u16 p16 = readU16(is);
|
||||
|
||||
v3s16 p(0,0,0);
|
||||
p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
|
||||
p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
||||
p.Y += p16 / MAP_BLOCKSIZE;
|
||||
p16 -= p.Y * MAP_BLOCKSIZE;
|
||||
p.X += p16;
|
||||
|
||||
if(meta->get(p) != NULL)
|
||||
{
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME<<": "
|
||||
<<"already set data at position"
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
|
||||
<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
NodeMetadata *data = new NodeMetadata(gamedef);
|
||||
bool need_timer = content_nodemeta_deserialize_legacy_meta(is, data);
|
||||
meta->set(p, data);
|
||||
|
||||
if(need_timer)
|
||||
timers->set(p, NodeTimer(1., 0.));
|
||||
}
|
||||
}
|
||||
|
||||
void content_nodemeta_serialize_legacy(std::ostream &os, NodeMetadataList *meta)
|
||||
{
|
||||
// Sorry, I was too lazy to implement this. --kahrl
|
||||
writeU16(os, 1); // version
|
||||
writeU16(os, 0); // count
|
||||
}
|
||||
|
||||
// END
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -21,6 +21,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define CONTENT_NODEMETA_HEADER
|
||||
|
||||
#include "nodemetadata.h"
|
||||
#include "nodetimer.h"
|
||||
|
||||
/*
|
||||
Legacy nodemeta definitions
|
||||
*/
|
||||
|
||||
void content_nodemeta_deserialize_legacy(std::istream &is,
|
||||
NodeMetadataList *meta, NodeTimerList *timers,
|
||||
IGameDef *gamedef);
|
||||
|
||||
void content_nodemeta_serialize_legacy(std::ostream &os, NodeMetadataList *meta);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -32,5 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// Special type, not stored as a static object
|
||||
#define ACTIVEOBJECT_TYPE_PLAYER 100
|
||||
|
||||
// Special type, only exists as CAO
|
||||
#define ACTIVEOBJECT_TYPE_GENERIC 101
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -26,6 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serialization.h" // For compressZlib
|
||||
#include "tool.h" // For ToolCapabilities
|
||||
#include "gamedef.h"
|
||||
#include "player.h"
|
||||
#include "scriptapi.h"
|
||||
#include "genericobject.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
@@ -138,6 +142,9 @@ TestSAO proto_TestSAO(NULL, v3f(0,0,0));
|
||||
|
||||
/*
|
||||
ItemSAO
|
||||
|
||||
DEPRECATED: New dropped items are implemented in Lua; see
|
||||
builtin/item_entity.lua.
|
||||
*/
|
||||
|
||||
class ItemSAO : public ServerActiveObject
|
||||
@@ -199,9 +206,12 @@ class ItemSAO : public ServerActiveObject
|
||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||
v3f pos_f = getBasePosition();
|
||||
v3f pos_f_old = pos_f;
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
@@ -282,13 +292,6 @@ class ItemSAO : public ServerActiveObject
|
||||
ServerActiveObject *puncher,
|
||||
float time_from_last_punch)
|
||||
{
|
||||
// Directly delete item in creative mode
|
||||
if(g_settings->getBool("creative_mode") == true)
|
||||
{
|
||||
m_removed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Take item into inventory
|
||||
ItemStack item = createItemStack();
|
||||
Inventory *inv = puncher->getInventory();
|
||||
@@ -333,9 +336,6 @@ ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||
LuaEntitySAO
|
||||
*/
|
||||
|
||||
#include "scriptapi.h"
|
||||
#include "luaentity_common.h"
|
||||
|
||||
// Prototype (registers item for deserialization)
|
||||
LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", "");
|
||||
|
||||
@@ -345,11 +345,11 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||
m_init_name(name),
|
||||
m_init_state(state),
|
||||
m_registered(false),
|
||||
m_prop(new LuaEntityProperties),
|
||||
m_hp(-1),
|
||||
m_velocity(0,0,0),
|
||||
m_acceleration(0,0,0),
|
||||
m_yaw(0),
|
||||
m_properties_sent(true),
|
||||
m_last_sent_yaw(0),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_last_sent_velocity(0,0,0),
|
||||
@@ -374,7 +374,6 @@ LuaEntitySAO::~LuaEntitySAO()
|
||||
lua_State *L = m_env->getLua();
|
||||
scriptapi_luaentity_rm(L, m_id);
|
||||
}
|
||||
delete m_prop;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::addedToEnvironment()
|
||||
@@ -387,13 +386,12 @@ void LuaEntitySAO::addedToEnvironment()
|
||||
|
||||
if(m_registered){
|
||||
// Get properties
|
||||
scriptapi_luaentity_get_properties(L, m_id, m_prop);
|
||||
scriptapi_luaentity_get_properties(L, m_id, &m_prop);
|
||||
// Initialize HP from properties
|
||||
m_hp = m_prop->hp_max;
|
||||
m_hp = m_prop.hp_max;
|
||||
// Activate entity, supplying serialized state
|
||||
scriptapi_luaentity_activate(L, m_id, m_init_state.c_str());
|
||||
}
|
||||
|
||||
// Activate entity, supplying serialized state
|
||||
scriptapi_luaentity_activate(L, m_id, m_init_state.c_str());
|
||||
}
|
||||
|
||||
ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
|
||||
@@ -433,24 +431,35 @@ ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
|
||||
|
||||
void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
if(!m_properties_sent)
|
||||
{
|
||||
m_properties_sent = true;
|
||||
std::string str = getPropertyPacket();
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
m_last_sent_position_timer += dtime;
|
||||
|
||||
if(m_prop->physical){
|
||||
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||
if(m_prop.physical){
|
||||
core::aabbox3d<f32> box = m_prop.collisionbox;
|
||||
box.MinEdge *= BS;
|
||||
box.MaxEdge *= BS;
|
||||
collisionMoveResult moveresult;
|
||||
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||
v3f p_pos = getBasePosition();
|
||||
f32 stepheight = 0; // Maximum climbable step height
|
||||
v3f p_pos = m_base_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
setBasePosition(p_pos);
|
||||
m_base_position = p_pos;
|
||||
m_velocity = p_velocity;
|
||||
|
||||
m_velocity += dtime * m_acceleration;
|
||||
m_acceleration = p_acceleration;
|
||||
} else {
|
||||
m_base_position += dtime * m_velocity + 0.5 * dtime
|
||||
* dtime * m_acceleration;
|
||||
@@ -482,16 +491,10 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
|
||||
if(m_armor_groups_sent == false){
|
||||
m_armor_groups_sent = true;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, LUAENTITY_CMD_UPDATE_ARMOR_GROUPS);
|
||||
writeU16(os, m_armor_groups.size());
|
||||
for(ItemGroupList::const_iterator i = m_armor_groups.begin();
|
||||
i != m_armor_groups.end(); i++){
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
std::string str = gob_cmd_update_armor_groups(
|
||||
m_armor_groups);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, os.str());
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
@@ -499,18 +502,15 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
std::string LuaEntitySAO::getClientInitializationData()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 1);
|
||||
// pos
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(""); // name
|
||||
writeU8(os, 0); // is_player
|
||||
writeV3F1000(os, m_base_position);
|
||||
// yaw
|
||||
writeF1000(os, m_yaw);
|
||||
// hp
|
||||
writeS16(os, m_hp);
|
||||
// properties
|
||||
std::ostringstream prop_os(std::ios::binary);
|
||||
m_prop->serialize(prop_os);
|
||||
os<<serializeLongString(prop_os.str());
|
||||
writeU8(os, 2); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
// return result
|
||||
return os.str();
|
||||
}
|
||||
@@ -573,15 +573,9 @@ int LuaEntitySAO::punch(v3f dir,
|
||||
<<" hp, health now "<<getHP()<<" hp"<<std::endl;
|
||||
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, LUAENTITY_CMD_PUNCHED);
|
||||
// damage
|
||||
writeS16(os, result.damage);
|
||||
// result_hp
|
||||
writeS16(os, getHP());
|
||||
std::string str = gob_cmd_punched(result.damage, getHP());
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, os.str());
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
@@ -604,17 +598,6 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
|
||||
scriptapi_luaentity_rightclick(L, m_id, clicker);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setHP(s16 hp)
|
||||
{
|
||||
if(hp < 0) hp = 0;
|
||||
m_hp = hp;
|
||||
}
|
||||
|
||||
s16 LuaEntitySAO::getHP()
|
||||
{
|
||||
return m_hp;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setPos(v3f pos)
|
||||
{
|
||||
m_base_position = pos;
|
||||
@@ -644,6 +627,33 @@ std::string LuaEntitySAO::getDescription()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setHP(s16 hp)
|
||||
{
|
||||
if(hp < 0) hp = 0;
|
||||
m_hp = hp;
|
||||
}
|
||||
|
||||
s16 LuaEntitySAO::getHP() const
|
||||
{
|
||||
return m_hp;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups)
|
||||
{
|
||||
m_armor_groups = armor_groups;
|
||||
m_armor_groups_sent = false;
|
||||
}
|
||||
|
||||
ObjectProperties* LuaEntitySAO::accessObjectProperties()
|
||||
{
|
||||
return &m_prop;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::notifyObjectPropertiesModified()
|
||||
{
|
||||
m_properties_sent = false;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setVelocity(v3f velocity)
|
||||
{
|
||||
m_velocity = velocity;
|
||||
@@ -676,29 +686,23 @@ float LuaEntitySAO::getYaw()
|
||||
|
||||
void LuaEntitySAO::setTextureMod(const std::string &mod)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, LUAENTITY_CMD_SET_TEXTURE_MOD);
|
||||
// parameters
|
||||
os<<serializeString(mod);
|
||||
std::string str = gob_cmd_set_texture_mod(mod);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
|
||||
bool select_horiz_by_yawpitch)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, LUAENTITY_CMD_SET_SPRITE);
|
||||
// parameters
|
||||
writeV2S16(os, p);
|
||||
writeU16(os, num_frames);
|
||||
writeF1000(os, framelength);
|
||||
writeU8(os, select_horiz_by_yawpitch);
|
||||
std::string str = gob_cmd_set_sprite(
|
||||
p,
|
||||
num_frames,
|
||||
framelength,
|
||||
select_horiz_by_yawpitch
|
||||
);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
@@ -707,10 +711,9 @@ std::string LuaEntitySAO::getName()
|
||||
return m_init_name;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups)
|
||||
std::string LuaEntitySAO::getPropertyPacket()
|
||||
{
|
||||
m_armor_groups = armor_groups;
|
||||
m_armor_groups_sent = false;
|
||||
return gob_cmd_set_properties(m_prop);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
@@ -725,27 +728,417 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
|
||||
float update_interval = m_env->getSendRecommendedInterval();
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, LUAENTITY_CMD_UPDATE_POSITION);
|
||||
|
||||
// do_interpolate
|
||||
writeU8(os, do_interpolate);
|
||||
// pos
|
||||
writeV3F1000(os, m_base_position);
|
||||
// velocity
|
||||
writeV3F1000(os, m_velocity);
|
||||
// acceleration
|
||||
writeV3F1000(os, m_acceleration);
|
||||
// yaw
|
||||
writeF1000(os, m_yaw);
|
||||
// is_end_position (for interpolation)
|
||||
writeU8(os, is_movement_end);
|
||||
// update_interval (for interpolation)
|
||||
writeF1000(os, update_interval);
|
||||
|
||||
std::string str = gob_cmd_update_position(
|
||||
m_base_position,
|
||||
m_velocity,
|
||||
m_acceleration,
|
||||
m_yaw,
|
||||
do_interpolate,
|
||||
is_movement_end,
|
||||
update_interval
|
||||
);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
ActiveObjectMessage aom(getId(), false, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
/*
|
||||
PlayerSAO
|
||||
*/
|
||||
|
||||
// No prototype, PlayerSAO does not need to be deserialized
|
||||
|
||||
PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
||||
const std::set<std::string> &privs, bool is_singleplayer):
|
||||
ServerActiveObject(env_, v3f(0,0,0)),
|
||||
m_player(player_),
|
||||
m_peer_id(peer_id_),
|
||||
m_inventory(NULL),
|
||||
m_last_good_position(0,0,0),
|
||||
m_last_good_position_age(0),
|
||||
m_time_from_last_punch(0),
|
||||
m_nocheat_dig_pos(32767, 32767, 32767),
|
||||
m_nocheat_dig_time(0),
|
||||
m_wield_index(0),
|
||||
m_position_not_sent(false),
|
||||
m_armor_groups_sent(false),
|
||||
m_properties_sent(true),
|
||||
m_privs(privs),
|
||||
m_is_singleplayer(is_singleplayer),
|
||||
// public
|
||||
m_teleported(false),
|
||||
m_inventory_not_sent(false),
|
||||
m_hp_not_sent(false),
|
||||
m_wielded_item_not_sent(false)
|
||||
{
|
||||
assert(m_player);
|
||||
assert(m_peer_id != 0);
|
||||
setBasePosition(m_player->getPosition());
|
||||
m_inventory = &m_player->inventory;
|
||||
m_armor_groups["choppy"] = 2;
|
||||
m_armor_groups["fleshy"] = 3;
|
||||
|
||||
m_prop.hp_max = PLAYER_MAX_HP;
|
||||
m_prop.physical = false;
|
||||
m_prop.weight = 75;
|
||||
m_prop.collisionbox = core::aabbox3d<f32>(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
|
||||
m_prop.visual = "upright_sprite";
|
||||
m_prop.visual_size = v2f(1, 2);
|
||||
m_prop.textures.clear();
|
||||
m_prop.textures.push_back("player.png");
|
||||
m_prop.textures.push_back("player_back.png");
|
||||
m_prop.spritediv = v2s16(1,1);
|
||||
m_prop.is_visible = (getHP() != 0);
|
||||
m_prop.makes_footstep_sound = true;
|
||||
}
|
||||
|
||||
PlayerSAO::~PlayerSAO()
|
||||
{
|
||||
if(m_inventory != &m_player->inventory)
|
||||
delete m_inventory;
|
||||
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getDescription()
|
||||
{
|
||||
return std::string("player ") + m_player->getName();
|
||||
}
|
||||
|
||||
// Called after id has been set and has been inserted in environment
|
||||
void PlayerSAO::addedToEnvironment()
|
||||
{
|
||||
ServerActiveObject::addedToEnvironment();
|
||||
ServerActiveObject::setBasePosition(m_player->getPosition());
|
||||
m_player->setPlayerSAO(this);
|
||||
m_player->peer_id = m_peer_id;
|
||||
m_last_good_position = m_player->getPosition();
|
||||
m_last_good_position_age = 0.0;
|
||||
}
|
||||
|
||||
// Called before removing from environment
|
||||
void PlayerSAO::removingFromEnvironment()
|
||||
{
|
||||
ServerActiveObject::removingFromEnvironment();
|
||||
if(m_player->getPlayerSAO() == this)
|
||||
{
|
||||
m_player->setPlayerSAO(NULL);
|
||||
m_player->peer_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerSAO::isStaticAllowed() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayerSAO::unlimitedTransferDistance() const
|
||||
{
|
||||
return g_settings->getBool("unlimited_player_transfer_distance");
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getClientInitializationData()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(m_player->getName()); // name
|
||||
writeU8(os, 1); // is_player
|
||||
writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0));
|
||||
writeF1000(os, m_player->getYaw());
|
||||
writeS16(os, getHP());
|
||||
writeU8(os, 2); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getStaticData()
|
||||
{
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
void PlayerSAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
if(!m_properties_sent)
|
||||
{
|
||||
m_properties_sent = true;
|
||||
std::string str = getPropertyPacket();
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
m_time_from_last_punch += dtime;
|
||||
m_nocheat_dig_time += dtime;
|
||||
|
||||
if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
|
||||
{
|
||||
m_last_good_position = m_player->getPosition();
|
||||
m_last_good_position_age = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Check player movements
|
||||
|
||||
NOTE: Actually the server should handle player physics like the
|
||||
client does and compare player's position to what is calculated
|
||||
on our side. This is required when eg. players fly due to an
|
||||
explosion. Altough a node-based alternative might be possible
|
||||
too, and much more lightweight.
|
||||
*/
|
||||
|
||||
float player_max_speed = 0;
|
||||
float player_max_speed_up = 0;
|
||||
if(m_privs.count("fast") != 0){
|
||||
// Fast speed
|
||||
player_max_speed = BS * 20;
|
||||
player_max_speed_up = BS * 20;
|
||||
} else {
|
||||
// Normal speed
|
||||
player_max_speed = BS * 4.0;
|
||||
player_max_speed_up = BS * 4.0;
|
||||
}
|
||||
// Tolerance
|
||||
player_max_speed *= 2.5;
|
||||
player_max_speed_up *= 2.5;
|
||||
|
||||
m_last_good_position_age += dtime;
|
||||
if(m_last_good_position_age >= 1.0){
|
||||
float age = m_last_good_position_age;
|
||||
v3f diff = (m_player->getPosition() - m_last_good_position);
|
||||
float d_vert = diff.Y;
|
||||
diff.Y = 0;
|
||||
float d_horiz = diff.getLength();
|
||||
/*infostream<<m_player->getName()<<"'s horizontal speed is "
|
||||
<<(d_horiz/age)<<std::endl;*/
|
||||
if(d_horiz <= age * player_max_speed &&
|
||||
(d_vert < 0 || d_vert < age * player_max_speed_up)){
|
||||
m_last_good_position = m_player->getPosition();
|
||||
} else {
|
||||
actionstream<<"Player "<<m_player->getName()
|
||||
<<" moved too fast; resetting position"
|
||||
<<std::endl;
|
||||
m_player->setPosition(m_last_good_position);
|
||||
m_teleported = true;
|
||||
}
|
||||
m_last_good_position_age = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
|
||||
if(m_position_not_sent)
|
||||
{
|
||||
m_position_not_sent = false;
|
||||
float update_interval = m_env->getSendRecommendedInterval();
|
||||
std::string str = gob_cmd_update_position(
|
||||
m_player->getPosition() + v3f(0,BS*1,0),
|
||||
v3f(0,0,0),
|
||||
v3f(0,0,0),
|
||||
m_player->getYaw(),
|
||||
true,
|
||||
false,
|
||||
update_interval
|
||||
);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
if(m_wielded_item_not_sent)
|
||||
{
|
||||
m_wielded_item_not_sent = false;
|
||||
// GenericCAO has no special way to show this
|
||||
}
|
||||
|
||||
if(m_armor_groups_sent == false){
|
||||
m_armor_groups_sent = true;
|
||||
std::string str = gob_cmd_update_armor_groups(
|
||||
m_armor_groups);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSAO::setBasePosition(const v3f &position)
|
||||
{
|
||||
ServerActiveObject::setBasePosition(position);
|
||||
m_position_not_sent = true;
|
||||
}
|
||||
|
||||
void PlayerSAO::setPos(v3f pos)
|
||||
{
|
||||
m_player->setPosition(pos);
|
||||
// Movement caused by this command is always valid
|
||||
m_last_good_position = pos;
|
||||
m_last_good_position_age = 0;
|
||||
// Force position change on client
|
||||
m_teleported = true;
|
||||
}
|
||||
|
||||
void PlayerSAO::moveTo(v3f pos, bool continuous)
|
||||
{
|
||||
m_player->setPosition(pos);
|
||||
// Movement caused by this command is always valid
|
||||
m_last_good_position = pos;
|
||||
m_last_good_position_age = 0;
|
||||
// Force position change on client
|
||||
m_teleported = true;
|
||||
}
|
||||
|
||||
int PlayerSAO::punch(v3f dir,
|
||||
const ToolCapabilities *toolcap,
|
||||
ServerActiveObject *puncher,
|
||||
float time_from_last_punch)
|
||||
{
|
||||
if(!toolcap)
|
||||
return 0;
|
||||
|
||||
// No effect if PvP disabled
|
||||
if(g_settings->getBool("enable_pvp") == false){
|
||||
if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER){
|
||||
std::string str = gob_cmd_punched(0, getHP());
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HitParams hitparams = getHitParams(m_armor_groups, toolcap,
|
||||
time_from_last_punch);
|
||||
|
||||
actionstream<<"Player "<<m_player->getName()<<" punched by "
|
||||
<<puncher->getDescription()<<", damage "<<hitparams.hp
|
||||
<<" HP"<<std::endl;
|
||||
|
||||
setHP(getHP() - hitparams.hp);
|
||||
|
||||
if(hitparams.hp != 0)
|
||||
{
|
||||
std::string str = gob_cmd_punched(hitparams.hp, getHP());
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
return hitparams.wear;
|
||||
}
|
||||
|
||||
void PlayerSAO::rightClick(ServerActiveObject *clicker)
|
||||
{
|
||||
}
|
||||
|
||||
s16 PlayerSAO::getHP() const
|
||||
{
|
||||
return m_player->hp;
|
||||
}
|
||||
|
||||
void PlayerSAO::setHP(s16 hp)
|
||||
{
|
||||
s16 oldhp = m_player->hp;
|
||||
|
||||
if(hp < 0)
|
||||
hp = 0;
|
||||
else if(hp > PLAYER_MAX_HP)
|
||||
hp = PLAYER_MAX_HP;
|
||||
|
||||
if(hp < oldhp && g_settings->getBool("enable_damage") == false)
|
||||
{
|
||||
m_hp_not_sent = true; // fix wrong prediction on client
|
||||
return;
|
||||
}
|
||||
|
||||
m_player->hp = hp;
|
||||
|
||||
if(hp != oldhp)
|
||||
m_hp_not_sent = true;
|
||||
|
||||
// On death or reincarnation send an active object message
|
||||
if((hp == 0) != (oldhp == 0))
|
||||
{
|
||||
// Will send new is_visible value based on (getHP()!=0)
|
||||
m_properties_sent = false;
|
||||
// Send new HP
|
||||
std::string str = gob_cmd_punched(0, getHP());
|
||||
ActiveObjectMessage aom(getId(), true, str);
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups)
|
||||
{
|
||||
m_armor_groups = armor_groups;
|
||||
m_armor_groups_sent = false;
|
||||
}
|
||||
|
||||
ObjectProperties* PlayerSAO::accessObjectProperties()
|
||||
{
|
||||
return &m_prop;
|
||||
}
|
||||
|
||||
void PlayerSAO::notifyObjectPropertiesModified()
|
||||
{
|
||||
m_properties_sent = false;
|
||||
}
|
||||
|
||||
Inventory* PlayerSAO::getInventory()
|
||||
{
|
||||
return m_inventory;
|
||||
}
|
||||
const Inventory* PlayerSAO::getInventory() const
|
||||
{
|
||||
return m_inventory;
|
||||
}
|
||||
|
||||
InventoryLocation PlayerSAO::getInventoryLocation() const
|
||||
{
|
||||
InventoryLocation loc;
|
||||
loc.setPlayer(m_player->getName());
|
||||
return loc;
|
||||
}
|
||||
|
||||
void PlayerSAO::setInventoryModified()
|
||||
{
|
||||
m_inventory_not_sent = true;
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getWieldList() const
|
||||
{
|
||||
return "main";
|
||||
}
|
||||
|
||||
int PlayerSAO::getWieldIndex() const
|
||||
{
|
||||
return m_wield_index;
|
||||
}
|
||||
|
||||
void PlayerSAO::setWieldIndex(int i)
|
||||
{
|
||||
if(i != m_wield_index)
|
||||
{
|
||||
m_wield_index = i;
|
||||
m_wielded_item_not_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSAO::disconnected()
|
||||
{
|
||||
m_peer_id = 0;
|
||||
m_removed = true;
|
||||
if(m_player->getPlayerSAO() == this)
|
||||
{
|
||||
m_player->setPlayerSAO(NULL);
|
||||
m_player->peer_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getPropertyPacket()
|
||||
{
|
||||
m_prop.is_visible = (getHP() != 0);
|
||||
return gob_cmd_set_properties(m_prop);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -23,18 +23,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serverobject.h"
|
||||
#include "content_object.h"
|
||||
#include "itemgroup.h"
|
||||
#include "player.h"
|
||||
#include "object_properties.h"
|
||||
|
||||
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||
const std::string itemstring);
|
||||
|
||||
/*
|
||||
LuaEntitySAO
|
||||
|
||||
This is the only SAO that needs to have a bunch of it's internals exposed.
|
||||
LuaEntitySAO needs some internals exposed.
|
||||
*/
|
||||
|
||||
struct LuaEntityProperties;
|
||||
|
||||
class LuaEntitySAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
@@ -42,7 +40,9 @@ class LuaEntitySAO : public ServerActiveObject
|
||||
const std::string &name, const std::string &state);
|
||||
~LuaEntitySAO();
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_LUAENTITY;}
|
||||
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
||||
u8 getSendType() const
|
||||
{ return ACTIVEOBJECT_TYPE_GENERIC; }
|
||||
virtual void addedToEnvironment();
|
||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||
const std::string &data);
|
||||
@@ -59,7 +59,10 @@ class LuaEntitySAO : public ServerActiveObject
|
||||
float getMinimumSavedMovement();
|
||||
std::string getDescription();
|
||||
void setHP(s16 hp);
|
||||
s16 getHP();
|
||||
s16 getHP() const;
|
||||
void setArmorGroups(const ItemGroupList &armor_groups);
|
||||
ObjectProperties* accessObjectProperties();
|
||||
void notifyObjectPropertiesModified();
|
||||
/* LuaEntitySAO-specific */
|
||||
void setVelocity(v3f velocity);
|
||||
v3f getVelocity();
|
||||
@@ -71,21 +74,22 @@ class LuaEntitySAO : public ServerActiveObject
|
||||
void setSprite(v2s16 p, int num_frames, float framelength,
|
||||
bool select_horiz_by_yawpitch);
|
||||
std::string getName();
|
||||
void setArmorGroups(const ItemGroupList &armor_groups);
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||
|
||||
std::string m_init_name;
|
||||
std::string m_init_state;
|
||||
bool m_registered;
|
||||
struct LuaEntityProperties *m_prop;
|
||||
struct ObjectProperties m_prop;
|
||||
|
||||
s16 m_hp;
|
||||
v3f m_velocity;
|
||||
v3f m_acceleration;
|
||||
float m_yaw;
|
||||
ItemGroupList m_armor_groups;
|
||||
|
||||
|
||||
bool m_properties_sent;
|
||||
float m_last_sent_yaw;
|
||||
v3f m_last_sent_position;
|
||||
v3f m_last_sent_velocity;
|
||||
@@ -94,5 +98,150 @@ class LuaEntitySAO : public ServerActiveObject
|
||||
bool m_armor_groups_sent;
|
||||
};
|
||||
|
||||
/*
|
||||
PlayerSAO needs some internals exposed.
|
||||
*/
|
||||
|
||||
class PlayerSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
||||
const std::set<std::string> &privs, bool is_singleplayer);
|
||||
~PlayerSAO();
|
||||
u8 getType() const
|
||||
{ return ACTIVEOBJECT_TYPE_PLAYER; }
|
||||
u8 getSendType() const
|
||||
{ return ACTIVEOBJECT_TYPE_GENERIC; }
|
||||
std::string getDescription();
|
||||
|
||||
/*
|
||||
Active object <-> environment interface
|
||||
*/
|
||||
|
||||
void addedToEnvironment();
|
||||
void removingFromEnvironment();
|
||||
bool isStaticAllowed() const;
|
||||
bool unlimitedTransferDistance() const;
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
void step(float dtime, bool send_recommended);
|
||||
void setBasePosition(const v3f &position);
|
||||
void setPos(v3f pos);
|
||||
void moveTo(v3f pos, bool continuous);
|
||||
|
||||
/*
|
||||
Interaction interface
|
||||
*/
|
||||
|
||||
int punch(v3f dir,
|
||||
const ToolCapabilities *toolcap,
|
||||
ServerActiveObject *puncher,
|
||||
float time_from_last_punch);
|
||||
void rightClick(ServerActiveObject *clicker);
|
||||
s16 getHP() const;
|
||||
void setHP(s16 hp);
|
||||
|
||||
void setArmorGroups(const ItemGroupList &armor_groups);
|
||||
ObjectProperties* accessObjectProperties();
|
||||
void notifyObjectPropertiesModified();
|
||||
|
||||
/*
|
||||
Inventory interface
|
||||
*/
|
||||
|
||||
Inventory* getInventory();
|
||||
const Inventory* getInventory() const;
|
||||
InventoryLocation getInventoryLocation() const;
|
||||
void setInventoryModified();
|
||||
std::string getWieldList() const;
|
||||
int getWieldIndex() const;
|
||||
void setWieldIndex(int i);
|
||||
|
||||
/*
|
||||
PlayerSAO-specific
|
||||
*/
|
||||
|
||||
void disconnected();
|
||||
|
||||
Player* getPlayer()
|
||||
{
|
||||
return m_player;
|
||||
}
|
||||
u16 getPeerID() const
|
||||
{
|
||||
return m_peer_id;
|
||||
}
|
||||
|
||||
// Cheat prevention
|
||||
|
||||
v3f getLastGoodPosition() const
|
||||
{
|
||||
return m_last_good_position;
|
||||
}
|
||||
float resetTimeFromLastPunch()
|
||||
{
|
||||
float r = m_time_from_last_punch;
|
||||
m_time_from_last_punch = 0.0;
|
||||
return r;
|
||||
}
|
||||
void noCheatDigStart(v3s16 p)
|
||||
{
|
||||
m_nocheat_dig_pos = p;
|
||||
m_nocheat_dig_time = 0;
|
||||
}
|
||||
v3s16 getNoCheatDigPos()
|
||||
{
|
||||
return m_nocheat_dig_pos;
|
||||
}
|
||||
float getNoCheatDigTime()
|
||||
{
|
||||
return m_nocheat_dig_time;
|
||||
}
|
||||
void noCheatDigEnd()
|
||||
{
|
||||
m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
|
||||
}
|
||||
|
||||
// Other
|
||||
|
||||
void updatePrivileges(const std::set<std::string> &privs,
|
||||
bool is_singleplayer)
|
||||
{
|
||||
m_privs = privs;
|
||||
m_is_singleplayer = is_singleplayer;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
|
||||
Player *m_player;
|
||||
u16 m_peer_id;
|
||||
Inventory *m_inventory;
|
||||
|
||||
// Cheat prevention
|
||||
v3f m_last_good_position;
|
||||
float m_last_good_position_age;
|
||||
float m_time_from_last_punch;
|
||||
v3s16 m_nocheat_dig_pos;
|
||||
float m_nocheat_dig_time;
|
||||
|
||||
int m_wield_index;
|
||||
bool m_position_not_sent;
|
||||
ItemGroupList m_armor_groups;
|
||||
bool m_armor_groups_sent;
|
||||
bool m_properties_sent;
|
||||
struct ObjectProperties m_prop;
|
||||
// Cached privileges for enforcement
|
||||
std::set<std::string> m_privs;
|
||||
bool m_is_singleplayer;
|
||||
|
||||
public:
|
||||
// Some flags used by Server
|
||||
bool m_teleported;
|
||||
bool m_inventory_not_sent;
|
||||
bool m_hp_not_sent;
|
||||
bool m_wielded_item_not_sent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
306
src/craftdef.cpp
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -23,10 +23,40 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include "utility.h"
|
||||
#include <algorithm>
|
||||
#include "gamedef.h"
|
||||
#include "inventory.h"
|
||||
#include "util/serialize.h"
|
||||
#include "strfnd.h"
|
||||
|
||||
// Check if input matches recipe
|
||||
// Takes recipe groups into account
|
||||
static bool inputItemMatchesRecipe(const std::string &inp_name,
|
||||
const std::string &rec_name, IItemDefManager *idef)
|
||||
{
|
||||
// Exact name
|
||||
if(inp_name == rec_name)
|
||||
return true;
|
||||
|
||||
// Group
|
||||
if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){
|
||||
const struct ItemDefinition &def = idef->get(inp_name);
|
||||
Strfnd f(rec_name.substr(6));
|
||||
bool all_groups_match = true;
|
||||
do{
|
||||
std::string check_group = f.next(",");
|
||||
if(itemgroup_get(def.groups, check_group) == 0){
|
||||
all_groups_match = false;
|
||||
break;
|
||||
}
|
||||
}while(!f.atend());
|
||||
if(all_groups_match)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Didn't match
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deserialize an itemstring then return the name of the item
|
||||
static std::string craftGetItemName(const std::string &itemstring, IGameDef *gamedef)
|
||||
@@ -64,6 +94,20 @@ static std::vector<std::string> craftGetItemNames(
|
||||
return result;
|
||||
}
|
||||
|
||||
// convert a list of item names, to ItemStacks.
|
||||
static std::vector<ItemStack> craftGetItems(
|
||||
const std::vector<std::string> &items, IGameDef *gamedef)
|
||||
{
|
||||
std::vector<ItemStack> result;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
i = items.begin();
|
||||
i != items.end(); i++)
|
||||
{
|
||||
result.push_back(ItemStack(std::string(*i),(u16)1,(u16)0,"",gamedef->getItemDefManager()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compute bounding rectangle given a matrix of items
|
||||
// Returns false if every item is ""
|
||||
static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
|
||||
@@ -106,6 +150,8 @@ static bool craftGetBounds(const std::vector<std::string> &items, unsigned int w
|
||||
return success;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This became useless when group support was added to shapeless recipes
|
||||
// Convert a list of item names to a multiset
|
||||
static std::multiset<std::string> craftMakeMultiset(const std::vector<std::string> &names)
|
||||
{
|
||||
@@ -119,6 +165,7 @@ static std::multiset<std::string> craftMakeMultiset(const std::vector<std::strin
|
||||
}
|
||||
return set;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Removes 1 from each item stack
|
||||
static void craftDecrementInput(CraftInput &input, IGameDef *gamedef)
|
||||
@@ -260,6 +307,7 @@ std::string CraftOutput::dump() const
|
||||
/*
|
||||
CraftReplacements
|
||||
*/
|
||||
|
||||
std::string CraftReplacements::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
@@ -276,6 +324,27 @@ std::string CraftReplacements::dump() const
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftReplacements::serialize(std::ostream &os) const
|
||||
{
|
||||
writeU16(os, pairs.size());
|
||||
for(u32 i=0; i<pairs.size(); i++)
|
||||
{
|
||||
os<<serializeString(pairs[i].first);
|
||||
os<<serializeString(pairs[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
void CraftReplacements::deSerialize(std::istream &is)
|
||||
{
|
||||
pairs.clear();
|
||||
u32 count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
std::string first = deSerializeString(is);
|
||||
std::string second = deSerializeString(is);
|
||||
pairs.push_back(std::make_pair(first, second));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinition
|
||||
@@ -381,9 +450,9 @@ bool CraftDefinitionShaped::check(const CraftInput &input, IGameDef *gamedef) co
|
||||
unsigned int rec_x = rec_min_x + x;
|
||||
unsigned int rec_y = rec_min_y + y;
|
||||
|
||||
if(
|
||||
inp_names[inp_y * inp_width + inp_x] !=
|
||||
rec_names[rec_y * rec_width + rec_x]
|
||||
if(!inputItemMatchesRecipe(
|
||||
inp_names[inp_y * inp_width + inp_x],
|
||||
rec_names[rec_y * rec_width + rec_x], gamedef->idef())
|
||||
){
|
||||
return false;
|
||||
}
|
||||
@@ -397,6 +466,11 @@ CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *
|
||||
return CraftOutput(output, 0);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
@@ -418,12 +492,7 @@ void CraftDefinitionShaped::serializeBody(std::ostream &os) const
|
||||
writeU16(os, recipe.size());
|
||||
for(u32 i=0; i<recipe.size(); i++)
|
||||
os<<serializeString(recipe[i]);
|
||||
writeU16(os, replacements.pairs.size());
|
||||
for(u32 i=0; i<replacements.pairs.size(); i++)
|
||||
{
|
||||
os<<serializeString(replacements.pairs[i].first);
|
||||
os<<serializeString(replacements.pairs[i].second);
|
||||
}
|
||||
replacements.serialize(os);
|
||||
}
|
||||
|
||||
void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
|
||||
@@ -436,14 +505,7 @@ void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
|
||||
u32 count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
recipe.push_back(deSerializeString(is));
|
||||
replacements.pairs.clear();
|
||||
count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
std::string first = deSerializeString(is);
|
||||
std::string second = deSerializeString(is);
|
||||
replacements.pairs.push_back(std::make_pair(first, second));
|
||||
}
|
||||
replacements.deSerialize(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,17 +521,48 @@ bool CraftDefinitionShapeless::check(const CraftInput &input, IGameDef *gamedef)
|
||||
{
|
||||
if(input.method != CRAFT_METHOD_NORMAL)
|
||||
return false;
|
||||
|
||||
// Filter empty items out of input
|
||||
std::vector<std::string> input_filtered;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(i->name != "")
|
||||
input_filtered.push_back(i->name);
|
||||
}
|
||||
|
||||
// Get input item multiset
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
std::multiset<std::string> inp_names_multiset = craftMakeMultiset(inp_names);
|
||||
// If there is a wrong number of items in input, no match
|
||||
if(input_filtered.size() != recipe.size()){
|
||||
/*dstream<<"Number of input items ("<<input_filtered.size()
|
||||
<<") does not match recipe size ("<<recipe.size()<<") "
|
||||
<<"of recipe with output="<<output<<std::endl;*/
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get recipe item multiset
|
||||
std::vector<std::string> rec_names = craftGetItemNames(recipe, gamedef);
|
||||
std::multiset<std::string> rec_names_multiset = craftMakeMultiset(rec_names);
|
||||
// Try with all permutations of the recipe
|
||||
std::vector<std::string> recipe_copy = recipe;
|
||||
// Start from the lexicographically first permutation (=sorted)
|
||||
std::sort(recipe_copy.begin(), recipe_copy.end());
|
||||
//while(std::prev_permutation(recipe_copy.begin(), recipe_copy.end())){}
|
||||
do{
|
||||
// If all items match, the recipe matches
|
||||
bool all_match = true;
|
||||
//dstream<<"Testing recipe (output="<<output<<"):";
|
||||
for(size_t i=0; i<recipe.size(); i++){
|
||||
//dstream<<" ("<<input_filtered[i]<<" == "<<recipe_copy[i]<<")";
|
||||
if(!inputItemMatchesRecipe(input_filtered[i], recipe_copy[i],
|
||||
gamedef->idef())){
|
||||
all_match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//dstream<<" -> match="<<all_match<<std::endl;
|
||||
if(all_match)
|
||||
return true;
|
||||
}while(std::next_permutation(recipe_copy.begin(), recipe_copy.end()));
|
||||
|
||||
// Recipe is matched when the multisets coincide
|
||||
return inp_names_multiset == rec_names_multiset;
|
||||
return false;
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
@@ -477,6 +570,11 @@ CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDe
|
||||
return CraftOutput(output, 0);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionShapeless::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftInput(CRAFT_METHOD_NORMAL,0,craftGetItems(recipe,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
@@ -497,12 +595,7 @@ void CraftDefinitionShapeless::serializeBody(std::ostream &os) const
|
||||
writeU16(os, recipe.size());
|
||||
for(u32 i=0; i<recipe.size(); i++)
|
||||
os<<serializeString(recipe[i]);
|
||||
writeU16(os, replacements.pairs.size());
|
||||
for(u32 i=0; i<replacements.pairs.size(); i++)
|
||||
{
|
||||
os<<serializeString(replacements.pairs[i].first);
|
||||
os<<serializeString(replacements.pairs[i].second);
|
||||
}
|
||||
replacements.serialize(os);
|
||||
}
|
||||
|
||||
void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
|
||||
@@ -514,14 +607,7 @@ void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
|
||||
u32 count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
recipe.push_back(deSerializeString(is));
|
||||
replacements.pairs.clear();
|
||||
count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
std::string first = deSerializeString(is);
|
||||
std::string second = deSerializeString(is);
|
||||
replacements.pairs.push_back(std::make_pair(first, second));
|
||||
}
|
||||
replacements.deSerialize(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -607,6 +693,13 @@ CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameD
|
||||
return CraftOutput(repaired.getItemString(), 0);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionToolRepair::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<ItemStack> stack;
|
||||
stack.push_back(ItemStack());
|
||||
return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack);
|
||||
}
|
||||
|
||||
void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
@@ -645,16 +738,26 @@ bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) c
|
||||
if(input.method != CRAFT_METHOD_COOKING)
|
||||
return false;
|
||||
|
||||
// Get input item multiset
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
std::multiset<std::string> inp_names_multiset = craftMakeMultiset(inp_names);
|
||||
// Filter empty items out of input
|
||||
std::vector<std::string> input_filtered;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(i->name != "")
|
||||
input_filtered.push_back(i->name);
|
||||
}
|
||||
|
||||
// Get recipe item multiset
|
||||
std::multiset<std::string> rec_names_multiset;
|
||||
rec_names_multiset.insert(craftGetItemName(recipe, gamedef));
|
||||
|
||||
// Recipe is matched when the multisets coincide
|
||||
return inp_names_multiset == rec_names_multiset;
|
||||
// If there is a wrong number of items in input, no match
|
||||
if(input_filtered.size() != 1){
|
||||
/*dstream<<"Number of input items ("<<input_filtered.size()
|
||||
<<") does not match recipe size (1) "
|
||||
<<"of cooking recipe with output="<<output<<std::endl;*/
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the single input item
|
||||
return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
@@ -662,9 +765,16 @@ CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef
|
||||
return CraftOutput(output, cooktime);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionCooking::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<std::string> rec;
|
||||
rec.push_back(recipe);
|
||||
return CraftInput(CRAFT_METHOD_COOKING,cooktime,craftGetItems(rec,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionCooking::dump() const
|
||||
@@ -672,7 +782,8 @@ std::string CraftDefinitionCooking::dump() const
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(cooking, output=\""<<output
|
||||
<<"\", recipe=\""<<recipe
|
||||
<<"\", cooktime="<<cooktime<<")";
|
||||
<<"\", cooktime="<<cooktime<<")"
|
||||
<<", replacements="<<replacements.dump()<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -681,6 +792,7 @@ void CraftDefinitionCooking::serializeBody(std::ostream &os) const
|
||||
os<<serializeString(output);
|
||||
os<<serializeString(recipe);
|
||||
writeF1000(os, cooktime);
|
||||
replacements.serialize(os);
|
||||
}
|
||||
|
||||
void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
|
||||
@@ -690,6 +802,7 @@ void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
|
||||
output = deSerializeString(is);
|
||||
recipe = deSerializeString(is);
|
||||
cooktime = readF1000(is);
|
||||
replacements.deSerialize(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -706,16 +819,26 @@ bool CraftDefinitionFuel::check(const CraftInput &input, IGameDef *gamedef) cons
|
||||
if(input.method != CRAFT_METHOD_FUEL)
|
||||
return false;
|
||||
|
||||
// Get input item multiset
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
std::multiset<std::string> inp_names_multiset = craftMakeMultiset(inp_names);
|
||||
// Filter empty items out of input
|
||||
std::vector<std::string> input_filtered;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(i->name != "")
|
||||
input_filtered.push_back(i->name);
|
||||
}
|
||||
|
||||
// Get recipe item multiset
|
||||
std::multiset<std::string> rec_names_multiset;
|
||||
rec_names_multiset.insert(craftGetItemName(recipe, gamedef));
|
||||
|
||||
// Recipe is matched when the multisets coincide
|
||||
return inp_names_multiset == rec_names_multiset;
|
||||
// If there is a wrong number of items in input, no match
|
||||
if(input_filtered.size() != 1){
|
||||
/*dstream<<"Number of input items ("<<input_filtered.size()
|
||||
<<") does not match recipe size (1) "
|
||||
<<"of fuel recipe with burntime="<<burntime<<std::endl;*/
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the single input item
|
||||
return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
@@ -723,16 +846,24 @@ CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *ga
|
||||
return CraftOutput("", burntime);
|
||||
}
|
||||
|
||||
CraftInput CraftDefinitionFuel::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<std::string> rec;
|
||||
rec.push_back(recipe);
|
||||
return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef));
|
||||
}
|
||||
|
||||
void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionFuel::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(fuel, recipe=\""<<recipe
|
||||
<<"\", burntime="<<burntime<<")";
|
||||
<<"\", burntime="<<burntime<<")"
|
||||
<<", replacements="<<replacements.dump()<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -740,6 +871,7 @@ void CraftDefinitionFuel::serializeBody(std::ostream &os) const
|
||||
{
|
||||
os<<serializeString(recipe);
|
||||
writeF1000(os, burntime);
|
||||
replacements.serialize(os);
|
||||
}
|
||||
|
||||
void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
|
||||
@@ -748,6 +880,7 @@ void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
|
||||
"unsupported CraftDefinitionFuel version");
|
||||
recipe = deSerializeString(is);
|
||||
burntime = readF1000(is);
|
||||
replacements.deSerialize(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -813,6 +946,47 @@ class CCraftDefManager: public IWritableCraftDefManager
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const
|
||||
{
|
||||
CraftOutput tmpout;
|
||||
tmpout.item = "";
|
||||
tmpout.time = 0;
|
||||
|
||||
// If output item is empty, abort.
|
||||
if(output.item.empty())
|
||||
return false;
|
||||
|
||||
// Walk crafting definitions from back to front, so that later
|
||||
// definitions can override earlier ones.
|
||||
for(std::vector<CraftDefinition*>::const_reverse_iterator
|
||||
i = m_craft_definitions.rbegin();
|
||||
i != m_craft_definitions.rend(); i++)
|
||||
{
|
||||
CraftDefinition *def = *i;
|
||||
|
||||
/*infostream<<"Checking "<<input.dump()<<std::endl
|
||||
<<" against "<<def->dump()<<std::endl;*/
|
||||
|
||||
try {
|
||||
tmpout = def->getOutput(input, gamedef);
|
||||
if(tmpout.item.substr(0,output.item.length()) == output.item)
|
||||
{
|
||||
// Get output, then decrement input (if requested)
|
||||
input = def->getInput(output, gamedef);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
errorstream<<"getCraftResult: ERROR: "
|
||||
<<"Serialization error in recipe "
|
||||
<<def->dump()<<std::endl;
|
||||
// then go on with the next craft definition
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual std::string dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
|
||||
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -106,6 +106,8 @@ struct CraftReplacements
|
||||
pairs(pairs_)
|
||||
{}
|
||||
std::string dump() const;
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -128,6 +130,8 @@ class CraftDefinition
|
||||
// Returns the output structure, meaning depends on crafting method
|
||||
// The implementation can assume that check(input) returns true
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||
// the inverse of the above
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const=0;
|
||||
// Decreases count of every input item
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;
|
||||
|
||||
@@ -162,6 +166,7 @@ class CraftDefinitionShaped: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -203,6 +208,7 @@ class CraftDefinitionShapeless: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -240,6 +246,7 @@ class CraftDefinitionToolRepair: public CraftDefinition
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -270,14 +277,16 @@ class CraftDefinitionCooking: public CraftDefinition
|
||||
CraftDefinitionCooking(
|
||||
const std::string &output_,
|
||||
const std::string &recipe_,
|
||||
float cooktime_):
|
||||
output(output_), recipe(recipe_), cooktime(cooktime_)
|
||||
float cooktime_,
|
||||
const CraftReplacements &replacements_):
|
||||
output(output_), recipe(recipe_), cooktime(cooktime_), replacements(replacements_)
|
||||
{}
|
||||
virtual ~CraftDefinitionCooking(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -293,6 +302,8 @@ class CraftDefinitionCooking: public CraftDefinition
|
||||
std::string recipe;
|
||||
// Time in seconds
|
||||
float cooktime;
|
||||
// Replacement items for decrementInput()
|
||||
CraftReplacements replacements;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -305,14 +316,17 @@ class CraftDefinitionFuel: public CraftDefinition
|
||||
CraftDefinitionFuel():
|
||||
recipe(""), burntime()
|
||||
{}
|
||||
CraftDefinitionFuel(std::string recipe_, float burntime_):
|
||||
recipe(recipe_), burntime(burntime_)
|
||||
CraftDefinitionFuel(std::string recipe_,
|
||||
float burntime_,
|
||||
const CraftReplacements &replacements_):
|
||||
recipe(recipe_), burntime(burntime_), replacements(replacements_)
|
||||
{}
|
||||
virtual ~CraftDefinitionFuel(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
@@ -326,6 +340,8 @@ class CraftDefinitionFuel: public CraftDefinition
|
||||
std::string recipe;
|
||||
// Time in seconds
|
||||
float burntime;
|
||||
// Replacement items for decrementInput()
|
||||
CraftReplacements replacements;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -340,6 +356,8 @@ class ICraftDefManager
|
||||
// The main crafting function
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
@@ -356,6 +374,8 @@ class IWritableCraftDefManager : public ICraftDefManager
|
||||
// The main crafting function
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "debug.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
/*
|
||||
Debug output
|
||||
|
||||
21
src/debug.h
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -24,10 +24,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include <iostream>
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include <irrMap.h>
|
||||
#include "threads.h"
|
||||
#include "gettime.h"
|
||||
#include "constants.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -39,6 +39,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#else
|
||||
#endif
|
||||
|
||||
// Whether to catch all std::exceptions.
|
||||
// Assert will be called on such an event.
|
||||
// In debug mode, leave these for the debugger and don't catch them.
|
||||
#ifdef NDEBUG
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
#else
|
||||
#define CATCH_UNHANDLED_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
Debug output
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -25,7 +25,6 @@ void set_default_settings(Settings *settings)
|
||||
|
||||
settings->setDefault("port", "");
|
||||
settings->setDefault("name", "");
|
||||
settings->setDefault("footprints", "false");
|
||||
|
||||
// Client stuff
|
||||
|
||||
@@ -70,10 +69,14 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("wanted_fps", "30");
|
||||
settings->setDefault("fps_max", "60");
|
||||
// A bit more than the server will send around the player, to make fog blend well
|
||||
settings->setDefault("viewing_range_nodes_min", "35");
|
||||
settings->setDefault("viewing_range_nodes_max", "160");
|
||||
settings->setDefault("viewing_range_nodes_min", "35");
|
||||
settings->setDefault("screenW", "800");
|
||||
settings->setDefault("screenH", "600");
|
||||
settings->setDefault("fullscreen", "false");
|
||||
settings->setDefault("fullscreen_bpp", "24");
|
||||
settings->setDefault("fsaa", "0");
|
||||
settings->setDefault("vsync", "false");
|
||||
settings->setDefault("address", "");
|
||||
settings->setDefault("random_input", "false");
|
||||
settings->setDefault("client_unload_unused_data_timeout", "600");
|
||||
@@ -81,7 +84,7 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("fov", "72");
|
||||
settings->setDefault("view_bobbing", "true");
|
||||
settings->setDefault("new_style_water", "false");
|
||||
settings->setDefault("new_style_leaves", "false");
|
||||
settings->setDefault("new_style_leaves", "true");
|
||||
settings->setDefault("smooth_lighting", "true");
|
||||
settings->setDefault("enable_texture_atlas", "true");
|
||||
settings->setDefault("texture_path", "");
|
||||
@@ -94,10 +97,13 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("enable_clouds", "true");
|
||||
settings->setDefault("screenshot_path", ".");
|
||||
settings->setDefault("view_bobbing_amount", "1.0");
|
||||
settings->setDefault("enable_3d_clouds", "false");
|
||||
settings->setDefault("enable_3d_clouds", "true");
|
||||
settings->setDefault("opaque_water", "false");
|
||||
settings->setDefault("console_color", "(0,0,0)");
|
||||
settings->setDefault("console_alpha", "200");
|
||||
settings->setDefault("enable_sound", "true");
|
||||
settings->setDefault("sound_volume", "0.8");
|
||||
settings->setDefault("desynchronize_mapblock_texture_animation", "true");
|
||||
|
||||
// Server stuff
|
||||
// "map-dir" doesn't exist by default.
|
||||
@@ -111,9 +117,12 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("fixed_map_seed", "");
|
||||
settings->setDefault("give_initial_stuff", "false");
|
||||
settings->setDefault("default_password", "");
|
||||
settings->setDefault("default_privs", "build, shout");
|
||||
settings->setDefault("default_privs", "interact, shout");
|
||||
settings->setDefault("unlimited_player_transfer_distance", "true");
|
||||
settings->setDefault("enable_pvp", "true");
|
||||
settings->setDefault("disallow_empty_password", "false");
|
||||
settings->setDefault("disable_anticheat", "false");
|
||||
settings->setDefault("enable_rollback_recording", "false");
|
||||
|
||||
settings->setDefault("profiler_print_interval", "0");
|
||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||
@@ -123,14 +132,14 @@ void set_default_settings(Settings *settings)
|
||||
// This causes frametime jitter on client side, or does it?
|
||||
settings->setDefault("max_simultaneous_block_sends_per_client", "4");
|
||||
settings->setDefault("max_simultaneous_block_sends_server_total", "20");
|
||||
settings->setDefault("max_block_send_distance", "10");
|
||||
settings->setDefault("max_block_generate_distance", "6");
|
||||
settings->setDefault("max_block_send_distance", "9");
|
||||
settings->setDefault("max_block_generate_distance", "7");
|
||||
settings->setDefault("time_send_interval", "5");
|
||||
settings->setDefault("time_speed", "96");
|
||||
settings->setDefault("time_speed", "72");
|
||||
settings->setDefault("server_unload_unused_data_timeout", "29");
|
||||
settings->setDefault("server_map_save_interval", "5.3");
|
||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
settings->setDefault("enable_experimental", "false");
|
||||
settings->setDefault("dedicated_server_step", "0.05");
|
||||
settings->setDefault("ignore_world_load_errors", "false");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -37,11 +37,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodemetadata.h"
|
||||
#include "main.h" // For g_settings, g_profiler
|
||||
#include "gamedef.h"
|
||||
#include "serverremoteplayer.h"
|
||||
#ifndef SERVER
|
||||
#include "clientmap.h"
|
||||
#include "localplayer.h"
|
||||
#endif
|
||||
#include "daynightratio.h"
|
||||
#include "map.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@@ -325,6 +326,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L,
|
||||
m_emerger(emerger),
|
||||
m_random_spawn_timer(3),
|
||||
m_send_recommended_timer(0),
|
||||
m_active_block_interval_overload_skip(0),
|
||||
m_game_time(0),
|
||||
m_game_time_fraction_counter(0)
|
||||
{
|
||||
@@ -349,6 +351,17 @@ ServerEnvironment::~ServerEnvironment()
|
||||
}
|
||||
}
|
||||
|
||||
Map & ServerEnvironment::getMap()
|
||||
{
|
||||
return *m_map;
|
||||
}
|
||||
|
||||
ServerMap & ServerEnvironment::getServerMap()
|
||||
{
|
||||
return *m_map;
|
||||
}
|
||||
|
||||
|
||||
void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||
{
|
||||
std::string players_path = savedir + "/players";
|
||||
@@ -368,7 +381,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||
//infostream<<"Checking player file "<<path<<std::endl;
|
||||
|
||||
// Load player to see what is its name
|
||||
ServerRemotePlayer testplayer(this);
|
||||
RemotePlayer testplayer(m_gamedef);
|
||||
{
|
||||
// Open file and deserialize
|
||||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
@@ -482,7 +495,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
//infostream<<"Checking player file "<<path<<std::endl;
|
||||
|
||||
// Load player to see what is its name
|
||||
ServerRemotePlayer testplayer(this);
|
||||
RemotePlayer testplayer(m_gamedef);
|
||||
{
|
||||
// Open file and deserialize
|
||||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
@@ -510,12 +523,10 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
if(player == NULL)
|
||||
{
|
||||
//infostream<<"Is a new player"<<std::endl;
|
||||
player = new ServerRemotePlayer(this);
|
||||
player = new RemotePlayer(m_gamedef);
|
||||
newplayer = true;
|
||||
}
|
||||
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
||||
|
||||
// Load player
|
||||
{
|
||||
verbosestream<<"Reading player "<<testplayer.getName()<<" from "
|
||||
@@ -527,9 +538,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
infostream<<"Failed to read "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
srp->deSerialize(is);
|
||||
srp->m_last_good_position = srp->getBasePosition();
|
||||
srp->m_last_good_position_age = 0;
|
||||
player->deSerialize(is);
|
||||
}
|
||||
|
||||
if(newplayer)
|
||||
@@ -637,13 +646,15 @@ class ABMHandler
|
||||
i->timer -= trigger_interval;
|
||||
actual_interval = trigger_interval;
|
||||
}
|
||||
ActiveABM aabm;
|
||||
aabm.abm = abm;
|
||||
float intervals = actual_interval / trigger_interval;
|
||||
if(intervals == 0)
|
||||
continue;
|
||||
float chance = abm->getTriggerChance();
|
||||
if(chance == 0)
|
||||
chance = 1;
|
||||
aabm.chance = 1.0 / pow((float)1.0/chance, (float)intervals);
|
||||
ActiveABM aabm;
|
||||
aabm.abm = abm;
|
||||
aabm.chance = chance / intervals;
|
||||
if(aabm.chance == 0)
|
||||
aabm.chance = 1;
|
||||
// Trigger neighbors
|
||||
@@ -651,27 +662,30 @@ class ABMHandler
|
||||
= abm->getRequiredNeighbors();
|
||||
for(std::set<std::string>::iterator
|
||||
i = required_neighbors_s.begin();
|
||||
i != required_neighbors_s.end(); i++){
|
||||
content_t c = ndef->getId(*i);
|
||||
if(c == CONTENT_IGNORE)
|
||||
continue;
|
||||
aabm.required_neighbors.insert(c);
|
||||
i != required_neighbors_s.end(); i++)
|
||||
{
|
||||
ndef->getIds(*i, aabm.required_neighbors);
|
||||
}
|
||||
// Trigger contents
|
||||
std::set<std::string> contents_s = abm->getTriggerContents();
|
||||
for(std::set<std::string>::iterator
|
||||
i = contents_s.begin(); i != contents_s.end(); i++){
|
||||
content_t c = ndef->getId(*i);
|
||||
if(c == CONTENT_IGNORE)
|
||||
continue;
|
||||
std::map<content_t, std::list<ActiveABM> >::iterator j;
|
||||
j = m_aabms.find(c);
|
||||
if(j == m_aabms.end()){
|
||||
std::list<ActiveABM> aabmlist;
|
||||
m_aabms[c] = aabmlist;
|
||||
i = contents_s.begin(); i != contents_s.end(); i++)
|
||||
{
|
||||
std::set<content_t> ids;
|
||||
ndef->getIds(*i, ids);
|
||||
for(std::set<content_t>::const_iterator k = ids.begin();
|
||||
k != ids.end(); k++)
|
||||
{
|
||||
content_t c = *k;
|
||||
std::map<content_t, std::list<ActiveABM> >::iterator j;
|
||||
j = m_aabms.find(c);
|
||||
if(j == m_aabms.end()){
|
||||
std::list<ActiveABM> aabmlist;
|
||||
m_aabms[c] = aabmlist;
|
||||
j = m_aabms.find(c);
|
||||
}
|
||||
j->second.push_back(aabm);
|
||||
}
|
||||
j->second.push_back(aabm);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -772,17 +786,18 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
||||
// Activate stored objects
|
||||
activateObjects(block);
|
||||
|
||||
// Run node metadata
|
||||
bool changed = block->m_node_metadata->step((float)dtime_s);
|
||||
if(changed)
|
||||
{
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = block->getPos();
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"node metadata modified in activateBlock");
|
||||
// Run node timers
|
||||
std::map<v3s16, NodeTimer> elapsed_timers =
|
||||
block->m_node_timers.step((float)dtime_s);
|
||||
if(!elapsed_timers.empty()){
|
||||
MapNode n;
|
||||
for(std::map<v3s16, NodeTimer>::iterator
|
||||
i = elapsed_timers.begin();
|
||||
i != elapsed_timers.end(); i++){
|
||||
n = block->getNodeNoEx(i->first);
|
||||
if(scriptapi_node_on_timer(m_lua,i->first,n,i->second.elapsed))
|
||||
block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0));
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle ActiveBlockModifiers */
|
||||
@@ -1063,24 +1078,30 @@ void ServerEnvironment::step(float dtime)
|
||||
block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
|
||||
"Timestamp older than 60s (step)");
|
||||
|
||||
// Run node metadata
|
||||
bool changed = block->m_node_metadata->step(dtime);
|
||||
if(changed)
|
||||
{
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = p;
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"node metadata modified in step");
|
||||
// Run node timers
|
||||
std::map<v3s16, NodeTimer> elapsed_timers =
|
||||
block->m_node_timers.step((float)dtime);
|
||||
if(!elapsed_timers.empty()){
|
||||
MapNode n;
|
||||
for(std::map<v3s16, NodeTimer>::iterator
|
||||
i = elapsed_timers.begin();
|
||||
i != elapsed_timers.end(); i++){
|
||||
n = block->getNodeNoEx(i->first);
|
||||
if(scriptapi_node_on_timer(m_lua,i->first,n,i->second.elapsed))
|
||||
block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float abm_interval = 1.0;
|
||||
if(m_active_block_modifier_interval.step(dtime, abm_interval))
|
||||
{
|
||||
do{ // breakable
|
||||
if(m_active_block_interval_overload_skip > 0){
|
||||
ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips");
|
||||
m_active_block_interval_overload_skip--;
|
||||
break;
|
||||
}
|
||||
ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg /1s", SPT_AVG);
|
||||
TimeTaker timer("modify in active blocks");
|
||||
|
||||
@@ -1113,8 +1134,9 @@ void ServerEnvironment::step(float dtime)
|
||||
infostream<<"WARNING: active block modifiers took "
|
||||
<<time_ms<<"ms (longer than "
|
||||
<<max_time_ms<<"ms)"<<std::endl;
|
||||
m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1;
|
||||
}
|
||||
}
|
||||
}while(0);
|
||||
|
||||
/*
|
||||
Step script environment (run global on_step())
|
||||
@@ -1747,6 +1769,15 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
force_delete = true;
|
||||
} else {
|
||||
u16 new_id = pending_delete ? id : 0;
|
||||
// If static counterpart already exists, remove it first.
|
||||
// This shouldn't happen, but happens rarely for some
|
||||
// unknown reason. Unsuccessful attempts have been made to
|
||||
// find said reason.
|
||||
if(new_id && block->m_static_objects.m_active.find(new_id)){
|
||||
infostream<<"ServerEnv: WARNING: Performing hack #83274"
|
||||
<<std::endl;
|
||||
block->m_static_objects.remove(new_id);
|
||||
}
|
||||
block->m_static_objects.insert(new_id, s_obj);
|
||||
|
||||
// Only mark block as modified if data changed considerably
|
||||
@@ -1890,7 +1921,8 @@ void ClientEnvironment::step(float dtime)
|
||||
stepTimeOfDay(dtime);
|
||||
|
||||
// Get some settings
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
bool fly_allowed = m_gamedef->checkLocalPrivilege("fly");
|
||||
bool free_move = fly_allowed && g_settings->getBool("free_move");
|
||||
|
||||
// Get local player
|
||||
LocalPlayer *lplayer = getLocalPlayer();
|
||||
@@ -2004,13 +2036,15 @@ void ClientEnvironment::step(float dtime)
|
||||
if(info.t == COLLISION_FALL)
|
||||
{
|
||||
//f32 tolerance = BS*10; // 2 without damage
|
||||
f32 tolerance = BS*12; // 3 without damage
|
||||
//f32 tolerance = BS*12; // 3 without damage
|
||||
f32 tolerance = BS*14; // 5 without damage
|
||||
f32 factor = 1;
|
||||
if(info.speed > tolerance)
|
||||
{
|
||||
f32 damage_f = (info.speed - tolerance)/BS*factor;
|
||||
u16 damage = (u16)(damage_f+0.5);
|
||||
damageLocalPlayer(damage, true);
|
||||
if(damage != 0)
|
||||
damageLocalPlayer(damage, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2074,7 +2108,7 @@ void ClientEnvironment::step(float dtime)
|
||||
catch(InvalidPositionException &e){
|
||||
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
||||
}
|
||||
player->updateLight(light);
|
||||
player->light = light;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2226,8 +2260,19 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||
|
||||
obj->setId(id);
|
||||
|
||||
obj->initialize(init_data);
|
||||
|
||||
try
|
||||
{
|
||||
obj->initialize(init_data);
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
errorstream<<"ClientEnvironment::addActiveObject():"
|
||||
<<" id="<<id<<" type="<<type
|
||||
<<": SerializationError in initialize(),"
|
||||
<<" init_data="<<serializeJsonString(init_data)
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
addActiveObject(obj);
|
||||
}
|
||||
|
||||
@@ -2258,7 +2303,18 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
obj->processMessage(data);
|
||||
try
|
||||
{
|
||||
obj->processMessage(data);
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
errorstream<<"ClientEnvironment::processActiveObjectMessage():"
|
||||
<<" id="<<id<<" type="<<obj->getType()
|
||||
<<" SerializationError in processMessage(),"
|
||||
<<" message="<<serializeJsonString(data)
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -31,12 +31,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "player.h"
|
||||
#include "map.h"
|
||||
#include <ostream>
|
||||
#include "utility.h"
|
||||
#include "activeobject.h"
|
||||
#include "util/container.h"
|
||||
#include "util/numeric.h"
|
||||
#include "mapnode.h"
|
||||
#include "mapblock.h"
|
||||
|
||||
class Server;
|
||||
class ServerEnvironment;
|
||||
@@ -45,6 +47,8 @@ class ServerActiveObject;
|
||||
typedef struct lua_State lua_State;
|
||||
class ITextureSource;
|
||||
class IGameDef;
|
||||
class Map;
|
||||
class ServerMap;
|
||||
class ClientMap;
|
||||
|
||||
class Environment
|
||||
@@ -190,11 +194,9 @@ class ServerEnvironment : public Environment
|
||||
IBackgroundBlockEmerger *emerger);
|
||||
~ServerEnvironment();
|
||||
|
||||
Map & getMap()
|
||||
{ return *m_map; }
|
||||
Map & getMap();
|
||||
|
||||
ServerMap & getServerMap()
|
||||
{ return *m_map; }
|
||||
ServerMap & getServerMap();
|
||||
|
||||
lua_State* getLua()
|
||||
{ return m_lua; }
|
||||
@@ -358,6 +360,7 @@ class ServerEnvironment : public Environment
|
||||
IntervalLimiter m_active_blocks_management_interval;
|
||||
IntervalLimiter m_active_block_modifier_interval;
|
||||
IntervalLimiter m_active_blocks_nodemetadata_interval;
|
||||
int m_active_block_interval_overload_skip;
|
||||
// Time from the beginning of the game in seconds.
|
||||
// Incremented in step().
|
||||
u32 m_game_time;
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2012 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Part of 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -125,7 +125,7 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
|
||||
hp.ma = (4)*BS;
|
||||
/*hp.gh = BS*base_rock_level_2d(seed, p2d);
|
||||
hp.ma = BS*get_mud_add_amount(seed, p2d);*/
|
||||
hp.have_sand = mapgen::get_have_sand(seed, p2d);
|
||||
hp.have_sand = mapgen::get_have_beach(seed, p2d);
|
||||
if(hp.gh > BS*WATER_LEVEL)
|
||||
hp.tree_amount = mapgen::tree_amount_2d(seed, p2d);
|
||||
else
|
||||
|
||||
@@ -3,16 +3,16 @@ Part of Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
distance according to map seed
|
||||
*/
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
|
||||
#define FARMESH_MATERIAL_COUNT 2
|
||||
|
||||
|
||||
@@ -4,30 +4,31 @@ Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
|
||||
|
||||
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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "filecache.h"
|
||||
|
||||
#include "clientserver.h"
|
||||
#include "log.h"
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "hex.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
bool FileCache::loadByPath(const std::string &path, std::ostream &os)
|
||||
{
|
||||
|
||||
@@ -4,16 +4,16 @@ Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
|
||||
|
||||
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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
@@ -214,6 +214,7 @@ bool DeleteSingleFileOrEmptyDirectory(std::string path)
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
std::vector<DirListNode> GetDirListing(std::string pathstring)
|
||||
{
|
||||
|
||||
@@ -3,16 +3,16 @@ Minetest-c55
|
||||
Copyright (C) 2010 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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
548
src/game.cpp
@@ -3,22 +3,22 @@ Minetest-c55
|
||||
Copyright (C) 2010-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
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "game.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
@@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "server.h"
|
||||
#include "guiPauseMenu.h"
|
||||
#include "guiPasswordChange.h"
|
||||
#include "guiInventoryMenu.h"
|
||||
#include "guiFormSpecMenu.h"
|
||||
#include "guiTextInputMenu.h"
|
||||
#include "guiDeathScreen.h"
|
||||
#include "tool.h"
|
||||
@@ -61,17 +61,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#endif
|
||||
#include "event_manager.h"
|
||||
#include <list>
|
||||
|
||||
/*
|
||||
Setting this to 1 enables a special camera mode that forces
|
||||
the renderers to think that the camera statically points from
|
||||
the starting place to a static direction.
|
||||
|
||||
This allows one to move around with the player and see what
|
||||
is actually drawn behind solid things and behind the player.
|
||||
*/
|
||||
#define FIELD_OF_VIEW_TEST 0
|
||||
|
||||
#include "util/directiontables.h"
|
||||
|
||||
/*
|
||||
Text input system
|
||||
@@ -87,6 +77,10 @@ struct TextDestChat : public TextDest
|
||||
{
|
||||
m_client->typeChatMessage(text);
|
||||
}
|
||||
void gotText(std::map<std::string, std::string> fields)
|
||||
{
|
||||
m_client->typeChatMessage(narrow_to_wide(fields["text"]));
|
||||
}
|
||||
|
||||
Client *m_client;
|
||||
};
|
||||
@@ -98,18 +92,39 @@ struct TextDestNodeMetadata : public TextDest
|
||||
m_p = p;
|
||||
m_client = client;
|
||||
}
|
||||
// This is deprecated I guess? -celeron55
|
||||
void gotText(std::wstring text)
|
||||
{
|
||||
std::string ntext = wide_to_narrow(text);
|
||||
infostream<<"Changing text of a sign node: "
|
||||
<<ntext<<std::endl;
|
||||
m_client->sendSignNodeText(m_p, ntext);
|
||||
infostream<<"Submitting 'text' field of node at ("<<m_p.X<<","
|
||||
<<m_p.Y<<","<<m_p.Z<<"): "<<ntext<<std::endl;
|
||||
std::map<std::string, std::string> fields;
|
||||
fields["text"] = ntext;
|
||||
m_client->sendNodemetaFields(m_p, "", fields);
|
||||
}
|
||||
void gotText(std::map<std::string, std::string> fields)
|
||||
{
|
||||
m_client->sendNodemetaFields(m_p, "", fields);
|
||||
}
|
||||
|
||||
v3s16 m_p;
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
struct TextDestPlayerInventory : public TextDest
|
||||
{
|
||||
TextDestPlayerInventory(Client *client)
|
||||
{
|
||||
m_client = client;
|
||||
}
|
||||
void gotText(std::map<std::string, std::string> fields)
|
||||
{
|
||||
m_client->sendInventoryFields("", fields);
|
||||
}
|
||||
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
/* Respawn menu callback */
|
||||
|
||||
class MainRespawnInitiator: public IRespawnInitiator
|
||||
@@ -130,6 +145,51 @@ class MainRespawnInitiator: public IRespawnInitiator
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
/* Form update callback */
|
||||
|
||||
class NodeMetadataFormSource: public IFormSource
|
||||
{
|
||||
public:
|
||||
NodeMetadataFormSource(ClientMap *map, v3s16 p):
|
||||
m_map(map),
|
||||
m_p(p)
|
||||
{
|
||||
}
|
||||
std::string getForm()
|
||||
{
|
||||
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
|
||||
if(!meta)
|
||||
return "";
|
||||
return meta->getString("formspec");
|
||||
}
|
||||
std::string resolveText(std::string str)
|
||||
{
|
||||
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
|
||||
if(!meta)
|
||||
return str;
|
||||
return meta->resolveString(str);
|
||||
}
|
||||
|
||||
ClientMap *m_map;
|
||||
v3s16 m_p;
|
||||
};
|
||||
|
||||
class PlayerInventoryFormSource: public IFormSource
|
||||
{
|
||||
public:
|
||||
PlayerInventoryFormSource(Client *client):
|
||||
m_client(client)
|
||||
{
|
||||
}
|
||||
std::string getForm()
|
||||
{
|
||||
LocalPlayer* player = m_client->getEnv().getLocalPlayer();
|
||||
return player->inventory_formspec;
|
||||
}
|
||||
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
/*
|
||||
Hotbar draw routine
|
||||
*/
|
||||
@@ -281,14 +341,12 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
core::line3d<f32> shootline, f32 d,
|
||||
bool liquids_pointable,
|
||||
bool look_for_object,
|
||||
core::aabbox3d<f32> &hilightbox,
|
||||
bool &should_show_hilightbox,
|
||||
std::vector<aabb3f> &hilightboxes,
|
||||
ClientActiveObject *&selected_object)
|
||||
{
|
||||
PointedThing result;
|
||||
|
||||
hilightbox = core::aabbox3d<f32>(0,0,0,0,0,0);
|
||||
should_show_hilightbox = false;
|
||||
hilightboxes.clear();
|
||||
selected_object = NULL;
|
||||
|
||||
INodeDefManager *nodedef = client->getNodeDefManager();
|
||||
@@ -299,27 +357,27 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
{
|
||||
selected_object = client->getSelectedActiveObject(d*BS,
|
||||
camera_position, shootline);
|
||||
}
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
core::aabbox3d<f32> *selection_box
|
||||
= selected_object->getSelectionBox();
|
||||
// Box should exist because object was returned in the
|
||||
// first place
|
||||
assert(selection_box);
|
||||
|
||||
v3f pos = selected_object->getPosition();
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
if(selected_object->doShowSelectionBox())
|
||||
{
|
||||
aabb3f *selection_box = selected_object->getSelectionBox();
|
||||
// Box should exist because object was
|
||||
// returned in the first place
|
||||
assert(selection_box);
|
||||
|
||||
hilightbox = core::aabbox3d<f32>(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos
|
||||
);
|
||||
v3f pos = selected_object->getPosition();
|
||||
hilightboxes.push_back(aabb3f(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos));
|
||||
}
|
||||
|
||||
should_show_hilightbox = selected_object->doShowSelectionBox();
|
||||
|
||||
result.type = POINTEDTHING_OBJECT;
|
||||
result.object_id = selected_object->getId();
|
||||
return result;
|
||||
result.type = POINTEDTHING_OBJECT;
|
||||
result.object_id = selected_object->getId();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// That didn't work, try to find a pointed at node
|
||||
@@ -339,6 +397,14 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
|
||||
s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
|
||||
|
||||
// Prevent signed number overflow
|
||||
if(yend==32767)
|
||||
yend=32766;
|
||||
if(zend==32767)
|
||||
zend=32766;
|
||||
if(xend==32767)
|
||||
xend=32766;
|
||||
|
||||
for(s16 y = ystart; y <= yend; y++)
|
||||
for(s16 z = zstart; z <= zend; z++)
|
||||
for(s16 x = xstart; x <= xend; x++)
|
||||
@@ -355,196 +421,64 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
if(!isPointableNode(n, client, liquids_pointable))
|
||||
continue;
|
||||
|
||||
std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
|
||||
|
||||
v3s16 np(x,y,z);
|
||||
v3f npf = intToFloat(np, BS);
|
||||
|
||||
f32 d = 0.01;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
const ContentFeatures &f = nodedef->get(n);
|
||||
|
||||
if(f.selection_box.type == NODEBOX_FIXED)
|
||||
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
core::aabbox3d<f32> box = f.selection_box.fixed;
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
v3s16 facedirs[6] = {
|
||||
v3s16(-1,0,0),
|
||||
v3s16(1,0,0),
|
||||
v3s16(0,-1,0),
|
||||
v3s16(0,1,0),
|
||||
v3s16(0,0,-1),
|
||||
v3s16(0,0,1),
|
||||
};
|
||||
|
||||
core::aabbox3d<f32> faceboxes[6] = {
|
||||
// X-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MinEdge.X+d, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// X+
|
||||
core::aabbox3d<f32>(
|
||||
box.MaxEdge.X-d, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// Y-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MinEdge.Y+d, box.MaxEdge.Z
|
||||
),
|
||||
// Y+
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MaxEdge.Y-d, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// Z-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MinEdge.Z+d
|
||||
),
|
||||
// Z+
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MaxEdge.Z-d,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
};
|
||||
|
||||
for(u16 i=0; i<6; i++)
|
||||
for(u16 j=0; j<6; j++)
|
||||
{
|
||||
v3f facedir_f(facedirs[i].X, facedirs[i].Y, facedirs[i].Z);
|
||||
v3f centerpoint = npf + facedir_f * BS/2;
|
||||
v3s16 facedir = g_6dirs[j];
|
||||
aabb3f facebox = box;
|
||||
|
||||
f32 d = 0.001*BS;
|
||||
if(facedir.X > 0)
|
||||
facebox.MinEdge.X = facebox.MaxEdge.X-d;
|
||||
else if(facedir.X < 0)
|
||||
facebox.MaxEdge.X = facebox.MinEdge.X+d;
|
||||
else if(facedir.Y > 0)
|
||||
facebox.MinEdge.Y = facebox.MaxEdge.Y-d;
|
||||
else if(facedir.Y < 0)
|
||||
facebox.MaxEdge.Y = facebox.MinEdge.Y+d;
|
||||
else if(facedir.Z > 0)
|
||||
facebox.MinEdge.Z = facebox.MaxEdge.Z-d;
|
||||
else if(facedir.Z < 0)
|
||||
facebox.MaxEdge.Z = facebox.MinEdge.Z+d;
|
||||
|
||||
v3f centerpoint = facebox.getCenter();
|
||||
f32 distance = (centerpoint - camera_position).getLength();
|
||||
if(distance >= mindistance)
|
||||
continue;
|
||||
if(!faceboxes[i].intersectsWithLine(shootline))
|
||||
if(!facebox.intersectsWithLine(shootline))
|
||||
continue;
|
||||
|
||||
v3s16 np_above = np + facedir;
|
||||
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np+facedirs[i];
|
||||
result.node_abovesurface = np_above;
|
||||
mindistance = distance;
|
||||
hilightbox = box;
|
||||
should_show_hilightbox = true;
|
||||
}
|
||||
}
|
||||
else if(f.selection_box.type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
v3s16 dir = n.getWallMountedDir(nodedef);
|
||||
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();
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
// top
|
||||
if(dir == v3s16(0,1,0)){
|
||||
box = f.selection_box.wall_top;
|
||||
}
|
||||
// bottom
|
||||
else if(dir == v3s16(0,-1,0)){
|
||||
box = f.selection_box.wall_bottom;
|
||||
}
|
||||
// side
|
||||
else{
|
||||
v3f vertices[2] =
|
||||
hilightboxes.clear();
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i2 = boxes.begin();
|
||||
i2 != boxes.end(); i2++)
|
||||
{
|
||||
f.selection_box.wall_side.MinEdge,
|
||||
f.selection_box.wall_side.MaxEdge
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
}
|
||||
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np;
|
||||
mindistance = distance;
|
||||
hilightbox = box;
|
||||
should_show_hilightbox = true;
|
||||
aabb3f box = *i2;
|
||||
box.MinEdge += npf + v3f(-d,-d,-d);
|
||||
box.MaxEdge += npf + v3f(d,d,d);
|
||||
hilightboxes.push_back(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // NODEBOX_REGULAR
|
||||
{
|
||||
for(u16 i=0; i<6; i++)
|
||||
{
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
v3f centerpoint = npf + dir_f * BS/2;
|
||||
f32 distance =
|
||||
(centerpoint - camera_position).getLength();
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np + dirs[i];
|
||||
mindistance = distance;
|
||||
|
||||
//hilightbox = facebox;
|
||||
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(np, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
hilightbox = nodebox;
|
||||
should_show_hilightbox = true;
|
||||
}
|
||||
} // if distance < mindistance
|
||||
} // for dirs
|
||||
} // regular block
|
||||
} // for coords
|
||||
|
||||
return result;
|
||||
@@ -955,10 +889,14 @@ void the_game(
|
||||
ISoundManager *sound = NULL;
|
||||
bool sound_is_dummy = false;
|
||||
#if USE_SOUND
|
||||
infostream<<"Attempting to use OpenAL audio"<<std::endl;
|
||||
sound = createOpenALSoundManager(&soundfetcher);
|
||||
if(!sound)
|
||||
infostream<<"Failed to initialize OpenAL audio"<<std::endl;
|
||||
if(g_settings->getBool("enable_sound")){
|
||||
infostream<<"Attempting to use OpenAL audio"<<std::endl;
|
||||
sound = createOpenALSoundManager(&soundfetcher);
|
||||
if(!sound)
|
||||
infostream<<"Failed to initialize OpenAL audio"<<std::endl;
|
||||
} else {
|
||||
infostream<<"Sound disabled."<<std::endl;
|
||||
}
|
||||
#endif
|
||||
if(!sound){
|
||||
infostream<<"Using dummy audio."<<std::endl;
|
||||
@@ -1208,6 +1146,16 @@ void the_game(
|
||||
*/
|
||||
Inventory local_inventory(itemdef);
|
||||
|
||||
/*
|
||||
Find out size of crack animation
|
||||
*/
|
||||
int crack_animation_length = 5;
|
||||
{
|
||||
video::ITexture *t = tsrc->getTextureRaw("crack_anylength.png");
|
||||
v2u32 size = t->getOriginalSize();
|
||||
crack_animation_length = size.Y / size.X;
|
||||
}
|
||||
|
||||
/*
|
||||
Add some gui stuff
|
||||
*/
|
||||
@@ -1487,7 +1435,7 @@ void the_game(
|
||||
hotbar_imagesize = 64;
|
||||
|
||||
// Hilight boxes collected during the loop and displayed
|
||||
core::list< core::aabbox3d<f32> > hilightboxes;
|
||||
std::vector<aabb3f> hilightboxes;
|
||||
|
||||
// Info text
|
||||
std::wstring infotext;
|
||||
@@ -1561,27 +1509,19 @@ void the_game(
|
||||
infostream<<"the_game: "
|
||||
<<"Launching inventory"<<std::endl;
|
||||
|
||||
GUIInventoryMenu *menu =
|
||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, v2s16(8,7),
|
||||
GUIFormSpecMenu *menu =
|
||||
new GUIFormSpecMenu(guienv, guiroot, -1,
|
||||
&g_menumgr,
|
||||
&client, gamedef);
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setCurrentPlayer();
|
||||
|
||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", inventoryloc, "main",
|
||||
v2s32(0, 3), v2s32(8, 4)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", inventoryloc, "craft",
|
||||
v2s32(3, 0), v2s32(3, 3)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", inventoryloc, "craftpreview",
|
||||
v2s32(7, 1), v2s32(1, 1)));
|
||||
|
||||
menu->setDrawSpec(draw_spec);
|
||||
|
||||
PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
|
||||
assert(src);
|
||||
menu->setFormSpec(src->getForm(), inventoryloc);
|
||||
menu->setFormSource(src);
|
||||
menu->setTextDest(new TextDestPlayerInventory(&client));
|
||||
menu->drop();
|
||||
}
|
||||
else if(input->wasKeyDown(EscapeKey))
|
||||
@@ -1636,6 +1576,8 @@ void the_game(
|
||||
g_settings->set("free_move","true");
|
||||
statustext = L"free_move enabled";
|
||||
statustext_time = 0;
|
||||
if(!client.checkPrivilege("fly"))
|
||||
statustext += L" (note: no 'fly' privilege)";
|
||||
}
|
||||
}
|
||||
else if(input->wasKeyDown(getKeySetting("keymap_fastmove")))
|
||||
@@ -1651,6 +1593,8 @@ void the_game(
|
||||
g_settings->set("fast_move","true");
|
||||
statustext = L"fast_move enabled";
|
||||
statustext_time = 0;
|
||||
if(!client.checkPrivilege("fast"))
|
||||
statustext += L" (note: no 'fast' privilege)";
|
||||
}
|
||||
}
|
||||
else if(input->wasKeyDown(getKeySetting("keymap_screenshot")))
|
||||
@@ -2076,8 +2020,9 @@ void the_game(
|
||||
// Update sound listener
|
||||
sound->updateListener(camera.getCameraNode()->getPosition(),
|
||||
v3f(0,0,0), // velocity
|
||||
camera.getCameraNode()->getTarget(),
|
||||
camera.getDirection(),
|
||||
camera.getCameraNode()->getUpVector());
|
||||
sound->setListenerGain(g_settings->getFloat("sound_volume"));
|
||||
|
||||
/*
|
||||
Update sound maker
|
||||
@@ -2100,8 +2045,6 @@ void the_game(
|
||||
core::line3d<f32> shootline(camera_position,
|
||||
camera_position + camera_direction * BS * (d+1));
|
||||
|
||||
core::aabbox3d<f32> hilightbox;
|
||||
bool should_show_hilightbox = false;
|
||||
ClientActiveObject *selected_object = NULL;
|
||||
|
||||
PointedThing pointed = getPointedThing(
|
||||
@@ -2110,7 +2053,7 @@ void the_game(
|
||||
camera_position, shootline, d,
|
||||
playeritem_liquids_pointable, !ldown_for_dig,
|
||||
// output
|
||||
hilightbox, should_show_hilightbox,
|
||||
hilightboxes,
|
||||
selected_object);
|
||||
|
||||
if(pointed != pointed_old)
|
||||
@@ -2119,12 +2062,6 @@ void the_game(
|
||||
//dstream<<"Pointing at "<<pointed.dump()<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Visualize selection
|
||||
*/
|
||||
if(should_show_hilightbox)
|
||||
hilightboxes.push_back(hilightbox);
|
||||
|
||||
/*
|
||||
Stop digging when
|
||||
- releasing left mouse button
|
||||
@@ -2186,10 +2123,10 @@ void the_game(
|
||||
ClientMap &map = client.getEnv().getClientMap();
|
||||
NodeMetadata *meta = map.getNodeMetadata(nodepos);
|
||||
if(meta){
|
||||
infotext = narrow_to_wide(meta->infoText());
|
||||
infotext = narrow_to_wide(meta->getString("infotext"));
|
||||
} else {
|
||||
MapNode n = map.getNode(nodepos);
|
||||
if(nodedef->get(n).tname_tiles[0] == "unknown_block.png"){
|
||||
if(nodedef->get(n).tiledef[0].name == "unknown_block.png"){
|
||||
infotext = L"Unknown node: ";
|
||||
infotext += narrow_to_wide(nodedef->get(n).name);
|
||||
}
|
||||
@@ -2214,7 +2151,9 @@ void the_game(
|
||||
ldown_for_dig = true;
|
||||
}
|
||||
MapNode n = client.getEnv().getClientMap().getNode(nodepos);
|
||||
|
||||
|
||||
// NOTE: Similar piece of code exists on the server side for
|
||||
// cheat detection.
|
||||
// Get digging parameters
|
||||
DigParams params = getDigParams(nodedef->get(n).groups,
|
||||
&playeritem_toolcap);
|
||||
@@ -2254,20 +2193,20 @@ void the_game(
|
||||
|
||||
if(dig_time_complete >= 0.001)
|
||||
{
|
||||
dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
|
||||
dig_index = (u16)((float)crack_animation_length
|
||||
* dig_time/dig_time_complete);
|
||||
}
|
||||
// This is for torches
|
||||
else
|
||||
{
|
||||
dig_index = CRACK_ANIMATION_LENGTH;
|
||||
dig_index = crack_animation_length;
|
||||
}
|
||||
|
||||
|
||||
// Don't show cracks if not diggable
|
||||
if(dig_time_complete >= 100000.0)
|
||||
{
|
||||
}
|
||||
else if(dig_index < CRACK_ANIMATION_LENGTH)
|
||||
else if(dig_index < crack_animation_length)
|
||||
{
|
||||
//TimeTaker timer("client.setTempMod");
|
||||
//infostream<<"dig_index="<<dig_index<<std::endl;
|
||||
@@ -2285,7 +2224,7 @@ void the_game(
|
||||
digging = false;
|
||||
|
||||
nodig_delay_timer = dig_time_complete
|
||||
/ (float)CRACK_ANIMATION_LENGTH;
|
||||
/ (float)crack_animation_length;
|
||||
|
||||
// We don't want a corresponding delay to
|
||||
// very time consuming nodes
|
||||
@@ -2311,35 +2250,9 @@ void the_game(
|
||||
{
|
||||
infostream<<"Ground right-clicked"<<std::endl;
|
||||
|
||||
// If metadata provides an inventory view, activate it
|
||||
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
|
||||
{
|
||||
infostream<<"Launching custom inventory view"<<std::endl;
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setNodeMeta(nodepos);
|
||||
|
||||
|
||||
/*
|
||||
Create menu
|
||||
*/
|
||||
|
||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||
v2s16 invsize =
|
||||
GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
draw_spec,
|
||||
meta->getInventoryDrawSpecString(),
|
||||
inventoryloc);
|
||||
|
||||
GUIInventoryMenu *menu =
|
||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, invsize,
|
||||
&client, gamedef);
|
||||
menu->setDrawSpec(draw_spec);
|
||||
menu->drop();
|
||||
}
|
||||
// If metadata provides text input, activate text input
|
||||
else if(meta && meta->allowsTextInput() && !random_input)
|
||||
// Sign special case, at least until formspec is properly implemented.
|
||||
// Deprecated?
|
||||
if(meta && meta->getString("formspec") == "hack:sign_text_input" && !random_input)
|
||||
{
|
||||
infostream<<"Launching metadata text input"<<std::endl;
|
||||
|
||||
@@ -2347,17 +2260,78 @@ void the_game(
|
||||
|
||||
TextDest *dest = new TextDestNodeMetadata(nodepos, &client);
|
||||
|
||||
std::wstring wtext = narrow_to_wide(meta->getText());
|
||||
std::wstring wtext = narrow_to_wide(meta->getString("text"));
|
||||
|
||||
(new GUITextInputMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, dest,
|
||||
wtext))->drop();
|
||||
}
|
||||
// If metadata provides an inventory view, activate it
|
||||
else if(meta && meta->getString("formspec") != "" && !random_input)
|
||||
{
|
||||
infostream<<"Launching custom inventory view"<<std::endl;
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setNodeMeta(nodepos);
|
||||
|
||||
/* Create menu */
|
||||
|
||||
GUIFormSpecMenu *menu =
|
||||
new GUIFormSpecMenu(guienv, guiroot, -1,
|
||||
&g_menumgr,
|
||||
&client, gamedef);
|
||||
menu->setFormSpec(meta->getString("formspec"),
|
||||
inventoryloc);
|
||||
menu->setFormSource(new NodeMetadataFormSource(
|
||||
&client.getEnv().getClientMap(), nodepos));
|
||||
menu->setTextDest(new TextDestNodeMetadata(nodepos, &client));
|
||||
menu->drop();
|
||||
}
|
||||
// Otherwise report right click to server
|
||||
else
|
||||
{
|
||||
// Report to server
|
||||
client.interact(3, pointed);
|
||||
camera.setDigging(1); // right click animation
|
||||
|
||||
// If the wielded item has node placement prediction,
|
||||
// make that happen
|
||||
const ItemDefinition &def =
|
||||
playeritem.getDefinition(itemdef);
|
||||
if(def.node_placement_prediction != "")
|
||||
do{ // breakable
|
||||
verbosestream<<"Node placement prediction for "
|
||||
<<playeritem.name<<" is "
|
||||
<<def.node_placement_prediction<<std::endl;
|
||||
v3s16 p = neighbourpos;
|
||||
// Place inside node itself if buildable_to
|
||||
try{
|
||||
MapNode n_under = map.getNode(nodepos);
|
||||
if(nodedef->get(n_under).buildable_to)
|
||||
p = nodepos;
|
||||
}catch(InvalidPositionException &e){}
|
||||
// Find id of predicted node
|
||||
content_t id;
|
||||
bool found =
|
||||
nodedef->getId(def.node_placement_prediction, id);
|
||||
if(!found){
|
||||
errorstream<<"Node placement prediction failed for "
|
||||
<<playeritem.name<<" (places "
|
||||
<<def.node_placement_prediction
|
||||
<<") - Name not known"<<std::endl;
|
||||
break;
|
||||
}
|
||||
MapNode n(id);
|
||||
try{
|
||||
// This triggers the required mesh update too
|
||||
client.addNode(p, n);
|
||||
}catch(InvalidPositionException &e){
|
||||
errorstream<<"Node placement prediction failed for "
|
||||
<<playeritem.name<<" (places "
|
||||
<<def.node_placement_prediction
|
||||
<<") - Position not loaded"<<std::endl;
|
||||
}
|
||||
}while(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2596,11 +2570,12 @@ void the_game(
|
||||
char temptext[300];
|
||||
snprintf(temptext, 300,
|
||||
"(% .1f, % .1f, % .1f)"
|
||||
" (yaw = %.1f)",
|
||||
" (yaw = %.1f) (seed = %lli)",
|
||||
player_position.X/BS,
|
||||
player_position.Y/BS,
|
||||
player_position.Z/BS,
|
||||
wrapDegrees_0_360(camera_yaw));
|
||||
wrapDegrees_0_360(camera_yaw),
|
||||
client.getMapSeed());
|
||||
|
||||
guitext2->setText(narrow_to_wide(temptext).c_str());
|
||||
guitext2->setVisible(true);
|
||||
@@ -2764,9 +2739,10 @@ void the_game(
|
||||
|
||||
if(show_hud)
|
||||
{
|
||||
for(core::list<aabb3f>::Iterator i=hilightboxes.begin();
|
||||
i != hilightboxes.end(); i++)
|
||||
{
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = hilightboxes.begin();
|
||||
i != hilightboxes.end(); i++)
|
||||
{
|
||||
/*infostream<<"hilightbox min="
|
||||
<<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
|
||||
<<" max="
|
||||
|
||||