diff --git a/.gitignore b/.gitignore
index ce00d585e..f0c372ab7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,4 +19,4 @@ cmake_install.cmake
src/jthread/libjthread.a
debug.txt
bin/debug.txt
-
+minetestmapper/map.png
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6403a9dd9..aae390f38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,11 +5,11 @@ if(${CMAKE_VERSION} STREQUAL "2.8.2")
endif(${CMAKE_VERSION} STREQUAL "2.8.2")
# This can be read from ${PROJECT_NAME} after project() is called
-project(minetest)
+project(minetest-delta)
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)
-set(VERSION_PATCH 20110704_0)
+set(VERSION_PATCH 20110720_0)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
# Configuration options
@@ -48,18 +48,18 @@ if(WIN32)
set(EXAMPLE_CONF_DIR ".")
elseif(APPLE)
# random placeholders
- set(DATADIR "share/minetest")
+ set(DATADIR "share/${PROJECT_NAME}")
set(BINDIR "bin")
- set(DOCDIR "share/doc/minetest")
+ set(DOCDIR "share/doc/${PROJECT_NAME}")
set(EXAMPLE_CONF_DIR ".")
elseif(UNIX) # Linux, BSD etc
- set(DATADIR "share/minetest")
+ set(DATADIR "share/${PROJECT_NAME}")
set(BINDIR "bin")
- set(DOCDIR "share/doc/minetest")
- set(EXAMPLE_CONF_DIR "share/doc/minetest")
+ set(DOCDIR "share/doc/${PROJECT_NAME}")
+ set(EXAMPLE_CONF_DIR "share/doc/${PROJECT_NAME}")
endif()
-install(FILES "README.txt" DESTINATION "${DOCDIR}")
+install(FILES "doc/README.txt" DESTINATION "${DOCDIR}")
install(FILES "minetest.conf.example" DESTINATION "${DOCDIR}")
#
@@ -103,8 +103,8 @@ elseif(APPLE)
set(CPACK_BUNDLE_NAME ${PROJECT_NAME})
set(CPACK_BUNDLE_ICON "")
set(CPACK_BUNDLE_PLIST "")
- set(CPACK_BUNDLE_STARTUP_COMMAND "Contents/MacOS/minetest")
- set(CPACK_GENERATOR Bundle)
+ set(CPACK_BUNDLE_STARTUP_COMMAND "Contents/MacOS/${PROJECT_NAME}")
+ set(CPACK_GENERATOR "Bundle")
else()
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-linux")
set(CPACK_GENERATOR TGZ)
diff --git a/README b/README
new file mode 100644
index 000000000..82fcdd331
--- /dev/null
+++ b/README
@@ -0,0 +1,41 @@
+Minetest Δ (“Minetest Delta”) is a fork of Minetest-c55 , incorporating experimental features that are not (yet) included in Minetest-c55.
+
+New features:
+* Submenu for key assignment
+* configurable far mesh tree display (boolean)
+* configurable far mesh rendering distance
+* volumetric clouds (using fake shading)
+* translation support (including questionable translation into german)
+* build system uses local jthread & sqlite libraries if available
+
+New bricks:
+* Sandstone (crafted from 4 sand, yields sand)
+* Cactus (plant that grows on sand)
+* Clay (found in sand at sea level, yields 4 lumps of clay)
+* Brick (made from 4 clay bricks, yields 4 clay bricks)
+* Papyrus (plant that grows in shallow water)
+* Book shelf (made from 6 wood and 3 books, sandwhiched)
+* Rail (made from 6 iron ingots and 3 sticks, vertically sandwhiched)
+
+New materials:
+* Lump of clay
+* Clay brick (made from lumps of clay in the furnace)
+* Paper (made from 3 papyrus horizontally)
+* Book (made from 3 paper vertically)
+
+Alternate graphics:
+* Player
+* Omsk birds (instead of Oerkki ghosts)
+* Rat
+* Glass
+* Heart
+
+Building on GNU/Linux or OS X:
+ cmake . -DRUN_IN_PLACE=1
+ make -j2
+
+The “upstream” branch contains vanilla minetest-c55, created using:
+ hg-fast-export -r ~/share/src/games/minetest -o upstream
+ git push origin upstream/master:upstream -f
+
+All new/replaced graphics done by erlehmann are dual-licensed under GPL (version 2 or, at your option, any later version) and CC-BY-SA (version 3.0 or, at your option, any later version).
diff --git a/README.txt b/README.txt
index 41048992e..662f2770b 100644
--- a/README.txt
+++ b/README.txt
@@ -90,6 +90,8 @@ Compiling on Windows:
http://www.winimage.com/zLibDll/index.html
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
http://www.winimage.com/zLibDll/index.html
+ * gettext bibrary and tools:
+ http://gnuwin32.sourceforge.net/downlinks/gettext.php
* And, of course, Minetest-c55:
http://celeron.55.lt/~celeron55/minetest/download
- Steps:
@@ -117,6 +119,10 @@ Compiling on Windows:
+ lib
+ include
...
+ + gettext
+ +bin
+ +include
+ +lib
+ minetest
+ src
+ doc
@@ -145,6 +151,10 @@ Compiling on Windows:
ZLIB_DLL DIR/zlib125dll/dll32/zlibwapi.dll
ZLIB_INCLUDE_DIR DIR/zlib-1.2.5
ZLIB_LIBRARIES DIR/zlib125dll/dll32/zlibwapi.lib
+ GETTEXT_BIN_DIR DIR/gettext/bin
+ GETTEXT_INCLUDE_DIR DIR/gettext/include
+ GETTEXT_LIBRARIES DIR/gettext/lib/intl.lib
+ GETTEXT_MSGFMT DIR/gettext/bin/msgfmt
-----------------
- Hit "Configure"
- Hit "Generate"
diff --git a/cmake/Modules/FindGettextLib.cmake b/cmake/Modules/FindGettextLib.cmake
new file mode 100644
index 000000000..b99fd33b8
--- /dev/null
+++ b/cmake/Modules/FindGettextLib.cmake
@@ -0,0 +1,80 @@
+# Package finder for gettext libs and include files
+
+SET(CUSTOM_GETTEXT_PATH "${PROJECT_SOURCE_DIR}/../../gettext"
+ CACHE FILEPATH "path to custom gettext")
+
+# by default
+SET(GETTEXT_FOUND FALSE)
+
+FIND_PATH(GETTEXT_INCLUDE_DIR
+ NAMES libintl.h
+ PATHS "${CUSTOM_GETTEXT_PATH}/include"
+ DOC "gettext include directory")
+
+FIND_PROGRAM(GETTEXT_MSGFMT
+ NAMES msgfmt
+ PATHS "${CUSTOM_GETTEXT_PATH}/bin"
+ DOC "path to msgfmt")
+
+FIND_PROGRAM(GETTEXT_MSGMERGE
+ NAMES msgmerge
+ PATHS "${CUSTOM_GETTEXT_PATH}/bin"
+ DOC "path to msgmerge")
+
+FIND_PROGRAM(GETTEXT_MSGEN
+ NAMES msgen
+ PATHS "${CUSTOM_GETTEXT_PATH}/bin"
+ DOC "path to msgen")
+
+FIND_PROGRAM(GETTEXT_EXTRACT
+ NAMES xgettext
+ PATHS "${CUSTOM_GETTEXT_PATH}/bin"
+ DOC "path to xgettext")
+
+# modern Linux, as well as Mac, seem to not need require special linking
+# they do not because gettext is part of glibc
+# TODO check the requirements on other BSDs and older Linux
+IF (WIN32)
+ IF(MSVC)
+ SET(GETTEXT_LIB_NAMES
+ libintl.lib intl.lib libintl3.lib intl3.lib)
+ ELSE()
+ SET(GETTEXT_LIB_NAMES
+ libintl.dll.a intl.dll.a libintl3.dll.a intl3.dll.a)
+ ENDIF()
+ FIND_LIBRARY(GETTEXT_LIBRARY
+ NAMES ${GETTEXT_LIB_NAMES}
+ PATHS "${CUSTOM_GETTEXT_PATH}/lib"
+ DOC "gettext *intl*.lib")
+ FIND_FILE(GETTEXT_DLL
+ NAMES libintl.dll intl.dll libintl3.dll intl3.dll
+ PATHS "${CUSTOM_GETTEXT_PATH}/bin" "${CUSTOM_GETTEXT_PATH}/lib"
+ DOC "gettext *intl*.dll")
+ FIND_FILE(GETTEXT_ICONV_DLL
+ NAMES libiconv2.dll
+ PATHS "${CUSTOM_GETTEXT_PATH}/bin" "${CUSTOM_GETTEXT_PATH}/lib"
+ DOC "gettext *iconv*.lib")
+ENDIF(WIN32)
+
+
+IF(GETTEXT_INCLUDE_DIR AND GETTEXT_MSGFMT)
+ IF (WIN32)
+ # in the Win32 case check also for the extra linking requirements
+ IF(GETTEXT_LIBRARY AND GETTEXT_DLL AND GETTEXT_ICONV_DLL)
+ SET(GETTEXT_FOUND TRUE)
+ ENDIF()
+ ELSE(WIN32)
+ SET(GETTEXT_FOUND TRUE)
+ ENDIF(WIN32)
+ENDIF()
+
+IF(GETTEXT_FOUND)
+ SET(GETTEXT_PO_PATH ${CMAKE_SOURCE_DIR}/po)
+ SET(GETTEXT_MO_BUILD_PATH ${CMAKE_BINARY_DIR}/locale//LC_MESSAGES)
+ SET(GETTEXT_MO_DEST_PATH locale//LC_MESSAGES)
+ FILE(GLOB GETTEXT_AVAILABLE_LOCALES RELATIVE ${GETTEXT_PO_PATH} "${GETTEXT_PO_PATH}/*")
+ MACRO(SET_MO_PATHS _buildvar _destvar _locale)
+ STRING(REPLACE "" ${_locale} ${_buildvar} ${GETTEXT_MO_BUILD_PATH})
+ STRING(REPLACE "" ${_locale} ${_destvar} ${GETTEXT_MO_DEST_PATH})
+ ENDMACRO(SET_MO_PATHS)
+ENDIF()
diff --git a/cmake/Modules/FindJthread.cmake b/cmake/Modules/FindJthread.cmake
new file mode 100644
index 000000000..302a3c22f
--- /dev/null
+++ b/cmake/Modules/FindJthread.cmake
@@ -0,0 +1,18 @@
+# Look for jthread, use our own if not found
+
+FIND_PATH(JTHREAD_INCLUDE_DIR jthread.h)
+
+FIND_LIBRARY(JTHREAD_LIBRARY NAMES jthread)
+
+IF(JTHREAD_LIBRARY AND JTHREAD_INCLUDE_DIR)
+ SET( JTHREAD_FOUND TRUE )
+ENDIF(JTHREAD_LIBRARY AND JTHREAD_INCLUDE_DIR)
+
+IF(JTHREAD_FOUND)
+ MESSAGE(STATUS "Found system jthread header file in ${JTHREAD_INCLUDE_DIR}")
+ MESSAGE(STATUS "Found system jthread library ${JTHREAD_LIBRARY}")
+ELSE(JTHREAD_FOUND)
+ SET(JTHREAD_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/jthread)
+ SET(JTHREAD_LIBRARY jthread)
+ MESSAGE(STATUS "Using project jthread library")
+ENDIF(JTHREAD_FOUND)
diff --git a/cmake/Modules/FindSqlite3.cmake b/cmake/Modules/FindSqlite3.cmake
new file mode 100644
index 000000000..ecce6e38e
--- /dev/null
+++ b/cmake/Modules/FindSqlite3.cmake
@@ -0,0 +1,18 @@
+# Look for sqlite3, use our own if not found
+
+FIND_PATH(SQLITE3_INCLUDE_DIR sqlite3.h)
+
+FIND_LIBRARY(SQLITE3_LIBRARY NAMES sqlite3)
+
+IF(SQLITE3_LIBRARY AND SQLITE3_INCLUDE_DIR)
+ SET( SQLITE3_FOUND TRUE )
+ENDIF(SQLITE3_LIBRARY AND SQLITE3_INCLUDE_DIR)
+
+IF(SQLITE3_FOUND)
+ MESSAGE(STATUS "Found system sqlite3 header file in ${SQLITE3_INCLUDE_DIR}")
+ MESSAGE(STATUS "Found system sqlite3 library ${SQLITE3_LIBRARY}")
+ELSE(SQLITE3_FOUND)
+ SET(SQLITE3_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/sqlite)
+ SET(SQLITE3_LIBRARY sqlite3)
+ MESSAGE(STATUS "Using project sqlite3 library")
+ENDIF(SQLITE3_FOUND)
diff --git a/data/book.png b/data/book.png
new file mode 100644
index 000000000..176fb6aa9
Binary files /dev/null and b/data/book.png differ
diff --git a/data/bookshelf.png b/data/bookshelf.png
new file mode 100644
index 000000000..5ecc50ff3
Binary files /dev/null and b/data/bookshelf.png differ
diff --git a/data/brick.png b/data/brick.png
new file mode 100644
index 000000000..32d77f347
Binary files /dev/null and b/data/brick.png differ
diff --git a/data/cactus_side.png b/data/cactus_side.png
new file mode 100644
index 000000000..fc479fde6
Binary files /dev/null and b/data/cactus_side.png differ
diff --git a/data/cactus_top.png b/data/cactus_top.png
new file mode 100644
index 000000000..f9e68df51
Binary files /dev/null and b/data/cactus_top.png differ
diff --git a/data/clay.png b/data/clay.png
new file mode 100644
index 000000000..3557429d8
Binary files /dev/null and b/data/clay.png differ
diff --git a/data/clay_brick.png b/data/clay_brick.png
new file mode 100644
index 000000000..e36648e48
Binary files /dev/null and b/data/clay_brick.png differ
diff --git a/data/fence.png b/data/fence.png
new file mode 100644
index 000000000..0b99f0eb5
Binary files /dev/null and b/data/fence.png differ
diff --git a/data/firefly.png b/data/firefly.png
new file mode 100644
index 000000000..40df7fa1c
Binary files /dev/null and b/data/firefly.png differ
diff --git a/data/lump_of_clay.png b/data/lump_of_clay.png
new file mode 100644
index 000000000..be0bab9d7
Binary files /dev/null and b/data/lump_of_clay.png differ
diff --git a/data/paper.png b/data/paper.png
new file mode 100644
index 000000000..ae5c06bc6
Binary files /dev/null and b/data/paper.png differ
diff --git a/data/papyrus.png b/data/papyrus.png
new file mode 100644
index 000000000..bf0dec7fe
Binary files /dev/null and b/data/papyrus.png differ
diff --git a/data/rail.png b/data/rail.png
new file mode 100644
index 000000000..18176d9f3
Binary files /dev/null and b/data/rail.png differ
diff --git a/data/rail_crossing.png b/data/rail_crossing.png
new file mode 100644
index 000000000..984640577
Binary files /dev/null and b/data/rail_crossing.png differ
diff --git a/data/rail_curved.png b/data/rail_curved.png
new file mode 100644
index 000000000..62afa3d2b
Binary files /dev/null and b/data/rail_curved.png differ
diff --git a/data/rail_t_junction.png b/data/rail_t_junction.png
new file mode 100644
index 000000000..9985f63cd
Binary files /dev/null and b/data/rail_t_junction.png differ
diff --git a/data/rat.png b/data/rat.png
index d1a0e2ae2..96d44c3fa 100644
Binary files a/data/rat.png and b/data/rat.png differ
diff --git a/data/sandstone.png b/data/sandstone.png
new file mode 100644
index 000000000..c4759b4d0
Binary files /dev/null and b/data/sandstone.png differ
diff --git a/doc/README.txt b/doc/README.txt
new file mode 100644
index 000000000..645e2a560
--- /dev/null
+++ b/doc/README.txt
@@ -0,0 +1,238 @@
+Minetest-c55
+---------------
+An InfiniMiner/Minecraft inspired game.
+Copyright (c) 2010-2011 Perttu Ahola
+
+Further documentation:
+----------------------
+- Website: http://celeron.55.lt/~celeron55/minetest/
+- Wiki: http://celeron.55.lt/~celeron55/minetest/wiki/
+- Forum: http://celeron.55.lt/~celeron55/minetest/forum/
+
+This is a development version:
+------------------------------
+- Don't expect it to work as well as a finished game will.
+- Please report any bugs to me. That way I can fix them to the next release.
+ - debug.txt is useful when the game crashes.
+
+Controls:
+---------
+- See the in-game pause menu
+- Settable in the configuration file, see the section below.
+
+Map directory:
+--------------
+- Map is stored in a directory, which can be removed to generate a new map.
+- There is a command-line option for it: --map-dir
+- For a RUN_IN_PLACE build, it is located in:
+ ../map
+- Otherwise something like this:
+ Windows: C:\Documents and Settings\user\Application Data\minetest\map
+ Linux: ~/.minetest/map
+ OS X: ~/Library/Application Support/minetest/map
+
+Configuration file:
+-------------------
+- An optional configuration file can be used. See minetest.conf.example.
+- Path to file can be passed as a parameter to the executable:
+ --config
+- Defaults:
+ - If built with -DRUN_IN_PLACE=1:
+ ../minetest.conf
+ ../../minetest.conf
+ - Otherwise something like this:
+ Windows: C:\Documents and Settings\user\Application Data\minetest\minetest.conf
+ Linux: ~/.minetest/minetest.conf
+ OS X: ~/Library/Application Support/minetest.conf
+
+Command-line options:
+---------------------
+- Use --help
+
+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
+
+Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
+$ wget https://bitbucket.org/celeron55/minetest/get/tip.tar.gz
+$ tar xf tip.tar.gz
+$ cd minetest
+
+Build a version that runs directly from the source directory:
+$ cmake . -DRUN_IN_PLACE=1
+$ make -j2
+
+Run it:
+$ cd bin
+$ ./minetest
+
+- Use cmake . -LH to see all CMake options and their current state
+- If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0
+- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
+- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=
+ - Note that the Debug build is considerably slower
+
+Compiling on Windows:
+---------------------
+
+- You need:
+ * CMake:
+ http://www.cmake.org/cmake/resources/software.html
+ * MinGW or Visual Studio
+ http://www.mingw.org/
+ http://msdn.microsoft.com/en-us/vstudio/default
+ * Irrlicht SDK 1.7:
+ http://irrlicht.sourceforge.net/downloads.html
+ * Zlib headers (zlib125.zip)
+ http://www.winimage.com/zLibDll/index.html
+ * Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
+ http://www.winimage.com/zLibDll/index.html
+ * And, of course, Minetest-c55:
+ http://celeron.55.lt/~celeron55/minetest/download
+- Steps:
+ - Select a directory called DIR hereafter in which you will operate.
+ - Make sure you have CMake and a compiler installed.
+ - Download all the other stuff to DIR and extract them into there. All those
+ packages contain a nice base directory in them, which should end up being
+ the direct subdirectories of DIR.
+ - You will end up with a directory structure like this (+=dir, -=file):
+ -----------------
+ + DIR
+ - zlib-1.2.5.tar.gz
+ - zlib125dll.zip
+ - irrlicht-1.7.1.zip
+ - 110214175330.zip (or whatever, this is the minetest source)
+ + zlib-1.2.5
+ - zlib.h
+ + win32
+ ...
+ + zlib125dll
+ - readme.txt
+ + dll32
+ ...
+ + irrlicht-1.7.1
+ + lib
+ + include
+ ...
+ + minetest
+ + src
+ + doc
+ - CMakeLists.txt
+ ...
+ -----------------
+ - Start up the CMake GUI
+ - Select "Browse Source..." and select DIR/minetest
+ - Now, if using MSVC:
+ - Select "Browse Build..." and select DIR/minetest-build
+ - Else if using MinGW:
+ - Select "Browse Build..." and select DIR/minetest
+ - Select "Configure"
+ - Select your compiler
+ - It will warn about missing stuff, ignore that at this point. (later don't)
+ - Make sure the configuration is as follows
+ (note that the versions may differ for you):
+ -----------------
+ BUILD_CLIENT [X]
+ BUILD_SERVER [ ]
+ CMAKE_BUILD_TYPE Release
+ CMAKE_INSTALL_PREFIX DIR/minetest-install
+ IRRLICHT_SOURCE_DIR DIR/irrlicht-1.7.1
+ RUN_IN_PLACE [X]
+ WARN_ALL [ ]
+ ZLIB_DLL DIR/zlib125dll/dll32/zlibwapi.dll
+ ZLIB_INCLUDE_DIR DIR/zlib-1.2.5
+ ZLIB_LIBRARIES DIR/zlib125dll/dll32/zlibwapi.lib
+ -----------------
+ - Hit "Configure"
+ - Hit "Generate"
+ If using MSVC:
+ - Open the generated minetest.sln
+ - The project defaults to the "Debug" configuration. Make very sure to
+ select "Release", unless you want to debug some stuff (it's slower)
+ - Build the ALL_BUILD project
+ - Build the INSTALL project
+ - You should now have a working game with the executable in
+ DIR/minetest-install/bin/minetest.exe
+ - Additionally you may create a zip package by building the PACKAGE
+ project.
+ If using MinGW:
+ - Using the command line, browse to the build directory and run 'make'
+ (or mingw32-make or whatever it happens to be)
+ - You should now have a working game with the executable in
+ DIR/minetest/bin/minetest.exe
+
+License of Minetest-c55
+-----------------------
+
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola
+
+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.
+
+Irrlicht
+---------------
+
+This program uses the Irrlicht Engine. http://irrlicht.sourceforge.net/
+
+ The Irrlicht Engine License
+
+Copyright © 2002-2005 Nikolaus Gebhardt
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute
+it freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you use
+ this software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
+
+JThread
+---------------
+
+This program uses the JThread library. License for JThread follows:
+
+Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+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.
+
+
diff --git a/genmap.py b/genmap.py
new file mode 100755
index 000000000..a60509403
--- /dev/null
+++ b/genmap.py
@@ -0,0 +1,271 @@
+#!/usr/bin/python2
+
+# This is an example script that generates some valid map data.
+
+import struct
+import random
+import os
+import sys
+import zlib
+import array
+from pnoise import pnoise
+
+# Old directory format:
+# world/sectors/XXXXZZZZ/YYYY
+# XXXX,YYYY,ZZZZ = coordinates in hexadecimal
+# fffe = -2
+# ffff = -1
+# 0000 = 0
+# 0001 = 1
+#
+# New directory format:
+# world/sectors2/XXX/ZZZ/YYYY
+# XXX,YYYY,ZZZ = coordinates in hexadecimal
+# fffe = -2
+# ffff = -1
+# 0000 = 0
+# 0001 = 1
+# ffe = -2
+# fff = -1
+# 000 = 0
+# 001 = 1
+#
+# For more proper file format documentation, refer to mapformat.txt
+# For node type documentation, refer to mapnode.h
+# NodeMetadata documentation is not complete, refer to nodemeta.cpp
+#
+
+# Seed for generating terrain
+SEED = 0
+
+# 0=old, 1=new
+SECTOR_DIR_FORMAT = 1
+
+mapdir = "world"
+
+def to4h(i):
+ s = "";
+ s += '{0:1x}'.format((i>>12) & 0x000f)
+ s += '{0:1x}'.format((i>>8) & 0x000f)
+ s += '{0:1x}'.format((i>>4) & 0x000f)
+ s += '{0:1x}'.format((i>>0) & 0x000f)
+ return s
+
+def to3h(i):
+ s = "";
+ s += '{0:1x}'.format((i>>8) & 0x000f)
+ s += '{0:1x}'.format((i>>4) & 0x000f)
+ s += '{0:1x}'.format((i>>0) & 0x000f)
+ return s
+
+def get_sector_dir(px, pz):
+ global SECTOR_DIR_FORMAT
+ if SECTOR_DIR_FORMAT == 0:
+ return "/sectors/"+to4h(px)+to4h(pz)
+ elif SECTOR_DIR_FORMAT == 1:
+ return "/sectors2/"+to3h(px)+"/"+to3h(pz)
+ else:
+ assert(0)
+
+def getrand_air_stone():
+ i = random.randrange(0,2)
+ if i==0:
+ return 0
+ return 254
+
+# 3-dimensional vector (position)
+class v3:
+ def __init__(self, x=0, y=0, z=0):
+ self.X = x
+ self.Y = y
+ self.Z = z
+
+class NodeMeta:
+ def __init__(self, type_id, data):
+ self.type_id = type_id
+ self.data = data
+
+class StaticObject:
+ def __init__(self):
+ self.type_id = 0
+ self.data = ""
+
+def ser_u16(i):
+ return chr((i>>8)&0xff) + chr((i>>0)&0xff)
+def ser_u32(i):
+ return (chr((i>>24)&0xff) + chr((i>>16)&0xff)
+ + chr((i>>8)&0xff) + chr((i>>0)&0xff))
+
+# A 16x16x16 chunk of map
+class MapBlock:
+ def __init__(self):
+ self.content = array.array('B')
+ self.param1 = array.array('B')
+ self.param2 = array.array('B')
+ for i in range(16*16*16):
+ # Initialize to air
+ self.content.append(254)
+ # Full light on sunlight, none when no sunlight
+ self.param1.append(15)
+ # No additional parameters
+ self.param2.append(0)
+
+ # key = v3 pos
+ # value = NodeMeta
+ self.nodemeta = {}
+
+ # key = v3 pos
+ # value = StaticObject
+ self.static_objects = {}
+
+ def set_content(self, v3, b):
+ self.content[v3.Z*16*16+v3.Y*16+v3.X] = b
+ def set_param1(self, v3, b):
+ self.param1[v3.Z*16*16+v3.Y*16+v3.X] = b
+ def set_param2(self, v3, b):
+ self.param2[v3.Z*16*16+v3.Y*16+v3.X] = b
+
+ # Get data for serialization. Returns a string.
+ def serialize_data(self):
+ s = ""
+ for i in range(16*16*16):
+ s += chr(self.content[i])
+ for i in range(16*16*16):
+ s += chr(self.param1[i])
+ for i in range(16*16*16):
+ s += chr(self.param2[i])
+ return s
+
+ def serialize_nodemeta(self):
+ s = ""
+ s += ser_u16(1)
+ s += ser_u16(len(self.nodemeta))
+ for pos, meta in self.nodemeta.items():
+ pos_i = pos.Z*16*16 + pos.Y*16 + pos.X
+ s += ser_u16(pos_i)
+ s += ser_u16(meta.type_id)
+ s += ser_u16(len(meta.data))
+ s += meta.data
+ return s
+
+ def serialize_staticobj(self):
+ s = ""
+ s += chr(0)
+ s += ser_u16(len(self.static_objects))
+ for pos, obj in self.static_objects.items():
+ pos_i = pos.Z*16*16 + pos.Y*16 + pos.X
+ s += ser_s32(pos.X*1000)
+ s += ser_s32(pos.Y*1000)
+ s += ser_s32(pos.Z*1000)
+ s += ser_u16(obj.type_id)
+ s += ser_u16(len(obj.data))
+ s += obj.data
+ return s
+
+def writeblock(mapdir, px,py,pz, block):
+
+ sectordir = mapdir + get_sector_dir(px, pz);
+
+ try:
+ os.makedirs(sectordir)
+ except OSError:
+ pass
+
+ path = sectordir+"/"+to4h(py)
+
+ print("writing block file "+path)
+
+ f = open(sectordir+"/"+to4h(py), "wb")
+
+ if f == None:
+ return
+
+ # version
+ version = 17
+ f.write(struct.pack('B', version))
+
+ # flags
+ # 0x01=is_undg, 0x02=dn_diff, 0x04=lighting_expired
+ flags = 0 + 0x02 + 0x04
+ f.write(struct.pack('B', flags))
+
+ # data
+ c_obj = zlib.compressobj()
+ c_obj.compress(block.serialize_data())
+ f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number
+ f.write(c_obj.flush())
+
+ # node metadata
+ c_obj = zlib.compressobj()
+ c_obj.compress(block.serialize_nodemeta())
+ f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number
+ f.write(c_obj.flush())
+
+ # mapblockobject count
+ f.write(ser_u16(0))
+
+ # static objects
+ f.write(block.serialize_staticobj())
+
+ # timestamp
+ f.write(ser_u32(0xffffffff))
+
+ f.close()
+
+for z0 in range(-1,3):
+ for x0 in range(-1,3):
+ for y0 in range(-1,3):
+ print("generating block "+str(x0)+","+str(y0)+","+str(z0))
+ #v3 blockp = v3(x0,y0,z0)
+
+ # Create a MapBlock
+ block = MapBlock()
+
+ # Generate stuff in it
+ for z in range(0,16):
+ for x in range(0,16):
+ h = 20.0*pnoise((x0*16+x)/100.,(z0*16+z)/100.,SEED+0)
+ h += 5.0*pnoise((x0*16+x)/25.,(z0*16+z)/25.,SEED+0)
+ if pnoise((x0*16+x)/25.,(z0*16+z)/25.,SEED+92412) > 0.05:
+ h += 10
+ #print("r="+str(r))
+ # This enables comparison by ==
+ h = int(h)
+ for y in range(0,16):
+ p = v3(x,y,z)
+ b = 254
+ y1 = y0*16+y
+ if y1 <= h-3:
+ b = 0 #stone
+ elif y1 <= h and y1 <= 0:
+ b = 8 #mud
+ elif y1 == h:
+ b = 1 #grass
+ elif y1 < h:
+ b = 8 #mud
+ elif y1 <= 1:
+ b = 9 #water
+
+ # Material content
+ block.set_content(p, b)
+
+ # Place a sign at the center at surface level.
+ # Placing a sign means placing the sign node and
+ # adding node metadata to the mapblock.
+ if x == 8 and z == 8 and y0*16 <= h-1 and (y0+1)*16-1 > h:
+ p = v3(8,h+1-y0*16,8)
+ # 14 = Sign
+ content_type = 14
+ block.set_content(p, content_type)
+ # This places the sign to the bottom of the cube.
+ # Working values: 0x01, 0x02, 0x04, 0x08, 0x10, 0x20
+ block.set_param2(p, 0x08)
+ # Then add metadata to hold the text of the sign
+ s = "Hello at sector ("+str(x0)+","+str(z0)+")"
+ meta = NodeMeta(content_type, ser_u16(len(s))+s)
+ block.nodemeta[p] = meta
+
+ # Write it on disk
+ writeblock(mapdir, x0,y0,z0, block)
+
+#END
diff --git a/makepackage_binary.sh b/makepackage_binary.sh
new file mode 100755
index 000000000..32d19865a
--- /dev/null
+++ b/makepackage_binary.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+PROJECT_NAME=minetest-delta
+PACKAGEDIR=../$PROJECT_NAME-packages
+PACKAGENAME=$PROJECT_NAME-binary-`date +%y%m%d%H%M%S`
+PACKAGEPATH=$PACKAGEDIR/$PACKAGENAME
+
+mkdir -p $PACKAGEPATH
+mkdir -p $PACKAGEPATH/bin
+mkdir -p $PACKAGEPATH/data
+mkdir -p $PACKAGEPATH/doc
+mkdir -p $PACKAGEPATH/locale/de/LC_MESSAGES/
+
+cp minetest.conf.example $PACKAGEPATH/
+
+cp bin/$PROJECT_NAME.exe $PACKAGEPATH/bin/
+cp bin/Irrlicht.dll $PACKAGEPATH/bin/
+cp bin/zlibwapi.dll $PACKAGEPATH/bin/
+#cp bin/test $PACKAGEPATH/bin/
+#cp bin/fasttest $PACKAGEPATH/bin/
+#cp bin/server $PACKAGEPATH/bin/
+#cp ../irrlicht/irrlicht-1.7.1/lib/Linux/libIrrlicht.a $PACKAGEPATH/bin/
+#cp ../jthread/jthread-1.2.1/src/.libs/libjthread-1.2.1.so $PACKAGEPATH/bin/
+
+cp -r data/fontlucida.png $PACKAGEPATH/data/
+cp -r data/player.png $PACKAGEPATH/data/
+cp -r data/player_back.png $PACKAGEPATH/data/
+cp -r data/stone.png $PACKAGEPATH/data/
+cp -r data/grass.png $PACKAGEPATH/data/
+cp -r data/grass_footsteps.png $PACKAGEPATH/data/
+cp -r data/water.png $PACKAGEPATH/data/
+cp -r data/tree.png $PACKAGEPATH/data/
+cp -r data/leaves.png $PACKAGEPATH/data/
+cp -r data/mese.png $PACKAGEPATH/data/
+cp -r data/cloud.png $PACKAGEPATH/data/
+cp -r data/sign.png $PACKAGEPATH/data/
+cp -r data/sign_back.png $PACKAGEPATH/data/
+cp -r data/rat.png $PACKAGEPATH/data/
+cp -r data/mud.png $PACKAGEPATH/data/
+cp -r data/torch.png $PACKAGEPATH/data/
+cp -r data/torch_on_floor.png $PACKAGEPATH/data/
+cp -r data/torch_on_ceiling.png $PACKAGEPATH/data/
+cp -r data/tree_top.png $PACKAGEPATH/data/
+cp -r data/coalstone.png $PACKAGEPATH/data/
+cp -r data/crack.png $PACKAGEPATH/data/
+cp -r data/wood.png $PACKAGEPATH/data/
+cp -r data/stick.png $PACKAGEPATH/data/
+cp -r data/tool_wpick.png $PACKAGEPATH/data/
+cp -r data/tool_stpick.png $PACKAGEPATH/data/
+cp -r data/tool_mesepick.png $PACKAGEPATH/data/
+cp -r data/grass_side.png $PACKAGEPATH/data/
+cp -r data/lump_of_coal.png $PACKAGEPATH/data/
+cp -r data/lump_of_iron.png $PACKAGEPATH/data/
+cp -r data/mineral_coal.png $PACKAGEPATH/data/
+cp -r data/mineral_iron.png $PACKAGEPATH/data/
+cp -r data/sand.png $PACKAGEPATH/data/
+
+#cp -r data/pauseMenu.gui $PACKAGEPATH/data/
+
+cp -r doc/README.txt $PACKAGEPATH/doc/README.txt
+
+cp -r locale/de/LC_MESSAGES/$PROJECT_NAME.mo $PACKAGEPATH/locale/de/LC_MESSAGES/
+
+cd $PACKAGEDIR
+rm $PACKAGENAME.zip
+zip -r $PACKAGENAME.zip $PACKAGENAME
+
diff --git a/minetest-icon.svg b/minetest-icon.svg
new file mode 100644
index 000000000..46c9ac702
--- /dev/null
+++ b/minetest-icon.svg
@@ -0,0 +1,183 @@
+
+
+
+
diff --git a/minetestmapper/colors.txt b/minetestmapper/colors.txt
new file mode 100644
index 000000000..e70f56e1e
--- /dev/null
+++ b/minetestmapper/colors.txt
@@ -0,0 +1,25 @@
+0 128 128 128
+1 107 134 51
+2 39 66 106
+3 255 255 0
+4 86 58 31
+5 48 95 8
+6 102 129 38
+7 178 178 0
+8 101 84 36
+9 39 66 106
+12 104 78 42
+13 210 194 156
+14 117 86 41
+15 128 79 0
+16 118 118 118
+18 123 123 123
+19 199 199 199
+20 183 183 222
+21 103 78 42
+22 219 202 178
+23 78 154 6
+24 204 0 0
+25 211 215 207
+26 138 226 52
+27 104 78 42
diff --git a/minetestmapper/minetestmapper2.py b/minetestmapper/minetestmapper2.py
new file mode 100755
index 000000000..8dc3de2f4
--- /dev/null
+++ b/minetestmapper/minetestmapper2.py
@@ -0,0 +1,275 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Made by j0gge, modified by celeron55
+
+# This program is free software. It comes without any warranty, to
+# the extent permitted by applicable law. You can redistribute it
+# and/or modify it under the terms of the Do What The Fuck You Want
+# To Public License, Version 2, as published by Sam Hocevar. See
+# http://sam.zoy.org/wtfpl/COPYING for more details.
+
+# Requires Python Imaging Library: http://www.pythonware.com/products/pil/
+
+# Some speed-up: ...lol, actually it slows it down.
+#import psyco ; psyco.full()
+#from psyco.classes import *
+
+import zlib
+import Image, ImageDraw
+import os
+import string
+import time
+
+def hex_to_int(h):
+ i = int(h,16)
+ if(i > 2047):
+ i-=4096
+ return i
+
+def hex4_to_int(h):
+ i = int(h,16)
+ if(i > 32767):
+ i-=65536
+ return i
+
+def int_to_hex3(i):
+ if(i < 0):
+ return "%03X" % (i + 4096)
+ else:
+ return "%03X" % i
+
+def int_to_hex4(i):
+ if(i < 0):
+ return "%04X" % (i + 65536)
+ else:
+ return "%04X" % i
+
+def limit(i,l,h):
+ if(i>h):
+ i=h
+ if(i sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+ xlist.append(x)
+ zlist.append(z)
+
+if os.path.exists(path + "sectors"):
+ for filename in os.listdir(path + "sectors"):
+ x = hex4_to_int(filename[:4])
+ z = hex4_to_int(filename[-4:])
+ if x < sector_xmin or x > sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+ xlist.append(x)
+ zlist.append(z)
+
+w = (max(xlist) - min(xlist)) * 16 + 16
+h = (max(zlist) - min(zlist)) * 16 + 16
+
+print "w="+str(w)+" h="+str(h)
+
+im = Image.new("RGB", (w, h), "white")
+impix = im.load()
+
+stuff={}
+
+starttime = time.time()
+
+# Go through all sectors.
+for n in range(len(xlist)):
+ #if n > 500:
+ # break
+ if n % 200 == 0:
+ nowtime = time.time()
+ dtime = nowtime - starttime
+ n_per_second = 1.0 * n / dtime
+ if n_per_second != 0:
+ seconds_per_n = 1.0 / n_per_second
+ time_guess = seconds_per_n * len(xlist)
+ remaining_s = time_guess - dtime
+ remaining_minutes = int(remaining_s / 60)
+ remaining_s -= remaining_minutes * 60;
+ print("Processing sector "+str(n)+" of "+str(len(xlist))
+ +" ("+str(round(100.0*n/len(xlist), 1))+"%)"
+ +" (ETA: "+str(remaining_minutes)+"m "
+ +str(int(remaining_s))+"s)")
+
+ xpos = xlist[n]
+ zpos = zlist[n]
+
+ xhex = int_to_hex3(xpos)
+ zhex = int_to_hex3(zpos)
+ xhex4 = int_to_hex4(xpos)
+ zhex4 = int_to_hex4(zpos)
+
+ sector1 = xhex4.lower() + zhex4.lower()
+ sector2 = xhex.lower() + "/" + zhex.lower()
+
+ ylist=[]
+
+ sectortype = ""
+
+ try:
+ for filename in os.listdir(path + "sectors/" + sector1):
+ if(filename != "meta"):
+ pos = int(filename,16)
+ if(pos > 32767):
+ pos-=65536
+ ylist.append(pos)
+ sectortype = "old"
+ except OSError:
+ pass
+
+ if sectortype != "old":
+ try:
+ for filename in os.listdir(path + "sectors2/" + sector2):
+ if(filename != "meta"):
+ pos = int(filename,16)
+ if(pos > 32767):
+ pos-=65536
+ ylist.append(pos)
+ sectortype = "new"
+ except OSError:
+ pass
+
+ if sectortype == "":
+ continue
+
+ ylist.sort()
+
+ # Make a list of pixels of the sector that are to be looked for.
+ pixellist = []
+ for x in range(16):
+ for y in range(16):
+ pixellist.append((x,y))
+
+ # Go through the Y axis from top to bottom.
+ for ypos in reversed(ylist):
+
+ yhex = int_to_hex4(ypos)
+
+ filename = ""
+ if sectortype == "old":
+ filename = path + "sectors/" + sector1 + "/" + yhex.lower()
+ else:
+ filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
+
+ f = file(filename, "rb")
+
+ # Let's just memorize these even though it's not really necessary.
+ version = f.read(1)
+ flags = f.read(1)
+
+ dec_o = zlib.decompressobj()
+ try:
+ mapdata = dec_o.decompress(f.read())
+ except:
+ mapdata = []
+
+ f.close()
+
+ if(len(mapdata)<4096):
+ print "bad: " + xhex+zhex+"/"+yhex + " " + len(mapdata)
+ else:
+ chunkxpos=xpos*16
+ chunkypos=ypos*16
+ chunkzpos=zpos*16
+ for (x,z) in reversed(pixellist):
+ for y in reversed(range(16)):
+ datapos=x+y*16+z*256
+ if(ord(mapdata[datapos])!=254):
+ try:
+ pixellist.remove((x,z))
+ # Memorize information on the type and height of the block and for drawing the picture.
+ stuff[(chunkxpos+x,chunkzpos+z)]=(chunkypos+y,ord(mapdata[datapos]))
+ break
+ except:
+ print "strange block: " + xhex+zhex+"/"+yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " block: " + str(ord(mapdata[datapos]))
+
+ # After finding all the pixeld in the sector, we can move on to the next sector without having to continue the Y axis.
+ if(len(pixellist)==0):
+ break
+
+print "Drawing image"
+# Drawing the picture
+starttime = time.time()
+n = 0
+minx = min(xlist)
+minz = min(zlist)
+for (x,z) in stuff.iterkeys():
+ if n % 500000 == 0:
+ nowtime = time.time()
+ dtime = nowtime - starttime
+ n_per_second = 1.0 * n / dtime
+ if n_per_second != 0:
+ listlen = len(stuff)
+ seconds_per_n = 1.0 / n_per_second
+ time_guess = seconds_per_n * listlen
+ remaining_s = time_guess - dtime
+ remaining_minutes = int(remaining_s / 60)
+ remaining_s -= remaining_minutes * 60;
+ print("Drawing pixel "+str(n)+" of "+str(listlen)
+ +" ("+str(round(100.0*n/listlen, 1))+"%)"
+ +" (ETA: "+str(remaining_minutes)+"m "
+ +str(int(remaining_s))+"s)")
+ n += 1
+
+ (r,g,b)=colors[stuff[(x,z)][1]]
+
+ # Comparing heights of a couple of adjacent blocks and changing brightness accordingly.
+ try:
+ y1=stuff[(x-1,z)][0]
+ y2=stuff[(x,z-1)][0]
+ y=stuff[(x,z)][0]
+
+ d=(y-y1+y-y2)*12
+
+ if(d>36):
+ d=36
+
+ r=limit(r+d,0,255)
+ g=limit(g+d,0,255)
+ b=limit(b+d,0,255)
+ except:
+ pass
+ #impix[w-1-(x-minx*16),h-1-(z-minz*16)]=(r,g,b)
+ impix[x-minx*16,h-1-(z-minz*16)]=(r,g,b)
+
+# Flip the picture to make it right and save.
+#print "Transposing"
+#im=im.transpose(Image.FLIP_TOP_BOTTOM)
+print "Saving"
+im.save(output)
diff --git a/pnoise.py b/pnoise.py
new file mode 100644
index 000000000..fcab5ac15
--- /dev/null
+++ b/pnoise.py
@@ -0,0 +1,102 @@
+#
+# A python perlin noise implementation, from
+# http://www.fundza.com/c4serious/noise/perlin/perlin.html
+#
+# This is used for testing how to create maps with a python script.
+#
+
+import math
+p = (
+151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,
+30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,
+62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,
+125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,
+83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,
+143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,
+196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,
+250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,
+58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,
+221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,
+224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,
+12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,
+199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,
+205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
+151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,
+30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,
+62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,
+125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,
+83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,
+143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,
+196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,
+250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,
+58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,
+221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,
+224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,
+12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,
+199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,
+205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180)
+
+def lerp(t, a, b):
+ return a + t * (b - a)
+
+def fade(t):
+ return t * t * t * (t * (t * 6 - 15) + 10)
+
+def grad(hash, x, y, z):
+ h = hash & 15
+ if h < 8:
+ u = x
+ else:
+ u = y
+ if h < 4:
+ v = y
+ elif h == 12 or h == 14:
+ v = x
+ else:
+ v = z
+ if h & 1 != 0:
+ u = -u
+ if h & 2 != 0:
+ v = -v
+ return u + v
+
+def pnoise(x, y, z):
+ global p
+ X = int(math.floor(x)) & 255
+ Y = int(math.floor(y)) & 255
+ Z = int(math.floor(z)) & 255
+ x -= math.floor(x)
+ y -= math.floor(y)
+ z -= math.floor(z)
+
+ u = fade(x)
+ v = fade(y)
+ w = fade(z)
+
+ A = p[X] + Y
+ AA = p[A] + Z
+ AB = p[A + 1] + Z
+ B = p[X + 1] + Y
+ BA = p[B] + Z
+ BB = p[B + 1] + Z
+
+ pAA = p[AA]
+ pAB = p[AB]
+ pBA = p[BA]
+ pBB = p[BB]
+ pAA1 = p[AA + 1]
+ pBA1 = p[BA + 1]
+ pAB1 = p[AB + 1]
+ pBB1 = p[BB + 1]
+
+ gradAA = grad(pAA, x, y, z)
+ gradBA = grad(pBA, x-1, y, z)
+ gradAB = grad(pAB, x, y-1, z)
+ gradBB = grad(pBB, x-1, y-1, z)
+ gradAA1 = grad(pAA1,x, y, z-1)
+ gradBA1 = grad(pBA1,x-1, y, z-1)
+ gradAB1 = grad(pAB1,x, y-1, z-1)
+ gradBB1 = grad(pBB1,x-1, y-1, z-1)
+ return lerp(w,
+ lerp(v, lerp(u, gradAA, gradBA), lerp(u, gradAB, gradBB)),
+ lerp(v, lerp(u, gradAA1,gradBA1),lerp(u, gradAB1,gradBB1)))
diff --git a/po/de/minetest.po b/po/de/minetest.po
new file mode 100644
index 000000000..69b57fd95
--- /dev/null
+++ b/po/de/minetest.po
@@ -0,0 +1,123 @@
+# German translations for minetest-c55 package.
+# Copyright (C) 2011 celeron
+# This file is distributed under the same license as the minetest-c55 package.
+# Constantin Wenger , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-22 11:00+0200\n"
+"PO-Revision-Date: 2011-07-20 16:58+0100\n"
+"Last-Translator: Constantin Wenger \n"
+"Language-Team: Deutsch <>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+
+#: src/guiMainMenu.cpp:180
+msgid "Name/Password"
+msgstr "Name/Passwort"
+
+#: src/guiMainMenu.cpp:203
+msgid "Address/Port"
+msgstr "Adresse / Port"
+
+#: src/guiMainMenu.cpp:223
+msgid "Leave address blank to start a local server."
+msgstr "Lasse die Adresse frei um einen eigenen Server zu starten"
+
+#: src/guiMainMenu.cpp:230
+msgid "Fancy trees"
+msgstr "Schöne Bäume"
+
+#: src/guiMainMenu.cpp:236
+msgid "Smooth Lighting"
+msgstr "Besseres Licht"
+
+#: src/guiMainMenu.cpp:244
+msgid "Start Game / Connect"
+msgstr "Spiel starten / Verbinden"
+
+#: src/guiMainMenu.cpp:253
+msgid "Change keys"
+msgstr "Tastenbelegung ändern"
+
+#: src/guiMainMenu.cpp:276
+msgid "Creative Mode"
+msgstr "Kreativitätsmodus"
+
+#: src/guiMainMenu.cpp:282
+msgid "Enable Damage"
+msgstr "Schaden einschalten"
+
+#: src/guiMainMenu.cpp:290
+msgid "Delete map"
+msgstr "Karte löschen"
+
+#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
+msgid "Proceed"
+msgstr "Fortsetzen"
+
+#: src/guiPasswordChange.cpp:102
+msgid "Old Password"
+msgstr "Altes Passwort"
+
+#: src/guiPasswordChange.cpp:117
+msgid "New Password"
+msgstr "Neues Passwort"
+
+#: src/guiPasswordChange.cpp:131
+msgid "Confirm Password"
+msgstr "Passwort wiederholen"
+
+#: src/guiPasswordChange.cpp:146
+msgid "Change"
+msgstr "Ändern"
+
+#: src/guiPasswordChange.cpp:155
+msgid "Passwords do not match!"
+msgstr "Passwörter passen nicht zusammen"
+
+#: src/guiPauseMenu.cpp:110
+msgid "Continue"
+msgstr "Weiter"
+
+#: src/guiPauseMenu.cpp:117
+msgid "Change Password"
+msgstr "Passwort ändern"
+
+#: src/guiPauseMenu.cpp:124
+msgid "Disconnect"
+msgstr "Verbindung trennen"
+
+#: src/guiPauseMenu.cpp:131
+msgid "Exit to OS"
+msgstr "Programm beenden"
+
+#: src/guiPauseMenu.cpp:138
+msgid ""
+"Keys:\n"
+"- WASD: Walk\n"
+"- Mouse left: dig blocks\n"
+"- Mouse right: place blocks\n"
+"- Mouse wheel: select item\n"
+"- 0...9: select item\n"
+"- Shift: sneak\n"
+"- R: Toggle viewing all loaded chunks\n"
+"- I: Inventory menu\n"
+"- ESC: This menu\n"
+"- T: Chat\n"
+msgstr ""
+"Tastenkürzel:\n"
+"- WASD: Gehen\n"
+"- linke Maustaste: dig blocks\n"
+"- rechte Maustaste: place blocks\n"
+"- Mausrad: Item auswählen\n"
+"- 0...9: Item auswählen\n"
+"- Shift: ducken\n"
+"- R: Alle geladenen Kartenteile anzeigen, umschalten\n"
+"- I: Inventarmenü\n"
+"- T: Chat\n"
diff --git a/po/en/minetest.pot b/po/en/minetest.pot
new file mode 100644
index 000000000..e242c494b
--- /dev/null
+++ b/po/en/minetest.pot
@@ -0,0 +1,113 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: minetest\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-22 11:02+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/guiMainMenu.cpp:180
+msgid "Name/Password"
+msgstr ""
+
+#: src/guiMainMenu.cpp:203
+msgid "Address/Port"
+msgstr ""
+
+#: src/guiMainMenu.cpp:223
+msgid "Leave address blank to start a local server."
+msgstr ""
+
+#: src/guiMainMenu.cpp:230
+msgid "Fancy trees"
+msgstr ""
+
+#: src/guiMainMenu.cpp:236
+msgid "Smooth Lighting"
+msgstr ""
+
+#: src/guiMainMenu.cpp:244
+msgid "Start Game / Connect"
+msgstr ""
+
+#: src/guiMainMenu.cpp:253
+msgid "Change keys"
+msgstr ""
+
+#: src/guiMainMenu.cpp:276
+msgid "Creative Mode"
+msgstr ""
+
+#: src/guiMainMenu.cpp:282
+msgid "Enable Damage"
+msgstr ""
+
+#: src/guiMainMenu.cpp:290
+msgid "Delete map"
+msgstr ""
+
+#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
+msgid "Proceed"
+msgstr ""
+
+#: src/guiPasswordChange.cpp:102
+msgid "Old Password"
+msgstr ""
+
+#: src/guiPasswordChange.cpp:117
+msgid "New Password"
+msgstr ""
+
+#: src/guiPasswordChange.cpp:131
+msgid "Confirm Password"
+msgstr ""
+
+#: src/guiPasswordChange.cpp:146
+msgid "Change"
+msgstr ""
+
+#: src/guiPasswordChange.cpp:155
+msgid "Passwords do not match!"
+msgstr ""
+
+#: src/guiPauseMenu.cpp:110
+msgid "Continue"
+msgstr ""
+
+#: src/guiPauseMenu.cpp:117
+msgid "Change Password"
+msgstr ""
+
+#: src/guiPauseMenu.cpp:124
+msgid "Disconnect"
+msgstr ""
+
+#: src/guiPauseMenu.cpp:131
+msgid "Exit to OS"
+msgstr ""
+
+#: src/guiPauseMenu.cpp:138
+msgid ""
+"Keys:\n"
+"- WASD: Walk\n"
+"- Mouse left: dig blocks\n"
+"- Mouse right: place blocks\n"
+"- Mouse wheel: select item\n"
+"- 0...9: select item\n"
+"- Shift: sneak\n"
+"- R: Toggle viewing all loaded chunks\n"
+"- I: Inventory menu\n"
+"- ESC: This menu\n"
+"- T: Chat\n"
+msgstr ""
diff --git a/po/fr/minetest.po b/po/fr/minetest.po
new file mode 100644
index 000000000..b060c424c
--- /dev/null
+++ b/po/fr/minetest.po
@@ -0,0 +1,123 @@
+# French translations for minetest-c55 package.
+# Copyright (C) 2011 celeron
+# This file is distributed under the same license as the minetest-c55 package.
+# Cyriaque 'Cisoun' Skrapits , 2011
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-22 11:00+0200\n"
+"PO-Revision-Date: 2011-07-21 15:48+0200\n"
+"Last-Translator: Cyriaque 'Cisoun' Skrapits \n"
+"Language-Team: Français <>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+
+#: src/guiMainMenu.cpp:180
+msgid "Name/Password"
+msgstr "Nom / MdP"
+
+#: src/guiMainMenu.cpp:203
+msgid "Address/Port"
+msgstr "Adresse / Port"
+
+#: src/guiMainMenu.cpp:223
+msgid "Leave address blank to start a local server."
+msgstr "Laisser l'adresse vide pour lancer un serveur local."
+
+#: src/guiMainMenu.cpp:230
+msgid "Fancy trees"
+msgstr "Arbres spéciaux"
+
+#: src/guiMainMenu.cpp:236
+msgid "Smooth Lighting"
+msgstr "Lumière douce"
+
+#: src/guiMainMenu.cpp:244
+msgid "Start Game / Connect"
+msgstr "Démarrer / Connecter"
+
+#: src/guiMainMenu.cpp:253
+msgid "Change keys"
+msgstr "Changer touches"
+
+#: src/guiMainMenu.cpp:276
+msgid "Creative Mode"
+msgstr "Mode créatif"
+
+#: src/guiMainMenu.cpp:282
+msgid "Enable Damage"
+msgstr "Activer blessures"
+
+#: src/guiMainMenu.cpp:290
+msgid "Delete map"
+msgstr "Supprimer carte"
+
+#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
+msgid "Proceed"
+msgstr "OK"
+
+#: src/guiPasswordChange.cpp:102
+msgid "Old Password"
+msgstr "Ancien mot de passe"
+
+#: src/guiPasswordChange.cpp:117
+msgid "New Password"
+msgstr "Nouveau mot de passe"
+
+#: src/guiPasswordChange.cpp:131
+msgid "Confirm Password"
+msgstr "Confirmer mot de passe"
+
+#: src/guiPasswordChange.cpp:146
+msgid "Change"
+msgstr "Changer"
+
+#: src/guiPasswordChange.cpp:155
+msgid "Passwords do not match!"
+msgstr "Mauvaise correspondance!"
+
+#: src/guiPauseMenu.cpp:110
+msgid "Continue"
+msgstr "Continuer"
+
+#: src/guiPauseMenu.cpp:117
+msgid "Change Password"
+msgstr "Changer mot de passe"
+
+#: src/guiPauseMenu.cpp:124
+msgid "Disconnect"
+msgstr "Déconnection"
+
+#: src/guiPauseMenu.cpp:131
+msgid "Exit to OS"
+msgstr "Quitter le jeu"
+
+#: src/guiPauseMenu.cpp:138
+msgid ""
+"Keys:\n"
+"- WASD: Walk\n"
+"- Mouse left: dig blocks\n"
+"- Mouse right: place blocks\n"
+"- Mouse wheel: select item\n"
+"- 0...9: select item\n"
+"- Shift: sneak\n"
+"- R: Toggle viewing all loaded chunks\n"
+"- I: Inventory menu\n"
+"- ESC: This menu\n"
+"- T: Chat\n"
+msgstr ""
+"Touches:\n"
+"- WASD: Marcher\n"
+"- Clic gauche: Creuser bloc\n"
+"- Clic droite: Insérer bloc\n"
+"- Roulette: Sélection élément\n"
+"- 0...9: Sélection élément\n"
+"- Shift: S'accroupir\n"
+"- R: Active la vue de tous les blocs\n"
+"- I: Inventaire\n"
+"- T: Chat\n"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 847269456..c93762cab 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,10 +1,32 @@
-project(minetest)
+project(minetest-delta)
cmake_minimum_required( VERSION 2.6 )
if(RUN_IN_PLACE)
add_definitions ( -DRUN_IN_PLACE )
endif(RUN_IN_PLACE)
+OPTION(USE_GETTEXT "Use GetText for internationalization" OFF)
+
+if(USE_GETTEXT)
+ find_package(GettextLib REQUIRED)
+ message(STATUS "gettext include path: ${GETTEXT_INCLUDE_DIR}")
+ message(STATUS "gettext msgfmt path: ${GETTEXT_MSGFMT}")
+ if(WIN32)
+ message(STATUS "gettext library: ${GETTEXT_LIBRARY}")
+ message(STATUS "gettext dll: ${GETTEXT_DLL}")
+ message(STATUS "gettext iconv dll: ${GETTEXT_ICONV_DLL}")
+ endif()
+ if (GETTEXT_FOUND)
+ add_definitions( -DUSE_GETTEXT )
+ message(STATUS "GetText enabled; locales found: ${GETTEXT_AVAILABLE_LOCALES}")
+ else()
+ message(STATUS "ERROR: GetText enabled but not found, disabling")
+ set(USE_GETTEXT FALSE)
+ endif(GETTEXT_FOUND)
+else(USE_GETTEXT)
+ message(STATUS "GetText disabled")
+endif(USE_GETTEXT)
+
if(NOT MSVC)
set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
endif()
@@ -27,6 +49,8 @@ if(WIN32)
CACHE FILEPATH "Path to zlibwapi.lib")
set(ZLIB_DLL "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.dll"
CACHE FILEPATH "Path to zlibwapi.dll (for installation)")
+ set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2"
+ CACHE PATH "irrlicht dir")
else()
# Unix probably
if(BUILD_CLIENT)
@@ -55,6 +79,9 @@ else()
set(CLIENT_PLATFORM_LIBS ${CLIENT_PLATFORM_LIBS} ${XXF86VM_LIBRARY})
endif()
+find_package(Jthread REQUIRED)
+find_package(Sqlite3 REQUIRED)
+
configure_file(
"${PROJECT_SOURCE_DIR}/cmake_config.h.in"
"${PROJECT_BINARY_DIR}/cmake_config.h"
@@ -110,6 +137,7 @@ set(minetest_SRCS
clouds.cpp
clientobject.cpp
guiMainMenu.cpp
+ guiKeyChangeMenu.cpp
guiMessageMenu.cpp
guiTextInputMenu.cpp
guiInventoryMenu.cpp
@@ -133,16 +161,17 @@ include_directories(
${ZLIB_INCLUDE_DIR}
${CMAKE_BUILD_TYPE}
${PNG_INCLUDE_DIR}
- "${PROJECT_SOURCE_DIR}/jthread"
- "${PROJECT_SOURCE_DIR}/sqlite"
+ ${GETTEXT_INCLUDE_DIR}
+ ${JTHREAD_INCLUDE_DIR}
+ ${SQLITE3_INCLUDE_DIR}
)
set(EXECUTABLE_OUTPUT_PATH ../bin)
if(BUILD_CLIENT)
- add_executable(minetest ${minetest_SRCS})
+ add_executable(${PROJECT_NAME} ${minetest_SRCS})
target_link_libraries(
- minetest
+ ${PROJECT_NAME}
${ZLIB_LIBRARIES}
${IRRLICHT_LIBRARY}
${OPENGL_LIBRARIES}
@@ -150,21 +179,22 @@ if(BUILD_CLIENT)
${BZIP2_LIBRARIES}
${PNG_LIBRARIES}
${X11_LIBRARIES}
+ ${GETTEXT_LIBRARY}
${PLATFORM_LIBS}
${CLIENT_PLATFORM_LIBS}
- jthread
- sqlite3
+ ${JTHREAD_LIBRARY}
+ ${SQLITE3_LIBRARY}
)
endif(BUILD_CLIENT)
if(BUILD_SERVER)
- add_executable(minetestserver ${minetestserver_SRCS})
+ add_executable(${PROJECT_NAME}server ${minetestserver_SRCS})
target_link_libraries(
- minetestserver
+ ${PROJECT_NAME}server
${ZLIB_LIBRARIES}
${PLATFORM_LIBS}
- jthread
- sqlite3
+ ${JTHREAD_LIBRARY}
+ ${SQLITE3_LIBRARY}
)
endif(BUILD_SERVER)
@@ -185,7 +215,7 @@ if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1")
if(BUILD_SERVER)
- set_target_properties(minetestserver PROPERTIES
+ set_target_properties(${PROJECT_NAME}server PROPERTIES
COMPILE_DEFINITIONS "SERVER")
endif(BUILD_SERVER)
@@ -215,7 +245,7 @@ else()
endif()
if(BUILD_SERVER)
- set_target_properties(minetestserver PROPERTIES
+ set_target_properties(${PROJECT_NAME}server PROPERTIES
COMPILE_DEFINITIONS "SERVER")
endif(BUILD_SERVER)
@@ -232,12 +262,20 @@ endif()
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../minetest.conf.example" DESTINATION ${EXAMPLE_CONF_DIR})
if(BUILD_CLIENT)
- install(TARGETS minetest DESTINATION ${BINDIR})
+ install(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
file(GLOB images "${CMAKE_CURRENT_SOURCE_DIR}/../data/*.png")
install(FILES ${images} DESTINATION ${DATADIR})
+ if (USE_GETTEXT)
+ foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
+ set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
+ set(MO_BUILD_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
+ install(FILES ${MO_BUILD_PATH} DESTINATION ${MO_DEST_PATH})
+ endforeach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
+ endif()
+
if(WIN32)
if(DEFINED IRRLICHT_DLL)
install(FILES ${IRRLICHT_DLL} DESTINATION ${BINDIR})
@@ -245,16 +283,82 @@ if(BUILD_CLIENT)
if(DEFINED ZLIB_DLL)
install(FILES ${ZLIB_DLL} DESTINATION ${BINDIR})
endif()
+ if(USE_GETTEXT)
+ if(DEFINED GETTEXT_DLL)
+ install(FILES ${GETTEXT_DLL} DESTINATION ${BINDIR})
+ endif()
+ if(DEFINED GETTEXT_ICONV_DLL)
+ install(FILES ${GETTEXT_ICONV_DLL} DESTINATION ${BINDIR})
+ endif()
+ endif(USE_GETTEXT)
endif()
endif(BUILD_CLIENT)
if(BUILD_SERVER)
- install(TARGETS minetestserver DESTINATION ${BINDIR})
+ install(TARGETS ${PROJECT_NAME}server DESTINATION ${BINDIR})
endif(BUILD_SERVER)
+if (USE_GETTEXT)
+ add_custom_command(OUTPUT "${GETTEXT_PO_PATH}/en"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${GETTEXT_PO_PATH}/en"
+ COMMENT "po-update [en]: creating translation template base directory")
+ set(POT_FILE "${GETTEXT_PO_PATH}/en/minetest.pot")
+ file(GLOB GETTEXT_POT_DEPS *.cpp *.h)
+ file(GLOB GETTEXT_POT_DEPS_REL RELATIVE ${CMAKE_SOURCE_DIR} *.cpp *.h)
+ add_custom_command(OUTPUT ${POT_FILE}
+ COMMAND ${GETTEXT_EXTRACT} -F -n -o ${POT_FILE} ${GETTEXT_POT_DEPS_REL}
+ DEPENDS "${GETTEXT_PO_PATH}/en" ${GETTEXT_POT_DEPS}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "po-update [en]: updating translation template")
+
+ set(PO_FILES)
+ set(MO_FILES)
+
+ foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
+ # skip the 'en' locale which is treated separately
+ if (NOT LOCALE STREQUAL "en")
+ set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/minetest.po")
+ add_custom_command(OUTPUT ${PO_FILE_PATH}
+ COMMAND ${GETTEXT_MSGMERGE} -F -U ${PO_FILE_PATH} ${POT_FILE}
+ DEPENDS ${POT_FILE}
+ WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
+ COMMENT "po-update [${LOCALE}]: updating strings")
+
+
+ set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
+ add_custom_command(OUTPUT ${MO_BUILD_PATH}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH}
+ COMMENT "mo-update [${LOCALE}]: Creating locale directory.")
+
+ set(MO_FILE_PATH "${MO_BUILD_PATH}/minetest.mo")
+
+ add_custom_command(
+ OUTPUT ${MO_FILE_PATH}
+ COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH}
+ DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH}
+ WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
+ COMMENT "mo-update [${LOCALE}]: Creating mo file."
+ )
+
+ set(MO_FILES ${MO_FILES} ${MO_FILE_PATH})
+ set(PO_FILES ${PO_FILES} ${PO_FILE_PATH})
+ endif(NOT LOCALE STREQUAL "en")
+ endforeach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
+
+ add_custom_target(translations ALL COMMENT "mo update" DEPENDS ${MO_FILES})
+ add_custom_target(updatepo COMMENT "po update" DEPENDS ${PO_FILES})
+endif(USE_GETTEXT)
+
# Subdirectories
-add_subdirectory(jthread)
+if (JTHREAD_FOUND)
+else (JTHREAD_FOUND)
+ add_subdirectory(jthread)
+endif (JTHREAD_FOUND)
+
+if (SQLITE3_FOUND)
+else (SQLITE3_FOUND)
add_subdirectory(sqlite)
+endif (SQLITE3_FOUND)
#end
diff --git a/src/client.cpp b/src/client.cpp
index 585fce11c..7ebb30fba 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -5,7 +5,7 @@ Copyright (C) 2010 celeron55, Perttu Ahola
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
-MeshUpdateQueue::(at your option) any later version.
+(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
@@ -328,7 +328,8 @@ void Client::step(float dtime)
core::list deleted_blocks;
- g_settings.getFloat("client_unload_unused_data_timeout");
+ float delete_unused_sectors_timeout =
+ g_settings.getFloat("client_delete_unused_sectors_timeout");
// Delete sector blocks
/*u32 num = m_env.getMap().unloadUnusedData
diff --git a/src/clouds.cpp b/src/clouds.cpp
index 122beedac..d754cc15e 100644
--- a/src/clouds.cpp
+++ b/src/clouds.cpp
@@ -84,7 +84,7 @@ void Clouds::render()
*/
const s16 cloud_radius_i = 12;
- const float cloud_size = BS*50;
+ const float cloud_size = BS*48;
const v2f cloud_speed(-BS*2, 0);
// Position of cloud noise origin in world coordinates
@@ -123,24 +123,88 @@ void Clouds::render()
(float)p_in_noise_i.X*cloud_size/BS/200,
(float)p_in_noise_i.Y*cloud_size/BS/200,
m_seed, 3, 0.4);
- if(noise < 0.8)
+ if(noise < 0.95)
continue;
-
- v2f p1 = p0 + v2f(1,1)*cloud_size;
- //video::SColor c(128,255,255,255);
float b = m_brightness;
- video::SColor c(128,b*230,b*230,b*255);
- video::S3DVertex vertices[4] =
+ video::SColor c_top(128,b*240,b*240,b*255);
+ video::SColor c_side_1(128,b*230,b*230,b*255);
+ video::SColor c_side_2(128,b*220,b*220,b*245);
+ video::SColor c_bottom(128,b*205,b*205,b*230);
+
+ video::S3DVertex v[4] =
{
- video::S3DVertex(p0.X,m_cloud_y,p0.Y, 0,0,0, c, 0,1),
- video::S3DVertex(p0.X,m_cloud_y,p1.Y, 0,0,0, c, 1,1),
- video::S3DVertex(p1.X,m_cloud_y,p1.Y, 0,0,0, c, 1,0),
- video::S3DVertex(p1.X,m_cloud_y,p0.Y, 0,0,0, c, 0,0),
+ 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),
+ video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0)
};
- u16 indices[] = {0,1,2,2,3,0};
- driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
- video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
+
+ f32 rx = cloud_size;
+ f32 ry = 8*BS;
+ f32 rz = cloud_size;
+
+ for(int i=0;i<6;i++)
+ {
+ switch(i)
+ {
+ case 0: // top
+ 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
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_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
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_2;
+ 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
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_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
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_2;
+ 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[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;
+ }
+
+ v3f pos = v3f(p0.X,m_cloud_y,p0.Y);
+
+ for(u16 i=0; i<4; i++)
+ v[i].Pos += pos;
+ u16 indices[] = {0,1,2,2,3,0};
+ driver->drawVertexPrimitiveList(v, 4, indices, 2,
+ video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
+ }
+
}
}
diff --git a/src/content_cao.cpp b/src/content_cao.cpp
index dc5ac400f..dfeaea85a 100644
--- a/src/content_cao.cpp
+++ b/src/content_cao.cpp
@@ -752,4 +752,161 @@ void Oerkki1CAO::initialize(const std::string &data)
updateNodePos();
}
+/*
+ FireflyCAO
+*/
+// Prototype
+FireflyCAO proto_FireflyCAO;
+
+FireflyCAO::FireflyCAO():
+ ClientActiveObject(0),
+ m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
+ m_node(NULL),
+ m_position(v3f(0,10*BS,0)),
+ m_yaw(0)
+{
+ ClientActiveObject::registerType(getType(), create);
+}
+
+FireflyCAO::~FireflyCAO()
+{
+}
+
+ClientActiveObject* FireflyCAO::create()
+{
+ return new FireflyCAO();
+}
+
+void FireflyCAO::addToScene(scene::ISceneManager *smgr)
+{
+ if(m_node != NULL)
+ return;
+
+ video::IVideoDriver* driver = smgr->getVideoDriver();
+
+ scene::SMesh *mesh = new scene::SMesh();
+ scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+ video::SColor c(255,255,255,255);
+ video::S3DVertex vertices[4] =
+ {
+ video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
+ video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
+ video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
+ video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
+ };
+ u16 indices[] = {0,1,2,2,3,0};
+ buf->append(vertices, 4, indices, 6);
+ // Set material
+ buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
+ buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
+ //buf->getMaterial().setTexture(0, NULL);
+ buf->getMaterial().setTexture
+ (0, driver->getTexture(getTexturePath("firefly.png").c_str()));
+ buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+ buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
+ buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+ // Add to mesh
+ mesh->addMeshBuffer(buf);
+ buf->drop();
+ m_node = smgr->addMeshSceneNode(mesh, NULL);
+ mesh->drop();
+ // Set it to use the materials of the meshbuffers directly.
+ // This is needed for changing the texture in the future
+ m_node->setReadOnlyMaterials(true);
+ updateNodePos();
+}
+
+void FireflyCAO::removeFromScene()
+{
+ if(m_node == NULL)
+ return;
+
+ m_node->remove();
+ m_node = NULL;
+}
+
+void FireflyCAO::updateLight(u8 light_at_pos)
+{
+ if(m_node == NULL)
+ return;
+
+ u8 li = 255;
+ video::SColor color(255,li,li,li);
+
+ scene::IMesh *mesh = m_node->getMesh();
+ if(mesh == NULL)
+ return;
+
+ u16 mc = mesh->getMeshBufferCount();
+ for(u16 j=0; jgetMeshBuffer(j);
+ video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+ u16 vc = buf->getVertexCount();
+ for(u16 i=0; isetPosition(m_position);
+ m_node->setPosition(pos_translator.vect_show);
+
+ v3f rot = m_node->getRotation();
+ rot.Y = 180.0 - m_yaw;
+ m_node->setRotation(rot);
+}
+
+void FireflyCAO::step(float dtime, ClientEnvironment *env)
+{
+ pos_translator.translate(dtime);
+ updateNodePos();
+}
+
+void FireflyCAO::processMessage(const std::string &data)
+{
+ //dstream<<"FireflyCAO: Got message"<* getSelectionBox()
+ {return &m_selection_box;}
+ v3f getPosition()
+ {return m_position;}
+
+private:
+ core::aabbox3d m_selection_box;
+ scene::IMeshSceneNode *m_node;
+ v3f m_position;
+ float m_yaw;
+ SmoothTranslator pos_translator;
+};
+
#endif
diff --git a/src/content_craft.cpp b/src/content_craft.cpp
index e4573a211..b5a1dc776 100644
--- a/src/content_craft.cpp
+++ b/src/content_craft.cpp
@@ -262,6 +262,24 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
+ // Rail
+ {
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[1] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[6] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[8] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_RAIL, 15);
+ }
+ }
+
// Chest
{
ItemSpec specs[9];
@@ -314,6 +332,87 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
+ // Sandstone
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_SANDSTONE, 1);
+ }
+ }
+
+ // Clay
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ specs[4] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ specs[6] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ specs[7] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_CLAY, 1);
+ }
+ }
+
+ // Brick
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ specs[4] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ specs[6] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ specs[7] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_BRICK, 1);
+ }
+ }
+
+ // Paper
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS);
+ specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS);
+ specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS);
+ if(checkItemCombination(items, specs))
+ {
+ return new CraftItem("paper", 1);
+ }
+ }
+
+ // Book
+ {
+ ItemSpec specs[9];
+ specs[1] = ItemSpec(ITEM_CRAFT, "paper");
+ specs[4] = ItemSpec(ITEM_CRAFT, "paper");
+ specs[7] = ItemSpec(ITEM_CRAFT, "paper");
+ if(checkItemCombination(items, specs))
+ {
+ return new CraftItem("book", 1);
+ }
+ }
+
+ // Book shelf
+ {
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[3] = ItemSpec(ITEM_CRAFT, "book");
+ specs[4] = ItemSpec(ITEM_CRAFT, "book");
+ specs[5] = ItemSpec(ITEM_CRAFT, "book");
+ specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_BOOKSHELF, 1);
+ }
+ }
+
return NULL;
}
@@ -354,10 +453,17 @@ void craft_set_creative_inventory(Player *player)
CONTENT_MUD,
CONTENT_STONE,
CONTENT_SAND,
+ CONTENT_SANDSTONE,
+ CONTENT_CLAY,
+ CONTENT_BRICK,
CONTENT_TREE,
CONTENT_LEAVES,
+ CONTENT_CACTUS,
+ CONTENT_PAPYRUS,
+ CONTENT_BOOKSHELF,
CONTENT_GLASS,
CONTENT_FENCE,
+ CONTENT_RAIL,
CONTENT_MESE,
CONTENT_WATERSOURCE,
CONTENT_CLOUD,
diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp
index 78fa6f3d1..322250606 100644
--- a/src/content_inventory.cpp
+++ b/src/content_inventory.cpp
@@ -49,14 +49,24 @@ std::string item_craft_get_image_name(const std::string &subname)
{
if(subname == "Stick")
return "stick.png";
+ else if(subname == "paper")
+ return "paper.png";
+ else if(subname == "book")
+ return "book.png";
else if(subname == "lump_of_coal")
return "lump_of_coal.png";
else if(subname == "lump_of_iron")
return "lump_of_iron.png";
+ else if(subname == "lump_of_clay")
+ return "lump_of_clay.png";
else if(subname == "steel_ingot")
return "steel_ingot.png";
+ else if(subname == "clay_brick")
+ return "clay_brick.png";
else if(subname == "rat")
return "rat.png";
+ else if(subname == "firefly")
+ return "firefly.png";
else
return "cloud.png"; // just something
}
@@ -69,13 +79,18 @@ ServerActiveObject* item_craft_create_object(const std::string &subname,
ServerActiveObject *obj = new RatSAO(env, id, pos);
return obj;
}
+ else if(subname == "firefly")
+ {
+ ServerActiveObject *obj = new FireflySAO(env, id, pos);
+ return obj;
+ }
return NULL;
}
s16 item_craft_get_drop_count(const std::string &subname)
{
- if(subname == "rat")
+ if(subname == "rat" || subname == "firefly")
return 1;
return -1;
@@ -83,7 +98,7 @@ s16 item_craft_get_drop_count(const std::string &subname)
bool item_craft_is_cookable(const std::string &subname)
{
- if(subname == "lump_of_iron")
+ if(subname == "lump_of_iron" || subname == "lump_of_clay")
return true;
return false;
@@ -93,6 +108,8 @@ InventoryItem* item_craft_create_cook_result(const std::string &subname)
{
if(subname == "lump_of_iron")
return new CraftItem("steel_ingot", 1);
+ else if(subname == "lump_of_clay")
+ return new CraftItem("clay_brick", 1);
return NULL;
}
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 38bc9620c..4a9fa5e98 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -188,6 +188,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
material_general.setFlag(video::EMF_FOG_ENABLE, true);
material_general.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
+ // Papyrus material
+ video::SMaterial material_papyrus;
+ material_papyrus.setFlag(video::EMF_LIGHTING, false);
+ material_papyrus.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_papyrus.setFlag(video::EMF_FOG_ENABLE, true);
+ material_papyrus.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+ AtlasPointer pa_papyrus = g_texturesource->getTexture(
+ g_texturesource->getTextureId("papyrus.png"));
+ material_papyrus.setTexture(0, pa_papyrus.atlas);
for(s16 z=0; zm_daynight_ratio)));
+ video::SColor c(255,l,l,l);
+ for(u32 j=0; j<4; j++)
+ {
+ video::S3DVertex vertices[4] =
+ {
+ video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
+ pa_papyrus.x0(), pa_papyrus.y1()),
+ video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
+ pa_papyrus.x1(), pa_papyrus.y1()),
+ video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
+ pa_papyrus.x1(), pa_papyrus.y0()),
+ video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
+ pa_papyrus.x0(), pa_papyrus.y0()),
+ };
+
+ if(j == 0)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(45);
+ }
+ else if(j == 1)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(-45);
+ }
+ else if(j == 2)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(135);
+ }
+ else if(j == 3)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(-135);
+ }
+
+ for(u16 i=0; i<4; i++)
+ {
+ vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+ }
+
+ u16 indices[] = {0,1,2,2,3,0};
+ // Add to mesh collector
+ collector.append(material_papyrus, vertices, 4, indices, 6);
+ }
+ }
+ else if(n.getContent() == CONTENT_RAIL)
+ {
+ u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+ video::SColor c(255,l,l,l);
+
+ bool is_rail_x [] = { false, false }; /* x-1, x+1 */
+ bool is_rail_z [] = { false, false }; /* z-1, z+1 */
+
+ MapNode n_minus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1,y,z));
+ MapNode n_plus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1,y,z));
+ MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1));
+ MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1));
+
+ if(n_minus_x.getContent() == CONTENT_RAIL)
+ is_rail_x[0] = true;
+ if(n_plus_x.getContent() == CONTENT_RAIL)
+ is_rail_x[1] = true;
+ if(n_minus_z.getContent() == CONTENT_RAIL)
+ is_rail_z[0] = true;
+ if(n_plus_z.getContent() == CONTENT_RAIL)
+ is_rail_z[1] = true;
+
+ float d = (float)BS/16;
+ video::S3DVertex vertices[4] =
+ {
+ video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
+ 0, 1),
+ video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
+ 1, 1),
+ video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c,
+ 1, 0),
+ video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c,
+ 0, 0),
+ };
+
+ video::SMaterial material_rail;
+ material_rail.setFlag(video::EMF_LIGHTING, false);
+ material_rail.setFlag(video::EMF_BACK_FACE_CULLING, false);
+ material_rail.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_rail.setFlag(video::EMF_FOG_ENABLE, true);
+ material_rail.MaterialType
+ = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
+ int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
+
+ // Assign textures
+ if(adjacencies < 2)
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
+ else if(adjacencies == 2)
+ {
+ if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
+ else
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_curved.png"));
+ }
+ else if(adjacencies == 3)
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_t_junction.png"));
+ else if(adjacencies == 4)
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_crossing.png"));
+
+ // Rotate textures
+ int angle = 0;
+
+ if(adjacencies == 1)
+ {
+ if(is_rail_x[0] || is_rail_x[1])
+ angle = 90;
+ }
+ else if(adjacencies == 2)
+ {
+ if(is_rail_x[0] && is_rail_x[1])
+ angle = 90;
+ else if(is_rail_x[0] && is_rail_z[0])
+ angle = 270;
+ else if(is_rail_x[0] && is_rail_z[1])
+ angle = 180;
+ else if(is_rail_x[1] && is_rail_z[1])
+ angle = 90;
+ }
+ else if(adjacencies == 3)
+ {
+ if(!is_rail_x[0])
+ angle=0;
+ if(!is_rail_x[1])
+ angle=180;
+ if(!is_rail_z[0])
+ angle=90;
+ if(!is_rail_z[1])
+ angle=270;
+ }
+
+ if(angle != 0) {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(angle);
+ }
+
+ for(s32 i=0; i<4; i++)
+ {
+ vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+ }
+
+ u16 indices[] = {0,1,2,2,3,0};
+ collector.append(material_rail, vertices, 4, indices, 6);
+ }
}
}
#endif
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index e2aed2458..8701ab887 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -47,6 +47,12 @@ content_t trans_table_19[][2] = {
{CONTENT_GLASS, 20},
{CONTENT_MOSSYCOBBLE, 22},
{CONTENT_GRAVEL, 23},
+ {CONTENT_SANDSTONE, 24},
+ {CONTENT_CACTUS, 25},
+ {CONTENT_BRICK, 26},
+ {CONTENT_CLAY, 27},
+ {CONTENT_PAPYRUS, 28},
+ {CONTENT_BOOKSHELF, 29},
};
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version)
@@ -152,6 +158,33 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
setDirtLikeDiggingProperties(f->digging_properties, 1.75);
+ i = CONTENT_SANDSTONE;
+ f = &content_features(i);
+ f->setAllTextures("sandstone.png");
+ f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(CONTENT_SAND)+" 1";
+ setDirtLikeDiggingProperties(f->digging_properties, 1.0);
+
+ i = CONTENT_CLAY;
+ f = &content_features(i);
+ f->setAllTextures("clay.png");
+ f->setInventoryTextureCube("clay.png", "clay.png", "clay.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("CraftItem lump_of_clay 4");
+ setDirtLikeDiggingProperties(f->digging_properties, 1.0);
+
+ i = CONTENT_BRICK;
+ f = &content_features(i);
+ f->setAllTextures("brick.png");
+ f->setInventoryTextureCube("brick.png", "brick.png", "brick.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("CraftItem clay_brick 4");
+ setStoneLikeDiggingProperties(f->digging_properties, 1.0);
+
i = CONTENT_TREE;
f = &content_features(i);
f->setAllTextures("tree.png");
@@ -180,6 +213,40 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
+ i = CONTENT_CACTUS;
+ f = &content_features(i);
+ f->setAllTextures("cactus_side.png");
+ f->setTexture(0, "cactus_top.png");
+ f->setTexture(1, "cactus_top.png");
+ f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+ setWoodLikeDiggingProperties(f->digging_properties, 0.75);
+
+ i = CONTENT_PAPYRUS;
+ f = &content_features(i);
+ f->setInventoryTexture("papyrus.png");
+ f->light_propagates = true;
+ f->param_type = CPT_LIGHT;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+ f->solidness = 0; // drawn separately, makes no faces
+ f->walkable = false;
+ setWoodLikeDiggingProperties(f->digging_properties, 0.25);
+
+ i = CONTENT_BOOKSHELF;
+ f = &content_features(i);
+ f->setAllTextures("bookshelf.png");
+ f->setTexture(0, "wood.png");
+ f->setTexture(1, "wood.png");
+ // FIXME: setInventoryTextureCube() only cares for the first texture
+ f->setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
+ //f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ setWoodLikeDiggingProperties(f->digging_properties, 0.75);
+
i = CONTENT_GLASS;
f = &content_features(i);
f->light_propagates = true;
@@ -201,6 +268,18 @@ void content_mapnode_init()
f->setInventoryTexture("item_fence.png");
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
+ i = CONTENT_RAIL;
+ f = &content_features(i);
+ f->setInventoryTexture("rail.png");
+ f->light_propagates = true;
+ f->param_type = CPT_LIGHT;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+ f->solidness = 0; // drawn separately, makes no faces
+ f->air_equivalent = true; // grass grows underneath
+ f->walkable = false;
+ setDirtLikeDiggingProperties(f->digging_properties, 0.75);
+
// Deprecated
i = CONTENT_COALSTONE;
f = &content_features(i);
@@ -255,6 +334,7 @@ void content_mapnode_init()
f->buildable_to = true;
f->liquid_type = LIQUID_FLOWING;
f->liquid_alternative_flowing = CONTENT_WATER;
+ f->liquid_alternative_source = CONTENT_WATERSOURCE;
i = CONTENT_WATERSOURCE;
f = &content_features(i);
@@ -286,6 +366,7 @@ void content_mapnode_init()
f->liquid_type = LIQUID_SOURCE;
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
f->liquid_alternative_flowing = CONTENT_WATER;
+ f->liquid_alternative_source = CONTENT_WATERSOURCE;
i = CONTENT_TORCH;
f = &content_features(i);
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index b484cb225..02c604c60 100644
--- a/src/content_mapnode.h
+++ b/src/content_mapnode.h
@@ -34,7 +34,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
// 0x000...0x07f (0...127): param2 is fully usable
// 126 and 127 are reserved.
-// Use these sparingly, only when the extra space in param2 is needed.
+// Use these sparingly, only when the extra space in param2 might be needed.
#define CONTENT_STONE 0
#define CONTENT_WATER 2
#define CONTENT_TORCH 3
@@ -42,10 +42,10 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_SIGN_WALL 14
#define CONTENT_CHEST 15
#define CONTENT_FURNACE 16
-//#define CONTENT_WORKBENCH 17
#define CONTENT_FENCE 21
+#define CONTENT_RAIL 30
-// 0x800...0xfff: param2 higher 4 bytes are not usable
+// 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable
#define CONTENT_GRASS 0x800 //1
#define CONTENT_TREE 0x801 //4
#define CONTENT_LEAVES 0x802 //5
@@ -62,6 +62,13 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_GLASS 0x80c //20
#define CONTENT_MOSSYCOBBLE 0x80d //22
#define CONTENT_GRAVEL 0x80e //23
+#define CONTENT_SANDSTONE 0x80f //24
+#define CONTENT_CACTUS 0x810 //25
+#define CONTENT_BRICK 0x811 //26
+#define CONTENT_CLAY 0x812 //27
+#define CONTENT_PAPYRUS 0x813 //28
+#define CONTENT_BOOKSHELF 0x814 //29
+
#endif
diff --git a/src/content_object.h b/src/content_object.h
index ecabd8a38..47f93d7d4 100644
--- a/src/content_object.h
+++ b/src/content_object.h
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define ACTIVEOBJECT_TYPE_ITEM 2
#define ACTIVEOBJECT_TYPE_RAT 3
#define ACTIVEOBJECT_TYPE_OERKKI1 4
+#define ACTIVEOBJECT_TYPE_FIREFLY 5
#endif
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index c41f4ed78..0b81855c1 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -693,4 +693,179 @@ void Oerkki1SAO::doDamage(u16 d)
}
}
+/*
+ FireflySAO
+*/
+// Prototype
+FireflySAO proto_FireflySAO(NULL, 0, v3f(0,0,0));
+
+FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos):
+ ServerActiveObject(env, id, pos),
+ m_is_active(false),
+ m_speed_f(0,0,0)
+{
+ ServerActiveObject::registerType(getType(), create);
+
+ m_oldpos = v3f(0,0,0);
+ m_last_sent_position = v3f(0,0,0);
+ m_yaw = 0;
+ m_counter1 = 0;
+ m_counter2 = 0;
+ m_age = 0;
+ m_touching_ground = false;
+}
+
+ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos,
+ const std::string &data)
+{
+ std::istringstream is(data, std::ios::binary);
+ char buf[1];
+ // read version
+ is.read(buf, 1);
+ u8 version = buf[0];
+ // check if version is supported
+ if(version != 0)
+ return NULL;
+ return new FireflySAO(env, id, pos);
+}
+
+void FireflySAO::step(float dtime, bool send_recommended)
+{
+ assert(m_env);
+
+ if(m_is_active == false)
+ {
+ if(m_inactive_interval.step(dtime, 0.5)==false)
+ return;
+ }
+
+ /*
+ The AI
+ */
+
+ // Apply (less) gravity
+ m_speed_f.Y -= dtime*3*BS;
+
+ /*
+ Move around if some player is close
+ */
+ bool player_is_close = false;
+ // Check connected players
+ core::list players = m_env->getPlayers(true);
+ core::list::Iterator i;
+ for(i = players.begin();
+ i != players.end(); i++)
+ {
+ Player *player = *i;
+ v3f playerpos = player->getPosition();
+ if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
+ {
+ player_is_close = true;
+ break;
+ }
+ }
+
+ m_is_active = player_is_close;
+
+ if(player_is_close == false)
+ {
+ m_speed_f.X = 0;
+ m_speed_f.Z = 0;
+ }
+ else
+ {
+ // Move around
+ v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
+ f32 speed = BS/2;
+ m_speed_f.X = speed * dir.X;
+ m_speed_f.Z = speed * dir.Z;
+
+ if(m_touching_ground && (m_oldpos - m_base_position).getLength()
+ < dtime*speed/2)
+ {
+ m_counter1 -= dtime;
+ if(m_counter1 < 0.0)
+ {
+ m_counter1 += 1.0;
+ m_speed_f.Y = 5.0*BS;
+ }
+ }
+
+ {
+ m_counter2 -= dtime;
+ if(m_counter2 < 0.0)
+ {
+ m_counter2 += (float)(myrand()%100)/100*3.0;
+ m_yaw += ((float)(myrand()%200)-100)/100*180;
+ m_yaw = wrapDegrees(m_yaw);
+ }
+ }
+ }
+
+ m_oldpos = m_base_position;
+
+ /*
+ Move it, with collision detection
+ */
+
+ core::aabbox3d box(-BS/3.,-BS*2/3.0,-BS/3., BS/3.,BS*4./3.,BS/3.);
+ collisionMoveResult moveresult;
+ // Maximum movement without glitches
+ f32 pos_max_d = BS*0.25;
+ // Limit speed
+ if(m_speed_f.getLength()*dtime > pos_max_d)
+ m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
+ v3f pos_f = getBasePosition();
+ v3f pos_f_old = pos_f;
+ moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
+ box, dtime, pos_f, m_speed_f);
+ m_touching_ground = moveresult.touching_ground;
+
+ setBasePosition(pos_f);
+
+ if(send_recommended == false)
+ return;
+
+ if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
+ {
+ m_last_sent_position = pos_f;
+
+ std::ostringstream os(std::ios::binary);
+ // command (0 = update position)
+ writeU8(os, 0);
+ // pos
+ writeV3F1000(os, m_base_position);
+ // yaw
+ writeF1000(os, m_yaw);
+ // create message and add to list
+ ActiveObjectMessage aom(getId(), false, os.str());
+ m_messages_out.push_back(aom);
+ }
+}
+
+std::string FireflySAO::getClientInitializationData()
+{
+ std::ostringstream os(std::ios::binary);
+ // version
+ writeU8(os, 0);
+ // pos
+ writeV3F1000(os, m_base_position);
+ return os.str();
+}
+
+std::string FireflySAO::getStaticData()
+{
+ //dstream<<__FUNCTION_NAME<(-BS*1000000,-BS*31000,-BS*1000000,
BS*1000000,BS*31000,BS*1000000);
+ trees = g_settings.getBool("farmesh_trees");
}
FarMesh::~FarMesh()
@@ -313,12 +314,11 @@ void FarMesh::render()
}
else
{
- /*// Trees if there are over 0.01 trees per MapNode
- if(tree_amount_avg > 0.01)
+ // Trees if there are over 0.01 trees per MapNode
+ if(trees && tree_amount_avg > 0.01)
c = video::SColor(255,50,128,50);
else
- c = video::SColor(255,107,134,51);*/
- c = video::SColor(255,107,134,51);
+ c = video::SColor(255,107,134,51);
ground_is_mud = true;
}
}
@@ -351,7 +351,7 @@ void FarMesh::render()
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
// Add some trees if appropriate
- if(tree_amount_avg >= 0.0065 && steepness < 1.4
+ if(trees && tree_amount_avg >= 0.0065 && steepness < 1.4
&& ground_is_mud == true)
{
driver->setMaterial(m_materials[1]);
@@ -404,11 +404,11 @@ void FarMesh::step(float dtime)
m_time += dtime;
}
-void FarMesh::update(v2f camera_p, float brightness, s16 render_range)
+void FarMesh::update(v2f camera_p, float brightness)
{
m_camera_pos = camera_p;
m_brightness = brightness;
- m_render_range = render_range;
+ m_render_range = g_settings.getS16("farmesh_distance")*10;
}
diff --git a/src/farmesh.h b/src/farmesh.h
index 0a30a8aef..577224e15 100644
--- a/src/farmesh.h
+++ b/src/farmesh.h
@@ -67,7 +67,7 @@ public:
void step(float dtime);
- void update(v2f camera_p, float brightness, s16 render_range);
+ void update(v2f camera_p, float brightness);
private:
video::SMaterial m_materials[FARMESH_MATERIAL_COUNT];
@@ -79,6 +79,7 @@ private:
float m_time;
Client *m_client;
s16 m_render_range;
+ bool trees;
};
#endif
diff --git a/src/game.cpp b/src/game.cpp
index 7e2ee44fc..b26d48967 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -538,6 +538,43 @@ void getPointedNode(Client *client, v3f player_position,
}
}
}
+ else if(n.getContent() == CONTENT_RAIL)
+ {
+ v3s16 dir = unpackDir(n.param0);
+ 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();
+
+ float d = (float)BS/16;
+ v3f vertices[4] =
+ {
+ v3f(BS/2, -BS/2+d, -BS/2),
+ v3f(-BS/2, -BS/2, BS/2),
+ };
+
+ for(s32 i=0; i<2; i++)
+ {
+ vertices[i] += npf;
+ }
+
+ core::aabbox3d box;
+
+ box = core::aabbox3d(vertices[0]);
+ box.addInternalPoint(vertices[1]);
+
+ if(distance < mindistance)
+ {
+ if(box.intersectsWithLine(shootline))
+ {
+ nodefound = true;
+ nodepos = np;
+ neighbourpos = np;
+ mindistance = distance;
+ nodehilightbox = box;
+ }
+ }
+ }
/*
Regular blocks
*/
@@ -1915,15 +1952,9 @@ void the_game(
*/
if(farmesh)
{
- farmesh_range = draw_control.wanted_range * 10;
- if(draw_control.range_all && farmesh_range < 500)
- farmesh_range = 500;
- if(farmesh_range > 1000)
- farmesh_range = 1000;
-
farmesh->step(dtime);
farmesh->update(v2f(player_position.X, player_position.Z),
- 0.05+brightness*0.95, farmesh_range);
+ 0.05+brightness*0.95);
}
// Store brightness value
@@ -1990,7 +2021,7 @@ void the_game(
endscenetime_avg = endscenetime_avg * 0.95 + (float)endscenetime*0.05;
char temptext[300];
- snprintf(temptext, 300, "Minetest-c55 %s ("
+ snprintf(temptext, 300, "Minetest-delta %s ("
"R: range_all=%i"
")"
" drawtime=%.0f, beginscenetime=%.0f"
diff --git a/src/gettext.h b/src/gettext.h
new file mode 100644
index 000000000..8ddb95346
--- /dev/null
+++ b/src/gettext.h
@@ -0,0 +1,19 @@
+#ifdef USE_GETTEXT
+#include
+#else
+#define gettext(String) String
+#define bindtextdomain(domain, dir) /* */
+#define textdomain(domain) /* */
+#endif
+
+#define _(String) gettext(String)
+#define gettext_noop(String) String
+#define N_(String) gettext_noop (String)
+
+inline wchar_t* chartowchar_t(const char *str)
+{
+ size_t l = strlen(str)+1;
+ wchar_t* nstr = new wchar_t[l];
+ mbstowcs(nstr, str, l);
+ return nstr;
+}
diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp
new file mode 100644
index 000000000..4a11cf93c
--- /dev/null
+++ b/src/guiKeyChangeMenu.cpp
@@ -0,0 +1,598 @@
+/*
+ Minetest-delta
+ Copyright (C) 2010-11 celeron55, Perttu Ahola
+ Copyright (C) 2011 Ciaran Gultnieks
+ Copyright (C) 2011 teddydestodes
+
+ 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 "guiKeyChangeMenu.h"
+#include "debug.h"
+#include "serialization.h"
+#include "keycode.h"
+#include "main.h"
+#include
+
+GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
+ gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
+ GUIModalMenu(env, parent, id, menumgr)
+{
+ activeKey = -1;
+ init_keys();
+}
+
+GUIKeyChangeMenu::~GUIKeyChangeMenu()
+{
+ removeChildren();
+}
+
+void GUIKeyChangeMenu::removeChildren()
+{
+ const core::list &children = getChildren();
+ core::list children_copy;
+ for (core::list::ConstIterator i = children.begin(); i
+ != children.end(); i++)
+ {
+ children_copy.push_back(*i);
+ }
+ for (core::list::Iterator i = children_copy.begin(); i
+ != children_copy.end(); i++)
+ {
+ (*i)->remove();
+ }
+}
+
+void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
+{
+ /*
+ Remove stuff
+ */
+ removeChildren();
+
+ /*
+ Calculate new sizes and positions
+ */
+
+ v2s32 size(620, 430);
+
+ core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
+ screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
+ screensize.Y / 2 + size.Y / 2);
+
+ DesiredRect = rect;
+ recalculateAbsolutePosition(false);
+
+ v2s32 topleft(0, 0);
+
+ {
+ core::rect < s32 > rect(0, 0, 125, 20);
+ rect += topleft + v2s32(25, 3);
+ const wchar_t *text = L"KEYBINDINGS";
+ //gui::IGUIStaticText *t =
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+ v2s32 offset(25, 40);
+ // buttons
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Forward";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->forward = Environment->addButton(rect, this,
+ GUI_ID_KEY_FORWARD_BUTTON,
+ narrow_to_wide(KeyNames[key_forward]).c_str());
+ }
+
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Backward";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->backward = Environment->addButton(rect, this,
+ GUI_ID_KEY_BACKWARD_BUTTON,
+ narrow_to_wide(KeyNames[key_backward]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Left";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->left = Environment->addButton(rect, this, GUI_ID_KEY_LEFT_BUTTON,
+ narrow_to_wide(KeyNames[key_left]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Right";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->right = Environment->addButton(rect, this,
+ GUI_ID_KEY_RIGHT_BUTTON,
+ narrow_to_wide(KeyNames[key_right]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Use";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->use = Environment->addButton(rect, this, GUI_ID_KEY_USE_BUTTON,
+ narrow_to_wide(KeyNames[key_use]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Sneak";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->sneak = Environment->addButton(rect, this,
+ GUI_ID_KEY_SNEAK_BUTTON,
+ narrow_to_wide(KeyNames[key_sneak]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Jump";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->jump = Environment->addButton(rect, this, GUI_ID_KEY_JUMP_BUTTON,
+ narrow_to_wide(KeyNames[key_jump]).c_str());
+ }
+
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Inventory";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->inventory = Environment->addButton(rect, this,
+ GUI_ID_KEY_INVENTORY_BUTTON,
+ narrow_to_wide(KeyNames[key_inventory]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Chat";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->chat = Environment->addButton(rect, this, GUI_ID_KEY_CHAT_BUTTON,
+ narrow_to_wide(KeyNames[key_chat]).c_str());
+ }
+
+ //next col
+ offset = v2s32(250, 40);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Toggle fly";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->fly = Environment->addButton(rect, this, GUI_ID_KEY_FLY_BUTTON,
+ narrow_to_wide(KeyNames[key_fly]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Toggle fast";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->fast = Environment->addButton(rect, this, GUI_ID_KEY_FAST_BUTTON,
+ narrow_to_wide(KeyNames[key_fast]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Range select";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->range = Environment->addButton(rect, this,
+ GUI_ID_KEY_RANGE_BUTTON,
+ narrow_to_wide(KeyNames[key_range]).c_str());
+ }
+
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Print stacks";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->dump = Environment->addButton(rect, this, GUI_ID_KEY_DUMP_BUTTON,
+ narrow_to_wide(KeyNames[key_dump]).c_str());
+ }
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40);
+ Environment->addButton(rect, this, GUI_ID_BACK_BUTTON, L"Save");
+ }
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40);
+ Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, L"Cancel");
+ }
+}
+
+void GUIKeyChangeMenu::drawMenu()
+{
+ gui::IGUISkin* skin = Environment->getSkin();
+ if (!skin)
+ return;
+ video::IVideoDriver* driver = Environment->getVideoDriver();
+
+ video::SColor bgcolor(140, 0, 0, 0);
+
+ {
+ core::rect < s32 > rect(0, 0, 620, 620);
+ rect += AbsoluteRect.UpperLeftCorner;
+ driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
+ }
+
+ gui::IGUIElement::draw();
+}
+
+bool GUIKeyChangeMenu::acceptInput()
+{
+ g_settings.set("keymap_forward", keycode_to_keyname(key_forward));
+ g_settings.set("keymap_backward", keycode_to_keyname(key_backward));
+ g_settings.set("keymap_left", keycode_to_keyname(key_left));
+ g_settings.set("keymap_right", keycode_to_keyname(key_right));
+ g_settings.set("keymap_jump", keycode_to_keyname(key_jump));
+ g_settings.set("keymap_sneak", keycode_to_keyname(key_sneak));
+ g_settings.set("keymap_inventory", keycode_to_keyname(key_inventory));
+ g_settings.set("keymap_chat", keycode_to_keyname(key_chat));
+ g_settings.set("keymap_rangeselect", keycode_to_keyname(key_range));
+ g_settings.set("keymap_freemove", keycode_to_keyname(key_fly));
+ g_settings.set("keymap_fastmove", keycode_to_keyname(key_fast));
+ g_settings.set("keymap_special1", keycode_to_keyname(key_use));
+ g_settings.set("keymap_print_debug_stacks", keycode_to_keyname(key_dump));
+ clearKeyCache();
+ return true;
+}
+void GUIKeyChangeMenu::init_keys()
+{
+ key_forward = getKeySetting("keymap_forward");
+ key_backward = getKeySetting("keymap_backward");
+ key_left = getKeySetting("keymap_left");
+ key_right = getKeySetting("keymap_right");
+ key_jump = getKeySetting("keymap_jump");
+ key_sneak = getKeySetting("keymap_sneak");
+ key_inventory = getKeySetting("keymap_inventory");
+ key_chat = getKeySetting("keymap_chat");
+ key_range = getKeySetting("keymap_rangeselect");
+ key_fly = getKeySetting("keymap_freemove");
+ key_fast = getKeySetting("keymap_fastmove");
+ key_use = getKeySetting("keymap_special1");
+ key_dump = getKeySetting("keymap_print_debug_stacks");
+}
+
+bool GUIKeyChangeMenu::resetMenu()
+{
+ if (activeKey >= 0)
+ {
+ switch (activeKey)
+ {
+ case GUI_ID_KEY_FORWARD_BUTTON:
+ this->forward->setText(
+ narrow_to_wide(KeyNames[key_forward]).c_str());
+ break;
+ case GUI_ID_KEY_BACKWARD_BUTTON:
+ this->backward->setText(
+ narrow_to_wide(KeyNames[key_backward]).c_str());
+ break;
+ case GUI_ID_KEY_LEFT_BUTTON:
+ this->left->setText(narrow_to_wide(KeyNames[key_left]).c_str());
+ break;
+ case GUI_ID_KEY_RIGHT_BUTTON:
+ this->right->setText(narrow_to_wide(KeyNames[key_right]).c_str());
+ break;
+ case GUI_ID_KEY_JUMP_BUTTON:
+ this->jump->setText(narrow_to_wide(KeyNames[key_jump]).c_str());
+ break;
+ case GUI_ID_KEY_SNEAK_BUTTON:
+ this->sneak->setText(narrow_to_wide(KeyNames[key_sneak]).c_str());
+ break;
+ case GUI_ID_KEY_INVENTORY_BUTTON:
+ this->inventory->setText(
+ narrow_to_wide(KeyNames[key_inventory]).c_str());
+ break;
+ case GUI_ID_KEY_CHAT_BUTTON:
+ this->chat->setText(narrow_to_wide(KeyNames[key_chat]).c_str());
+ break;
+ case GUI_ID_KEY_RANGE_BUTTON:
+ this->range->setText(narrow_to_wide(KeyNames[key_range]).c_str());
+ break;
+ case GUI_ID_KEY_FLY_BUTTON:
+ this->fly->setText(narrow_to_wide(KeyNames[key_fly]).c_str());
+ break;
+ case GUI_ID_KEY_FAST_BUTTON:
+ this->fast->setText(narrow_to_wide(KeyNames[key_fast]).c_str());
+ break;
+ case GUI_ID_KEY_USE_BUTTON:
+ this->use->setText(narrow_to_wide(KeyNames[key_use]).c_str());
+ break;
+ case GUI_ID_KEY_DUMP_BUTTON:
+ this->dump->setText(narrow_to_wide(KeyNames[key_dump]).c_str());
+ break;
+ }
+ activeKey = -1;
+ return false;
+ }
+ return true;
+}
+bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
+{
+ if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
+ && event.KeyInput.PressedDown)
+ {
+ if (activeKey == GUI_ID_KEY_FORWARD_BUTTON)
+ {
+ this->forward->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_forward = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_BACKWARD_BUTTON)
+ {
+ this->backward->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_backward = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_LEFT_BUTTON)
+ {
+ this->left->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_left = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_RIGHT_BUTTON)
+ {
+ this->right->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_right = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_JUMP_BUTTON)
+ {
+ this->jump->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_jump = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_SNEAK_BUTTON)
+ {
+ this->sneak->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_sneak = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_INVENTORY_BUTTON)
+ {
+ this->inventory->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_inventory = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_CHAT_BUTTON)
+ {
+ this->chat->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_chat = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_RANGE_BUTTON)
+ {
+ this->range->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_range = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_FLY_BUTTON)
+ {
+ this->fly->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_fly = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_FAST_BUTTON)
+ {
+ this->fast->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_fast = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_USE_BUTTON)
+ {
+ this->use->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_use = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_DUMP_BUTTON)
+ {
+ this->dump->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_dump = event.KeyInput.Key;
+ }
+
+ activeKey = -1;
+ return true;
+ }
+ if (event.EventType == EET_GUI_EVENT)
+ {
+ if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
+ && isVisible())
+ {
+ if (!canTakeFocus(event.GUIEvent.Element))
+ {
+ dstream << "GUIMainMenu: Not allowing focus change."
+ << std::endl;
+ // Returning true disables focus change
+ return true;
+ }
+ }
+ if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
+ {
+ switch (event.GUIEvent.Caller->getID())
+ {
+ case GUI_ID_BACK_BUTTON: //back
+ acceptInput();
+ quitMenu();
+ return true;
+ case GUI_ID_ABORT_BUTTON: //abort
+ quitMenu();
+ return true;
+ case GUI_ID_KEY_FORWARD_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->forward->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_BACKWARD_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->backward->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_LEFT_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->left->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_RIGHT_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->right->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_USE_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->use->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_FLY_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->fly->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_FAST_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->fast->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_JUMP_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->jump->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_CHAT_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->chat->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_SNEAK_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->sneak->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_INVENTORY_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->inventory->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_DUMP_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->dump->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_RANGE_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->range->setText(L"press Key");
+ break;
+ }
+ //Buttons
+
+ }
+ }
+ return Parent ? Parent->OnEvent(event) : false;
+}
+
diff --git a/src/guiKeyChangeMenu.h b/src/guiKeyChangeMenu.h
new file mode 100644
index 000000000..389ce7aee
--- /dev/null
+++ b/src/guiKeyChangeMenu.h
@@ -0,0 +1,133 @@
+/*
+ Minetest-delta
+ Copyright (C) 2010-11 celeron55, Perttu Ahola
+ Copyright (C) 2011 Ciaran Gultnieks
+ Copyright (C) 2011 teddydestodes
+
+ 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 GUIKEYCHANGEMENU_HEADER
+#define GUIKEYCHANGEMENU_HEADER
+
+#include "common_irrlicht.h"
+#include "utility.h"
+#include "modalMenu.h"
+#include "client.h"
+#include
+
+static const char *KeyNames[] =
+ { "-", "Left Button", "Right Button", "Cancel", "Middle Button", "X Button 1",
+ "X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-",
+ "-", "Shift", "Control", "Menu", "Pause", "Capital", "Kana", "-",
+ "Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert",
+ "Accept", "Mode Change", "Space", "Priot", "Next", "End", "Home",
+ "Left", "Up", "Right", "Down", "Select", "Print", "Execute",
+ "Snapshot", "Insert", "Delete", "Help", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C",
+ "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
+ "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Left Windows",
+ "Right Windows", "Apps", "-", "Sleep", "Numpad 0", "Numpad 1",
+ "Numpad 2", "Numpad 3", "Numpad 4", "Numpad 5", "Numpad 6", "Numpad 7",
+ "Numpad 8", "Numpad 9", "Numpad *", "Numpad +", "Numpad /", "Numpad -",
+ "Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
+ "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18",
+ "F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-",
+ "-", "-", "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "Left Shift", "Right Shight",
+ "Left Control", "Right Control", "Left Menu", "Right Menu", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel",
+ "ExSel", "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" };
+ enum
+ {
+ GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
+ //buttons
+ GUI_ID_KEY_FORWARD_BUTTON,
+ GUI_ID_KEY_BACKWARD_BUTTON,
+ GUI_ID_KEY_LEFT_BUTTON,
+ GUI_ID_KEY_RIGHT_BUTTON,
+ GUI_ID_KEY_USE_BUTTON,
+ GUI_ID_KEY_FLY_BUTTON,
+ GUI_ID_KEY_FAST_BUTTON,
+ GUI_ID_KEY_JUMP_BUTTON,
+ GUI_ID_KEY_CHAT_BUTTON,
+ GUI_ID_KEY_SNEAK_BUTTON,
+ GUI_ID_KEY_INVENTORY_BUTTON,
+ GUI_ID_KEY_DUMP_BUTTON,
+ GUI_ID_KEY_RANGE_BUTTON
+ };
+
+class GUIKeyChangeMenu: public GUIModalMenu
+{
+public:
+ GUIKeyChangeMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
+ s32 id, IMenuManager *menumgr);
+ ~GUIKeyChangeMenu();
+
+ void removeChildren();
+ /*
+ Remove and re-add (or reposition) stuff
+ */
+ void regenerateGui(v2u32 screensize);
+
+ void drawMenu();
+
+ bool acceptInput();
+
+ bool OnEvent(const SEvent& event);
+
+private:
+
+ void init_keys();
+
+ bool resetMenu();
+
+ gui::IGUIButton *forward;
+ gui::IGUIButton *backward;
+ gui::IGUIButton *left;
+ gui::IGUIButton *right;
+ gui::IGUIButton *use;
+ gui::IGUIButton *sneak;
+ gui::IGUIButton *jump;
+ gui::IGUIButton *inventory;
+ gui::IGUIButton *fly;
+ gui::IGUIButton *fast;
+ gui::IGUIButton *range;
+ gui::IGUIButton *dump;
+ gui::IGUIButton *chat;
+
+ u32 activeKey;
+ u32 key_forward;
+ u32 key_backward;
+ u32 key_left;
+ u32 key_right;
+ u32 key_use;
+ u32 key_sneak;
+ u32 key_jump;
+ u32 key_inventory;
+ u32 key_fly;
+ u32 key_fast;
+ u32 key_range;
+ u32 key_chat;
+ u32 key_dump;
+};
+
+#endif
+
diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp
index ef0a013f1..1d7f224f6 100644
--- a/src/guiMainMenu.cpp
+++ b/src/guiMainMenu.cpp
@@ -18,10 +18,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "guiMainMenu.h"
+#include "guiKeyChangeMenu.h"
#include "debug.h"
#include "serialization.h"
#include
+
+
+#include "gettext.h"
+
GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
@@ -34,6 +39,10 @@ GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
m_gamecallback(gamecallback)
{
assert(m_data);
+ this->env = env;
+ this->parent = parent;
+ this->id = id;
+ this->menumgr = menumgr;
}
GUIMainMenu::~GUIMainMenu()
@@ -70,35 +79,35 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
// Client options
{
- gui::IGUIElement *e = getElementFromId(258);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
if(e != NULL)
text_name = e->getText();
else
text_name = m_data->name;
}
{
- gui::IGUIElement *e = getElementFromId(256);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
if(e != NULL)
text_address = e->getText();
else
text_address = m_data->address;
}
{
- gui::IGUIElement *e = getElementFromId(257);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
if(e != NULL)
text_port = e->getText();
else
text_port = m_data->port;
}
{
- gui::IGUIElement *e = getElementFromId(263);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
else
fancy_trees = m_data->fancy_trees;
}
{
- gui::IGUIElement *e = getElementFromId(262);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
else
@@ -107,14 +116,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
// Server options
{
- gui::IGUIElement *e = getElementFromId(259);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
else
creative_mode = m_data->creative_mode;
}
{
- gui::IGUIElement *e = getElementFromId(261);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
else
@@ -168,14 +177,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, 50+6);
- const wchar_t *text = L"Name/Password";
- Environment->addStaticText(text, rect, false, true, this, -1);
+ Environment->addStaticText(chartowchar_t(gettext("Name/Password")),
+ rect, false, true, this, -1);
}
{
core::rect rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, 50);
gui::IGUIElement *e =
- Environment->addEditBox(text_name.c_str(), rect, true, this, 258);
+ Environment->addEditBox(text_name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
if(text_name == L"")
Environment->setFocus(e);
}
@@ -191,14 +200,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, 100+6);
- const wchar_t *text = L"Address/Port";
- Environment->addStaticText(text, rect, false, true, this, -1);
+ Environment->addStaticText(chartowchar_t(gettext("Address/Port")),
+ rect, false, true, this, -1);
}
{
core::rect rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, 100);
gui::IGUIElement *e =
- Environment->addEditBox(text_address.c_str(), rect, true, this, 256);
+ Environment->addEditBox(text_address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT);
if(text_name != L"")
Environment->setFocus(e);
}
@@ -206,34 +215,43 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
core::rect rect(0, 0, 120, 30);
//rect += topleft_client + v2s32(160+250+20, 125);
rect += topleft_client + v2s32(size_client.X-60-100, 100);
- Environment->addEditBox(text_port.c_str(), rect, true, this, 257);
+ Environment->addEditBox(text_port.c_str(), rect, true, this, GUI_ID_PORT_INPUT);
}
{
core::rect rect(0, 0, 400, 20);
rect += topleft_client + v2s32(160, 100+35);
- const wchar_t *text = L"Leave address blank to start a local server.";
- Environment->addStaticText(text, rect, false, true, this, -1);
+ Environment->addStaticText(chartowchar_t(gettext("Leave address blank to start a local server.")),
+ rect, false, true, this, -1);
}
{
core::rect rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150);
- Environment->addCheckBox(fancy_trees, rect, this, 263,
- L"Fancy trees");
+ Environment->addCheckBox(fancy_trees, rect, this, GUI_ID_FANCYTREE_CB,
+ chartowchar_t(gettext("Fancy trees")));
}
{
core::rect rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150+30);
- Environment->addCheckBox(smooth_lighting, rect, this, 262,
- L"Smooth Lighting");
+ Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB,
+ chartowchar_t(gettext("Smooth Lighting")));
}
// Start game button
{
core::rect rect(0, 0, 180, 30);
//rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
rect += topleft_client + v2s32(size_client.X-180-40, 150+25);
- Environment->addButton(rect, this, 257, L"Start Game / Connect");
+ Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
+ chartowchar_t(gettext("Start Game / Connect")));
}
+ // Key change button
+ {
+ core::rect rect(0, 0, 100, 30);
+ //rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
+ rect += topleft_client + v2s32(size_client.X-180-40-100-20, 150+25);
+ Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON,
+ chartowchar_t(gettext("Change keys")));
+ }
/*
Server section
*/
@@ -254,19 +272,22 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 250, 30);
rect += topleft_server + v2s32(35, 30);
- Environment->addCheckBox(creative_mode, rect, this, 259, L"Creative Mode");
+ Environment->addCheckBox(creative_mode, rect, this, GUI_ID_CREATIVE_CB,
+ chartowchar_t(gettext("Creative Mode")));
}
{
core::rect rect(0, 0, 250, 30);
rect += topleft_server + v2s32(35, 60);
- Environment->addCheckBox(enable_damage, rect, this, 261, L"Enable Damage");
+ Environment->addCheckBox(enable_damage, rect, this, GUI_ID_DAMAGE_CB,
+ chartowchar_t(gettext("Enable Damage")));
}
// Map delete button
{
core::rect rect(0, 0, 130, 30);
//rect += topleft_server + v2s32(size_server.X-40-130, 100+25);
rect += topleft_server + v2s32(40, 100+25);
- Environment->addButton(rect, this, 260, L"Delete world");
+ Environment->addButton(rect, this, GUI_ID_DELETE_MAP_BUTTON,
+ chartowchar_t(gettext("Delete map")));
}
}
@@ -300,7 +321,7 @@ void GUIMainMenu::drawMenu()
void GUIMainMenu::acceptInput()
{
{
- gui::IGUIElement *e = getElementFromId(258);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
if(e != NULL)
m_data->name = e->getText();
}
@@ -310,32 +331,32 @@ void GUIMainMenu::acceptInput()
m_data->password = e->getText();
}
{
- gui::IGUIElement *e = getElementFromId(256);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
if(e != NULL)
m_data->address = e->getText();
}
{
- gui::IGUIElement *e = getElementFromId(257);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
if(e != NULL)
m_data->port = e->getText();
}
{
- gui::IGUIElement *e = getElementFromId(259);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
}
{
- gui::IGUIElement *e = getElementFromId(261);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
}
{
- gui::IGUIElement *e = getElementFromId(262);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
}
{
- gui::IGUIElement *e = getElementFromId(263);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
}
@@ -377,11 +398,16 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
{
switch(event.GUIEvent.Caller->getID())
{
- case 257: // Start game
+ case GUI_ID_JOIN_GAME_BUTTON: // Start game
acceptInput();
quitMenu();
return true;
- case 260: // Delete map
+ case GUI_ID_CHANGE_KEYS_BUTTON: {
+ GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
+ kmenu->drop();
+ return true;
+ }
+ case GUI_ID_DELETE_MAP_BUTTON: // Delete map
// Don't accept input data, just set deletion request
m_data->delete_map = true;
m_accepted = true;
@@ -393,7 +419,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
{
switch(event.GUIEvent.Caller->getID())
{
- case 256: case 257: case 258: case 264:
+ case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
acceptInput();
quitMenu();
return true;
diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h
index edd519024..87561f797 100644
--- a/src/guiMainMenu.h
+++ b/src/guiMainMenu.h
@@ -27,6 +27,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// For IGameCallback
#include "guiPauseMenu.h"
+enum
+{
+ GUI_ID_QUIT_BUTTON = 101,
+ GUI_ID_NAME_INPUT,
+ GUI_ID_ADDRESS_INPUT,
+ GUI_ID_PORT_INPUT,
+ GUI_ID_FANCYTREE_CB,
+ GUI_ID_SMOOTH_LIGHTING_CB,
+ GUI_ID_DAMAGE_CB,
+ GUI_ID_CREATIVE_CB,
+ GUI_ID_JOIN_GAME_BUTTON,
+ GUI_ID_CHANGE_KEYS_BUTTON,
+ GUI_ID_DELETE_MAP_BUTTON
+};
+
struct MainMenuData
{
MainMenuData():
@@ -87,6 +102,11 @@ private:
MainMenuData *m_data;
bool m_accepted;
IGameCallback *m_gamecallback;
+
+ gui::IGUIEnvironment* env;
+ gui::IGUIElement* parent;
+ s32 id;
+ IMenuManager *menumgr;
};
#endif
diff --git a/src/guiMessageMenu.cpp b/src/guiMessageMenu.cpp
index 192911355..155be6029 100644
--- a/src/guiMessageMenu.cpp
+++ b/src/guiMessageMenu.cpp
@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h"
#include
+#include "gettext.h"
+
GUIMessageMenu::GUIMessageMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
@@ -87,7 +89,8 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize)
core::rect rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
gui::IGUIElement *e =
- Environment->addButton(rect, this, 257, L"Proceed");
+ Environment->addButton(rect, this, 257,
+ chartowchar_t(gettext("Proceed")));
Environment->setFocus(e);
}
}
diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp
index ec1cd029a..fabe75110 100644
--- a/src/guiPasswordChange.cpp
+++ b/src/guiPasswordChange.cpp
@@ -21,6 +21,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "serialization.h"
#include
+#include "gettext.h"
+
const int ID_oldPassword = 256;
const int ID_newPassword1 = 257;
const int ID_newPassword2 = 258;
@@ -97,8 +99,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
- const wchar_t *text = L"Old Password";
- Environment->addStaticText(text, rect, false, true, this, -1);
+ Environment->addStaticText(chartowchar_t(gettext("Old Password")),
+ rect, false, true, this, -1);
}
{
core::rect rect(0, 0, 230, 30);
@@ -112,8 +114,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
- const wchar_t *text = L"New Password";
- Environment->addStaticText(text, rect, false, true, this, -1);
+ Environment->addStaticText(chartowchar_t(gettext("New Password")),
+ rect, false, true, this, -1);
}
{
core::rect rect(0, 0, 230, 30);
@@ -126,8 +128,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
- const wchar_t *text = L"Confirm Password";
- Environment->addStaticText(text, rect, false, true, this, -1);
+ Environment->addStaticText(chartowchar_t(gettext("Confirm Password")),
+ rect, false, true, this, -1);
}
{
core::rect rect(0, 0, 230, 30);
@@ -141,16 +143,17 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, ypos);
- Environment->addButton(rect, this, ID_change, L"Change");
+ Environment->addButton(rect, this, ID_change, chartowchar_t(gettext("Change")));
}
ypos += 50;
{
core::rect rect(0, 0, 300, 20);
rect += topleft_client + v2s32(35, ypos);
- const wchar_t *text = L"Passwords do not match!";
IGUIElement *e =
- Environment->addStaticText(text, rect, false, true, this, ID_message);
+ Environment->addStaticText(
+ chartowchar_t(gettext("Passwords do not match!")),
+ rect, false, true, this, ID_message);
e->setVisible(false);
}
diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp
index d32d1a10b..61485518c 100644
--- a/src/guiPauseMenu.cpp
+++ b/src/guiPauseMenu.cpp
@@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h"
#include "main.h"
+#include "gettext.h"
+
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback,
@@ -104,43 +106,47 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
- Environment->addButton(rect, this, 256, L"Continue");
+ Environment->addButton(rect, this, 256,
+ chartowchar_t(gettext("Continue")));
}
btn_y += btn_height + btn_gap;
{
core::rect rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
- Environment->addButton(rect, this, 261, L"Change Password");
+ Environment->addButton(rect, this, 261,
+ chartowchar_t(gettext("Change Password")));
}
btn_y += btn_height + btn_gap;
{
core::rect rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
- Environment->addButton(rect, this, 260, L"Disconnect");
+ Environment->addButton(rect, this, 260,
+ chartowchar_t(gettext("Disconnect")));
}
btn_y += btn_height + btn_gap;
{
core::rect rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
- Environment->addButton(rect, this, 257, L"Exit to OS");
+ Environment->addButton(rect, this, 257,
+ chartowchar_t(gettext("Exit to OS")));
}
{
core::rect rect(0, 0, 180, 240);
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
- const wchar_t *text =
- L"Keys:\n"
- L"- WASD: Walk\n"
- L"- Mouse left: dig blocks\n"
- L"- Mouse right: place blocks\n"
- L"- Mouse wheel: select item\n"
- L"- 0...9: select item\n"
- L"- Shift: sneak\n"
- L"- R: Toggle viewing all loaded chunks\n"
- L"- I: Inventory menu\n"
- L"- ESC: This menu\n"
- L"- T: Chat\n";
- Environment->addStaticText(text, rect, false, true, this, 258);
+ Environment->addStaticText(chartowchar_t(gettext(
+ "Keys:\n"
+ "- WASD: Walk\n"
+ "- Mouse left: dig blocks\n"
+ "- Mouse right: place blocks\n"
+ "- Mouse wheel: select item\n"
+ "- 0...9: select item\n"
+ "- Shift: sneak\n"
+ "- R: Toggle viewing all loaded chunks\n"
+ "- I: Inventory menu\n"
+ "- ESC: This menu\n"
+ "- T: Chat\n"
+ )), rect, false, true, this, 258);
}
{
core::rect rect(0, 0, 180, 220);
@@ -166,8 +172,8 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
);*/
std::ostringstream os;
- os<<"Minetest-c55\n";
- os<<"by Perttu Ahola\n";
+ os<<"Minetest-delta\n";
+ os<<"by Perttu Ahola and contributors\n";
os<<"celeron55@gmail.com\n";
os<
+#include "gettext.h"
+
GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
@@ -105,7 +107,8 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize)
{
core::rect rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
- Environment->addButton(rect, this, 257, L"Proceed");
+ Environment->addButton(rect, this, 257,
+ chartowchar_t(gettext("Proceed")));
}
}
diff --git a/src/keycode.cpp b/src/keycode.cpp
index ad3c0b401..f014914d0 100644
--- a/src/keycode.cpp
+++ b/src/keycode.cpp
@@ -171,6 +171,46 @@ irr::EKEY_CODE keyname_to_keycode(const char *name)
return irr::KEY_KEY_CODES_COUNT;
}
+static const char *KeyNames[] =
+{ "-", "KEY_LBUTTON", "KEY_RBUTTON", "Cancel", "Middle Button", "X Button 1",
+ "X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-",
+ "-", "KEY_SHIFT", "Control", "Menu", "Pause", "Capital", "Kana", "-",
+ "Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert",
+ "Accept", "Mode Change", "KEY_SPACE", "Priot", "Next", "KEY_END",
+ "KEY_HOME", "Left", "Up", "Right", "Down", "Select", "KEY_PRINT",
+ "Execute", "Snapshot", "Insert", "Delete", "Help", "KEY_KEY_0",
+ "KEY_KEY_1", "KEY_KEY_2", "KEY_KEY_3", "KEY_KEY_4", "KEY_KEY_5",
+ "KEY_KEY_6", "KEY_KEY_7", "KEY_KEY_8", "KEY_KEY_9", "-", "-", "-", "-",
+ "-", "-", "-", "KEY_KEY_A", "KEY_KEY_B", "KEY_KEY_C", "KEY_KEY_D",
+ "KEY_KEY_E", "KEY_KEY_F", "KEY_KEY_G", "KEY_KEY_H", "KEY_KEY_I",
+ "KEY_KEY_J", "KEY_KEY_K", "KEY_KEY_L", "KEY_KEY_M", "KEY_KEY_N",
+ "KEY_KEY_O", "KEY_KEY_P", "KEY_KEY_Q", "KEY_KEY_R", "KEY_KEY_S",
+ "KEY_KEY_T", "KEY_KEY_U", "KEY_KEY_V", "KEY_KEY_W", "KEY_KEY_X",
+ "KEY_KEY_Y", "KEY_KEY_Z", "Left Windows", "Right Windows", "Apps", "-",
+ "Sleep", "KEY_NUMPAD0", "KEY_NUMPAD1", "KEY_NUMPAD2", "KEY_NUMPAD3",
+ "KEY_NUMPAD4", "KEY_NUMPAD5", "KEY_NUMPAD6", "KEY_NUMPAD7",
+ "KEY_NUMPAD8", "KEY_NUMPAD9", "Numpad *", "Numpad +", "Numpad /",
+ "Numpad -", "Numpad .", "Numpad /", "KEY_F1", "KEY_F2", "KEY_F3",
+ "KEY_F4", "KEY_F5", "KEY_F6", "KEY_F7", "KEY_F8", "KEY_F9", "KEY_F10",
+ "KEY_F11", "KEY_F12", "KEY_F13", "KEY_F14", "KEY_F15", "KEY_F16",
+ "KEY_F17", "KEY_F18", "KEY_F19", "KEY_F20", "KEY_F21", "KEY_F22",
+ "KEY_F23", "KEY_F24", "-", "-", "-", "-", "-", "-", "-", "-",
+ "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "KEY_LSHIFT", "KEY_RSHIFT", "Left Control",
+ "Right Control", "Left Menu", "Right Menu", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel", "ExSel",
+ "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" };
+
+std::string keycode_to_keyname(s32 keycode)
+{
+ return KeyNames[keycode];
+}
+
/*
Key config
*/
@@ -189,4 +229,7 @@ irr::EKEY_CODE getKeySetting(const char *settingname)
return c;
}
-
+void clearKeyCache()
+{
+ g_key_setting_cache.clear();
+}
diff --git a/src/keycode.h b/src/keycode.h
index f19fe3442..300682b12 100644
--- a/src/keycode.h
+++ b/src/keycode.h
@@ -21,11 +21,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define KEYCODE_HEADER
#include "common_irrlicht.h"
+#include
irr::EKEY_CODE keyname_to_keycode(const char *name);
+std::string keycode_to_keyname(s32 keycode);
// Key configuration getter
irr::EKEY_CODE getKeySetting(const char *settingname);
+// Clear fast lookup cache
+void clearKeyCache();
+
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 5aff62bf2..783faa4e2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -357,6 +357,12 @@ TODO: Merge bahamada's audio stuff (clean patch available)
TODO: Move content_features to mapnode_content_features.{h,cpp} or so
+TODO: Add some kind of content range validation to mapnode serialization
+
+TODO: Make sure menu text position is fixed
+
+TODO: Fix sector over limits error
+
Making it more portable:
------------------------
@@ -419,6 +425,8 @@ Doing currently:
#include "keycode.h"
#include "tile.h"
+#include "gettext.h"
+
// This makes textures
ITextureSource *g_texturesource = NULL;
@@ -1148,6 +1156,10 @@ int main(int argc, char *argv[])
// Create user data directory
fs::CreateDir(porting::path_userdata);
+
+ setlocale(LC_MESSAGES, "");
+ bindtextdomain("minetest", (porting::path_userdata+"/locale").c_str());
+ textdomain("minetest");
// Initialize debug streams
#ifdef RUN_IN_PLACE
@@ -1363,6 +1375,9 @@ int main(int argc, char *argv[])
// Set device in game parameters
device = device;
+
+ // Set the window caption
+ device->setWindowCaption(L"Minetest [Main Menu]");
// Create time getter
g_timegetter = new IrrlichtTimeGetter(device);
diff --git a/src/map.cpp b/src/map.cpp
index dd32e55ba..1c63943c4 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1240,17 +1240,19 @@ void Map::removeNodeAndUpdate(v3s16 p,
}
/*
- Add neighboring liquid nodes to transform queue.
+ Add neighboring liquid nodes and this node to transform queue.
+ (it's vital for the node itself to get updated last.)
*/
- v3s16 dirs[6] = {
+ v3s16 dirs[7] = {
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
+ v3s16(0,0,0), // self
};
- for(u16 i=0; i<6; i++)
+ for(u16 i=0; i<7; i++)
{
try
{
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index d4143b6d6..bc4f82280 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -85,7 +85,7 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
MapNode treenode(CONTENT_TREE);
MapNode leavesnode(CONTENT_LEAVES);
- s16 trunk_h = myrand_range(3, 6);
+ s16 trunk_h = myrand_range(4, 5);
v3s16 p1 = p0;
for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]);
Buffer leaves_d(leaves_a.getVolume());
for(s32 i=0; i= 1.0)
@@ -1345,7 +1373,8 @@ void make_block(BlockMakeData *data)
data->seed, v2s16(blockpos.X, blockpos.Z), 1);
// Maximum amount of ground above the bottom of the central block
s16 maximum_ground_depth = maximum_groundlevel - node_min.Y;
-
+
+ #if 0
/*
Special case for high air or water: Just fill with air and water.
*/
@@ -1379,6 +1408,7 @@ void make_block(BlockMakeData *data)
// We're done
return;
}
+ #endif
/*
If block is deep underground, this is set to true and ground
@@ -1808,6 +1838,8 @@ void make_block(BlockMakeData *data)
u32 current_depth = 0;
bool air_detected = false;
bool water_detected = false;
+ bool have_clay = false;
+
// Use fast index incrementing
s16 start_y = node_max.Y+2;
v3s16 em = vmanip.m_area.getExtent();
@@ -1834,7 +1866,19 @@ void make_block(BlockMakeData *data)
{
if(have_sand)
{
- vmanip.m_data[i] = MapNode(CONTENT_SAND);
+ // Determine whether to have clay in the sand here
+ double claynoise = noise2d_perlin(
+ 0.5+(float)p2d.X/500, 0.5+(float)p2d.Y/500,
+ data->seed+4321, 6, 0.95) + 0.5;
+
+ have_clay = (y <= WATER_LEVEL) && (y >= WATER_LEVEL-2) && (
+ ((claynoise > 0) && (claynoise < 0.04) && (current_depth == 0)) ||
+ ((claynoise > 0) && (claynoise < 0.12) && (current_depth == 1))
+ );
+ if (have_clay)
+ vmanip.m_data[i] = MapNode(CONTENT_CLAY);
+ else
+ vmanip.m_data[i] = MapNode(CONTENT_SAND);
}
#if 1
else if(current_depth==0 && !water_detected
@@ -1894,7 +1938,7 @@ void make_block(BlockMakeData *data)
{
u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i];
- if(n->getContent() != CONTENT_AIR && n->getContent() != CONTENT_IGNORE)
+ if(n->getContent() != CONTENT_AIR && n->getContent() != CONTENT_WATERSOURCE && n->getContent() != CONTENT_IGNORE)
{
found = true;
break;
@@ -1903,19 +1947,33 @@ void make_block(BlockMakeData *data)
// If not found, handle next one
if(found == false)
continue;
- /*
- Trees grow only on mud and grass
- */
+
{
u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i];
- if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS)
- continue;
+
+ if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS && n->getContent() != CONTENT_SAND)
+ continue;
+
+ // Papyrus grows only on mud and in water
+ if(n->getContent() == CONTENT_MUD && y <= WATER_LEVEL)
+ {
+ p.Y++;
+ make_papyrus(vmanip, p);
+ }
+ // Trees grow only on mud and grass, on land
+ else if((n->getContent() == CONTENT_MUD || n->getContent() == CONTENT_GRASS) && y > WATER_LEVEL + 2)
+ {
+ p.Y++;
+ make_tree(vmanip, p);
+ }
+ // Cactii grow only on sand, on land
+ else if(n->getContent() == CONTENT_SAND && y > WATER_LEVEL + 2)
+ {
+ p.Y++;
+ make_cactus(vmanip, p);
+ }
}
- // Tree will be placed one higher
- p.Y++;
- // Make a tree
- make_tree(vmanip, p);
}
#if 0
diff --git a/src/mapnode.h b/src/mapnode.h
index 1b10a546b..3b7ef5878 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -148,6 +148,8 @@ struct ContentFeatures
// If the content is liquid, this is the flowing version of the liquid.
// If content is liquid, this is the same content.
content_t liquid_alternative_flowing;
+ // If the content is liquid, this is the source version of the liquid.
+ content_t liquid_alternative_source;
// Amount of light the node emits
u8 light_source;
diff --git a/src/porting.cpp b/src/porting.cpp
index 7de042ab5..ff8cb3862 100644
--- a/src/porting.cpp
+++ b/src/porting.cpp
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include "config.h"
#include "debug.h"
+#include "filesys.h"
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
@@ -210,6 +211,11 @@ void initializePaths()
path_data = std::string(buf) + "/../share/" + APPNAME;
//path_data = std::string(INSTALL_PREFIX) + "/share/" + APPNAME;
+ if (!fs::PathExists(path_data)) {
+ dstream<<"WARNING: data path " << path_data << " not found!";
+ path_data = std::string(buf) + "/../data";
+ dstream<<" Trying " << path_data << std::endl;
+ }
path_userdata = std::string(getenv("HOME")) + "/." + APPNAME;