diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | .hgtags | 17 | ||||
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | README | 35 | ||||
-rw-r--r-- | data/book.png | bin | 0 -> 292 bytes | |||
-rw-r--r-- | data/bookshelf.png | bin | 0 -> 597 bytes | |||
-rw-r--r-- | data/brick.png | bin | 0 -> 604 bytes | |||
-rw-r--r-- | data/cactus_side.png | bin | 0 -> 279 bytes | |||
-rw-r--r-- | data/cactus_top.png | bin | 0 -> 236 bytes | |||
-rw-r--r-- | data/clay.png | bin | 0 -> 613 bytes | |||
-rw-r--r-- | data/clay_brick.png | bin | 0 -> 249 bytes | |||
-rw-r--r-- | data/fence.png | bin | 0 -> 539 bytes | |||
-rw-r--r-- | data/glass.png | bin | 1309 -> 381 bytes | |||
-rw-r--r-- | data/heart.png | bin | 308 -> 258 bytes | |||
-rw-r--r-- | data/lump_of_clay.png | bin | 0 -> 210 bytes | |||
-rw-r--r-- | data/menulogo.png | bin | 498 -> 653 bytes | |||
-rw-r--r-- | data/oerkki1.png | bin | 250 -> 270 bytes | |||
-rw-r--r-- | data/paper.png | bin | 0 -> 242 bytes | |||
-rw-r--r-- | data/papyrus.png | bin | 0 -> 366 bytes | |||
-rw-r--r-- | data/player.png | bin | 212 -> 652 bytes | |||
-rw-r--r-- | data/player_back.png | bin | 201 -> 292 bytes | |||
-rw-r--r-- | data/rail.png | bin | 0 -> 507 bytes | |||
-rw-r--r-- | data/rail_crossing.png | bin | 0 -> 555 bytes | |||
-rw-r--r-- | data/rail_curved.png | bin | 0 -> 545 bytes | |||
-rw-r--r-- | data/rail_t_junction.png | bin | 0 -> 542 bytes | |||
-rw-r--r-- | data/rat.png | bin | 920 -> 276 bytes | |||
-rw-r--r-- | data/sandstone.png | bin | 0 -> 772 bytes | |||
-rw-r--r-- | doc/README.txt | 238 | ||||
-rwxr-xr-x | genmap.py | 271 | ||||
-rwxr-xr-x | makepackage_binary.sh | 63 | ||||
-rw-r--r-- | minetestmapper/colors.txt | 25 | ||||
-rwxr-xr-x | minetestmapper/minetestmapper2.py | 275 | ||||
-rw-r--r-- | pnoise.py | 102 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/client.cpp | 6 | ||||
-rw-r--r-- | src/content_craft.cpp | 106 | ||||
-rw-r--r-- | src/content_inventory.cpp | 12 | ||||
-rw-r--r-- | src/content_mapblock.cpp | 167 | ||||
-rw-r--r-- | src/content_mapnode.cpp | 75 | ||||
-rw-r--r-- | src/content_mapnode.h | 7 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 2 | ||||
-rw-r--r-- | src/farmesh.cpp | 14 | ||||
-rw-r--r-- | src/farmesh.h | 3 | ||||
-rw-r--r-- | src/game.cpp | 45 | ||||
-rw-r--r-- | src/guiKeyChangeMenu.cpp | 598 | ||||
-rw-r--r-- | src/guiKeyChangeMenu.h | 133 | ||||
-rw-r--r-- | src/guiMainMenu.cpp | 71 | ||||
-rw-r--r-- | src/guiMainMenu.h | 20 | ||||
-rw-r--r-- | src/keycode.cpp | 45 | ||||
-rw-r--r-- | src/keycode.h | 3 | ||||
-rw-r--r-- | src/map.cpp | 46 | ||||
-rw-r--r-- | src/mapgen.cpp | 92 | ||||
-rw-r--r-- | src/mapnode.h | 4 |
53 files changed, 2384 insertions, 98 deletions
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 @@ -1,18 +1 @@ c37bcfd89dd627fdb131ae3f77fcaab02721bf76 working -69547bd6be420eb40f55524fd2131cbbaa2e0e29 110107195706-exp -e3c3c8e27bbc8c9b61710517a78944deb1c61696 110211211322 -23880c78e40c50ad54fcd8844510f7a423b37f2a 110212200513 -20c49c98c92a62df457b773c562df41d4167492b 110214175330 -10be2b71f965585af90af96903e83b4ddff52bf9 20110424_0 -9b05d4bfee9312aef4182fa6f63b4237368cec34 0.2.20110529_0 -6fa0a8b40406aa567f8fa84b5e2045a7e3762c1d 0.2.20110529_1 -cf6dd618ef0b7514c81ae87749733b5a328fc763 0.2.20110529_2 -96efc17b4cd92aacbe947b520a6ba91727d42f03 0.2.20110602_0 -0000000000000000000000000000000000000000 0.2.20110602_0 -6f17cd3f6c5481e6abc906fc441980c764632cbc 0.2.20110602_0 -dd08a9b5cb84d55b7576bb3fde3068dd263bc3bc 0.2.20110618_0_dev -25aa2021937f7a8b36808390983cebbc16ae6965 0.2.20110704_0 -25aa2021937f7a8b36808390983cebbc16ae6965 0.2.20110704_0 -0000000000000000000000000000000000000000 0.2.20110704_0 -0000000000000000000000000000000000000000 0.2.20110704_0 -65263ec55caf526e3f3e0bdc6657ce42daee46bc 0.2.20110704_0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6403a9dd9..15f4a6453 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ elseif(UNIX) # Linux, BSD etc set(EXAMPLE_CONF_DIR "share/doc/minetest") endif() -install(FILES "README.txt" DESTINATION "${DOCDIR}") +install(FILES "doc/README.txt" DESTINATION "${DOCDIR}") install(FILES "minetest.conf.example" DESTINATION "${DOCDIR}") # @@ -104,7 +104,7 @@ elseif(APPLE) set(CPACK_BUNDLE_ICON "") set(CPACK_BUNDLE_PLIST "") set(CPACK_BUNDLE_STARTUP_COMMAND "Contents/MacOS/minetest") - set(CPACK_GENERATOR Bundle) + set(CPACK_GENERATOR "Bundle") else() set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-linux") set(CPACK_GENERATOR TGZ) @@ -0,0 +1,35 @@ +Minetest Δ (“Minetest Delta”) is a fork of Minetest-c55 <http://celeron.55.lt/~celeron55/minetest/>, incorporating experimental features that are not (yet) included in Minetest-c55. + +New features: +* Submenu for key assignment (changes apply after restart) +* configurable far mesh tree display (boolean) +* configurable far mesh rendering distance + +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, yields paper) +* 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 +* Book (made from 3 paper) + +Alternate graphics: +* Player +* Omsk birds (instead of Oerkki ghosts) +* Rat +* Glass + +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 diff --git a/data/book.png b/data/book.png Binary files differnew file mode 100644 index 000000000..176fb6aa9 --- /dev/null +++ b/data/book.png diff --git a/data/bookshelf.png b/data/bookshelf.png Binary files differnew file mode 100644 index 000000000..5ecc50ff3 --- /dev/null +++ b/data/bookshelf.png diff --git a/data/brick.png b/data/brick.png Binary files differnew file mode 100644 index 000000000..32d77f347 --- /dev/null +++ b/data/brick.png diff --git a/data/cactus_side.png b/data/cactus_side.png Binary files differnew file mode 100644 index 000000000..fc479fde6 --- /dev/null +++ b/data/cactus_side.png diff --git a/data/cactus_top.png b/data/cactus_top.png Binary files differnew file mode 100644 index 000000000..f9e68df51 --- /dev/null +++ b/data/cactus_top.png diff --git a/data/clay.png b/data/clay.png Binary files differnew file mode 100644 index 000000000..3557429d8 --- /dev/null +++ b/data/clay.png diff --git a/data/clay_brick.png b/data/clay_brick.png Binary files differnew file mode 100644 index 000000000..e36648e48 --- /dev/null +++ b/data/clay_brick.png diff --git a/data/fence.png b/data/fence.png Binary files differnew file mode 100644 index 000000000..0b99f0eb5 --- /dev/null +++ b/data/fence.png diff --git a/data/glass.png b/data/glass.png Binary files differindex 8598ce670..35ea596d5 100644 --- a/data/glass.png +++ b/data/glass.png diff --git a/data/heart.png b/data/heart.png Binary files differindex 6bc183e04..bea1aefd6 100644 --- a/data/heart.png +++ b/data/heart.png diff --git a/data/lump_of_clay.png b/data/lump_of_clay.png Binary files differnew file mode 100644 index 000000000..be0bab9d7 --- /dev/null +++ b/data/lump_of_clay.png diff --git a/data/menulogo.png b/data/menulogo.png Binary files differindex 76595c48d..cb6983e5c 100644 --- a/data/menulogo.png +++ b/data/menulogo.png diff --git a/data/oerkki1.png b/data/oerkki1.png Binary files differindex 33cbac9e7..aad2ddb41 100644 --- a/data/oerkki1.png +++ b/data/oerkki1.png diff --git a/data/paper.png b/data/paper.png Binary files differnew file mode 100644 index 000000000..ae5c06bc6 --- /dev/null +++ b/data/paper.png diff --git a/data/papyrus.png b/data/papyrus.png Binary files differnew file mode 100644 index 000000000..bf0dec7fe --- /dev/null +++ b/data/papyrus.png diff --git a/data/player.png b/data/player.png Binary files differindex 90adf9747..60ac4854b 100644 --- a/data/player.png +++ b/data/player.png diff --git a/data/player_back.png b/data/player_back.png Binary files differindex 530aa7519..447c1fd8f 100644 --- a/data/player_back.png +++ b/data/player_back.png diff --git a/data/rail.png b/data/rail.png Binary files differnew file mode 100644 index 000000000..18176d9f3 --- /dev/null +++ b/data/rail.png diff --git a/data/rail_crossing.png b/data/rail_crossing.png Binary files differnew file mode 100644 index 000000000..984640577 --- /dev/null +++ b/data/rail_crossing.png diff --git a/data/rail_curved.png b/data/rail_curved.png Binary files differnew file mode 100644 index 000000000..62afa3d2b --- /dev/null +++ b/data/rail_curved.png diff --git a/data/rail_t_junction.png b/data/rail_t_junction.png Binary files differnew file mode 100644 index 000000000..9985f63cd --- /dev/null +++ b/data/rail_t_junction.png diff --git a/data/rat.png b/data/rat.png Binary files differindex d1a0e2ae2..96d44c3fa 100644 --- a/data/rat.png +++ b/data/rat.png diff --git a/data/sandstone.png b/data/sandstone.png Binary files differnew file mode 100644 index 000000000..c4759b4d0 --- /dev/null +++ b/data/sandstone.png 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 <celeron55@gmail.com> + +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 <path-to-file> +- 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=<Debug or Release> + - 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 <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +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..f00ec608c --- /dev/null +++ b/makepackage_binary.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +PACKAGEDIR=../minetest-packages +PACKAGENAME=minetest-c55-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 + +cp minetest.conf.example $PACKAGEPATH/ + +cp bin/minetest.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 + +cd $PACKAGEDIR +rm $PACKAGENAME.zip +zip -r $PACKAGENAME.zip $PACKAGENAME + 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<l):
+ i=l
+ return i
+
+# Fix these!
+path="../map/"
+output="map.png"
+
+sector_xmin = -1000/16
+sector_xmax = 1000/16
+sector_zmin = -1000/16
+sector_zmax = 1000/16
+
+# Load color information for the blocks.
+colors = {}
+f = file("colors.txt")
+for line in f:
+ values = string.split(line)
+ colors[int(values[0])] = (int(values[1]), int(values[2]), int(values[3]))
+f.close()
+
+xlist = []
+zlist = []
+
+# List all sectors to memory and calculate the width and heigth of the resulting picture.
+if os.path.exists(path + "sectors2"):
+ for filename in os.listdir(path + "sectors2"):
+ for filename2 in os.listdir(path + "sectors2/" + filename):
+ x = hex_to_int(filename)
+ z = hex_to_int(filename2)
+ if x < sector_xmin or x > sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+ xlist.append(x)
+ zlist.append(z)
+
+if os.path.exists(path + "sectors"):
+ for filename in os.listdir(path + "sectors"):
+ x = hex4_to_int(filename[:4])
+ z = hex4_to_int(filename[-4:])
+ if x < sector_xmin or x > sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+ xlist.append(x)
+ zlist.append(z)
+
+w = (max(xlist) - min(xlist)) * 16 + 16
+h = (max(zlist) - min(zlist)) * 16 + 16
+
+print "w="+str(w)+" h="+str(h)
+
+im = Image.new("RGB", (w, h), "white")
+impix = im.load()
+
+stuff={}
+
+starttime = time.time()
+
+# Go through all sectors.
+for n in range(len(xlist)):
+ #if n > 500:
+ # break
+ if n % 200 == 0:
+ nowtime = time.time()
+ dtime = nowtime - starttime
+ n_per_second = 1.0 * n / dtime
+ if n_per_second != 0:
+ seconds_per_n = 1.0 / n_per_second
+ time_guess = seconds_per_n * len(xlist)
+ remaining_s = time_guess - dtime
+ remaining_minutes = int(remaining_s / 60)
+ remaining_s -= remaining_minutes * 60;
+ print("Processing sector "+str(n)+" of "+str(len(xlist))
+ +" ("+str(round(100.0*n/len(xlist), 1))+"%)"
+ +" (ETA: "+str(remaining_minutes)+"m "
+ +str(int(remaining_s))+"s)")
+
+ xpos = xlist[n]
+ zpos = zlist[n]
+
+ xhex = int_to_hex3(xpos)
+ zhex = int_to_hex3(zpos)
+ xhex4 = int_to_hex4(xpos)
+ zhex4 = int_to_hex4(zpos)
+
+ sector1 = xhex4.lower() + zhex4.lower()
+ sector2 = xhex.lower() + "/" + zhex.lower()
+
+ ylist=[]
+
+ sectortype = ""
+
+ try:
+ for filename in os.listdir(path + "sectors/" + sector1):
+ if(filename != "meta"):
+ pos = int(filename,16)
+ if(pos > 32767):
+ pos-=65536
+ ylist.append(pos)
+ sectortype = "old"
+ except OSError:
+ pass
+
+ if sectortype != "old":
+ try:
+ for filename in os.listdir(path + "sectors2/" + sector2):
+ if(filename != "meta"):
+ pos = int(filename,16)
+ if(pos > 32767):
+ pos-=65536
+ ylist.append(pos)
+ sectortype = "new"
+ except OSError:
+ pass
+
+ if sectortype == "":
+ continue
+
+ ylist.sort()
+
+ # Make a list of pixels of the sector that are to be looked for.
+ pixellist = []
+ for x in range(16):
+ for y in range(16):
+ pixellist.append((x,y))
+
+ # Go through the Y axis from top to bottom.
+ for ypos in reversed(ylist):
+
+ yhex = int_to_hex4(ypos)
+
+ filename = ""
+ if sectortype == "old":
+ filename = path + "sectors/" + sector1 + "/" + yhex.lower()
+ else:
+ filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
+
+ f = file(filename, "rb")
+
+ # Let's just memorize these even though it's not really necessary.
+ version = f.read(1)
+ flags = f.read(1)
+
+ dec_o = zlib.decompressobj()
+ try:
+ mapdata = dec_o.decompress(f.read())
+ except:
+ mapdata = []
+
+ f.close()
+
+ if(len(mapdata)<4096):
+ print "bad: " + xhex+zhex+"/"+yhex + " " + len(mapdata)
+ else:
+ chunkxpos=xpos*16
+ chunkypos=ypos*16
+ chunkzpos=zpos*16
+ for (x,z) in reversed(pixellist):
+ for y in reversed(range(16)):
+ datapos=x+y*16+z*256
+ if(ord(mapdata[datapos])!=254):
+ try:
+ pixellist.remove((x,z))
+ # Memorize information on the type and height of the block and for drawing the picture.
+ stuff[(chunkxpos+x,chunkzpos+z)]=(chunkypos+y,ord(mapdata[datapos]))
+ break
+ except:
+ print "strange block: " + xhex+zhex+"/"+yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " block: " + str(ord(mapdata[datapos]))
+
+ # After finding all the pixeld in the sector, we can move on to the next sector without having to continue the Y axis.
+ if(len(pixellist)==0):
+ break
+
+print "Drawing image"
+# Drawing the picture
+starttime = time.time()
+n = 0
+minx = min(xlist)
+minz = min(zlist)
+for (x,z) in stuff.iterkeys():
+ if n % 500000 == 0:
+ nowtime = time.time()
+ dtime = nowtime - starttime
+ n_per_second = 1.0 * n / dtime
+ if n_per_second != 0:
+ listlen = len(stuff)
+ seconds_per_n = 1.0 / n_per_second
+ time_guess = seconds_per_n * listlen
+ remaining_s = time_guess - dtime
+ remaining_minutes = int(remaining_s / 60)
+ remaining_s -= remaining_minutes * 60;
+ print("Drawing pixel "+str(n)+" of "+str(listlen)
+ +" ("+str(round(100.0*n/listlen, 1))+"%)"
+ +" (ETA: "+str(remaining_minutes)+"m "
+ +str(int(remaining_s))+"s)")
+ n += 1
+
+ (r,g,b)=colors[stuff[(x,z)][1]]
+
+ # Comparing heights of a couple of adjacent blocks and changing brightness accordingly.
+ try:
+ y1=stuff[(x-1,z)][0]
+ y2=stuff[(x,z-1)][0]
+ y=stuff[(x,z)][0]
+
+ d=(y-y1+y-y2)*12
+
+ if(d>36):
+ d=36
+
+ r=limit(r+d,0,255)
+ g=limit(g+d,0,255)
+ b=limit(b+d,0,255)
+ except:
+ pass
+ #impix[w-1-(x-minx*16),h-1-(z-minz*16)]=(r,g,b)
+ impix[x-minx*16,h-1-(z-minz*16)]=(r,g,b)
+
+# Flip the picture to make it right and save.
+#print "Transposing"
+#im=im.transpose(Image.FLIP_TOP_BOTTOM)
+print "Saving"
+im.save(output)
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/src/CMakeLists.txt b/src/CMakeLists.txt index 847269456..dfe5b5753 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -110,6 +110,7 @@ set(minetest_SRCS clouds.cpp clientobject.cpp guiMainMenu.cpp + guiKeyChangeMenu.cpp guiMessageMenu.cpp guiTextInputMenu.cpp guiInventoryMenu.cpp diff --git a/src/client.cpp b/src/client.cpp index 585fce11c..4f0baa573 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -5,7 +5,7 @@ Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or -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<v3s16> 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 @@ -931,7 +932,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) */ //m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio()); - /* Add it to mesh update queue and set it to be acknowledged after update. */ diff --git a/src/content_craft.cpp b/src/content_craft.cpp index 32d2e6d48..069e68300 100644 --- a/src/content_craft.cpp +++ b/src/content_craft.cpp @@ -261,6 +261,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]; @@ -313,6 +331,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; } @@ -353,10 +452,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 ac48a6195..7d995cb5f 100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@ -49,12 +49,20 @@ 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 @@ -83,7 +91,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 +101,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 bdc9baa2a..4c28fe3c6 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; z<MAP_BLOCKSIZE; z++) for(s16 y=0; y<MAP_BLOCKSIZE; y++) for(s16 x=0; x<MAP_BLOCKSIZE; x++) @@ -857,9 +867,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data, TileSpec ts = n.getTile(dir); AtlasPointer ap = ts.texture; material_general.setTexture(0, ap.atlas); - video::S3DVertex vertices[4] = - { + { /*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1), video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1), video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0), @@ -895,14 +904,56 @@ void mapblock_mesh_generate_special(MeshMakeData *data, vertices[i].Pos.rotateXZBy(90); } else if(j == 4) + + 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_general, vertices, 4, indices, 6); + } + } +#endif + else if(n.d == CONTENT_PAPYRUS) + { + u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_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.rotateYZBy(-90); + vertices[i].Pos.rotateXZBy(45); } - else if(j == 5) + else if(j == 1) { for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateYZBy(90); + 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++) @@ -912,11 +963,113 @@ void mapblock_mesh_generate_special(MeshMakeData *data, u16 indices[] = {0,1,2,2,3,0}; // Add to mesh collector - collector.append(material_general, vertices, 4, indices, 6); + collector.append(material_papyrus, vertices, 4, indices, 6); } } -#endif + else if(n.d == 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.d == CONTENT_RAIL) + is_rail_x[0] = true; + if(n_plus_x.d == CONTENT_RAIL) + is_rail_x[1] = true; + if(n_minus_z.d == CONTENT_RAIL) + is_rail_z[0] = true; + if(n_plus_z.d == 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 d82ccc5c9..79e10fd61 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -99,6 +99,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"); @@ -127,6 +154,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; @@ -148,6 +209,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); @@ -202,6 +275,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); @@ -233,6 +307,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 e314807f9..e53624c21 100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@ -50,6 +50,13 @@ void content_mapnode_init(); #define CONTENT_FENCE 21 #define CONTENT_MOSSYCOBBLE 22 #define CONTENT_GRAVEL 23 +#define CONTENT_SANDSTONE 24 +#define CONTENT_CACTUS 25 +#define CONTENT_BRICK 26 +#define CONTENT_CLAY 27 +#define CONTENT_PAPYRUS 28 +#define CONTENT_BOOKSHELF 29 +#define CONTENT_RAIL 30 #endif diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index cda9eb79a..cbc78ad3f 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -70,6 +70,8 @@ void set_default_settings() g_settings.setDefault("fast_move", "false"); g_settings.setDefault("invert_mouse", "false"); g_settings.setDefault("enable_farmesh", "false"); + g_settings.setDefault("farmesh_trees", "true"); + g_settings.setDefault("farmesh_distance", "40"); g_settings.setDefault("enable_clouds", "true"); g_settings.setDefault("invisible_stone", "false"); g_settings.setDefault("screenshot_path", "."); diff --git a/src/farmesh.cpp b/src/farmesh.cpp index 8f91e3a1a..2cd922434 100644 --- a/src/farmesh.cpp +++ b/src/farmesh.cpp @@ -70,6 +70,7 @@ FarMesh::FarMesh( m_box = core::aabbox3d<f32>(-BS*1000000,-BS*31000,-BS*1000000, BS*1000000,BS*31000,BS*1000000); + trees = g_settings.getBool("farmesh_trees"); } FarMesh::~FarMesh() @@ -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 faadd0fe7..d77b45da5 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -538,6 +538,43 @@ void getPointedNode(Client *client, v3f player_position, } } } + else if(n.d == CONTENT_RAIL) + { + v3s16 dir = unpackDir(n.dir); + 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<f32> box; + + box = core::aabbox3d<f32>(vertices[0]); + box.addInternalPoint(vertices[1]); + + if(distance < mindistance) + { + if(box.intersectsWithLine(shootline)) + { + nodefound = true; + nodepos = np; + neighbourpos = np; + mindistance = distance; + nodehilightbox = box; + } + } + } /* 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 diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp new file mode 100644 index 000000000..3e594aeca --- /dev/null +++ b/src/guiKeyChangeMenu.cpp @@ -0,0 +1,598 @@ +/* + Minetest-delta + Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com> + Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com> + Copyright (C) 2011 teddydestodes <derkomtur@schattengang.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (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 <string> + +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<gui::IGUIElement*> &children = getChildren(); + core::list<gui::IGUIElement*> children_copy; + for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i + != children.end(); i++) + { + children_copy.push_back(*i); + } + for (core::list<gui::IGUIElement*>::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(); Y U NO SCOPE?! + 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 <celeron55@gmail.com> + Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com> + Copyright (C) 2011 teddydestodes <derkomtur@schattengang.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (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 <string> + +static const char *KeyNames[] = + { "-", "Left Button", "Right Button", "Cancel", "Middle Button", "X Button 1", + "X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-", + "-", "Shift", "Control", "Menu", "Pause", "Capital", "Kana", "-", + "Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert", + "Accept", "Mode Change", "Space", "Priot", "Next", "End", "Home", + "Left", "Up", "Right", "Down", "Select", "Print", "Execute", + "Snapshot", "Insert", "Delete", "Help", "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C", + "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", + "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Left Windows", + "Right Windows", "Apps", "-", "Sleep", "Numpad 0", "Numpad 1", + "Numpad 2", "Numpad 3", "Numpad 4", "Numpad 5", "Numpad 6", "Numpad 7", + "Numpad 8", "Numpad 9", "Numpad *", "Numpad +", "Numpad /", "Numpad -", + "Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", + "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", + "F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-", + "-", "-", "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "Left Shift", "Right Shight", + "Left Control", "Right Control", "Left Menu", "Right Menu", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel", + "ExSel", "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" }; + enum + { + GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR, + //buttons + GUI_ID_KEY_FORWARD_BUTTON, + GUI_ID_KEY_BACKWARD_BUTTON, + GUI_ID_KEY_LEFT_BUTTON, + GUI_ID_KEY_RIGHT_BUTTON, + GUI_ID_KEY_USE_BUTTON, + GUI_ID_KEY_FLY_BUTTON, + GUI_ID_KEY_FAST_BUTTON, + GUI_ID_KEY_JUMP_BUTTON, + GUI_ID_KEY_CHAT_BUTTON, + GUI_ID_KEY_SNEAK_BUTTON, + GUI_ID_KEY_INVENTORY_BUTTON, + GUI_ID_KEY_DUMP_BUTTON, + GUI_ID_KEY_RANGE_BUTTON + }; + +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..cea32860b 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -18,10 +18,13 @@ 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 <string> + + GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, @@ -34,6 +37,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 +77,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 +114,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 @@ -175,7 +182,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> 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); } @@ -198,7 +205,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 230, 30); rect += topleft_client + v2s32(160, 100); gui::IGUIElement *e = - Environment->addEditBox(text_address.c_str(), rect, true, this, 256); + Environment->addEditBox(text_address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT); if(text_name != L"") Environment->setFocus(e); } @@ -206,7 +213,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> 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<s32> rect(0, 0, 400, 20); @@ -217,13 +224,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_client + v2s32(35, 150); - Environment->addCheckBox(fancy_trees, rect, this, 263, + Environment->addCheckBox(fancy_trees, rect, this, GUI_ID_FANCYTREE_CB, L"Fancy trees"); } { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_client + v2s32(35, 150+30); - Environment->addCheckBox(smooth_lighting, rect, this, 262, + Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB, L"Smooth Lighting"); } // Start game button @@ -231,9 +238,16 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> 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, L"Start Game / Connect"); } + // Key change button + { + core::rect<s32> 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, L"Change keys"); + } /* Server section */ @@ -254,19 +268,19 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_server + v2s32(35, 30); - Environment->addCheckBox(creative_mode, rect, this, 259, L"Creative Mode"); + Environment->addCheckBox(creative_mode, rect, this, GUI_ID_CREATIVE_CB, L"Creative Mode"); } { core::rect<s32> 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, L"Enable Damage"); } // Map delete button { core::rect<s32> 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, L"Delete map"); } } @@ -300,7 +314,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 +324,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 +391,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 +412,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/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..9c62004d8 100644 --- a/src/keycode.h +++ b/src/keycode.h @@ -21,11 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #define KEYCODE_HEADER #include "common_irrlicht.h" +#include <string> irr::EKEY_CODE keyname_to_keycode(const char *name); // Key configuration getter irr::EKEY_CODE getKeySetting(const char *settingname); +std::string keycode_to_keyname(s32 keycode); +void clearCache(); #endif diff --git a/src/map.cpp b/src/map.cpp index dc66b4d55..10e1302b1 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1241,16 +1241,24 @@ void Map::removeNodeAndUpdate(v3s16 p, /* Add neighboring liquid nodes to transform queue. + + Also add horizontal neighbors of node on top of removed node + because they could be affected of the water on top flowing + down instead of into them. */ - v3s16 dirs[6] = { + v3s16 dirs[10] = { v3s16(0,0,1), // back v3s16(0,1,0), // top + v3s16(1,1,0), // topright + v3s16(-1,1,0), // topleft + v3s16(0,1,1), // topback + v3s16(0,1,-1), // topfront v3s16(1,0,0), // right v3s16(0,0,-1), // front v3s16(0,-1,0), // bottom v3s16(-1,0,0), // left }; - for(u16 i=0; i<6; i++) + for(u16 i=0; i<10; i++) { try { @@ -1571,6 +1579,9 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) // Turn possible source into non-source u8 nonsource_c = make_liquid_flowing(n0.d); + // Counts surrounding liquid source blocks + u8 surrounding_sources = 0; + /* If not source, check that some node flows into this one and what is the level of liquid in this one @@ -1605,7 +1616,9 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) } bool n2_is_source = !content_flowing_liquid(n2.d); s8 n2_liquid_level = 8; - if(n2_is_source == false) + if(n2_is_source) + surrounding_sources++; + else n2_liquid_level = n2.param2 & 0x07; s8 new_liquid_level = -1; @@ -1619,7 +1632,20 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) } else if(n2_liquid_level > 0) { - new_liquid_level = n2_liquid_level - 1; + // If the neighbor node isn't a source and flows downwards, + // it doesn't flow into this node + if (n2_is_source) + { + new_liquid_level = n2_liquid_level - 1; + } + else + { + // Node below n2 + MapNode n3 = getNodeNoEx(p2 + v3s16(0,-1,0)); + // NOTE: collision of different liquids not yet handled here. + if (content_features(n3.d).liquid_type != LIQUID_FLOWING) + new_liquid_level = n2_liquid_level - 1; + } } if(new_liquid_level > new_liquid_level_max) @@ -1631,9 +1657,14 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) If liquid level should be something else, update it and add all the neighboring water nodes to the transform queue. */ - if(new_liquid_level_max != liquid_level) + if(new_liquid_level_max != liquid_level || (!is_source && surrounding_sources >= 2)) { - if(new_liquid_level_max == -1) + if (surrounding_sources >= 2) + { + n0.d = content_features(n0.d).liquid_alternative_source; + setNode(p0,n0); + } + else if(new_liquid_level_max == -1) { // Remove water alltoghether n0.d = CONTENT_AIR; @@ -1643,6 +1674,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) else { n0.param2 = new_liquid_level_max; + liquid_level = new_liquid_level_max; setNode(p0, n0); } @@ -1750,7 +1782,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) } else { - if(liquid_next_level > liquid_level) + if(liquid_next_level > n2_liquid_level) { n2.param2 = liquid_next_level; setNode(p2, n2); diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 4a2a39aec..dfea862a5 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<trunk_h; ii++) { @@ -97,7 +97,7 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0) // p1 is now the last piece of the trunk p1.Y -= 1; - VoxelArea leaves_a(v3s16(-2,-2,-2), v3s16(2,2,2)); + VoxelArea leaves_a(v3s16(-2,-1,-2), v3s16(2,2,2)); //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]); Buffer<u8> leaves_d(leaves_a.getVolume()); for(s32 i=0; i<leaves_a.getVolume(); i++) @@ -152,6 +152,34 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0) } } +void make_papyrus(VoxelManipulator &vmanip, v3s16 p0) +{ + MapNode papyrusnode(CONTENT_PAPYRUS); + + s16 trunk_h = myrand_range(2, 3); + v3s16 p1 = p0; + for(s16 ii=0; ii<trunk_h; ii++) + { + if(vmanip.m_area.contains(p1)) + vmanip.m_data[vmanip.m_area.index(p1)] = papyrusnode; + p1.Y++; + } +} + +void make_cactus(VoxelManipulator &vmanip, v3s16 p0) +{ + MapNode cactusnode(CONTENT_CACTUS); + + s16 trunk_h = 3; + v3s16 p1 = p0; + for(s16 ii=0; ii<trunk_h; ii++) + { + if(vmanip.m_area.contains(p1)) + vmanip.m_data[vmanip.m_area.index(p1)] = cactusnode; + p1.Y++; + } +} + #if 0 static void make_randomstone(VoxelManipulator &vmanip, v3s16 p0) { @@ -909,8 +937,8 @@ NoiseParams get_cave_noise2_params(u64 seed) NoiseParams get_ground_noise1_params(u64 seed) { - return NoiseParams(NOISE_PERLIN, seed+983240, 5, - 0.60, 100.0, 30.0); + return NoiseParams(NOISE_PERLIN, seed+983240, 4, + 0.55, 80.0, 40.0); } NoiseParams get_ground_crumbleness_params(u64 seed) @@ -945,7 +973,7 @@ bool val_is_ground(double ground_noise1_val, v3s16 p, u64 seed) double f = 0.55 + noise2d_perlin( 0.5+(float)p.X/250, 0.5+(float)p.Z/250, - seed+920381, 3, 0.5); + seed+920381, 3, 0.45); if(f < 0.01) f = 0.01; else if(f >= 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->d != CONTENT_AIR && n->d != CONTENT_IGNORE) + if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != 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->d != CONTENT_MUD && n->d != CONTENT_GRASS) - continue; + + if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS && n->d != CONTENT_SAND) + continue; + + // Papyrus grows only on mud and in water + if(n->d == CONTENT_MUD && y <= WATER_LEVEL) + { + p.Y++; + make_papyrus(vmanip, p); + } + // Trees grow only on mud and grass, on land + else if((n->d == CONTENT_MUD || n->d == CONTENT_GRASS) && y > WATER_LEVEL + 2) + { + p.Y++; + make_tree(vmanip, p); + } + // Cactii grow only on sand, on land + else if(n->d == 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 36d48fb9e..8bbd4eb79 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -150,8 +150,10 @@ struct ContentFeatures NodeMetadata *initial_metadata; // If the content is liquid, this is the flowing version of the liquid. - // If content is liquid, this is the same content. + // If content is flowing liquid, this is the same content. u8 liquid_alternative_flowing; + // If the content is liquid, this is the source version of the liquid. + u8 liquid_alternative_source; // Amount of light the node emits u8 light_source; |