forked from Mirrorlandia_minetest/minetest
commit
1c90f9fc2e
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
map/*
|
map/*
|
||||||
|
world/*
|
||||||
CMakeFiles/*
|
CMakeFiles/*
|
||||||
src/CMakeFiles/*
|
src/CMakeFiles/*
|
||||||
src/Makefile
|
src/Makefile
|
||||||
@ -17,4 +18,5 @@ Makefile
|
|||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
src/jthread/libjthread.a
|
src/jthread/libjthread.a
|
||||||
debug.txt
|
debug.txt
|
||||||
|
bin/debug.txt
|
||||||
minetestmapper/map.png
|
minetestmapper/map.png
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
map/*
|
map/*
|
||||||
|
world/*
|
||||||
CMakeFiles/*
|
CMakeFiles/*
|
||||||
src/CMakeFiles/*
|
src/CMakeFiles/*
|
||||||
src/Makefile
|
src/Makefile
|
||||||
|
@ -9,7 +9,7 @@ project(minetest)
|
|||||||
|
|
||||||
set(VERSION_MAJOR 0)
|
set(VERSION_MAJOR 0)
|
||||||
set(VERSION_MINOR 2)
|
set(VERSION_MINOR 2)
|
||||||
set(VERSION_PATCH 20110424_1_dev)
|
set(VERSION_PATCH 20110618_0_dev)
|
||||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||||
|
|
||||||
# Configuration options
|
# Configuration options
|
||||||
|
239
README.txt
Normal file
239
README.txt
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
Minetest-c55
|
||||||
|
---------------
|
||||||
|
An InfiniMiner/Minecraft inspired game.
|
||||||
|
Copyright (c) 2010-2011 Perttu Ahola <celeron55@gmail.com>
|
||||||
|
(see source files for other contributors)
|
||||||
|
|
||||||
|
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/
|
||||||
|
- doc/ directory of source distribution
|
||||||
|
|
||||||
|
This game is not finished:
|
||||||
|
--------------------------
|
||||||
|
- Don't expect it to work as well as a finished game will.
|
||||||
|
- Please report any bugs to me. debug.txt is useful.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
for i in `grep -L 'This program is free software' src/*.{h,cpp}`
|
|
||||||
do
|
|
||||||
cat licensecomment.txt > tempfile
|
|
||||||
cat $i >> tempfile
|
|
||||||
cp tempfile $i
|
|
||||||
done
|
|
||||||
rm tempfile
|
|
||||||
|
|
BIN
data/gravel.png
Normal file
BIN
data/gravel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 591 B |
BIN
data/item_fence.png
Normal file
BIN
data/item_fence.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
data/mossycobble.png
Normal file
BIN
data/mossycobble.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 965 B |
BIN
data/treeprop.png
Normal file
BIN
data/treeprop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
@ -3,7 +3,12 @@ Minetest-c55 changelog
|
|||||||
This should contain all the major changes.
|
This should contain all the major changes.
|
||||||
For minor stuff, refer to the commit log of the repository.
|
For minor stuff, refer to the commit log of the repository.
|
||||||
|
|
||||||
X:
|
2011-06-02:
|
||||||
|
- Password crash on windows fixed
|
||||||
|
- Optimized server CPU usage a lot
|
||||||
|
- Furnaces now work also while players are not near to them
|
||||||
|
|
||||||
|
2011-05-29:
|
||||||
- Optimized smooth lighting
|
- Optimized smooth lighting
|
||||||
- A number of small fixes
|
- A number of small fixes
|
||||||
- Added clouds and simple skyboxes
|
- Added clouds and simple skyboxes
|
||||||
@ -13,6 +18,10 @@ X:
|
|||||||
- Slightly updated map format
|
- Slightly updated map format
|
||||||
- Player passwords
|
- Player passwords
|
||||||
- All textures first searched from texture_path
|
- All textures first searched from texture_path
|
||||||
|
- Map directory ("map") has been renamed to "world" (just rename it to load an old world)
|
||||||
|
- Mouse inversion (invert_mouse)
|
||||||
|
- Grass doesn't grow immediately anymore
|
||||||
|
- Fence added
|
||||||
|
|
||||||
2011-04-24:
|
2011-04-24:
|
||||||
- Smooth lighting with simple ambient occlusion
|
- Smooth lighting with simple ambient occlusion
|
||||||
|
89
doc/mapformat.txt
Normal file
89
doc/mapformat.txt
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
I'll try to quickly document the newest block format in here (might contain
|
||||||
|
errors). Refer to the mapgen or minetestmapper script for the directory
|
||||||
|
structure and file naming. There are two sector namings possible,
|
||||||
|
sector/XXXXZZZZ and sector/XXX/ZZZ.
|
||||||
|
|
||||||
|
There also exists files map_meta.txt and chunk_meta, that are used by the
|
||||||
|
generator. If they are not found or invalid, the generator will currently
|
||||||
|
behave quite strangely.
|
||||||
|
|
||||||
|
The MapBlock file format (sectors2/XXX/ZZZ/YYYY):
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
NOTE: Byte order is MSB first.
|
||||||
|
|
||||||
|
u8 version
|
||||||
|
- map format version number, this one is version 17
|
||||||
|
|
||||||
|
u8 flags
|
||||||
|
- Flag bitmasks:
|
||||||
|
- 0x01: is_underground: Should be set to 0 if there will be no light
|
||||||
|
obstructions above the block. If/when sunlight of a block is updated and
|
||||||
|
there is no block above it, this value is checked for determining whether
|
||||||
|
sunlight comes from the top.
|
||||||
|
- 0x02: day_night_differs: Whether the lighting of the block is different on
|
||||||
|
day and night. Only blocks that have this bit set are updated when day
|
||||||
|
transforms to night.
|
||||||
|
- 0x04: lighting_expired: If true, lighting is invalid and should be updated.
|
||||||
|
If you can't calculate lighting in your generator properly, you could try
|
||||||
|
setting this 1 to everything and setting the uppermost block in every
|
||||||
|
sector as is_underground=0. I am quite sure it doesn't work properly,
|
||||||
|
though.
|
||||||
|
|
||||||
|
zlib-compressed map data:
|
||||||
|
- content:
|
||||||
|
u8[4096]: content types
|
||||||
|
u8[4096]: param1 values
|
||||||
|
u8[4096]: param2 values
|
||||||
|
|
||||||
|
zlib-compressed node metadata
|
||||||
|
- content:
|
||||||
|
u16 version (=1)
|
||||||
|
u16 count of metadata
|
||||||
|
foreach count:
|
||||||
|
u16 position (= p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
|
||||||
|
u16 type_id
|
||||||
|
u16 content_size
|
||||||
|
u8[content_size] misc. stuff contained in the metadata
|
||||||
|
|
||||||
|
u16 mapblockobject_count
|
||||||
|
- always write as 0.
|
||||||
|
- if read != 0, just fail.
|
||||||
|
|
||||||
|
foreach mapblockobject_count:
|
||||||
|
- deprecated, should not be used. Length of this data can only be known by
|
||||||
|
properly parsing it. Just hope not to run into any of this.
|
||||||
|
|
||||||
|
u8 static object version:
|
||||||
|
- currently 0
|
||||||
|
|
||||||
|
u16 static_object_count
|
||||||
|
|
||||||
|
foreach static_object_count:
|
||||||
|
u8 type (object type-id)
|
||||||
|
s32 pos_x * 1000
|
||||||
|
s32 pos_y * 1000
|
||||||
|
s32 pos_z * 1000
|
||||||
|
u16 data_size
|
||||||
|
u8[data_size] data
|
||||||
|
|
||||||
|
u32 timestamp
|
||||||
|
- Timestamp when last saved, as seconds from starting the game.
|
||||||
|
- 0xffffffff = invalid/unknown timestamp, nothing will be done with the time
|
||||||
|
difference when loaded (recommended)
|
||||||
|
|
||||||
|
Node metadata format:
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Sign metadata:
|
||||||
|
u16 string_len
|
||||||
|
u8[string_len] string
|
||||||
|
|
||||||
|
Furnace metadata:
|
||||||
|
TBD
|
||||||
|
|
||||||
|
Chest metadata:
|
||||||
|
TBD
|
||||||
|
|
||||||
|
// END
|
||||||
|
|
72
doc/protocol.txt
Normal file
72
doc/protocol.txt
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
Minetest-c55 protocol (incomplete, early draft):
|
||||||
|
Updated 2011-06-18
|
||||||
|
|
||||||
|
A custom protocol over UDP.
|
||||||
|
Integers are big endian.
|
||||||
|
Refer to connection.{h,cpp} for further reference.
|
||||||
|
|
||||||
|
Initialization:
|
||||||
|
- A dummy reliable packet with peer_id=PEER_ID_INEXISTENT=0 is sent to the server:
|
||||||
|
- Actually this can be sent without the reliable packet header, too, i guess,
|
||||||
|
but the sequence number in the header allows the sender to re-send the
|
||||||
|
packet without accidentally getting a double initialization.
|
||||||
|
- Packet content:
|
||||||
|
# Basic header
|
||||||
|
u32 protocol_id = PROTOCOL_ID = 0x4f457403
|
||||||
|
u16 sender_peer_id = PEER_ID_INEXISTENT = 0
|
||||||
|
u8 channel = 0
|
||||||
|
# Reliable packet header
|
||||||
|
u8 type = TYPE_RELIABLE = 3
|
||||||
|
u16 seqnum = SEQNUM_INITIAL = 65500
|
||||||
|
# Original packet header
|
||||||
|
u8 type = TYPE_ORIGINAL = 1
|
||||||
|
# And no actual payload.
|
||||||
|
- Server responds with something like this:
|
||||||
|
- Packet content:
|
||||||
|
# Basic header
|
||||||
|
u32 protocol_id = PROTOCOL_ID = 0x4f457403
|
||||||
|
u16 sender_peer_id = PEER_ID_INEXISTENT = 0
|
||||||
|
u8 channel = 0
|
||||||
|
# Reliable packet header
|
||||||
|
u8 type = TYPE_RELIABLE = 3
|
||||||
|
u16 seqnum = SEQNUM_INITIAL = 65500
|
||||||
|
# Control packet header
|
||||||
|
u8 type = TYPE_CONTROL = 0
|
||||||
|
u8 controltype = CONTROLTYPE_SET_PEER_ID = 1
|
||||||
|
u16 peer_id_new = assigned peer id to client (other than 0 or 1)
|
||||||
|
- Then the connection can be disconnected by sending:
|
||||||
|
- Packet content:
|
||||||
|
# Basic header
|
||||||
|
u32 protocol_id = PROTOCOL_ID = 0x4f457403
|
||||||
|
u16 sender_peer_id = whatever was gotten in CONTROLTYPE_SET_PEER_ID
|
||||||
|
u8 channel = 0
|
||||||
|
# Control packet header
|
||||||
|
u8 type = TYPE_CONTROL = 0
|
||||||
|
u8 controltype = CONTROLTYPE_DISCO = 2
|
||||||
|
|
||||||
|
- Here's a quick untested connect-disconnect done in PHP:
|
||||||
|
# host: ip of server (use gethostbyname(hostname) to get from a dns name)
|
||||||
|
# port: port of server
|
||||||
|
function check_if_minetestserver_up($host, $port)
|
||||||
|
{
|
||||||
|
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||||
|
$timeout = array("sec" => 1, "usec" => 0);
|
||||||
|
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout);
|
||||||
|
$buf = "\x4f\x45\x74\x03\x00\x00\x00\x03\xff\xdc\x01";
|
||||||
|
socket_sendto($socket, $buf, strlen($buf), 0, $host, $port);
|
||||||
|
$buf = socket_read($socket, 1000);
|
||||||
|
if($buf != "")
|
||||||
|
{
|
||||||
|
# We got a reply! read the peer id from it.
|
||||||
|
$peer_id = substr($buf, 9, 2);
|
||||||
|
|
||||||
|
# Disconnect
|
||||||
|
$buf = "\x4f\x45\x74\x03".$peer_id."\x00\x00\x02";
|
||||||
|
socket_sendto($socket, $buf, strlen($buf), 0, $host, $port);
|
||||||
|
socket_close($socket);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
280
genmap.py
280
genmap.py
@ -6,19 +6,42 @@ import struct
|
|||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import zlib
|
||||||
|
import array
|
||||||
from pnoise import pnoise
|
from pnoise import pnoise
|
||||||
|
|
||||||
"""
|
# Old directory format:
|
||||||
Map format:
|
# world/sectors/XXXXZZZZ/YYYY
|
||||||
map/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
|
||||||
|
#
|
||||||
|
|
||||||
XXXX,YYYY,ZZZZ = coordinates in hexadecimal
|
# Seed for generating terrain
|
||||||
|
SEED = 0
|
||||||
|
|
||||||
fffe = -2
|
# 0=old, 1=new
|
||||||
ffff = -1
|
SECTOR_DIR_FORMAT = 1
|
||||||
0000 = 0
|
|
||||||
0001 = 1
|
mapdir = "world"
|
||||||
"""
|
|
||||||
|
|
||||||
def to4h(i):
|
def to4h(i):
|
||||||
s = "";
|
s = "";
|
||||||
@ -28,64 +51,221 @@ def to4h(i):
|
|||||||
s += '{0:1x}'.format((i>>0) & 0x000f)
|
s += '{0:1x}'.format((i>>0) & 0x000f)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def getrand():
|
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)
|
i = random.randrange(0,2)
|
||||||
if i==0:
|
if i==0:
|
||||||
return 0
|
return 0
|
||||||
return 254
|
return 254
|
||||||
|
|
||||||
def writeblock(mapdir, px,py,pz, version):
|
# 3-dimensional vector (position)
|
||||||
sectordir = mapdir + "/sectors/" + to4h(px) + to4h(pz)
|
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:
|
try:
|
||||||
os.makedirs(sectordir)
|
os.makedirs(sectordir)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
path = sectordir+"/"+to4h(py)
|
||||||
|
|
||||||
|
print("writing block file "+path)
|
||||||
|
|
||||||
f = open(sectordir+"/"+to4h(py), "wb")
|
f = open(sectordir+"/"+to4h(py), "wb")
|
||||||
|
|
||||||
if version == 0:
|
if f == None:
|
||||||
# version
|
return
|
||||||
f.write(struct.pack('B', 0))
|
|
||||||
# is_underground
|
# version
|
||||||
f.write(struct.pack('B', 0))
|
version = 17
|
||||||
elif version == 2:
|
f.write(struct.pack('B', version))
|
||||||
# version
|
|
||||||
f.write(struct.pack('B', 2))
|
# flags
|
||||||
# is_underground
|
# 0x01=is_undg, 0x02=dn_diff, 0x04=lighting_expired
|
||||||
f.write(struct.pack('B', 0))
|
flags = 0 + 0x02 + 0x04
|
||||||
|
f.write(struct.pack('B', flags))
|
||||||
|
|
||||||
for z in range(0,16):
|
# data
|
||||||
for y in range(0,16):
|
c_obj = zlib.compressobj()
|
||||||
for x in range(0,16):
|
c_obj.compress(block.serialize_data())
|
||||||
b = 254
|
f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number
|
||||||
r = 20.0*pnoise((px*16+x)/100.,(pz*16+z)/100.,0)
|
f.write(c_obj.flush())
|
||||||
r += 5.0*pnoise((px*16+x)/25.,(pz*16+z)/25.,0)
|
|
||||||
#print("r="+str(r))
|
# node metadata
|
||||||
y1 = py*16+y
|
c_obj = zlib.compressobj()
|
||||||
if y1 <= r-3:
|
c_obj.compress(block.serialize_nodemeta())
|
||||||
b = 0 #stone
|
f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number
|
||||||
elif y1 <= r:
|
f.write(c_obj.flush())
|
||||||
b = 1 #grass
|
|
||||||
elif y1 <= 1:
|
# mapblockobject count
|
||||||
b = 9 #water
|
f.write(ser_u16(0))
|
||||||
if version == 0:
|
|
||||||
# Material content
|
# static objects
|
||||||
f.write(struct.pack('B', b))
|
f.write(block.serialize_staticobj())
|
||||||
elif version == 2:
|
|
||||||
# Material content
|
# timestamp
|
||||||
f.write(struct.pack('B', b))
|
f.write(ser_u32(0xffffffff))
|
||||||
# Brightness
|
|
||||||
f.write(struct.pack('B', 15))
|
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
mapdir = "map"
|
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
|
||||||
|
|
||||||
for z in range(-2,3):
|
# Material content
|
||||||
for y in range(-1,2):
|
block.set_content(p, b)
|
||||||
for x in range(-2,3):
|
|
||||||
print("generating block "+str(x)+","+str(y)+","+str(z))
|
# Place a sign at the center at surface level.
|
||||||
writeblock(mapdir, x,y,z, 0)
|
# 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
|
#END
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#keymap_special1 = KEY_KEY_E
|
#keymap_special1 = KEY_KEY_E
|
||||||
#keymap_print_debug_stacks = KEY_KEY_P
|
#keymap_print_debug_stacks = KEY_KEY_P
|
||||||
|
|
||||||
|
#invert_mouse = false
|
||||||
|
|
||||||
# The desired FPS
|
# The desired FPS
|
||||||
#wanted_fps = 30
|
#wanted_fps = 30
|
||||||
|
|
||||||
@ -56,6 +58,12 @@
|
|||||||
# Whether to fog out the end of the visible area
|
# Whether to fog out the end of the visible area
|
||||||
#enable_fog = true
|
#enable_fog = true
|
||||||
|
|
||||||
|
# Enable/disable clouds
|
||||||
|
#enable_clouds = true
|
||||||
|
|
||||||
|
# Experimental
|
||||||
|
#enable_farmesh = false
|
||||||
|
|
||||||
# Enable a bit lower water surface; disable for speed
|
# Enable a bit lower water surface; disable for speed
|
||||||
#new_style_water = true
|
#new_style_water = true
|
||||||
|
|
||||||
@ -90,10 +98,6 @@
|
|||||||
# Server side stuff
|
# Server side stuff
|
||||||
#
|
#
|
||||||
|
|
||||||
# Set to true to enable experimental features
|
|
||||||
# (varies from version to version, see wiki)
|
|
||||||
#enable_experimental = false
|
|
||||||
|
|
||||||
# Map directory (everything in the world is stored here)
|
# Map directory (everything in the world is stored here)
|
||||||
#map-dir = /home/palle/custom_map
|
#map-dir = /home/palle/custom_map
|
||||||
|
|
||||||
@ -102,9 +106,21 @@
|
|||||||
|
|
||||||
#enable_damage = false
|
#enable_damage = false
|
||||||
|
|
||||||
|
#default_password =
|
||||||
|
|
||||||
|
# Available privileges: build, teleport, settime, privs, shout
|
||||||
|
#default_privs = build, shout
|
||||||
|
|
||||||
# Gives some stuff to players at the beginning
|
# Gives some stuff to players at the beginning
|
||||||
#give_initial_stuff = false
|
#give_initial_stuff = false
|
||||||
|
|
||||||
|
# Set to true to enable experimental features
|
||||||
|
# (varies from version to version, see wiki)
|
||||||
|
#enable_experimental = false
|
||||||
|
|
||||||
|
# Profiler data print interval. 0 = disable.
|
||||||
|
#profiler_print_interval = 10
|
||||||
|
|
||||||
# Player and object positions are sent at intervals specified by this
|
# Player and object positions are sent at intervals specified by this
|
||||||
#objectdata_inverval = 0.2
|
#objectdata_inverval = 0.2
|
||||||
|
|
||||||
|
@ -61,6 +61,13 @@ configure_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
|
mapgen.cpp
|
||||||
|
content_inventory.cpp
|
||||||
|
content_nodemeta.cpp
|
||||||
|
content_craft.cpp
|
||||||
|
content_mapblock.cpp
|
||||||
|
content_mapnode.cpp
|
||||||
|
auth.cpp
|
||||||
collision.cpp
|
collision.cpp
|
||||||
nodemetadata.cpp
|
nodemetadata.cpp
|
||||||
serverobject.cpp
|
serverobject.cpp
|
||||||
@ -95,10 +102,11 @@ set(common_SRCS
|
|||||||
# Client sources
|
# Client sources
|
||||||
set(minetest_SRCS
|
set(minetest_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
|
mapblock_mesh.cpp
|
||||||
|
farmesh.cpp
|
||||||
keycode.cpp
|
keycode.cpp
|
||||||
clouds.cpp
|
clouds.cpp
|
||||||
clientobject.cpp
|
clientobject.cpp
|
||||||
guiFurnaceMenu.cpp
|
|
||||||
guiMainMenu.cpp
|
guiMainMenu.cpp
|
||||||
guiKeyChangeMenu.cpp
|
guiKeyChangeMenu.cpp
|
||||||
guiMessageMenu.cpp
|
guiMessageMenu.cpp
|
||||||
@ -125,6 +133,7 @@ include_directories(
|
|||||||
${CMAKE_BUILD_TYPE}
|
${CMAKE_BUILD_TYPE}
|
||||||
${PNG_INCLUDE_DIR}
|
${PNG_INCLUDE_DIR}
|
||||||
"${PROJECT_SOURCE_DIR}/jthread"
|
"${PROJECT_SOURCE_DIR}/jthread"
|
||||||
|
"${PROJECT_SOURCE_DIR}/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(EXECUTABLE_OUTPUT_PATH ../bin)
|
set(EXECUTABLE_OUTPUT_PATH ../bin)
|
||||||
@ -143,6 +152,7 @@ if(BUILD_CLIENT)
|
|||||||
${PLATFORM_LIBS}
|
${PLATFORM_LIBS}
|
||||||
${CLIENT_PLATFORM_LIBS}
|
${CLIENT_PLATFORM_LIBS}
|
||||||
jthread
|
jthread
|
||||||
|
sqlite3
|
||||||
)
|
)
|
||||||
endif(BUILD_CLIENT)
|
endif(BUILD_CLIENT)
|
||||||
|
|
||||||
@ -153,6 +163,7 @@ if(BUILD_SERVER)
|
|||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
${PLATFORM_LIBS}
|
${PLATFORM_LIBS}
|
||||||
jthread
|
jthread
|
||||||
|
sqlite3
|
||||||
)
|
)
|
||||||
endif(BUILD_SERVER)
|
endif(BUILD_SERVER)
|
||||||
|
|
||||||
@ -181,21 +192,22 @@ else()
|
|||||||
# Probably GCC
|
# Probably GCC
|
||||||
|
|
||||||
if(WARN_ALL)
|
if(WARN_ALL)
|
||||||
set(WARNING_FLAGS "-Wall")
|
set(RELEASE_WARNING_FLAGS "-Wall")
|
||||||
else()
|
else()
|
||||||
set(WARNING_FLAGS "")
|
set(RELEASE_WARNING_FLAGS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT APPLE)
|
if(NOT APPLE)
|
||||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-but-set-variable")
|
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-but-set-variable")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_OSX_ARCHITECTURES i386 CACHE STRING "do not build for 64-bit" FORCE)
|
set(CMAKE_OSX_ARCHITECTURES i386 CACHE STRING "do not build for 64-bit" FORCE)
|
||||||
set(ARCH i386)
|
set(ARCH i386)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
|
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall")
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS}")
|
||||||
|
|
||||||
if(USE_GPROF)
|
if(USE_GPROF)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
|
||||||
@ -242,5 +254,6 @@ endif(BUILD_SERVER)
|
|||||||
# Subdirectories
|
# Subdirectories
|
||||||
|
|
||||||
add_subdirectory(jthread)
|
add_subdirectory(jthread)
|
||||||
|
add_subdirectory(sqlite)
|
||||||
|
|
||||||
#end
|
#end
|
||||||
|
264
src/auth.cpp
Normal file
264
src/auth.cpp
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "auth.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <jmutexautolock.h>
|
||||||
|
//#include "main.h" // for g_settings
|
||||||
|
#include <sstream>
|
||||||
|
#include "strfnd.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
// Convert a privileges value into a human-readable string,
|
||||||
|
// with each component separated by a comma.
|
||||||
|
std::string privsToString(u64 privs)
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
if(privs & PRIV_BUILD)
|
||||||
|
os<<"build,";
|
||||||
|
if(privs & PRIV_TELEPORT)
|
||||||
|
os<<"teleport,";
|
||||||
|
if(privs & PRIV_SETTIME)
|
||||||
|
os<<"settime,";
|
||||||
|
if(privs & PRIV_PRIVS)
|
||||||
|
os<<"privs,";
|
||||||
|
if(privs & PRIV_SHOUT)
|
||||||
|
os<<"shout,";
|
||||||
|
if(os.tellp())
|
||||||
|
{
|
||||||
|
// Drop the trailing comma. (Why on earth can't
|
||||||
|
// you truncate a C++ stream anyway???)
|
||||||
|
std::string tmp = os.str();
|
||||||
|
return tmp.substr(0, tmp.length() -1);
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a comma-seperated list of privilege values into a
|
||||||
|
// privileges value. The reverse of privsToString(). Returns
|
||||||
|
// PRIV_INVALID if there is anything wrong with the input.
|
||||||
|
u64 stringToPrivs(std::string str)
|
||||||
|
{
|
||||||
|
u64 privs=0;
|
||||||
|
Strfnd f(str);
|
||||||
|
while(f.atend() == false)
|
||||||
|
{
|
||||||
|
std::string s = trim(f.next(","));
|
||||||
|
if(s == "build")
|
||||||
|
privs |= PRIV_BUILD;
|
||||||
|
else if(s == "teleport")
|
||||||
|
privs |= PRIV_TELEPORT;
|
||||||
|
else if(s == "settime")
|
||||||
|
privs |= PRIV_SETTIME;
|
||||||
|
else if(s == "privs")
|
||||||
|
privs |= PRIV_PRIVS;
|
||||||
|
else if(s == "shout")
|
||||||
|
privs |= PRIV_SHOUT;
|
||||||
|
else
|
||||||
|
return PRIV_INVALID;
|
||||||
|
}
|
||||||
|
return privs;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthManager::AuthManager(const std::string &authfilepath):
|
||||||
|
m_authfilepath(authfilepath),
|
||||||
|
m_modified(false)
|
||||||
|
{
|
||||||
|
m_mutex.Init();
|
||||||
|
|
||||||
|
try{
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: AuthManager: creating "
|
||||||
|
<<m_authfilepath<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthManager::~AuthManager()
|
||||||
|
{
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthManager::load()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
dstream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
|
||||||
|
std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
|
||||||
|
if(is.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
|
||||||
|
throw SerializationError("AuthManager::load(): Couldn't open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(is.eof() || is.good() == false)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read a line
|
||||||
|
std::string line;
|
||||||
|
std::getline(is, line, '\n');
|
||||||
|
|
||||||
|
std::istringstream iss(line);
|
||||||
|
|
||||||
|
// Read name
|
||||||
|
std::string name;
|
||||||
|
std::getline(iss, name, ':');
|
||||||
|
|
||||||
|
// Read password
|
||||||
|
std::string pwd;
|
||||||
|
std::getline(iss, pwd, ':');
|
||||||
|
|
||||||
|
// Read privileges
|
||||||
|
std::string stringprivs;
|
||||||
|
std::getline(iss, stringprivs, ':');
|
||||||
|
u64 privs = stringToPrivs(stringprivs);
|
||||||
|
|
||||||
|
// Store it
|
||||||
|
AuthData ad;
|
||||||
|
ad.pwd = pwd;
|
||||||
|
ad.privs = privs;
|
||||||
|
m_authdata[name] = ad;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthManager::save()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
dstream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
|
||||||
|
std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
|
||||||
|
if(os.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
|
||||||
|
throw SerializationError("AuthManager::save(): Couldn't open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(core::map<std::string, AuthData>::Iterator
|
||||||
|
i = m_authdata.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
std::string name = i.getNode()->getKey();
|
||||||
|
if(name == "")
|
||||||
|
continue;
|
||||||
|
AuthData ad = i.getNode()->getValue();
|
||||||
|
os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AuthManager::exists(const std::string &username)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, AuthData>::Node *n;
|
||||||
|
n = m_authdata.find(username);
|
||||||
|
if(n == NULL)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthManager::set(const std::string &username, AuthData ad)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
m_authdata[username] = ad;
|
||||||
|
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthManager::add(const std::string &username)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
m_authdata[username] = AuthData();
|
||||||
|
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AuthManager::getPassword(const std::string &username)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, AuthData>::Node *n;
|
||||||
|
n = m_authdata.find(username);
|
||||||
|
if(n == NULL)
|
||||||
|
throw AuthNotFoundException("");
|
||||||
|
|
||||||
|
return n->getValue().pwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthManager::setPassword(const std::string &username,
|
||||||
|
const std::string &password)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, AuthData>::Node *n;
|
||||||
|
n = m_authdata.find(username);
|
||||||
|
if(n == NULL)
|
||||||
|
throw AuthNotFoundException("");
|
||||||
|
|
||||||
|
AuthData ad = n->getValue();
|
||||||
|
ad.pwd = password;
|
||||||
|
n->setValue(ad);
|
||||||
|
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 AuthManager::getPrivs(const std::string &username)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, AuthData>::Node *n;
|
||||||
|
n = m_authdata.find(username);
|
||||||
|
if(n == NULL)
|
||||||
|
throw AuthNotFoundException("");
|
||||||
|
|
||||||
|
return n->getValue().privs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthManager::setPrivs(const std::string &username, u64 privs)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, AuthData>::Node *n;
|
||||||
|
n = m_authdata.find(username);
|
||||||
|
if(n == NULL)
|
||||||
|
throw AuthNotFoundException("");
|
||||||
|
|
||||||
|
AuthData ad = n->getValue();
|
||||||
|
ad.privs = privs;
|
||||||
|
n->setValue(ad);
|
||||||
|
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AuthManager::isModified()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
return m_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
101
src/auth.h
Normal file
101
src/auth.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AUTH_HEADER
|
||||||
|
#define AUTH_HEADER
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <jthread.h>
|
||||||
|
#include <jmutex.h>
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
|
// Player privileges. These form a bitmask stored in the privs field
|
||||||
|
// of the player, and define things they're allowed to do. See also
|
||||||
|
// the static methods Player::privsToString and stringToPrivs that
|
||||||
|
// convert these to human-readable form.
|
||||||
|
const u64 PRIV_BUILD = 1; // Can build - i.e. modify the world
|
||||||
|
const u64 PRIV_TELEPORT = 2; // Can teleport
|
||||||
|
const u64 PRIV_SETTIME = 4; // Can set the time
|
||||||
|
const u64 PRIV_PRIVS = 8; // Can grant and revoke privileges
|
||||||
|
const u64 PRIV_SERVER = 16; // Can manage the server (e.g. shutodwn
|
||||||
|
// ,settings)
|
||||||
|
const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all
|
||||||
|
// players
|
||||||
|
|
||||||
|
// Default privileges - these can be overriden for new players using the
|
||||||
|
// config option "default_privs" - however, this value still applies for
|
||||||
|
// players that existed before the privileges system was added.
|
||||||
|
const u64 PRIV_DEFAULT = PRIV_BUILD|PRIV_SHOUT;
|
||||||
|
const u64 PRIV_ALL = 0x7FFFFFFFFFFFFFFFULL;
|
||||||
|
const u64 PRIV_INVALID = 0x8000000000000000ULL;
|
||||||
|
|
||||||
|
// Convert a privileges value into a human-readable string,
|
||||||
|
// with each component separated by a comma.
|
||||||
|
std::string privsToString(u64 privs);
|
||||||
|
|
||||||
|
// Converts a comma-seperated list of privilege values into a
|
||||||
|
// privileges value. The reverse of privsToString(). Returns
|
||||||
|
// PRIV_INVALID if there is anything wrong with the input.
|
||||||
|
u64 stringToPrivs(std::string str);
|
||||||
|
|
||||||
|
struct AuthData
|
||||||
|
{
|
||||||
|
std::string pwd;
|
||||||
|
u64 privs;
|
||||||
|
|
||||||
|
AuthData():
|
||||||
|
privs(PRIV_DEFAULT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AuthNotFoundException : public BaseException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AuthNotFoundException(const char *s):
|
||||||
|
BaseException(s)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AuthManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AuthManager(const std::string &authfilepath);
|
||||||
|
~AuthManager();
|
||||||
|
void load();
|
||||||
|
void save();
|
||||||
|
bool exists(const std::string &username);
|
||||||
|
void set(const std::string &username, AuthData ad);
|
||||||
|
void add(const std::string &username);
|
||||||
|
std::string getPassword(const std::string &username);
|
||||||
|
void setPassword(const std::string &username,
|
||||||
|
const std::string &password);
|
||||||
|
u64 getPrivs(const std::string &username);
|
||||||
|
void setPrivs(const std::string &username, u64 privs);
|
||||||
|
bool isModified();
|
||||||
|
private:
|
||||||
|
JMutex m_mutex;
|
||||||
|
std::string m_authfilepath;
|
||||||
|
core::map<std::string, AuthData> m_authdata;
|
||||||
|
bool m_modified;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -71,9 +71,10 @@ std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_
|
|||||||
|
|
||||||
for (j = 0; (j < i + 1); j++)
|
for (j = 0; (j < i + 1); j++)
|
||||||
ret += base64_chars[char_array_4[j]];
|
ret += base64_chars[char_array_4[j]];
|
||||||
|
|
||||||
while((i++ < 3))
|
// Don't pad it with =
|
||||||
ret += '=';
|
/*while((i++ < 3))
|
||||||
|
ret += '=';*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +39,12 @@ void * MeshUpdateThread::Thread()
|
|||||||
QueuedMeshUpdate *q = m_queue_in.pop();
|
QueuedMeshUpdate *q = m_queue_in.pop();
|
||||||
if(q == NULL)
|
if(q == NULL)
|
||||||
{
|
{
|
||||||
sleep_ms(50);
|
sleep_ms(3);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopeProfiler sp(&g_profiler, "mesh make");
|
||||||
|
|
||||||
scene::SMesh *mesh_new = NULL;
|
scene::SMesh *mesh_new = NULL;
|
||||||
mesh_new = makeMapBlockMesh(q->data);
|
mesh_new = makeMapBlockMesh(q->data);
|
||||||
|
|
||||||
@ -218,12 +220,12 @@ void Client::step(float dtime)
|
|||||||
g_settings.getFloat("client_delete_unused_sectors_timeout");
|
g_settings.getFloat("client_delete_unused_sectors_timeout");
|
||||||
|
|
||||||
// Delete sector blocks
|
// Delete sector blocks
|
||||||
/*u32 num = m_env.getMap().deleteUnusedSectors
|
/*u32 num = m_env.getMap().unloadUnusedData
|
||||||
(delete_unused_sectors_timeout,
|
(delete_unused_sectors_timeout,
|
||||||
true, &deleted_blocks);*/
|
true, &deleted_blocks);*/
|
||||||
|
|
||||||
// Delete whole sectors
|
// Delete whole sectors
|
||||||
u32 num = m_env.getMap().deleteUnusedSectors
|
u32 num = m_env.getMap().unloadUnusedData
|
||||||
(delete_unused_sectors_timeout,
|
(delete_unused_sectors_timeout,
|
||||||
false, &deleted_blocks);
|
false, &deleted_blocks);
|
||||||
|
|
||||||
@ -306,8 +308,14 @@ void Client::step(float dtime)
|
|||||||
SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE);
|
SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE);
|
||||||
writeU16(&data[0], TOSERVER_INIT);
|
writeU16(&data[0], TOSERVER_INIT);
|
||||||
writeU8(&data[2], SER_FMT_VER_HIGHEST);
|
writeU8(&data[2], SER_FMT_VER_HIGHEST);
|
||||||
|
|
||||||
memset((char*)&data[3], 0, PLAYERNAME_SIZE);
|
memset((char*)&data[3], 0, PLAYERNAME_SIZE);
|
||||||
snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName());
|
snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName());
|
||||||
|
|
||||||
|
/*dstream<<"Client: password hash is \""<<m_password<<"\""
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
memset((char*)&data[23], 0, PASSWORD_SIZE);
|
||||||
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
|
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
|
||||||
|
|
||||||
// Send as unreliable
|
// Send as unreliable
|
||||||
@ -610,6 +618,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
// to be processed even if the serialisation format has
|
// to be processed even if the serialisation format has
|
||||||
// not been agreed yet, the same as TOCLIENT_INIT.
|
// not been agreed yet, the same as TOCLIENT_INIT.
|
||||||
m_access_denied = true;
|
m_access_denied = true;
|
||||||
|
m_access_denied_reason = L"Unknown";
|
||||||
|
if(datasize >= 4)
|
||||||
|
{
|
||||||
|
std::string datastring((char*)&data[2], datasize-2);
|
||||||
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
m_access_denied_reason = deSerializeWideString(is);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +795,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
|
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
|
||||||
|
/*
|
||||||
|
Add it to mesh update queue and set it to be acknowledged after update.
|
||||||
|
*/
|
||||||
addUpdateMeshTaskWithEdge(p, true);
|
addUpdateMeshTaskWithEdge(p, true);
|
||||||
}
|
}
|
||||||
else if(command == TOCLIENT_PLAYERPOS)
|
else if(command == TOCLIENT_PLAYERPOS)
|
||||||
|
@ -385,6 +385,11 @@ public:
|
|||||||
return m_access_denied;
|
return m_access_denied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::wstring accessDeniedReason()
|
||||||
|
{
|
||||||
|
return m_access_denied_reason;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Virtual methods from con::PeerHandler
|
// Virtual methods from con::PeerHandler
|
||||||
@ -440,10 +445,13 @@ private:
|
|||||||
|
|
||||||
std::string m_password;
|
std::string m_password;
|
||||||
bool m_access_denied;
|
bool m_access_denied;
|
||||||
|
std::wstring m_access_denied_reason;
|
||||||
|
|
||||||
InventoryContext m_inventory_context;
|
InventoryContext m_inventory_context;
|
||||||
|
|
||||||
Queue<ClientEvent> m_client_event_queue;
|
Queue<ClientEvent> m_client_event_queue;
|
||||||
|
|
||||||
|
friend class FarMesh;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !SERVER
|
#endif // !SERVER
|
||||||
|
@ -24,6 +24,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#define PROTOCOL_ID 0x4f457403
|
#define PROTOCOL_ID 0x4f457403
|
||||||
|
|
||||||
|
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
|
||||||
|
// base64-encoded SHA-1 (27+\0).
|
||||||
|
|
||||||
enum ToClientCommand
|
enum ToClientCommand
|
||||||
{
|
{
|
||||||
TOCLIENT_INIT = 0x10,
|
TOCLIENT_INIT = 0x10,
|
||||||
@ -154,6 +157,8 @@ enum ToClientCommand
|
|||||||
TOCLIENT_ACCESS_DENIED = 0x35,
|
TOCLIENT_ACCESS_DENIED = 0x35,
|
||||||
/*
|
/*
|
||||||
u16 command
|
u16 command
|
||||||
|
u16 reason_length
|
||||||
|
wstring reason
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ void Clouds::OnRegisterSceneNode()
|
|||||||
{
|
{
|
||||||
if(IsVisible)
|
if(IsVisible)
|
||||||
{
|
{
|
||||||
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
|
|
||||||
//SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
|
//SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
|
||||||
|
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISceneNode::OnRegisterSceneNode();
|
ISceneNode::OnRegisterSceneNode();
|
||||||
|
586
src/content_craft.cpp
Normal file
586
src/content_craft.cpp
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "content_craft.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
items: actually *items[9]
|
||||||
|
return value: allocates a new item, or returns NULL.
|
||||||
|
*/
|
||||||
|
InventoryItem *craft_get_result(InventoryItem **items)
|
||||||
|
{
|
||||||
|
// Wood
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE);
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new MaterialItem(CONTENT_WOOD, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stick
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new CraftItem("Stick", 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fence
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[5] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[6] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[8] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new MaterialItem(CONTENT_FENCE, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign
|
||||||
|
{
|
||||||
|
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_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
//return new MapBlockObjectItem("Sign");
|
||||||
|
return new MaterialItem(CONTENT_SIGN_WALL, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Torch
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_CRAFT, "lump_of_coal");
|
||||||
|
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new MaterialItem(CONTENT_TORCH, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wooden pick
|
||||||
|
{
|
||||||
|
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[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("WPick", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stone pick
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("STPick", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steel pick
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("SteelPick", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mese pick
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE);
|
||||||
|
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("MesePick", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wooden shovel
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("WShovel", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stone shovel
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("STShovel", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steel shovel
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("SteelShovel", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wooden axe
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("WAxe", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stone axe
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("STAxe", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steel axe
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("SteelAxe", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wooden sword
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("WSword", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stone sword
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("STSword", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steel sword
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new ToolItem("SteelSword", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
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_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
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_CHEST, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Furnace
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE);
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new MaterialItem(CONTENT_FURNACE, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steel block
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[6] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
specs[8] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
return new MaterialItem(CONTENT_STEEL, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void craft_set_creative_inventory(Player *player)
|
||||||
|
{
|
||||||
|
player->resetInventory();
|
||||||
|
|
||||||
|
// Give some good tools
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("MesePick", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("SteelPick", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("SteelAxe", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("SteelShovel", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Give materials
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CONTENT_IGNORE-terminated list
|
||||||
|
u8 material_items[] = {
|
||||||
|
CONTENT_TORCH,
|
||||||
|
CONTENT_COBBLE,
|
||||||
|
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,
|
||||||
|
CONTENT_CHEST,
|
||||||
|
CONTENT_FURNACE,
|
||||||
|
CONTENT_SIGN_WALL,
|
||||||
|
CONTENT_IGNORE
|
||||||
|
};
|
||||||
|
|
||||||
|
u8 *mip = material_items;
|
||||||
|
for(u16 i=0; i<PLAYER_INVENTORY_SIZE; i++)
|
||||||
|
{
|
||||||
|
if(*mip == CONTENT_IGNORE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
InventoryItem *item = new MaterialItem(*mip, 1);
|
||||||
|
player->inventory.addItem("main", item);
|
||||||
|
|
||||||
|
mip++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
||||||
|
|
||||||
|
// add torch first
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 1);
|
||||||
|
player->inventory.addItem("main", item);
|
||||||
|
|
||||||
|
// Then others
|
||||||
|
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
||||||
|
{
|
||||||
|
// Skip some materials
|
||||||
|
if(i == CONTENT_WATER || i == CONTENT_TORCH
|
||||||
|
|| i == CONTENT_COALSTONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InventoryItem *item = new MaterialItem(i, 1);
|
||||||
|
player->inventory.addItem("main", item);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*// Sign
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void craft_give_initial_stuff(Player *player)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("SteelPick", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 99);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("SteelAxe", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("SteelShovel", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_COBBLE, 99);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
/*{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_MESE, 6);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_COALSTONE, 6);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_WOOD, 6);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new CraftItem("Stick", 4);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("WPick", 32000);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("STPick", 32000);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}*/
|
||||||
|
/*// and some signs
|
||||||
|
for(u16 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
||||||
|
bool r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == true);
|
||||||
|
}*/
|
||||||
|
/*// Give some other stuff
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_TREE, 999);
|
||||||
|
bool r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == true);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -17,28 +17,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GUIFURNACEMENU_HEADER
|
#ifndef CONTENT_CRAFT_HEADER
|
||||||
#define GUIFURNACEMENU_HEADER
|
#define CONTENT_CRAFT_HEADER
|
||||||
|
|
||||||
#include "guiInventoryMenu.h"
|
class InventoryItem;
|
||||||
|
class Player;
|
||||||
|
|
||||||
class Client;
|
/*
|
||||||
|
items: actually *items[9]
|
||||||
|
return value: allocates a new item, or returns NULL.
|
||||||
|
*/
|
||||||
|
InventoryItem *craft_get_result(InventoryItem **items);
|
||||||
|
|
||||||
class GUIFurnaceMenu : public GUIInventoryMenu
|
void craft_set_creative_inventory(Player *player);
|
||||||
{
|
|
||||||
public:
|
// Called when give_initial_stuff setting is used
|
||||||
GUIFurnaceMenu(
|
void craft_give_initial_stuff(Player *player);
|
||||||
gui::IGUIEnvironment* env,
|
|
||||||
gui::IGUIElement* parent, s32 id,
|
|
||||||
IMenuManager *menumgr,
|
|
||||||
v3s16 nodepos,
|
|
||||||
Client *client
|
|
||||||
);
|
|
||||||
private:
|
|
||||||
|
|
||||||
v3s16 m_nodepos;
|
|
||||||
Client *m_client;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
108
src/content_inventory.cpp
Normal file
108
src/content_inventory.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "content_inventory.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "serverobject.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
|
||||||
|
bool item_material_is_cookable(u8 content)
|
||||||
|
{
|
||||||
|
if(content == CONTENT_TREE)
|
||||||
|
return true;
|
||||||
|
else if(content == CONTENT_COBBLE)
|
||||||
|
return true;
|
||||||
|
else if(content == CONTENT_SAND)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItem* item_material_create_cook_result(u8 content)
|
||||||
|
{
|
||||||
|
if(content == CONTENT_TREE)
|
||||||
|
return new CraftItem("lump_of_coal", 1);
|
||||||
|
else if(content == CONTENT_COBBLE)
|
||||||
|
return new MaterialItem(CONTENT_STONE, 1);
|
||||||
|
else if(content == CONTENT_SAND)
|
||||||
|
return new MaterialItem(CONTENT_GLASS, 1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
return "cloud.png"; // just something
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* item_craft_create_object(const std::string &subname,
|
||||||
|
ServerEnvironment *env, u16 id, v3f pos)
|
||||||
|
{
|
||||||
|
if(subname == "rat")
|
||||||
|
{
|
||||||
|
ServerActiveObject *obj = new RatSAO(env, id, pos);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 item_craft_get_drop_count(const std::string &subname)
|
||||||
|
{
|
||||||
|
if(subname == "rat")
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool item_craft_is_cookable(const std::string &subname)
|
||||||
|
{
|
||||||
|
if(subname == "lump_of_iron" || subname == "lump_of_clay")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
41
src/content_inventory.h
Normal file
41
src/content_inventory.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_INVENTORY_HEADER
|
||||||
|
#define CONTENT_INVENTORY_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h" // For u8, s16
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class InventoryItem;
|
||||||
|
class ServerActiveObject;
|
||||||
|
class ServerEnvironment;
|
||||||
|
|
||||||
|
bool item_material_is_cookable(u8 content);
|
||||||
|
InventoryItem* item_material_create_cook_result(u8 content);
|
||||||
|
|
||||||
|
std::string item_craft_get_image_name(const std::string &subname);
|
||||||
|
ServerActiveObject* item_craft_create_object(const std::string &subname,
|
||||||
|
ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
s16 item_craft_get_drop_count(const std::string &subname);
|
||||||
|
bool item_craft_is_cookable(const std::string &subname);
|
||||||
|
InventoryItem* item_craft_create_cook_result(const std::string &subname);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1076
src/content_mapblock.cpp
Normal file
1076
src/content_mapblock.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -17,3 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_MAPBLOCK_HEADER
|
||||||
|
#define CONTENT_MAPBLOCK_HEADER
|
||||||
|
|
||||||
|
#ifndef SERVER
|
||||||
|
#include "mapblock_mesh.h"
|
||||||
|
#include "utility.h"
|
||||||
|
void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
MeshCollector &collector);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
450
src/content_mapnode.cpp
Normal file
450
src/content_mapnode.cpp
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// For g_settings
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
#include "mapnode.h"
|
||||||
|
#include "content_nodemeta.h"
|
||||||
|
|
||||||
|
// TODO: Get rid of these and set up some attributes like toughness,
|
||||||
|
// fluffyness, and a funciton to calculate time and durability loss
|
||||||
|
// (and sound? and whatever else) from them
|
||||||
|
void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
|
||||||
|
void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
|
||||||
|
void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
|
||||||
|
|
||||||
|
void content_mapnode_init()
|
||||||
|
{
|
||||||
|
// Read some settings
|
||||||
|
bool new_style_water = g_settings.getBool("new_style_water");
|
||||||
|
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||||
|
bool invisible_stone = g_settings.getBool("invisible_stone");
|
||||||
|
|
||||||
|
u8 i;
|
||||||
|
ContentFeatures *f = NULL;
|
||||||
|
|
||||||
|
i = CONTENT_STONE;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("stone.png");
|
||||||
|
f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 1";
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
if(invisible_stone)
|
||||||
|
f->solidness = 0; // For debugging, hides regular stone
|
||||||
|
|
||||||
|
i = CONTENT_GRASS;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("mud.png^grass_side.png");
|
||||||
|
f->setTexture(0, "grass.png");
|
||||||
|
f->setTexture(1, "mud.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
|
||||||
|
setDirtLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
|
||||||
|
i = CONTENT_GRASS_FOOTSTEPS;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("mud.png^grass_side.png");
|
||||||
|
f->setTexture(0, "grass_footsteps.png");
|
||||||
|
f->setTexture(1, "mud.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
|
||||||
|
setDirtLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
|
||||||
|
i = CONTENT_MUD;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("mud.png");
|
||||||
|
f->setInventoryTextureCube("mud.png", "mud.png", "mud.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setDirtLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
|
||||||
|
i = CONTENT_SAND;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("sand.png");
|
||||||
|
f->setInventoryTextureCube("sand.png", "sand.png", "sand.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setDirtLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
|
||||||
|
i = CONTENT_GRAVEL;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("gravel.png");
|
||||||
|
f->setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
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");
|
||||||
|
f->setTexture(0, "tree_top.png");
|
||||||
|
f->setTexture(1, "tree_top.png");
|
||||||
|
f->param_type = CPT_MINERAL;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
|
||||||
|
i = CONTENT_LEAVES;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->light_propagates = true;
|
||||||
|
//f->param_type = CPT_MINERAL;
|
||||||
|
f->param_type = CPT_LIGHT;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
if(new_style_leaves)
|
||||||
|
{
|
||||||
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
|
f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f->setAllTextures("[noalpha:leaves.png");
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
|
||||||
|
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
|
||||||
|
|
||||||
|
i = CONTENT_FENCE;
|
||||||
|
f = &content_features(i);
|
||||||
|
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->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);
|
||||||
|
//f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
||||||
|
f->setAllTextures("stone.png^mineral_coal.png");
|
||||||
|
f->is_ground_content = true;
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 1.5);
|
||||||
|
|
||||||
|
i = CONTENT_WOOD;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("wood.png");
|
||||||
|
f->setInventoryTextureCube("wood.png", "wood.png", "wood.png");
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
|
||||||
|
|
||||||
|
i = CONTENT_MESE;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("mese.png");
|
||||||
|
f->setInventoryTextureCube("mese.png", "mese.png", "mese.png");
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 0.5);
|
||||||
|
|
||||||
|
i = CONTENT_CLOUD;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("cloud.png");
|
||||||
|
f->setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png");
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
|
||||||
|
i = CONTENT_AIR;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->param_type = CPT_LIGHT;
|
||||||
|
f->light_propagates = true;
|
||||||
|
f->sunlight_propagates = true;
|
||||||
|
f->solidness = 0;
|
||||||
|
f->walkable = false;
|
||||||
|
f->pointable = false;
|
||||||
|
f->diggable = false;
|
||||||
|
f->buildable_to = true;
|
||||||
|
f->air_equivalent = true;
|
||||||
|
|
||||||
|
i = CONTENT_WATER;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setInventoryTextureCube("water.png", "water.png", "water.png");
|
||||||
|
f->param_type = CPT_LIGHT;
|
||||||
|
f->light_propagates = true;
|
||||||
|
f->solidness = 0; // Drawn separately, makes no faces
|
||||||
|
f->walkable = false;
|
||||||
|
f->pointable = false;
|
||||||
|
f->diggable = false;
|
||||||
|
f->buildable_to = true;
|
||||||
|
f->liquid_type = LIQUID_FLOWING;
|
||||||
|
f->liquid_alternative_flowing = CONTENT_WATER;
|
||||||
|
|
||||||
|
i = CONTENT_WATERSOURCE;
|
||||||
|
f = &content_features(i);
|
||||||
|
//f->setInventoryTexture("water.png");
|
||||||
|
f->setInventoryTextureCube("water.png", "water.png", "water.png");
|
||||||
|
if(new_style_water)
|
||||||
|
{
|
||||||
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
|
}
|
||||||
|
else // old style
|
||||||
|
{
|
||||||
|
f->solidness = 1;
|
||||||
|
|
||||||
|
TileSpec t;
|
||||||
|
if(g_texturesource)
|
||||||
|
t.texture = g_texturesource->getTexture("water.png");
|
||||||
|
|
||||||
|
t.alpha = WATER_ALPHA;
|
||||||
|
t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||||
|
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
|
f->setAllTiles(t);
|
||||||
|
}
|
||||||
|
f->param_type = CPT_LIGHT;
|
||||||
|
f->light_propagates = true;
|
||||||
|
f->walkable = false;
|
||||||
|
f->pointable = false;
|
||||||
|
f->diggable = false;
|
||||||
|
f->buildable_to = true;
|
||||||
|
f->liquid_type = LIQUID_SOURCE;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
f->liquid_alternative_flowing = CONTENT_WATER;
|
||||||
|
|
||||||
|
i = CONTENT_TORCH;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setInventoryTexture("torch_on_floor.png");
|
||||||
|
f->param_type = CPT_LIGHT;
|
||||||
|
f->light_propagates = true;
|
||||||
|
f->sunlight_propagates = true;
|
||||||
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
|
f->walkable = false;
|
||||||
|
f->wall_mounted = true;
|
||||||
|
f->air_equivalent = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
f->light_source = LIGHT_MAX-1;
|
||||||
|
f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
|
||||||
|
|
||||||
|
i = CONTENT_SIGN_WALL;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setInventoryTexture("sign_wall.png");
|
||||||
|
f->param_type = CPT_LIGHT;
|
||||||
|
f->light_propagates = true;
|
||||||
|
f->sunlight_propagates = true;
|
||||||
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
|
f->walkable = false;
|
||||||
|
f->wall_mounted = true;
|
||||||
|
f->air_equivalent = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
if(f->initial_metadata == NULL)
|
||||||
|
f->initial_metadata = new SignNodeMetadata("Some sign");
|
||||||
|
f->digging_properties.set("", DiggingProperties(true, 0.5, 0));
|
||||||
|
|
||||||
|
i = CONTENT_CHEST;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->param_type = CPT_FACEDIR_SIMPLE;
|
||||||
|
f->setAllTextures("chest_side.png");
|
||||||
|
f->setTexture(0, "chest_top.png");
|
||||||
|
f->setTexture(1, "chest_top.png");
|
||||||
|
f->setTexture(5, "chest_front.png"); // Z-
|
||||||
|
f->setInventoryTexture("chest_top.png");
|
||||||
|
//f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
if(f->initial_metadata == NULL)
|
||||||
|
f->initial_metadata = new ChestNodeMetadata();
|
||||||
|
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
|
||||||
|
|
||||||
|
i = CONTENT_FURNACE;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->param_type = CPT_FACEDIR_SIMPLE;
|
||||||
|
f->setAllTextures("furnace_side.png");
|
||||||
|
f->setTexture(5, "furnace_front.png"); // Z-
|
||||||
|
f->setInventoryTexture("furnace_front.png");
|
||||||
|
//f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6";
|
||||||
|
if(f->initial_metadata == NULL)
|
||||||
|
f->initial_metadata = new FurnaceNodeMetadata();
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 3.0);
|
||||||
|
|
||||||
|
i = CONTENT_COBBLE;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("cobble.png");
|
||||||
|
f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
|
||||||
|
f->param_type = CPT_NONE;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 0.9);
|
||||||
|
|
||||||
|
i = CONTENT_MOSSYCOBBLE;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("mossycobble.png");
|
||||||
|
f->setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png");
|
||||||
|
f->param_type = CPT_NONE;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 0.8);
|
||||||
|
|
||||||
|
i = CONTENT_STEEL;
|
||||||
|
f = &content_features(i);
|
||||||
|
f->setAllTextures("steel_block.png");
|
||||||
|
f->setInventoryTextureCube("steel_block.png", "steel_block.png",
|
||||||
|
"steel_block.png");
|
||||||
|
f->param_type = CPT_NONE;
|
||||||
|
f->is_ground_content = true;
|
||||||
|
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||||
|
setStoneLikeDiggingProperties(f->digging_properties, 5.0);
|
||||||
|
|
||||||
|
// NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add MesePick to everything
|
||||||
|
*/
|
||||||
|
for(u16 i=0; i<256; i++)
|
||||||
|
{
|
||||||
|
content_features(i).digging_properties.set("MesePick",
|
||||||
|
DiggingProperties(true, 0.0, 65535./1337));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
|
||||||
|
{
|
||||||
|
list.set("",
|
||||||
|
DiggingProperties(true, 15.0*toughness, 0));
|
||||||
|
|
||||||
|
list.set("WPick",
|
||||||
|
DiggingProperties(true, 1.3*toughness, 65535./30.*toughness));
|
||||||
|
list.set("STPick",
|
||||||
|
DiggingProperties(true, 0.75*toughness, 65535./100.*toughness));
|
||||||
|
list.set("SteelPick",
|
||||||
|
DiggingProperties(true, 0.50*toughness, 65535./333.*toughness));
|
||||||
|
|
||||||
|
/*list.set("MesePick",
|
||||||
|
DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
|
||||||
|
{
|
||||||
|
list.set("",
|
||||||
|
DiggingProperties(true, 0.75*toughness, 0));
|
||||||
|
|
||||||
|
list.set("WShovel",
|
||||||
|
DiggingProperties(true, 0.4*toughness, 65535./50.*toughness));
|
||||||
|
list.set("STShovel",
|
||||||
|
DiggingProperties(true, 0.2*toughness, 65535./150.*toughness));
|
||||||
|
list.set("SteelShovel",
|
||||||
|
DiggingProperties(true, 0.15*toughness, 65535./400.*toughness));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
|
||||||
|
{
|
||||||
|
list.set("",
|
||||||
|
DiggingProperties(true, 3.0*toughness, 0));
|
||||||
|
|
||||||
|
list.set("WAxe",
|
||||||
|
DiggingProperties(true, 1.5*toughness, 65535./30.*toughness));
|
||||||
|
list.set("STAxe",
|
||||||
|
DiggingProperties(true, 0.75*toughness, 65535./100.*toughness));
|
||||||
|
list.set("SteelAxe",
|
||||||
|
DiggingProperties(true, 0.5*toughness, 65535./333.*toughness));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
62
src/content_mapnode.h
Normal file
62
src/content_mapnode.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_MAPNODE_HEADER
|
||||||
|
#define CONTENT_MAPNODE_HEADER
|
||||||
|
|
||||||
|
void content_mapnode_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Node content type IDs
|
||||||
|
*/
|
||||||
|
#define CONTENT_STONE 0
|
||||||
|
#define CONTENT_GRASS 1
|
||||||
|
#define CONTENT_WATER 2
|
||||||
|
#define CONTENT_TORCH 3
|
||||||
|
#define CONTENT_TREE 4
|
||||||
|
#define CONTENT_LEAVES 5
|
||||||
|
#define CONTENT_GRASS_FOOTSTEPS 6
|
||||||
|
#define CONTENT_MESE 7
|
||||||
|
#define CONTENT_MUD 8
|
||||||
|
#define CONTENT_WATERSOURCE 9
|
||||||
|
// Pretty much useless, clouds won't be drawn this way
|
||||||
|
#define CONTENT_CLOUD 10
|
||||||
|
#define CONTENT_COALSTONE 11
|
||||||
|
#define CONTENT_WOOD 12
|
||||||
|
#define CONTENT_SAND 13
|
||||||
|
#define CONTENT_SIGN_WALL 14
|
||||||
|
#define CONTENT_CHEST 15
|
||||||
|
#define CONTENT_FURNACE 16
|
||||||
|
//#define CONTENT_WORKBENCH 17
|
||||||
|
#define CONTENT_COBBLE 18
|
||||||
|
#define CONTENT_STEEL 19
|
||||||
|
#define CONTENT_GLASS 20
|
||||||
|
#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
|
||||||
|
|
321
src/content_nodemeta.cpp
Normal file
321
src/content_nodemeta.cpp
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "content_nodemeta.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
SignNodeMetadata
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
SignNodeMetadata proto_SignNodeMetadata("");
|
||||||
|
|
||||||
|
SignNodeMetadata::SignNodeMetadata(std::string text):
|
||||||
|
m_text(text)
|
||||||
|
{
|
||||||
|
NodeMetadata::registerType(typeId(), create);
|
||||||
|
}
|
||||||
|
u16 SignNodeMetadata::typeId() const
|
||||||
|
{
|
||||||
|
return CONTENT_SIGN_WALL;
|
||||||
|
}
|
||||||
|
NodeMetadata* SignNodeMetadata::create(std::istream &is)
|
||||||
|
{
|
||||||
|
std::string text = deSerializeString(is);
|
||||||
|
return new SignNodeMetadata(text);
|
||||||
|
}
|
||||||
|
NodeMetadata* SignNodeMetadata::clone()
|
||||||
|
{
|
||||||
|
return new SignNodeMetadata(m_text);
|
||||||
|
}
|
||||||
|
void SignNodeMetadata::serializeBody(std::ostream &os)
|
||||||
|
{
|
||||||
|
os<<serializeString(m_text);
|
||||||
|
}
|
||||||
|
std::string SignNodeMetadata::infoText()
|
||||||
|
{
|
||||||
|
return std::string("\"")+m_text+"\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ChestNodeMetadata
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
ChestNodeMetadata proto_ChestNodeMetadata;
|
||||||
|
|
||||||
|
ChestNodeMetadata::ChestNodeMetadata()
|
||||||
|
{
|
||||||
|
NodeMetadata::registerType(typeId(), create);
|
||||||
|
|
||||||
|
m_inventory = new Inventory();
|
||||||
|
m_inventory->addList("0", 8*4);
|
||||||
|
}
|
||||||
|
ChestNodeMetadata::~ChestNodeMetadata()
|
||||||
|
{
|
||||||
|
delete m_inventory;
|
||||||
|
}
|
||||||
|
u16 ChestNodeMetadata::typeId() const
|
||||||
|
{
|
||||||
|
return CONTENT_CHEST;
|
||||||
|
}
|
||||||
|
NodeMetadata* ChestNodeMetadata::create(std::istream &is)
|
||||||
|
{
|
||||||
|
ChestNodeMetadata *d = new ChestNodeMetadata();
|
||||||
|
d->m_inventory->deSerialize(is);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
NodeMetadata* ChestNodeMetadata::clone()
|
||||||
|
{
|
||||||
|
ChestNodeMetadata *d = new ChestNodeMetadata();
|
||||||
|
*d->m_inventory = *m_inventory;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
void ChestNodeMetadata::serializeBody(std::ostream &os)
|
||||||
|
{
|
||||||
|
m_inventory->serialize(os);
|
||||||
|
}
|
||||||
|
std::string ChestNodeMetadata::infoText()
|
||||||
|
{
|
||||||
|
return "Chest";
|
||||||
|
}
|
||||||
|
bool ChestNodeMetadata::nodeRemovalDisabled()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Disable removal if chest contains something
|
||||||
|
*/
|
||||||
|
InventoryList *list = m_inventory->getList("0");
|
||||||
|
if(list == NULL)
|
||||||
|
return false;
|
||||||
|
if(list->getUsedSlots() == 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::string ChestNodeMetadata::getInventoryDrawSpecString()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
"invsize[8,9;]"
|
||||||
|
"list[current_name;0;0,0;8,4;]"
|
||||||
|
"list[current_player;main;0,5;8,4;]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FurnaceNodeMetadata
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
FurnaceNodeMetadata proto_FurnaceNodeMetadata;
|
||||||
|
|
||||||
|
FurnaceNodeMetadata::FurnaceNodeMetadata()
|
||||||
|
{
|
||||||
|
NodeMetadata::registerType(typeId(), create);
|
||||||
|
|
||||||
|
m_inventory = new Inventory();
|
||||||
|
m_inventory->addList("fuel", 1);
|
||||||
|
m_inventory->addList("src", 1);
|
||||||
|
m_inventory->addList("dst", 4);
|
||||||
|
|
||||||
|
m_step_accumulator = 0;
|
||||||
|
m_fuel_totaltime = 0;
|
||||||
|
m_fuel_time = 0;
|
||||||
|
m_src_totaltime = 0;
|
||||||
|
m_src_time = 0;
|
||||||
|
}
|
||||||
|
FurnaceNodeMetadata::~FurnaceNodeMetadata()
|
||||||
|
{
|
||||||
|
delete m_inventory;
|
||||||
|
}
|
||||||
|
u16 FurnaceNodeMetadata::typeId() const
|
||||||
|
{
|
||||||
|
return CONTENT_FURNACE;
|
||||||
|
}
|
||||||
|
NodeMetadata* FurnaceNodeMetadata::clone()
|
||||||
|
{
|
||||||
|
FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
|
||||||
|
*d->m_inventory = *m_inventory;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
NodeMetadata* FurnaceNodeMetadata::create(std::istream &is)
|
||||||
|
{
|
||||||
|
FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
|
||||||
|
|
||||||
|
d->m_inventory->deSerialize(is);
|
||||||
|
|
||||||
|
int temp;
|
||||||
|
is>>temp;
|
||||||
|
d->m_fuel_totaltime = (float)temp/10;
|
||||||
|
is>>temp;
|
||||||
|
d->m_fuel_time = (float)temp/10;
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
void FurnaceNodeMetadata::serializeBody(std::ostream &os)
|
||||||
|
{
|
||||||
|
m_inventory->serialize(os);
|
||||||
|
os<<itos(m_fuel_totaltime*10)<<" ";
|
||||||
|
os<<itos(m_fuel_time*10)<<" ";
|
||||||
|
}
|
||||||
|
std::string FurnaceNodeMetadata::infoText()
|
||||||
|
{
|
||||||
|
//return "Furnace";
|
||||||
|
if(m_fuel_time >= m_fuel_totaltime)
|
||||||
|
{
|
||||||
|
InventoryList *src_list = m_inventory->getList("src");
|
||||||
|
assert(src_list);
|
||||||
|
InventoryItem *src_item = src_list->getItem(0);
|
||||||
|
|
||||||
|
if(src_item)
|
||||||
|
return "Furnace is out of fuel";
|
||||||
|
else
|
||||||
|
return "Furnace is inactive";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string s = "Furnace is active (";
|
||||||
|
s += itos(m_fuel_time/m_fuel_totaltime*100);
|
||||||
|
s += "%)";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void FurnaceNodeMetadata::inventoryModified()
|
||||||
|
{
|
||||||
|
dstream<<"Furnace inventory modification callback"<<std::endl;
|
||||||
|
}
|
||||||
|
bool FurnaceNodeMetadata::step(float dtime)
|
||||||
|
{
|
||||||
|
if(dtime > 60.0)
|
||||||
|
dstream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
|
||||||
|
// Update at a fixed frequency
|
||||||
|
const float interval = 2.0;
|
||||||
|
m_step_accumulator += dtime;
|
||||||
|
bool changed = false;
|
||||||
|
while(m_step_accumulator > interval)
|
||||||
|
{
|
||||||
|
m_step_accumulator -= interval;
|
||||||
|
dtime = interval;
|
||||||
|
|
||||||
|
//dstream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||||
|
|
||||||
|
InventoryList *dst_list = m_inventory->getList("dst");
|
||||||
|
assert(dst_list);
|
||||||
|
|
||||||
|
InventoryList *src_list = m_inventory->getList("src");
|
||||||
|
assert(src_list);
|
||||||
|
InventoryItem *src_item = src_list->getItem(0);
|
||||||
|
|
||||||
|
// Start only if there are free slots in dst, so that it can
|
||||||
|
// accomodate any result item
|
||||||
|
if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
|
||||||
|
{
|
||||||
|
m_src_totaltime = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_src_time = 0;
|
||||||
|
m_src_totaltime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If fuel is burning, increment the burn counters.
|
||||||
|
If item finishes cooking, move it to result.
|
||||||
|
*/
|
||||||
|
if(m_fuel_time < m_fuel_totaltime)
|
||||||
|
{
|
||||||
|
//dstream<<"Furnace is active"<<std::endl;
|
||||||
|
m_fuel_time += dtime;
|
||||||
|
m_src_time += dtime;
|
||||||
|
if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
|
||||||
|
&& src_item)
|
||||||
|
{
|
||||||
|
InventoryItem *cookresult = src_item->createCookResult();
|
||||||
|
dst_list->addItem(cookresult);
|
||||||
|
src_list->decrementMaterials(1);
|
||||||
|
m_src_time = 0;
|
||||||
|
m_src_totaltime = 0;
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If there is no source item or source item is not cookable, stop loop.
|
||||||
|
*/
|
||||||
|
if(src_item == NULL || m_src_totaltime < 0.001)
|
||||||
|
{
|
||||||
|
m_step_accumulator = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dstream<<"Furnace is out of fuel"<<std::endl;
|
||||||
|
|
||||||
|
InventoryList *fuel_list = m_inventory->getList("fuel");
|
||||||
|
assert(fuel_list);
|
||||||
|
InventoryItem *fuel_item = fuel_list->getItem(0);
|
||||||
|
|
||||||
|
if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
|
||||||
|
{
|
||||||
|
m_fuel_totaltime = 30;
|
||||||
|
m_fuel_time = 0;
|
||||||
|
fuel_list->decrementMaterials(1);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
|
||||||
|
{
|
||||||
|
m_fuel_totaltime = 30/4;
|
||||||
|
m_fuel_time = 0;
|
||||||
|
fuel_list->decrementMaterials(1);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if(ItemSpec(ITEM_CRAFT, "Stick").checkItem(fuel_item))
|
||||||
|
{
|
||||||
|
m_fuel_totaltime = 30/4/4;
|
||||||
|
m_fuel_time = 0;
|
||||||
|
fuel_list->decrementMaterials(1);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
|
||||||
|
{
|
||||||
|
m_fuel_totaltime = 40;
|
||||||
|
m_fuel_time = 0;
|
||||||
|
fuel_list->decrementMaterials(1);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//dstream<<"No fuel found"<<std::endl;
|
||||||
|
// No fuel, stop loop.
|
||||||
|
m_step_accumulator = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
"invsize[8,9;]"
|
||||||
|
"list[current_name;fuel;2,3;1,1;]"
|
||||||
|
"list[current_name;src;2,1;1,1;]"
|
||||||
|
"list[current_name;dst;5,1;2,2;]"
|
||||||
|
"list[current_player;main;0,5;8,4;]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
92
src/content_nodemeta.h
Normal file
92
src/content_nodemeta.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTENT_NODEMETA_HEADER
|
||||||
|
#define CONTENT_NODEMETA_HEADER
|
||||||
|
|
||||||
|
#include "nodemetadata.h"
|
||||||
|
|
||||||
|
class Inventory;
|
||||||
|
|
||||||
|
class SignNodeMetadata : public NodeMetadata
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SignNodeMetadata(std::string text);
|
||||||
|
//~SignNodeMetadata();
|
||||||
|
|
||||||
|
virtual u16 typeId() const;
|
||||||
|
static NodeMetadata* create(std::istream &is);
|
||||||
|
virtual NodeMetadata* clone();
|
||||||
|
virtual void serializeBody(std::ostream &os);
|
||||||
|
virtual std::string infoText();
|
||||||
|
|
||||||
|
std::string getText(){ return m_text; }
|
||||||
|
void setText(std::string t){ m_text = t; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_text;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ChestNodeMetadata : public NodeMetadata
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ChestNodeMetadata();
|
||||||
|
~ChestNodeMetadata();
|
||||||
|
|
||||||
|
virtual u16 typeId() const;
|
||||||
|
static NodeMetadata* create(std::istream &is);
|
||||||
|
virtual NodeMetadata* clone();
|
||||||
|
virtual void serializeBody(std::ostream &os);
|
||||||
|
virtual std::string infoText();
|
||||||
|
virtual Inventory* getInventory() {return m_inventory;}
|
||||||
|
virtual bool nodeRemovalDisabled();
|
||||||
|
virtual std::string getInventoryDrawSpecString();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Inventory *m_inventory;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FurnaceNodeMetadata : public NodeMetadata
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FurnaceNodeMetadata();
|
||||||
|
~FurnaceNodeMetadata();
|
||||||
|
|
||||||
|
virtual u16 typeId() const;
|
||||||
|
virtual NodeMetadata* clone();
|
||||||
|
static NodeMetadata* create(std::istream &is);
|
||||||
|
virtual void serializeBody(std::ostream &os);
|
||||||
|
virtual std::string infoText();
|
||||||
|
virtual Inventory* getInventory() {return m_inventory;}
|
||||||
|
virtual void inventoryModified();
|
||||||
|
virtual bool step(float dtime);
|
||||||
|
virtual std::string getInventoryDrawSpecString();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Inventory *m_inventory;
|
||||||
|
float m_step_accumulator;
|
||||||
|
float m_fuel_totaltime;
|
||||||
|
float m_fuel_time;
|
||||||
|
float m_src_totaltime;
|
||||||
|
float m_src_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -49,7 +49,7 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("wanted_fps", "30");
|
g_settings.setDefault("wanted_fps", "30");
|
||||||
g_settings.setDefault("fps_max", "60");
|
g_settings.setDefault("fps_max", "60");
|
||||||
g_settings.setDefault("viewing_range_nodes_max", "300");
|
g_settings.setDefault("viewing_range_nodes_max", "300");
|
||||||
g_settings.setDefault("viewing_range_nodes_min", "35");
|
g_settings.setDefault("viewing_range_nodes_min", "25");
|
||||||
g_settings.setDefault("screenW", "800");
|
g_settings.setDefault("screenW", "800");
|
||||||
g_settings.setDefault("screenH", "600");
|
g_settings.setDefault("screenH", "600");
|
||||||
g_settings.setDefault("address", "");
|
g_settings.setDefault("address", "");
|
||||||
@ -63,22 +63,28 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("enable_texture_atlas", "true");
|
g_settings.setDefault("enable_texture_atlas", "true");
|
||||||
g_settings.setDefault("texture_path", "");
|
g_settings.setDefault("texture_path", "");
|
||||||
g_settings.setDefault("video_driver", "opengl");
|
g_settings.setDefault("video_driver", "opengl");
|
||||||
|
|
||||||
g_settings.setDefault("free_move", "false");
|
g_settings.setDefault("free_move", "false");
|
||||||
g_settings.setDefault("continuous_forward", "false");
|
g_settings.setDefault("continuous_forward", "false");
|
||||||
g_settings.setDefault("fast_move", "false");
|
g_settings.setDefault("fast_move", "false");
|
||||||
|
g_settings.setDefault("invert_mouse", "false");
|
||||||
|
g_settings.setDefault("enable_farmesh", "false");
|
||||||
|
g_settings.setDefault("enable_clouds", "true");
|
||||||
|
g_settings.setDefault("invisible_stone", "false");
|
||||||
|
|
||||||
// Server stuff
|
// Server stuff
|
||||||
g_settings.setDefault("enable_experimental", "false");
|
g_settings.setDefault("enable_experimental", "false");
|
||||||
g_settings.setDefault("creative_mode", "false");
|
g_settings.setDefault("creative_mode", "false");
|
||||||
g_settings.setDefault("enable_damage", "false"); //TODO: Set to true
|
g_settings.setDefault("enable_damage", "false"); //TODO: Set to true when healing is possible
|
||||||
g_settings.setDefault("give_initial_stuff", "false");
|
g_settings.setDefault("give_initial_stuff", "false");
|
||||||
|
g_settings.setDefault("default_password", "");
|
||||||
|
g_settings.setDefault("default_privs", "build, shout");
|
||||||
|
g_settings.setDefault("profiler_print_interval", "0");
|
||||||
|
|
||||||
g_settings.setDefault("objectdata_interval", "0.2");
|
g_settings.setDefault("objectdata_interval", "0.2");
|
||||||
g_settings.setDefault("active_object_range", "2");
|
g_settings.setDefault("active_object_range", "2");
|
||||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
|
g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||||
g_settings.setDefault("max_block_send_distance", "8");
|
g_settings.setDefault("max_block_send_distance", "8");
|
||||||
g_settings.setDefault("max_block_generate_distance", "8");
|
g_settings.setDefault("max_block_generate_distance", "8");
|
||||||
g_settings.setDefault("time_send_interval", "20");
|
g_settings.setDefault("time_send_interval", "20");
|
||||||
@ -86,5 +92,6 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
|
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
|
||||||
g_settings.setDefault("server_map_save_interval", "60");
|
g_settings.setDefault("server_map_save_interval", "60");
|
||||||
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||||
|
//g_settings.setDefault("dungeon_rarity", "0.025");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
|
||||||
|
|
||||||
Environment::Environment():
|
Environment::Environment():
|
||||||
@ -426,7 +427,14 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
|||||||
testplayer.deSerialize(is);
|
testplayer.deSerialize(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
dstream<<"Loaded test player with name "<<testplayer.getName()<<std::endl;
|
if(!string_allowed(testplayer.getName(), PLAYERNAME_ALLOWED_CHARS))
|
||||||
|
{
|
||||||
|
dstream<<"Not loading player with invalid name: "
|
||||||
|
<<testplayer.getName()<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"Loaded test player with name "<<testplayer.getName()
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
// Search for the player
|
// Search for the player
|
||||||
std::string playername = testplayer.getName();
|
std::string playername = testplayer.getName();
|
||||||
@ -571,6 +579,66 @@ void spawnRandomObjects(MapBlock *block)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
||||||
|
{
|
||||||
|
// Get time difference
|
||||||
|
u32 dtime_s = 0;
|
||||||
|
u32 stamp = block->getTimestamp();
|
||||||
|
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
|
||||||
|
dtime_s = m_game_time - block->getTimestamp();
|
||||||
|
dtime_s += additional_dtime;
|
||||||
|
|
||||||
|
// Set current time as timestamp (and let it set ChangedFlag)
|
||||||
|
block->setTimestamp(m_game_time);
|
||||||
|
|
||||||
|
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
||||||
|
|
||||||
|
// Activate stored objects
|
||||||
|
activateObjects(block);
|
||||||
|
|
||||||
|
// Run node metadata
|
||||||
|
bool changed = block->m_node_metadata.step((float)dtime_s);
|
||||||
|
if(changed)
|
||||||
|
{
|
||||||
|
MapEditEvent event;
|
||||||
|
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||||
|
event.p = block->getPos();
|
||||||
|
m_map->dispatchEvent(&event);
|
||||||
|
|
||||||
|
block->setChangedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Do something
|
||||||
|
// TODO: Implement usage of ActiveBlockModifier
|
||||||
|
|
||||||
|
// Here's a quick demonstration
|
||||||
|
v3s16 p0;
|
||||||
|
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||||
|
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
||||||
|
for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
|
||||||
|
{
|
||||||
|
v3s16 p = p0 + block->getPosRelative();
|
||||||
|
MapNode n = block->getNodeNoEx(p0);
|
||||||
|
#if 1
|
||||||
|
// Test something:
|
||||||
|
// Convert all mud under proper day lighting to grass
|
||||||
|
if(n.d == CONTENT_MUD)
|
||||||
|
{
|
||||||
|
if(dtime_s > 300)
|
||||||
|
{
|
||||||
|
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||||
|
if(content_features(n_top.d).air_equivalent &&
|
||||||
|
n_top.getLight(LIGHTBANK_DAY) >= 13)
|
||||||
|
{
|
||||||
|
n.d = CONTENT_GRASS;
|
||||||
|
m_map->addNodeWithEvent(p, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServerEnvironment::step(float dtime)
|
void ServerEnvironment::step(float dtime)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
@ -686,8 +754,8 @@ void ServerEnvironment::step(float dtime)
|
|||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
if(block==NULL)
|
if(block==NULL)
|
||||||
continue;
|
continue;
|
||||||
|
// Set current time as timestamp (and let it set ChangedFlag)
|
||||||
// Set current time as timestamp
|
|
||||||
block->setTimestamp(m_game_time);
|
block->setTimestamp(m_game_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,23 +775,36 @@ void ServerEnvironment::step(float dtime)
|
|||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
if(block==NULL)
|
if(block==NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get time difference
|
// Get time difference
|
||||||
u32 dtime_s = 0;
|
u32 dtime_s = 0;
|
||||||
u32 stamp = block->getTimestamp();
|
u32 stamp = block->getTimestamp();
|
||||||
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
|
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
|
||||||
dtime_s = m_game_time - block->getTimestamp();
|
dtime_s = m_game_time - block->getTimestamp();
|
||||||
|
|
||||||
// Set current time as timestamp
|
// Set current time as timestamp (and let it set ChangedFlag)
|
||||||
block->setTimestamp(m_game_time);
|
block->setTimestamp(m_game_time);
|
||||||
|
|
||||||
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
||||||
|
|
||||||
// Activate stored objects
|
// Activate stored objects
|
||||||
activateObjects(block);
|
activateObjects(block);
|
||||||
|
|
||||||
|
// Run node metadata
|
||||||
|
bool changed = block->m_node_metadata.step((float)dtime_s);
|
||||||
|
if(changed)
|
||||||
|
{
|
||||||
|
MapEditEvent event;
|
||||||
|
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||||
|
event.p = p;
|
||||||
|
m_map->dispatchEvent(&event);
|
||||||
|
|
||||||
|
block->setChangedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Do something
|
// TODO: Do something
|
||||||
|
// TODO: Implement usage of ActiveBlockModifier
|
||||||
|
|
||||||
// Here's a quick demonstration
|
// Here's a quick demonstration
|
||||||
v3s16 p0;
|
v3s16 p0;
|
||||||
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||||
@ -736,7 +817,7 @@ void ServerEnvironment::step(float dtime)
|
|||||||
// Convert all mud under proper day lighting to grass
|
// Convert all mud under proper day lighting to grass
|
||||||
if(n.d == CONTENT_MUD)
|
if(n.d == CONTENT_MUD)
|
||||||
{
|
{
|
||||||
if(1)
|
if(dtime_s > 300)
|
||||||
{
|
{
|
||||||
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||||
if(content_features(n_top.d).air_equivalent &&
|
if(content_features(n_top.d).air_equivalent &&
|
||||||
@ -747,6 +828,22 @@ void ServerEnvironment::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Convert grass into mud if under something else than air
|
||||||
|
*/
|
||||||
|
else if(n.d == CONTENT_GRASS)
|
||||||
|
{
|
||||||
|
//if(myrand()%20 == 0)
|
||||||
|
{
|
||||||
|
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||||
|
if(n_top.d != CONTENT_AIR
|
||||||
|
&& n_top.d != CONTENT_IGNORE)
|
||||||
|
{
|
||||||
|
n.d = CONTENT_MUD;
|
||||||
|
m_map->addNodeWithEvent(p, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -754,8 +851,10 @@ void ServerEnvironment::step(float dtime)
|
|||||||
/*
|
/*
|
||||||
Mess around in active blocks
|
Mess around in active blocks
|
||||||
*/
|
*/
|
||||||
if(m_active_blocks_test_interval.step(dtime, 5.0))
|
if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
|
||||||
{
|
{
|
||||||
|
float dtime = 1.0;
|
||||||
|
|
||||||
for(core::map<v3s16, bool>::Iterator
|
for(core::map<v3s16, bool>::Iterator
|
||||||
i = m_active_blocks.m_list.getIterator();
|
i = m_active_blocks.m_list.getIterator();
|
||||||
i.atEnd()==false; i++)
|
i.atEnd()==false; i++)
|
||||||
@ -770,8 +869,41 @@ void ServerEnvironment::step(float dtime)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Set current time as timestamp
|
// Set current time as timestamp
|
||||||
block->setTimestamp(m_game_time);
|
block->setTimestampNoChangedFlag(m_game_time);
|
||||||
|
|
||||||
|
// Run node metadata
|
||||||
|
bool changed = block->m_node_metadata.step(dtime);
|
||||||
|
if(changed)
|
||||||
|
{
|
||||||
|
MapEditEvent event;
|
||||||
|
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||||
|
event.p = p;
|
||||||
|
m_map->dispatchEvent(&event);
|
||||||
|
|
||||||
|
block->setChangedFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m_active_blocks_test_interval.step(dtime, 10.0))
|
||||||
|
{
|
||||||
|
//float dtime = 10.0;
|
||||||
|
|
||||||
|
for(core::map<v3s16, bool>::Iterator
|
||||||
|
i = m_active_blocks.m_list.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
v3s16 p = i.getNode()->getKey();
|
||||||
|
|
||||||
|
/*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||||
|
<<") being handled"<<std::endl;*/
|
||||||
|
|
||||||
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
|
if(block==NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Set current time as timestamp
|
||||||
|
block->setTimestampNoChangedFlag(m_game_time);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do stuff!
|
Do stuff!
|
||||||
|
|
||||||
@ -784,6 +916,7 @@ void ServerEnvironment::step(float dtime)
|
|||||||
Everything should bind to inside this single content
|
Everything should bind to inside this single content
|
||||||
searching loop to keep things fast.
|
searching loop to keep things fast.
|
||||||
*/
|
*/
|
||||||
|
// TODO: Implement usage of ActiveBlockModifier
|
||||||
|
|
||||||
v3s16 p0;
|
v3s16 p0;
|
||||||
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||||
@ -792,11 +925,14 @@ void ServerEnvironment::step(float dtime)
|
|||||||
{
|
{
|
||||||
v3s16 p = p0 + block->getPosRelative();
|
v3s16 p = p0 + block->getPosRelative();
|
||||||
MapNode n = block->getNodeNoEx(p0);
|
MapNode n = block->getNodeNoEx(p0);
|
||||||
// Test something:
|
|
||||||
// Convert mud under proper lighting to grass
|
/*
|
||||||
|
Test something:
|
||||||
|
Convert mud under proper lighting to grass
|
||||||
|
*/
|
||||||
if(n.d == CONTENT_MUD)
|
if(n.d == CONTENT_MUD)
|
||||||
{
|
{
|
||||||
if(myrand()%10 == 0)
|
if(myrand()%20 == 0)
|
||||||
{
|
{
|
||||||
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||||
if(content_features(n_top.d).air_equivalent &&
|
if(content_features(n_top.d).air_equivalent &&
|
||||||
@ -807,6 +943,22 @@ void ServerEnvironment::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Convert grass into mud if under something else than air
|
||||||
|
*/
|
||||||
|
else if(n.d == CONTENT_GRASS)
|
||||||
|
{
|
||||||
|
//if(myrand()%20 == 0)
|
||||||
|
{
|
||||||
|
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||||
|
if(n_top.d != CONTENT_AIR
|
||||||
|
&& n_top.d != CONTENT_IGNORE)
|
||||||
|
{
|
||||||
|
n.d = CONTENT_MUD;
|
||||||
|
m_map->addNodeWithEvent(p, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -941,49 +1093,8 @@ u16 getFreeServerActiveObjectId(
|
|||||||
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
||||||
{
|
{
|
||||||
assert(object);
|
assert(object);
|
||||||
if(object->getId() == 0)
|
u16 id = addActiveObjectRaw(object, true);
|
||||||
{
|
return id;
|
||||||
u16 new_id = getFreeServerActiveObjectId(m_active_objects);
|
|
||||||
if(new_id == 0)
|
|
||||||
{
|
|
||||||
dstream<<"WARNING: ServerEnvironment::addActiveObject(): "
|
|
||||||
<<"no free ids available"<<std::endl;
|
|
||||||
delete object;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
object->setId(new_id);
|
|
||||||
}
|
|
||||||
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
|
||||||
{
|
|
||||||
dstream<<"WARNING: ServerEnvironment::addActiveObject(): "
|
|
||||||
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
|
||||||
delete object;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*dstream<<"INGO: ServerEnvironment::addActiveObject(): "
|
|
||||||
<<"added (id="<<object->getId()<<")"<<std::endl;*/
|
|
||||||
|
|
||||||
m_active_objects.insert(object->getId(), object);
|
|
||||||
|
|
||||||
// Add static object to active static list of the block
|
|
||||||
v3f objectpos = object->getBasePosition();
|
|
||||||
std::string staticdata = object->getStaticData();
|
|
||||||
StaticObject s_obj(object->getType(), objectpos, staticdata);
|
|
||||||
// Add to the block where the object is located in
|
|
||||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
|
||||||
if(block)
|
|
||||||
{
|
|
||||||
block->m_static_objects.m_active.insert(object->getId(), s_obj);
|
|
||||||
object->m_static_exists = true;
|
|
||||||
object->m_static_block = blockpos;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
dstream<<"WARNING: Server: Could not find a block for "
|
|
||||||
<<"storing newly added static active object"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return object->getId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1086,6 +1197,58 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
|
|||||||
************ Private methods *************
|
************ Private methods *************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
|
bool set_changed)
|
||||||
|
{
|
||||||
|
assert(object);
|
||||||
|
if(object->getId() == 0)
|
||||||
|
{
|
||||||
|
u16 new_id = getFreeServerActiveObjectId(m_active_objects);
|
||||||
|
if(new_id == 0)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): "
|
||||||
|
<<"no free ids available"<<std::endl;
|
||||||
|
delete object;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
object->setId(new_id);
|
||||||
|
}
|
||||||
|
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): "
|
||||||
|
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||||
|
delete object;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*dstream<<"INGO: ServerEnvironment::addActiveObjectRaw(): "
|
||||||
|
<<"added (id="<<object->getId()<<")"<<std::endl;*/
|
||||||
|
|
||||||
|
m_active_objects.insert(object->getId(), object);
|
||||||
|
|
||||||
|
// Add static object to active static list of the block
|
||||||
|
v3f objectpos = object->getBasePosition();
|
||||||
|
std::string staticdata = object->getStaticData();
|
||||||
|
StaticObject s_obj(object->getType(), objectpos, staticdata);
|
||||||
|
// Add to the block where the object is located in
|
||||||
|
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||||
|
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block)
|
||||||
|
{
|
||||||
|
block->m_static_objects.m_active.insert(object->getId(), s_obj);
|
||||||
|
object->m_static_exists = true;
|
||||||
|
object->m_static_block = blockpos;
|
||||||
|
|
||||||
|
if(set_changed)
|
||||||
|
block->setChangedFlag();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
dstream<<"WARNING: Server: Could not find a block for "
|
||||||
|
<<"storing newly added static active object"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return object->getId();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
||||||
*/
|
*/
|
||||||
@ -1176,8 +1339,8 @@ void ServerEnvironment::activateObjects(MapBlock *block)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// This will also add the object to the active static list
|
// This will also add the object to the active static list
|
||||||
addActiveObject(obj);
|
addActiveObjectRaw(obj, false);
|
||||||
//u16 id = addActiveObject(obj);
|
//u16 id = addActiveObjectRaw(obj, false);
|
||||||
}
|
}
|
||||||
// Clear stored list
|
// Clear stored list
|
||||||
block->m_static_objects.m_stored.clear();
|
block->m_static_objects.m_stored.clear();
|
||||||
@ -1190,7 +1353,8 @@ void ServerEnvironment::activateObjects(MapBlock *block)
|
|||||||
block->m_static_objects.m_stored.push_back(s_obj);
|
block->m_static_objects.m_stored.push_back(s_obj);
|
||||||
}
|
}
|
||||||
// Block has been modified
|
// Block has been modified
|
||||||
block->setChangedFlag();
|
// NOTE: No it has not really. Save I/O here.
|
||||||
|
//block->setChangedFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -112,25 +112,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Active block modifier interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ServerEnvironment;
|
|
||||||
|
|
||||||
class ActiveBlockModifier
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ActiveBlockModifier(){};
|
|
||||||
virtual ~ActiveBlockModifier(){};
|
|
||||||
|
|
||||||
virtual u32 getTriggerContentCount(){ return 1;}
|
|
||||||
virtual u8 getTriggerContent(u32 i) = 0;
|
|
||||||
virtual float getActiveInterval() = 0;
|
|
||||||
virtual u32 getActiveChance() = 0;
|
|
||||||
virtual void triggerEvent(ServerEnvironment *env, v3s16 p) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The server-side environment.
|
The server-side environment.
|
||||||
|
|
||||||
@ -140,6 +121,7 @@ public:
|
|||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
|
class ActiveBlockModifier;
|
||||||
|
|
||||||
class ServerEnvironment : public Environment
|
class ServerEnvironment : public Environment
|
||||||
{
|
{
|
||||||
@ -177,7 +159,8 @@ public:
|
|||||||
void loadMeta(const std::string &savedir);
|
void loadMeta(const std::string &savedir);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ActiveObjects
|
External ActiveObject interface
|
||||||
|
-------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ServerActiveObject* getActiveObject(u16 id);
|
ServerActiveObject* getActiveObject(u16 id);
|
||||||
@ -214,7 +197,38 @@ public:
|
|||||||
*/
|
*/
|
||||||
ActiveObjectMessage getActiveObjectMessage();
|
ActiveObjectMessage getActiveObjectMessage();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Activate objects and dynamically modify for the dtime determined
|
||||||
|
from timestamp and additional_dtime
|
||||||
|
*/
|
||||||
|
void activateBlock(MapBlock *block, u32 additional_dtime=0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
ActiveBlockModifiers (TODO)
|
||||||
|
-------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void addActiveBlockModifier(ActiveBlockModifier *abm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internal ActiveObject interface
|
||||||
|
-------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add an active object to the environment.
|
||||||
|
|
||||||
|
Called by addActiveObject.
|
||||||
|
|
||||||
|
Object may be deleted by environment immediately.
|
||||||
|
If id of object is 0, assigns a free id to it.
|
||||||
|
Returns the id of the object.
|
||||||
|
Returns 0 if not added and thus deleted.
|
||||||
|
*/
|
||||||
|
u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remove all objects that satisfy (m_removed && m_known_by_count==0)
|
Remove all objects that satisfy (m_removed && m_known_by_count==0)
|
||||||
*/
|
*/
|
||||||
@ -256,6 +270,7 @@ private:
|
|||||||
ActiveBlockList m_active_blocks;
|
ActiveBlockList m_active_blocks;
|
||||||
IntervalLimiter m_active_blocks_management_interval;
|
IntervalLimiter m_active_blocks_management_interval;
|
||||||
IntervalLimiter m_active_blocks_test_interval;
|
IntervalLimiter m_active_blocks_test_interval;
|
||||||
|
IntervalLimiter m_active_blocks_nodemetadata_interval;
|
||||||
// Time from the beginning of the game in seconds.
|
// Time from the beginning of the game in seconds.
|
||||||
// Incremented in step().
|
// Incremented in step().
|
||||||
u32 m_game_time;
|
u32 m_game_time;
|
||||||
@ -263,6 +278,29 @@ private:
|
|||||||
float m_game_time_fraction_counter;
|
float m_game_time_fraction_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Active block modifier interface.
|
||||||
|
|
||||||
|
These are fed into ServerEnvironment at initialization time;
|
||||||
|
ServerEnvironment handles deleting them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ActiveBlockModifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActiveBlockModifier(){};
|
||||||
|
virtual ~ActiveBlockModifier(){};
|
||||||
|
|
||||||
|
//virtual core::list<u8> update(ServerEnvironment *env) = 0;
|
||||||
|
virtual u32 getTriggerContentCount(){ return 1;}
|
||||||
|
virtual u8 getTriggerContent(u32 i) = 0;
|
||||||
|
virtual float getActiveInterval() = 0;
|
||||||
|
// chance of (1 / return value), 0 is disallowed
|
||||||
|
virtual u32 getActiveChance() = 0;
|
||||||
|
// This is called usually at interval for 1/chance of the nodes
|
||||||
|
virtual void triggerEvent(ServerEnvironment *env, v3s16 p) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
|
||||||
#include "clientobject.h"
|
#include "clientobject.h"
|
||||||
|
413
src/farmesh.cpp
Normal file
413
src/farmesh.cpp
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
Part of Minetest-c55
|
||||||
|
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
A quick messy implementation of terrain rendering for a long
|
||||||
|
distance according to map seed
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "farmesh.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "noise.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
#include "mapgen.h"
|
||||||
|
|
||||||
|
FarMesh::FarMesh(
|
||||||
|
scene::ISceneNode* parent,
|
||||||
|
scene::ISceneManager* mgr,
|
||||||
|
s32 id,
|
||||||
|
u64 seed,
|
||||||
|
Client *client
|
||||||
|
):
|
||||||
|
scene::ISceneNode(parent, mgr, id),
|
||||||
|
m_seed(seed),
|
||||||
|
m_camera_pos(0,0),
|
||||||
|
m_time(0),
|
||||||
|
m_client(client),
|
||||||
|
m_render_range(20*MAP_BLOCKSIZE)
|
||||||
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = mgr->getVideoDriver();
|
||||||
|
|
||||||
|
m_materials[0].setFlag(video::EMF_LIGHTING, false);
|
||||||
|
m_materials[0].setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||||
|
//m_materials[0].setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
m_materials[0].setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
m_materials[0].setFlag(video::EMF_FOG_ENABLE, false);
|
||||||
|
//m_materials[0].setFlag(video::EMF_ANTI_ALIASING, true);
|
||||||
|
//m_materials[0].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
|
m_materials[0].setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
|
||||||
|
m_materials[1].setFlag(video::EMF_LIGHTING, false);
|
||||||
|
m_materials[1].setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
m_materials[1].setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
m_materials[1].setFlag(video::EMF_FOG_ENABLE, false);
|
||||||
|
m_materials[1].setTexture
|
||||||
|
(0, driver->getTexture(getTexturePath("treeprop.png").c_str()));
|
||||||
|
m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
m_materials[1].setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
|
||||||
|
m_box = core::aabbox3d<f32>(-BS*1000000,-BS*31000,-BS*1000000,
|
||||||
|
BS*1000000,BS*31000,BS*1000000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FarMesh::~FarMesh()
|
||||||
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 FarMesh::getMaterialCount() const
|
||||||
|
{
|
||||||
|
return FARMESH_MATERIAL_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::SMaterial& FarMesh::getMaterial(u32 i)
|
||||||
|
{
|
||||||
|
return m_materials[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FarMesh::OnRegisterSceneNode()
|
||||||
|
{
|
||||||
|
if(IsVisible)
|
||||||
|
{
|
||||||
|
//SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
|
||||||
|
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
|
||||||
|
//SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISceneNode::OnRegisterSceneNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MYROUND(x) (x > 0.0 ? (int)x : (int)x - 1)
|
||||||
|
|
||||||
|
// Temporary hack
|
||||||
|
struct HeightPoint
|
||||||
|
{
|
||||||
|
float gh; // ground height
|
||||||
|
float ma; // mud amount
|
||||||
|
float have_sand;
|
||||||
|
float tree_amount;
|
||||||
|
};
|
||||||
|
core::map<v2s16, HeightPoint> g_heights;
|
||||||
|
|
||||||
|
HeightPoint ground_height(u64 seed, v2s16 p2d)
|
||||||
|
{
|
||||||
|
core::map<v2s16, HeightPoint>::Node *n = g_heights.find(p2d);
|
||||||
|
if(n)
|
||||||
|
return n->getValue();
|
||||||
|
HeightPoint hp;
|
||||||
|
s16 level = mapgen::find_ground_level_from_noise(seed, p2d, 3);
|
||||||
|
hp.gh = (level-4)*BS;
|
||||||
|
hp.ma = (4)*BS;
|
||||||
|
/*hp.gh = BS*base_rock_level_2d(seed, p2d);
|
||||||
|
hp.ma = BS*get_mud_add_amount(seed, p2d);*/
|
||||||
|
hp.have_sand = mapgen::get_have_sand(seed, p2d);
|
||||||
|
if(hp.gh > BS*WATER_LEVEL)
|
||||||
|
hp.tree_amount = mapgen::tree_amount_2d(seed, p2d);
|
||||||
|
else
|
||||||
|
hp.tree_amount = 0;
|
||||||
|
// No mud has been added if mud amount is less than 1
|
||||||
|
if(hp.ma < 1.0*BS)
|
||||||
|
hp.ma = 0.0;
|
||||||
|
//hp.gh -= BS*3; // Lower a bit so that it is not that much in the way
|
||||||
|
g_heights[p2d] = hp;
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FarMesh::render()
|
||||||
|
{
|
||||||
|
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||||
|
|
||||||
|
/*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
|
||||||
|
return;*/
|
||||||
|
if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
|
||||||
|
return;
|
||||||
|
/*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SKY_BOX)
|
||||||
|
return;*/
|
||||||
|
|
||||||
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||||
|
|
||||||
|
//const s16 grid_radius_i = 12;
|
||||||
|
//const float grid_size = BS*50;
|
||||||
|
const s16 grid_radius_i = m_render_range/MAP_BLOCKSIZE;
|
||||||
|
const float grid_size = BS*MAP_BLOCKSIZE;
|
||||||
|
const v2f grid_speed(-BS*0, 0);
|
||||||
|
|
||||||
|
// Position of grid noise origin in world coordinates
|
||||||
|
v2f world_grid_origin_pos_f(0,0);
|
||||||
|
// Position of grid noise origin from the camera
|
||||||
|
v2f grid_origin_from_camera_f = world_grid_origin_pos_f - m_camera_pos;
|
||||||
|
// The center point of drawing in the noise
|
||||||
|
v2f center_of_drawing_in_noise_f = -grid_origin_from_camera_f;
|
||||||
|
// The integer center point of drawing in the noise
|
||||||
|
v2s16 center_of_drawing_in_noise_i(
|
||||||
|
MYROUND(center_of_drawing_in_noise_f.X / grid_size),
|
||||||
|
MYROUND(center_of_drawing_in_noise_f.Y / grid_size)
|
||||||
|
);
|
||||||
|
// The world position of the integer center point of drawing in the noise
|
||||||
|
v2f world_center_of_drawing_in_noise_f = v2f(
|
||||||
|
center_of_drawing_in_noise_i.X * grid_size,
|
||||||
|
center_of_drawing_in_noise_i.Y * grid_size
|
||||||
|
) + world_grid_origin_pos_f;
|
||||||
|
|
||||||
|
for(s16 zi=-grid_radius_i; zi<grid_radius_i; zi++)
|
||||||
|
for(s16 xi=-grid_radius_i; xi<grid_radius_i; xi++)
|
||||||
|
{
|
||||||
|
/*// Don't draw very close to player
|
||||||
|
s16 dd = 3;
|
||||||
|
if(zi > -dd && zi < dd && xi > -dd && xi < dd)
|
||||||
|
continue;*/
|
||||||
|
|
||||||
|
v2s16 p_in_noise_i(
|
||||||
|
xi+center_of_drawing_in_noise_i.X,
|
||||||
|
zi+center_of_drawing_in_noise_i.Y
|
||||||
|
);
|
||||||
|
|
||||||
|
// If sector was drawn, don't draw it this way
|
||||||
|
if(m_client->m_env.getClientMap().sectorWasDrawn(p_in_noise_i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*if((p_in_noise_i.X + p_in_noise_i.Y)%2==0)
|
||||||
|
continue;*/
|
||||||
|
/*if((p_in_noise_i.X/2 + p_in_noise_i.Y/2)%2==0)
|
||||||
|
continue;*/
|
||||||
|
|
||||||
|
v2f p0 = v2f(xi,zi)*grid_size + world_center_of_drawing_in_noise_f;
|
||||||
|
|
||||||
|
/*double noise[4];
|
||||||
|
double d = 100*BS;
|
||||||
|
noise[0] = d*noise2d_perlin(
|
||||||
|
(float)(p_in_noise_i.X+0)*grid_size/BS/100,
|
||||||
|
(float)(p_in_noise_i.Y+0)*grid_size/BS/100,
|
||||||
|
m_seed, 3, 0.5);
|
||||||
|
|
||||||
|
noise[1] = d*noise2d_perlin(
|
||||||
|
(float)(p_in_noise_i.X+0)*grid_size/BS/100,
|
||||||
|
(float)(p_in_noise_i.Y+1)*grid_size/BS/100,
|
||||||
|
m_seed, 3, 0.5);
|
||||||
|
|
||||||
|
noise[2] = d*noise2d_perlin(
|
||||||
|
(float)(p_in_noise_i.X+1)*grid_size/BS/100,
|
||||||
|
(float)(p_in_noise_i.Y+1)*grid_size/BS/100,
|
||||||
|
m_seed, 3, 0.5);
|
||||||
|
|
||||||
|
noise[3] = d*noise2d_perlin(
|
||||||
|
(float)(p_in_noise_i.X+1)*grid_size/BS/100,
|
||||||
|
(float)(p_in_noise_i.Y+0)*grid_size/BS/100,
|
||||||
|
m_seed, 3, 0.5);*/
|
||||||
|
|
||||||
|
HeightPoint hps[5];
|
||||||
|
hps[0] = ground_height(m_seed, v2s16(
|
||||||
|
(p_in_noise_i.X+0)*grid_size/BS,
|
||||||
|
(p_in_noise_i.Y+0)*grid_size/BS));
|
||||||
|
hps[1] = ground_height(m_seed, v2s16(
|
||||||
|
(p_in_noise_i.X+0)*grid_size/BS,
|
||||||
|
(p_in_noise_i.Y+1)*grid_size/BS));
|
||||||
|
hps[2] = ground_height(m_seed, v2s16(
|
||||||
|
(p_in_noise_i.X+1)*grid_size/BS,
|
||||||
|
(p_in_noise_i.Y+1)*grid_size/BS));
|
||||||
|
hps[3] = ground_height(m_seed, v2s16(
|
||||||
|
(p_in_noise_i.X+1)*grid_size/BS,
|
||||||
|
(p_in_noise_i.Y+0)*grid_size/BS));
|
||||||
|
v2s16 centerpoint(
|
||||||
|
(p_in_noise_i.X+0)*grid_size/BS+MAP_BLOCKSIZE/2,
|
||||||
|
(p_in_noise_i.Y+0)*grid_size/BS+MAP_BLOCKSIZE/2);
|
||||||
|
hps[4] = ground_height(m_seed, centerpoint);
|
||||||
|
|
||||||
|
float noise[5];
|
||||||
|
float h_min = BS*65535;
|
||||||
|
float h_max = -BS*65536;
|
||||||
|
float ma_avg = 0;
|
||||||
|
float h_avg = 0;
|
||||||
|
u32 have_sand_count = 0;
|
||||||
|
float tree_amount_avg = 0;
|
||||||
|
for(u32 i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
noise[i] = hps[i].gh + hps[i].ma;
|
||||||
|
if(noise[i] < h_min)
|
||||||
|
h_min = noise[i];
|
||||||
|
if(noise[i] > h_max)
|
||||||
|
h_max = noise[i];
|
||||||
|
ma_avg += hps[i].ma;
|
||||||
|
h_avg += noise[i];
|
||||||
|
if(hps[i].have_sand)
|
||||||
|
have_sand_count++;
|
||||||
|
tree_amount_avg += hps[i].tree_amount;
|
||||||
|
}
|
||||||
|
ma_avg /= 5.0;
|
||||||
|
h_avg /= 5.0;
|
||||||
|
tree_amount_avg /= 5.0;
|
||||||
|
|
||||||
|
float steepness = (h_max - h_min)/grid_size;
|
||||||
|
|
||||||
|
float light_f = noise[0]+noise[1]-noise[2]-noise[3];
|
||||||
|
light_f /= 100;
|
||||||
|
if(light_f < -1.0) light_f = -1.0;
|
||||||
|
if(light_f > 1.0) light_f = 1.0;
|
||||||
|
//light_f += 1.0;
|
||||||
|
//light_f /= 2.0;
|
||||||
|
|
||||||
|
v2f p1 = p0 + v2f(1,1)*grid_size;
|
||||||
|
|
||||||
|
bool ground_is_sand = false;
|
||||||
|
bool ground_is_rock = false;
|
||||||
|
bool ground_is_mud = false;
|
||||||
|
video::SColor c;
|
||||||
|
// Detect water
|
||||||
|
if(h_avg < WATER_LEVEL*BS && h_max < (WATER_LEVEL+5)*BS)
|
||||||
|
{
|
||||||
|
//c = video::SColor(255,59,86,146);
|
||||||
|
c = video::SColor(255,82,120,204);
|
||||||
|
|
||||||
|
/*// Set to water level
|
||||||
|
for(u32 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
if(noise[i] < BS*WATER_LEVEL)
|
||||||
|
noise[i] = BS*WATER_LEVEL;
|
||||||
|
}*/
|
||||||
|
light_f = 0;
|
||||||
|
}
|
||||||
|
// Steep cliffs
|
||||||
|
else if(steepness > 2.0)
|
||||||
|
{
|
||||||
|
c = video::SColor(255,128,128,128);
|
||||||
|
ground_is_rock = true;
|
||||||
|
}
|
||||||
|
// Basic ground
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ma_avg < 2.0*BS)
|
||||||
|
{
|
||||||
|
c = video::SColor(255,128,128,128);
|
||||||
|
ground_is_rock = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(h_avg <= 2.5*BS && have_sand_count >= 2)
|
||||||
|
{
|
||||||
|
c = video::SColor(255,210,194,156);
|
||||||
|
ground_is_sand = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*// Trees if there are over 0.01 trees per MapNode
|
||||||
|
if(tree_amount_avg > 0.01)
|
||||||
|
c = video::SColor(255,50,128,50);
|
||||||
|
else
|
||||||
|
c = video::SColor(255,107,134,51);*/
|
||||||
|
c = video::SColor(255,107,134,51);
|
||||||
|
ground_is_mud = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to water level
|
||||||
|
for(u32 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
if(noise[i] < BS*WATER_LEVEL)
|
||||||
|
noise[i] = BS*WATER_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
float b = m_brightness + light_f*0.1*m_brightness;
|
||||||
|
if(b < 0) b = 0;
|
||||||
|
if(b > 2) b = 2;
|
||||||
|
|
||||||
|
c = video::SColor(255, b*c.getRed(), b*c.getGreen(), b*c.getBlue());
|
||||||
|
|
||||||
|
driver->setMaterial(m_materials[0]);
|
||||||
|
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(p0.X,noise[0],p0.Y, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(p0.X,noise[1],p1.Y, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(p1.X,noise[2],p1.Y, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(p1.X,noise[3],p0.Y, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||||
|
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
|
||||||
|
|
||||||
|
// Add some trees if appropriate
|
||||||
|
if(tree_amount_avg >= 0.0065 && steepness < 1.4
|
||||||
|
&& ground_is_mud == true)
|
||||||
|
{
|
||||||
|
driver->setMaterial(m_materials[1]);
|
||||||
|
|
||||||
|
float b = m_brightness;
|
||||||
|
c = video::SColor(255, b*255, b*255, b*255);
|
||||||
|
|
||||||
|
{
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(p0.X,noise[0],p0.Y,
|
||||||
|
0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(p0.X,noise[0]+BS*MAP_BLOCKSIZE,p0.Y,
|
||||||
|
0,0,0, c, 0,0),
|
||||||
|
video::S3DVertex(p1.X,noise[2]+BS*MAP_BLOCKSIZE,p1.Y,
|
||||||
|
0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(p1.X,noise[2],p1.Y,
|
||||||
|
0,0,0, c, 1,1),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||||
|
video::EVT_STANDARD, scene::EPT_TRIANGLES,
|
||||||
|
video::EIT_16BIT);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(p1.X,noise[3],p0.Y,
|
||||||
|
0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(p1.X,noise[3]+BS*MAP_BLOCKSIZE,p0.Y,
|
||||||
|
0,0,0, c, 0,0),
|
||||||
|
video::S3DVertex(p0.X,noise[1]+BS*MAP_BLOCKSIZE,p1.Y,
|
||||||
|
0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(p0.X,noise[1],p1.Y,
|
||||||
|
0,0,0, c, 1,1),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||||
|
video::EVT_STANDARD, scene::EPT_TRIANGLES,
|
||||||
|
video::EIT_16BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//driver->clearZBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FarMesh::step(float dtime)
|
||||||
|
{
|
||||||
|
m_time += dtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FarMesh::update(v2f camera_p, float brightness, s16 render_range)
|
||||||
|
{
|
||||||
|
m_camera_pos = camera_p;
|
||||||
|
m_brightness = brightness;
|
||||||
|
m_render_range = render_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
85
src/farmesh.h
Normal file
85
src/farmesh.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
Part of Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(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 FARMESH_HEADER
|
||||||
|
#define FARMESH_HEADER
|
||||||
|
|
||||||
|
/*
|
||||||
|
A quick messy implementation of terrain rendering for a long
|
||||||
|
distance according to map seed
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
|
||||||
|
#define FARMESH_MATERIAL_COUNT 2
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
class FarMesh : public scene::ISceneNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FarMesh(
|
||||||
|
scene::ISceneNode* parent,
|
||||||
|
scene::ISceneManager* mgr,
|
||||||
|
s32 id,
|
||||||
|
u64 seed,
|
||||||
|
Client *client
|
||||||
|
);
|
||||||
|
|
||||||
|
~FarMesh();
|
||||||
|
|
||||||
|
/*
|
||||||
|
ISceneNode methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void OnRegisterSceneNode();
|
||||||
|
|
||||||
|
virtual void render();
|
||||||
|
|
||||||
|
virtual const core::aabbox3d<f32>& getBoundingBox() const
|
||||||
|
{
|
||||||
|
return m_box;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual u32 getMaterialCount() const;
|
||||||
|
|
||||||
|
virtual video::SMaterial& getMaterial(u32 i);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Other stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
void step(float dtime);
|
||||||
|
|
||||||
|
void update(v2f camera_p, float brightness, s16 render_range);
|
||||||
|
|
||||||
|
private:
|
||||||
|
video::SMaterial m_materials[FARMESH_MATERIAL_COUNT];
|
||||||
|
core::aabbox3d<f32> m_box;
|
||||||
|
float m_cloud_y;
|
||||||
|
float m_brightness;
|
||||||
|
u64 m_seed;
|
||||||
|
v2f m_camera_pos;
|
||||||
|
float m_time;
|
||||||
|
Client *m_client;
|
||||||
|
s16 m_render_range;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
200
src/game.cpp
200
src/game.cpp
@ -25,11 +25,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "guiPasswordChange.h"
|
#include "guiPasswordChange.h"
|
||||||
#include "guiInventoryMenu.h"
|
#include "guiInventoryMenu.h"
|
||||||
#include "guiTextInputMenu.h"
|
#include "guiTextInputMenu.h"
|
||||||
#include "guiFurnaceMenu.h"
|
|
||||||
#include "materials.h"
|
#include "materials.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
|
#include "farmesh.h"
|
||||||
|
|
||||||
|
// TODO: Move content-aware stuff to separate file
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
#include "content_nodemeta.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Setting this to 1 enables a special camera mode that forces
|
Setting this to 1 enables a special camera mode that forces
|
||||||
@ -358,7 +362,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
|||||||
core::rect<s32>(core::position2d<s32>(0,0),
|
core::rect<s32>(core::position2d<s32>(0,0),
|
||||||
core::dimension2di(heart_texture->getOriginalSize())),
|
core::dimension2di(heart_texture->getOriginalSize())),
|
||||||
NULL, colors, true);
|
NULL, colors, true);
|
||||||
p += v2s32(20,0);
|
p += v2s32(16,0);
|
||||||
}
|
}
|
||||||
if(halfheartcount % 2 == 1)
|
if(halfheartcount % 2 == 1)
|
||||||
{
|
{
|
||||||
@ -371,7 +375,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
|||||||
driver->draw2DImage(heart_texture, rect,
|
driver->draw2DImage(heart_texture, rect,
|
||||||
core::rect<s32>(core::position2d<s32>(0,0), srcd),
|
core::rect<s32>(core::position2d<s32>(0,0), srcd),
|
||||||
NULL, colors, true);
|
NULL, colors, true);
|
||||||
p += v2s32(20,0);
|
p += v2s32(16,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,6 +636,10 @@ void update_skybox(video::IVideoDriver* driver,
|
|||||||
skybox->remove();
|
skybox->remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*// Disable skybox if FarMesh is enabled
|
||||||
|
if(g_settings.getBool("enable_farmesh"))
|
||||||
|
return;*/
|
||||||
|
|
||||||
if(brightness >= 0.5)
|
if(brightness >= 0.5)
|
||||||
{
|
{
|
||||||
skybox = smgr->addSkyBoxSceneNode(
|
skybox = smgr->addSkyBoxSceneNode(
|
||||||
@ -801,8 +809,9 @@ void the_game(
|
|||||||
{
|
{
|
||||||
if(client.accessDenied())
|
if(client.accessDenied())
|
||||||
{
|
{
|
||||||
error_message = L"Access denied. Check your password and try again.";
|
error_message = L"Access denied. Reason: "
|
||||||
std::cout<<DTIME<<"Access denied."<<std::endl;
|
+client.accessDeniedReason();
|
||||||
|
std::cout<<DTIME<<wide_to_narrow(error_message)<<std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -851,8 +860,21 @@ void the_game(
|
|||||||
|
|
||||||
float cloud_height = BS*100;
|
float cloud_height = BS*100;
|
||||||
Clouds *clouds = NULL;
|
Clouds *clouds = NULL;
|
||||||
clouds = new Clouds(smgr->getRootSceneNode(), smgr, -1,
|
if(g_settings.getBool("enable_clouds"))
|
||||||
cloud_height, time(0));
|
{
|
||||||
|
clouds = new Clouds(smgr->getRootSceneNode(), smgr, -1,
|
||||||
|
cloud_height, time(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FarMesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
FarMesh *farmesh = NULL;
|
||||||
|
if(g_settings.getBool("enable_farmesh"))
|
||||||
|
{
|
||||||
|
farmesh = new FarMesh(smgr->getRootSceneNode(), smgr, -1, client.getMapSeed(), &client);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Move into game
|
Move into game
|
||||||
@ -886,8 +908,8 @@ void the_game(
|
|||||||
gui::IGUIStaticText *guitext_chat = guienv->addStaticText(
|
gui::IGUIStaticText *guitext_chat = guienv->addStaticText(
|
||||||
L"",
|
L"",
|
||||||
core::rect<s32>(0,0,0,0),
|
core::rect<s32>(0,0,0,0),
|
||||||
false, false); // Disable word wrap as of now
|
//false, false); // Disable word wrap as of now
|
||||||
//false, true);
|
false, true);
|
||||||
//guitext_chat->setBackgroundColor(video::SColor(96,0,0,0));
|
//guitext_chat->setBackgroundColor(video::SColor(96,0,0,0));
|
||||||
core::list<ChatLine> chat_lines;
|
core::list<ChatLine> chat_lines;
|
||||||
|
|
||||||
@ -930,6 +952,9 @@ void the_game(
|
|||||||
core::list<float> frametime_log;
|
core::list<float> frametime_log;
|
||||||
|
|
||||||
float damage_flash_timer = 0;
|
float damage_flash_timer = 0;
|
||||||
|
s16 farmesh_range = 20*MAP_BLOCKSIZE;
|
||||||
|
|
||||||
|
bool invert_mouse = g_settings.getBool("invert_mouse");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Main loop
|
Main loop
|
||||||
@ -937,6 +962,10 @@ void the_game(
|
|||||||
|
|
||||||
bool first_loop_after_window_activation = true;
|
bool first_loop_after_window_activation = true;
|
||||||
|
|
||||||
|
// TODO: Convert the static interval timers to these
|
||||||
|
// Interval limiter for profiler
|
||||||
|
IntervalLimiter m_profiler_interval;
|
||||||
|
|
||||||
// Time is in milliseconds
|
// Time is in milliseconds
|
||||||
// NOTE: getRealTime() causes strange problems in wine (imprecision?)
|
// NOTE: getRealTime() causes strange problems in wine (imprecision?)
|
||||||
// NOTE: So we have to use getTime() and call run()s between them
|
// NOTE: So we have to use getTime() and call run()s between them
|
||||||
@ -1123,6 +1152,21 @@ void the_game(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Profiler
|
||||||
|
*/
|
||||||
|
float profiler_print_interval =
|
||||||
|
g_settings.getFloat("profiler_print_interval");
|
||||||
|
if(profiler_print_interval != 0)
|
||||||
|
{
|
||||||
|
if(m_profiler_interval.step(0.030, profiler_print_interval))
|
||||||
|
{
|
||||||
|
dstream<<"Profiler:"<<std::endl;
|
||||||
|
g_profiler.print(dstream);
|
||||||
|
g_profiler.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Direct handling of user input
|
Direct handling of user input
|
||||||
*/
|
*/
|
||||||
@ -1189,10 +1233,12 @@ void the_game(
|
|||||||
if(g_settings.getBool("free_move"))
|
if(g_settings.getBool("free_move"))
|
||||||
{
|
{
|
||||||
g_settings.set("free_move","false");
|
g_settings.set("free_move","false");
|
||||||
|
chat_lines.push_back(ChatLine(L"free_move disabled"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_settings.set("free_move","true");
|
g_settings.set("free_move","true");
|
||||||
|
chat_lines.push_back(ChatLine(L"free_move enabled"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(input->wasKeyDown(getKeySetting("keymap_fastmove")))
|
else if(input->wasKeyDown(getKeySetting("keymap_fastmove")))
|
||||||
@ -1200,10 +1246,12 @@ void the_game(
|
|||||||
if(g_settings.getBool("fast_move"))
|
if(g_settings.getBool("fast_move"))
|
||||||
{
|
{
|
||||||
g_settings.set("fast_move","false");
|
g_settings.set("fast_move","false");
|
||||||
|
chat_lines.push_back(ChatLine(L"fast_move disabled"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_settings.set("fast_move","true");
|
g_settings.set("fast_move","true");
|
||||||
|
chat_lines.push_back(ChatLine(L"fast_move enabled"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1355,7 +1403,11 @@ void the_game(
|
|||||||
if((device->isWindowActive() && noMenuActive()) || random_input)
|
if((device->isWindowActive() && noMenuActive()) || random_input)
|
||||||
{
|
{
|
||||||
if(!random_input)
|
if(!random_input)
|
||||||
device->getCursorControl()->setVisible(false);
|
{
|
||||||
|
// Mac OSX gets upset if this is set every frame
|
||||||
|
if(device->getCursorControl()->isVisible())
|
||||||
|
device->getCursorControl()->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
if(first_loop_after_window_activation){
|
if(first_loop_after_window_activation){
|
||||||
//std::cout<<"window active, first loop"<<std::endl;
|
//std::cout<<"window active, first loop"<<std::endl;
|
||||||
@ -1364,6 +1416,8 @@ void the_game(
|
|||||||
else{
|
else{
|
||||||
s32 dx = input->getMousePos().X - displaycenter.X;
|
s32 dx = input->getMousePos().X - displaycenter.X;
|
||||||
s32 dy = input->getMousePos().Y - displaycenter.Y;
|
s32 dy = input->getMousePos().Y - displaycenter.Y;
|
||||||
|
if(invert_mouse)
|
||||||
|
dy = -dy;
|
||||||
//std::cout<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
//std::cout<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
||||||
|
|
||||||
/*const float keyspeed = 500;
|
/*const float keyspeed = 500;
|
||||||
@ -1384,7 +1438,9 @@ void the_game(
|
|||||||
input->setMousePos(displaycenter.X, displaycenter.Y);
|
input->setMousePos(displaycenter.X, displaycenter.Y);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
device->getCursorControl()->setVisible(true);
|
// Mac OSX gets upset if this is set every frame
|
||||||
|
if(device->getCursorControl()->isVisible() == false)
|
||||||
|
device->getCursorControl()->setVisible(true);
|
||||||
|
|
||||||
//std::cout<<"window inactive"<<std::endl;
|
//std::cout<<"window inactive"<<std::endl;
|
||||||
first_loop_after_window_activation = true;
|
first_loop_after_window_activation = true;
|
||||||
@ -1696,7 +1752,41 @@ void the_game(
|
|||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Ground right-clicked"<<std::endl;
|
std::cout<<DTIME<<"Ground right-clicked"<<std::endl;
|
||||||
|
|
||||||
if(meta && meta->typeId() == CONTENT_SIGN_WALL && !random_input)
|
// If metadata provides an inventory view, activate it
|
||||||
|
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
|
||||||
|
{
|
||||||
|
dstream<<DTIME<<"Launching custom inventory view"<<std::endl;
|
||||||
|
/*
|
||||||
|
Construct the unique identification string of the node
|
||||||
|
*/
|
||||||
|
std::string current_name;
|
||||||
|
current_name += "nodemeta:";
|
||||||
|
current_name += itos(nodepos.X);
|
||||||
|
current_name += ",";
|
||||||
|
current_name += itos(nodepos.Y);
|
||||||
|
current_name += ",";
|
||||||
|
current_name += itos(nodepos.Z);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create menu
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||||
|
v2s16 invsize =
|
||||||
|
GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||||
|
draw_spec,
|
||||||
|
meta->getInventoryDrawSpecString(),
|
||||||
|
current_name);
|
||||||
|
|
||||||
|
GUIInventoryMenu *menu =
|
||||||
|
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||||
|
&g_menumgr, invsize,
|
||||||
|
client.getInventoryContext(),
|
||||||
|
&client);
|
||||||
|
menu->setDrawSpec(draw_spec);
|
||||||
|
menu->drop();
|
||||||
|
}
|
||||||
|
else if(meta && meta->typeId() == CONTENT_SIGN_WALL && !random_input)
|
||||||
{
|
{
|
||||||
dstream<<"Sign node right-clicked"<<std::endl;
|
dstream<<"Sign node right-clicked"<<std::endl;
|
||||||
|
|
||||||
@ -1713,51 +1803,6 @@ void the_game(
|
|||||||
&g_menumgr, dest,
|
&g_menumgr, dest,
|
||||||
wtext))->drop();
|
wtext))->drop();
|
||||||
}
|
}
|
||||||
else if(meta && meta->typeId() == CONTENT_CHEST && !random_input)
|
|
||||||
{
|
|
||||||
dstream<<"Chest node right-clicked"<<std::endl;
|
|
||||||
|
|
||||||
//ChestNodeMetadata *chestmeta = (ChestNodeMetadata*)meta;
|
|
||||||
|
|
||||||
std::string chest_inv_id;
|
|
||||||
chest_inv_id += "nodemeta:";
|
|
||||||
chest_inv_id += itos(nodepos.X);
|
|
||||||
chest_inv_id += ",";
|
|
||||||
chest_inv_id += itos(nodepos.Y);
|
|
||||||
chest_inv_id += ",";
|
|
||||||
chest_inv_id += itos(nodepos.Z);
|
|
||||||
|
|
||||||
GUIInventoryMenu *menu =
|
|
||||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
|
||||||
&g_menumgr, v2s16(8,9),
|
|
||||||
client.getInventoryContext(),
|
|
||||||
&client);
|
|
||||||
|
|
||||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
|
||||||
|
|
||||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
|
||||||
"list", chest_inv_id, "0",
|
|
||||||
v2s32(0, 0), v2s32(8, 4)));
|
|
||||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
|
||||||
"list", "current_player", "main",
|
|
||||||
v2s32(0, 5), v2s32(8, 4)));
|
|
||||||
|
|
||||||
menu->setDrawSpec(draw_spec);
|
|
||||||
|
|
||||||
menu->drop();
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(meta && meta->typeId() == CONTENT_FURNACE && !random_input)
|
|
||||||
{
|
|
||||||
dstream<<"Furnace node right-clicked"<<std::endl;
|
|
||||||
|
|
||||||
GUIFurnaceMenu *menu =
|
|
||||||
new GUIFurnaceMenu(guienv, guiroot, -1,
|
|
||||||
&g_menumgr, nodepos, &client);
|
|
||||||
|
|
||||||
menu->drop();
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
client.groundAction(1, nodepos, neighbourpos, g_selected_item);
|
client.groundAction(1, nodepos, neighbourpos, g_selected_item);
|
||||||
@ -1824,6 +1869,22 @@ void the_game(
|
|||||||
0.05+brightness*0.95);
|
0.05+brightness*0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update farmesh
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
// Store brightness value
|
// Store brightness value
|
||||||
old_brightness = brightness;
|
old_brightness = brightness;
|
||||||
|
|
||||||
@ -1833,11 +1894,19 @@ void the_game(
|
|||||||
|
|
||||||
if(g_settings.getBool("enable_fog") == true)
|
if(g_settings.getBool("enable_fog") == true)
|
||||||
{
|
{
|
||||||
f32 range = draw_control.wanted_range*BS + MAP_BLOCKSIZE*BS*1.5;
|
f32 range;
|
||||||
if(draw_control.range_all)
|
if(farmesh)
|
||||||
range = 100000*BS;
|
{
|
||||||
if(range < 50*BS)
|
range = BS*farmesh_range;
|
||||||
range = range * 0.5 + 25*BS;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
range = draw_control.wanted_range*BS + MAP_BLOCKSIZE*BS*1.5;
|
||||||
|
if(draw_control.range_all)
|
||||||
|
range = 100000*BS;
|
||||||
|
if(range < 50*BS)
|
||||||
|
range = range * 0.5 + 25*BS;
|
||||||
|
}
|
||||||
|
|
||||||
driver->setFog(
|
driver->setFog(
|
||||||
bgcolor,
|
bgcolor,
|
||||||
@ -1985,7 +2054,7 @@ void the_game(
|
|||||||
10,
|
10,
|
||||||
50,
|
50,
|
||||||
screensize.X - 10,
|
screensize.X - 10,
|
||||||
50 + text_height*chat_lines.size()
|
50 + guitext_chat->getTextHeight()
|
||||||
);
|
);
|
||||||
|
|
||||||
guitext_chat->setRelativePosition(rect);
|
guitext_chat->setRelativePosition(rect);
|
||||||
@ -2034,7 +2103,7 @@ void the_game(
|
|||||||
//driver->beginScene(false, true, bgcolor);
|
//driver->beginScene(false, true, bgcolor);
|
||||||
beginscenetime = timer.stop(true);
|
beginscenetime = timer.stop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//timer3.stop();
|
//timer3.stop();
|
||||||
|
|
||||||
//std::cout<<DTIME<<"smgr->drawAll()"<<std::endl;
|
//std::cout<<DTIME<<"smgr->drawAll()"<<std::endl;
|
||||||
@ -2166,7 +2235,8 @@ void the_game(
|
|||||||
/*
|
/*
|
||||||
Drop stuff
|
Drop stuff
|
||||||
*/
|
*/
|
||||||
clouds->drop();
|
if(clouds)
|
||||||
|
clouds->drop();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Draw a "shutting down" screen, which will be shown while the map
|
Draw a "shutting down" screen, which will be shown while the map
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
Minetest-c55
|
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(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 "guiFurnaceMenu.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
GUIFurnaceMenu::GUIFurnaceMenu(
|
|
||||||
gui::IGUIEnvironment* env,
|
|
||||||
gui::IGUIElement* parent, s32 id,
|
|
||||||
IMenuManager *menumgr,
|
|
||||||
v3s16 nodepos,
|
|
||||||
Client *client
|
|
||||||
):
|
|
||||||
GUIInventoryMenu(env, parent, id, menumgr, v2s16(8,9),
|
|
||||||
client->getInventoryContext(), client),
|
|
||||||
m_nodepos(nodepos),
|
|
||||||
m_client(client)
|
|
||||||
{
|
|
||||||
std::string furnace_inv_id;
|
|
||||||
furnace_inv_id += "nodemeta:";
|
|
||||||
furnace_inv_id += itos(nodepos.X);
|
|
||||||
furnace_inv_id += ",";
|
|
||||||
furnace_inv_id += itos(nodepos.Y);
|
|
||||||
furnace_inv_id += ",";
|
|
||||||
furnace_inv_id += itos(nodepos.Z);
|
|
||||||
|
|
||||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
|
||||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
|
||||||
"list", furnace_inv_id, "fuel",
|
|
||||||
v2s32(2, 3), v2s32(1, 1)));
|
|
||||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
|
||||||
"list", furnace_inv_id, "src",
|
|
||||||
v2s32(2, 1), v2s32(1, 1)));
|
|
||||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
|
||||||
"list", furnace_inv_id, "dst",
|
|
||||||
v2s32(5, 1), v2s32(2, 2)));
|
|
||||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
|
||||||
"list", "current_player", "main",
|
|
||||||
v2s32(0, 5), v2s32(8, 4)));
|
|
||||||
setDrawSpec(draw_spec);
|
|
||||||
}
|
|
||||||
|
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "guiInventoryMenu.h"
|
#include "guiInventoryMenu.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
|
#include "strfnd.h"
|
||||||
|
|
||||||
void drawInventoryItem(video::IVideoDriver *driver,
|
void drawInventoryItem(video::IVideoDriver *driver,
|
||||||
gui::IGUIFont *font,
|
gui::IGUIFont *font,
|
||||||
@ -412,5 +413,85 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
|||||||
return Parent ? Parent->OnEvent(event) : false;
|
return Parent ? Parent->OnEvent(event) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here is an example traditional set-up sequence for a DrawSpec list:
|
||||||
|
|
||||||
|
std::string furnace_inv_id = "nodemetadata:0,1,2";
|
||||||
|
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||||
|
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||||
|
"list", furnace_inv_id, "fuel",
|
||||||
|
v2s32(2, 3), v2s32(1, 1)));
|
||||||
|
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||||
|
"list", furnace_inv_id, "src",
|
||||||
|
v2s32(2, 1), v2s32(1, 1)));
|
||||||
|
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||||
|
"list", furnace_inv_id, "dst",
|
||||||
|
v2s32(5, 1), v2s32(2, 2)));
|
||||||
|
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||||
|
"list", "current_player", "main",
|
||||||
|
v2s32(0, 5), v2s32(8, 4)));
|
||||||
|
setDrawSpec(draw_spec);
|
||||||
|
|
||||||
|
Here is the string for creating the same DrawSpec list (a single line,
|
||||||
|
spread to multiple lines here):
|
||||||
|
|
||||||
|
GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||||
|
draw_spec,
|
||||||
|
"nodemetadata:0,1,2",
|
||||||
|
"invsize[8,9;]"
|
||||||
|
"list[current_name;fuel;2,3;1,1;]"
|
||||||
|
"list[current_name;src;2,1;1,1;]"
|
||||||
|
"list[current_name;dst;5,1;2,2;]"
|
||||||
|
"list[current_player;main;0,5;8,4;]");
|
||||||
|
|
||||||
|
Returns inventory menu size defined by invsize[].
|
||||||
|
*/
|
||||||
|
v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||||
|
core::array<GUIInventoryMenu::DrawSpec> &draw_spec,
|
||||||
|
const std::string &data,
|
||||||
|
const std::string ¤t_name)
|
||||||
|
{
|
||||||
|
v2s16 invsize(8,9);
|
||||||
|
Strfnd f(data);
|
||||||
|
while(f.atend() == false)
|
||||||
|
{
|
||||||
|
std::string type = trim(f.next("["));
|
||||||
|
//dstream<<"type="<<type<<std::endl;
|
||||||
|
if(type == "list")
|
||||||
|
{
|
||||||
|
std::string name = f.next(";");
|
||||||
|
if(name == "current_name")
|
||||||
|
name = current_name;
|
||||||
|
std::string subname = f.next(";");
|
||||||
|
s32 pos_x = stoi(f.next(","));
|
||||||
|
s32 pos_y = stoi(f.next(";"));
|
||||||
|
s32 geom_x = stoi(f.next(","));
|
||||||
|
s32 geom_y = stoi(f.next(";"));
|
||||||
|
dstream<<"list name="<<name<<", subname="<<subname
|
||||||
|
<<", pos=("<<pos_x<<","<<pos_y<<")"
|
||||||
|
<<", geom=("<<geom_x<<","<<geom_y<<")"
|
||||||
|
<<std::endl;
|
||||||
|
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||||
|
type, name, subname,
|
||||||
|
v2s32(pos_x,pos_y),v2s32(geom_x,geom_y)));
|
||||||
|
f.next("]");
|
||||||
|
}
|
||||||
|
else if(type == "invsize")
|
||||||
|
{
|
||||||
|
invsize.X = stoi(f.next(","));
|
||||||
|
invsize.Y = stoi(f.next(";"));
|
||||||
|
dstream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||||
|
f.next("]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ignore others
|
||||||
|
std::string ts = f.next("]");
|
||||||
|
dstream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,12 @@ public:
|
|||||||
v2s32 pos;
|
v2s32 pos;
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// See .cpp for format
|
||||||
|
static v2s16 makeDrawSpecArrayFromString(
|
||||||
|
core::array<GUIInventoryMenu::DrawSpec> &draw_spec,
|
||||||
|
const std::string &data,
|
||||||
|
const std::string ¤t_name);
|
||||||
|
|
||||||
GUIInventoryMenu(gui::IGUIEnvironment* env,
|
GUIInventoryMenu(gui::IGUIEnvironment* env,
|
||||||
gui::IGUIElement* parent, s32 id,
|
gui::IGUIElement* parent, s32 id,
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GUIMAINMENU_HEADER
|
#ifndef GUIMAINMENU_HEADER
|
||||||
#define GUIMAINMENU_HEADER
|
#define GUIMAINMENU_HEADER
|
||||||
@ -44,18 +44,19 @@ enum
|
|||||||
|
|
||||||
struct MainMenuData
|
struct MainMenuData
|
||||||
{
|
{
|
||||||
MainMenuData() :
|
MainMenuData():
|
||||||
// Client opts
|
// Client opts
|
||||||
fancy_trees(false), smooth_lighting(false),
|
fancy_trees(false),
|
||||||
// Server opts
|
smooth_lighting(false),
|
||||||
creative_mode(false), enable_damage(false),
|
// Server opts
|
||||||
// Actions
|
creative_mode(false),
|
||||||
delete_map(false)
|
enable_damage(false),
|
||||||
{
|
// Actions
|
||||||
}
|
delete_map(false)
|
||||||
|
{}
|
||||||
|
|
||||||
// These are in the native format of the gui elements
|
// These are in the native format of the gui elements
|
||||||
|
|
||||||
// Client options
|
// Client options
|
||||||
std::wstring address;
|
std::wstring address;
|
||||||
std::wstring port;
|
std::wstring port;
|
||||||
@ -70,23 +71,20 @@ struct MainMenuData
|
|||||||
bool delete_map;
|
bool delete_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GUIMainMenu: public GUIModalMenu
|
class GUIMainMenu : public GUIModalMenu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GUIMainMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id,
|
GUIMainMenu(gui::IGUIEnvironment* env,
|
||||||
IMenuManager *menumgr, MainMenuData *data,
|
gui::IGUIElement* parent, s32 id,
|
||||||
|
IMenuManager *menumgr,
|
||||||
|
MainMenuData *data,
|
||||||
IGameCallback *gamecallback);
|
IGameCallback *gamecallback);
|
||||||
~GUIMainMenu();
|
~GUIMainMenu();
|
||||||
|
|
||||||
gui::IGUIEnvironment* env;
|
|
||||||
gui::IGUIElement* parent;
|
|
||||||
s32 id;
|
|
||||||
IMenuManager *menumgr;
|
|
||||||
|
|
||||||
void removeChildren();
|
void removeChildren();
|
||||||
/*
|
/*
|
||||||
Remove and re-add (or reposition) stuff
|
Remove and re-add (or reposition) stuff
|
||||||
*/
|
*/
|
||||||
void regenerateGui(v2u32 screensize);
|
void regenerateGui(v2u32 screensize);
|
||||||
|
|
||||||
void drawMenu();
|
void drawMenu();
|
||||||
@ -99,11 +97,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OnEvent(const SEvent& event);
|
bool OnEvent(const SEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MainMenuData *m_data;
|
MainMenuData *m_data;
|
||||||
bool m_accepted;
|
bool m_accepted;
|
||||||
IGameCallback *m_gamecallback;
|
IGameCallback *m_gamecallback;
|
||||||
|
|
||||||
|
gui::IGUIEnvironment* env;
|
||||||
|
gui::IGUIElement* parent;
|
||||||
|
s32 id;
|
||||||
|
IMenuManager *menumgr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GUIMESSAGEMENU_HEADER
|
#ifndef GUIMESSAGEMENU_HEADER
|
||||||
#define GUIMESSAGEMENU_HEADER
|
#define GUIMESSAGEMENU_HEADER
|
||||||
@ -25,17 +25,19 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GUIMessageMenu: public GUIModalMenu
|
class GUIMessageMenu : public GUIModalMenu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GUIMessageMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id,
|
GUIMessageMenu(gui::IGUIEnvironment* env,
|
||||||
IMenuManager *menumgr, std::wstring message_text);
|
gui::IGUIElement* parent, s32 id,
|
||||||
|
IMenuManager *menumgr,
|
||||||
|
std::wstring message_text);
|
||||||
~GUIMessageMenu();
|
~GUIMessageMenu();
|
||||||
|
|
||||||
void removeChildren();
|
void removeChildren();
|
||||||
/*
|
/*
|
||||||
Remove and re-add (or reposition) stuff
|
Remove and re-add (or reposition) stuff
|
||||||
*/
|
*/
|
||||||
void regenerateGui(v2u32 screensize);
|
void regenerateGui(v2u32 screensize);
|
||||||
|
|
||||||
void drawMenu();
|
void drawMenu();
|
||||||
@ -43,13 +45,13 @@ public:
|
|||||||
bool OnEvent(const SEvent& event);
|
bool OnEvent(const SEvent& event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
true = ok'd
|
true = ok'd
|
||||||
*/
|
*/
|
||||||
bool getStatus()
|
bool getStatus()
|
||||||
{
|
{
|
||||||
return m_status;
|
return m_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::wstring m_message_text;
|
std::wstring m_message_text;
|
||||||
bool m_status;
|
bool m_status;
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Part of Minetest-c55
|
||||||
Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
it under the terms of the GNU General Public License as published by
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
copyright notice and this permission notice appear in all copies.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
GNU General Public License for more details.
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
You should have received a copy of the GNU General Public License along
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "guiPasswordChange.h"
|
#include "guiPasswordChange.h"
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Part of Minetest-c55
|
||||||
Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
it under the terms of the GNU General Public License as published by
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
copyright notice and this permission notice appear in all copies.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
GNU General Public License for more details.
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
You should have received a copy of the GNU General Public License along
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GUIPASSWORDCHANGE_HEADER
|
#ifndef GUIPASSWORDCHANGE_HEADER
|
||||||
|
@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
#include "content_inventory.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InventoryItem
|
InventoryItem
|
||||||
@ -110,36 +112,12 @@ ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f
|
|||||||
|
|
||||||
bool MaterialItem::isCookable()
|
bool MaterialItem::isCookable()
|
||||||
{
|
{
|
||||||
if(m_content == CONTENT_TREE)
|
return item_material_is_cookable(m_content);
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(m_content == CONTENT_COBBLE)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(m_content == CONTENT_SAND)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryItem *MaterialItem::createCookResult()
|
InventoryItem *MaterialItem::createCookResult()
|
||||||
{
|
{
|
||||||
if(m_content == CONTENT_TREE)
|
return item_material_create_cook_result(m_content);
|
||||||
{
|
|
||||||
return new CraftItem("lump_of_coal", 1);
|
|
||||||
}
|
|
||||||
else if(m_content == CONTENT_COBBLE)
|
|
||||||
{
|
|
||||||
return new MaterialItem(CONTENT_STONE, 1);
|
|
||||||
}
|
|
||||||
else if(m_content == CONTENT_SAND)
|
|
||||||
{
|
|
||||||
return new MaterialItem(CONTENT_GLASS, 1);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,29 +130,8 @@ video::ITexture * CraftItem::getImage()
|
|||||||
if(g_texturesource == NULL)
|
if(g_texturesource == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
std::string name;
|
std::string name = item_craft_get_image_name(m_subname);
|
||||||
|
|
||||||
if(m_subname == "Stick")
|
|
||||||
name = "stick.png";
|
|
||||||
else if(m_subname == "paper")
|
|
||||||
name = "paper.png";
|
|
||||||
else if(m_subname == "book")
|
|
||||||
name = "book.png";
|
|
||||||
else if(m_subname == "lump_of_coal")
|
|
||||||
name = "lump_of_coal.png";
|
|
||||||
else if(m_subname == "lump_of_iron")
|
|
||||||
name = "lump_of_iron.png";
|
|
||||||
else if(m_subname == "lump_of_clay")
|
|
||||||
name = "lump_of_clay.png";
|
|
||||||
else if(m_subname == "steel_ingot")
|
|
||||||
name = "steel_ingot.png";
|
|
||||||
else if(m_subname == "clay_brick")
|
|
||||||
name = "clay_brick.png";
|
|
||||||
else if(m_subname == "rat")
|
|
||||||
name = "rat.png";
|
|
||||||
else
|
|
||||||
name = "cloud.png";
|
|
||||||
|
|
||||||
// Get such a texture
|
// Get such a texture
|
||||||
return g_texturesource->getTextureRaw(name);
|
return g_texturesource->getTextureRaw(name);
|
||||||
}
|
}
|
||||||
@ -183,50 +140,35 @@ video::ITexture * CraftItem::getImage()
|
|||||||
ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
|
ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
|
||||||
{
|
{
|
||||||
// Special cases
|
// Special cases
|
||||||
if(m_subname == "rat")
|
ServerActiveObject *obj = item_craft_create_object(m_subname, env, id, pos);
|
||||||
{
|
if(obj)
|
||||||
ServerActiveObject *obj = new RatSAO(env, id, pos);
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
|
||||||
// Default
|
// Default
|
||||||
else
|
return InventoryItem::createSAO(env, id, pos);
|
||||||
{
|
|
||||||
return InventoryItem::createSAO(env, id, pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 CraftItem::getDropCount()
|
u16 CraftItem::getDropCount()
|
||||||
{
|
{
|
||||||
// Special cases
|
// Special cases
|
||||||
if(m_subname == "rat")
|
s16 dc = item_craft_get_drop_count(m_subname);
|
||||||
return 1;
|
if(dc != -1)
|
||||||
|
return dc;
|
||||||
// Default
|
// Default
|
||||||
else
|
return InventoryItem::getDropCount();
|
||||||
return InventoryItem::getDropCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CraftItem::isCookable()
|
bool CraftItem::isCookable()
|
||||||
{
|
{
|
||||||
if(m_subname == "lump_of_iron" || m_subname == "lump_of_clay")
|
return item_craft_is_cookable(m_subname);
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryItem *CraftItem::createCookResult()
|
InventoryItem *CraftItem::createCookResult()
|
||||||
{
|
{
|
||||||
if(m_subname == "lump_of_iron")
|
return item_craft_create_cook_result(m_subname);
|
||||||
{
|
|
||||||
return new CraftItem("steel_ingot", 1);
|
|
||||||
}
|
|
||||||
else if(m_subname == "lump_of_clay")
|
|
||||||
return new CraftItem("clay_brick", 1);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MapBlockObjectItem
|
MapBlockObjectItem DEPRECATED
|
||||||
TODO: Remove
|
TODO: Remove
|
||||||
*/
|
*/
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
@ -528,7 +470,7 @@ InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem)
|
|||||||
//setDirty(true);
|
//setDirty(true);
|
||||||
|
|
||||||
// If it is an empty position, it's an easy job.
|
// If it is an empty position, it's an easy job.
|
||||||
InventoryItem *to_item = m_items[i];
|
InventoryItem *to_item = getItem(i);
|
||||||
if(to_item == NULL)
|
if(to_item == NULL)
|
||||||
{
|
{
|
||||||
m_items[i] = newitem;
|
m_items[i] = newitem;
|
||||||
@ -560,7 +502,7 @@ InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem)
|
|||||||
bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
|
bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
|
||||||
{
|
{
|
||||||
// If it is an empty position, it's an easy job.
|
// If it is an empty position, it's an easy job.
|
||||||
InventoryItem *to_item = m_items[i];
|
InventoryItem *to_item = getItem(i);
|
||||||
if(to_item == NULL)
|
if(to_item == NULL)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -586,7 +528,7 @@ InventoryItem * InventoryList::takeItem(u32 i, u32 count)
|
|||||||
|
|
||||||
//setDirty(true);
|
//setDirty(true);
|
||||||
|
|
||||||
InventoryItem *item = m_items[i];
|
InventoryItem *item = getItem(i);
|
||||||
// If it is an empty position, return NULL
|
// If it is an empty position, return NULL
|
||||||
if(item == NULL)
|
if(item == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
#include "main.h" // For g_settings
|
#include "main.h" // For g_settings
|
||||||
|
|
||||||
#define CHECKKEY(x){if(strcmp(name, #x)==0) return irr::x;}
|
#define CHECKKEY(x){if(strcmp(name, #x)==0) return irr::x;}
|
||||||
|
|
||||||
irr::EKEY_CODE keyname_to_keycode(const char *name)
|
irr::EKEY_CODE keyname_to_keycode(const char *name)
|
||||||
@ -209,9 +210,10 @@ std::string keycode_to_keyname(s32 keycode)
|
|||||||
{
|
{
|
||||||
return KeyNames[keycode];
|
return KeyNames[keycode];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Key config
|
Key config
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// A simple cache for quicker lookup
|
// A simple cache for quicker lookup
|
||||||
core::map<std::string, irr::EKEY_CODE> g_key_setting_cache;
|
core::map<std::string, irr::EKEY_CODE> g_key_setting_cache;
|
||||||
@ -220,7 +222,7 @@ irr::EKEY_CODE getKeySetting(const char *settingname)
|
|||||||
{
|
{
|
||||||
core::map<std::string, irr::EKEY_CODE>::Node *n;
|
core::map<std::string, irr::EKEY_CODE>::Node *n;
|
||||||
n = g_key_setting_cache.find(settingname);
|
n = g_key_setting_cache.find(settingname);
|
||||||
if (n)
|
if(n)
|
||||||
return n->getValue();
|
return n->getValue();
|
||||||
irr::EKEY_CODE c = keyname_to_keycode(g_settings.get(settingname).c_str());
|
irr::EKEY_CODE c = keyname_to_keycode(g_settings.get(settingname).c_str());
|
||||||
g_key_setting_cache.insert(settingname, c);
|
g_key_setting_cache.insert(settingname, c);
|
||||||
@ -231,4 +233,3 @@ void clearKeyCache()
|
|||||||
{
|
{
|
||||||
g_key_setting_cache.clear();
|
g_key_setting_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,5 +29,6 @@ irr::EKEY_CODE keyname_to_keycode(const char *name);
|
|||||||
irr::EKEY_CODE getKeySetting(const char *settingname);
|
irr::EKEY_CODE getKeySetting(const char *settingname);
|
||||||
std::string keycode_to_keyname(s32 keycode);
|
std::string keycode_to_keyname(s32 keycode);
|
||||||
void clearCache();
|
void clearCache();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
201
src/main.cpp
201
src/main.cpp
@ -89,6 +89,17 @@ SUGG: Make a system for pregenerating quick information for mapblocks, so
|
|||||||
that the client can show them as cubes before they are actually sent
|
that the client can show them as cubes before they are actually sent
|
||||||
or even generated.
|
or even generated.
|
||||||
|
|
||||||
|
SUGG: Erosion simulation at map generation time
|
||||||
|
- Simulate water flows, which would carve out dirt fast and
|
||||||
|
then turn stone into gravel and sand and relocate it.
|
||||||
|
- How about relocating minerals, too? Coal and gold in
|
||||||
|
downstream sand and gravel would be kind of cool
|
||||||
|
- This would need a better way of handling minerals, mainly
|
||||||
|
to have mineral content as a separate field. the first
|
||||||
|
parameter field is free for this.
|
||||||
|
- Simulate rock falling from cliffs when water has removed
|
||||||
|
enough solid rock from the bottom
|
||||||
|
|
||||||
Gaming ideas:
|
Gaming ideas:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -172,7 +183,15 @@ TODO: A setting for enabling bilinear filtering for textures
|
|||||||
|
|
||||||
TODO: Better control of draw_control.wanted_max_blocks
|
TODO: Better control of draw_control.wanted_max_blocks
|
||||||
|
|
||||||
TODO: Block mesh generator to tile properly on smooth lighting
|
TODO: Further investigate the use of GPU lighting in addition to the
|
||||||
|
current one
|
||||||
|
|
||||||
|
TODO: Artificial (night) light could be more yellow colored than sunlight.
|
||||||
|
- This is technically doable.
|
||||||
|
- Also the actual colors of the textures could be made less colorful
|
||||||
|
in the dark but it's a bit more difficult.
|
||||||
|
|
||||||
|
SUGG: Somehow make the night less colorful
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
--------------
|
--------------
|
||||||
@ -198,6 +217,9 @@ TODO: Don't update all meshes always on single node changes, but
|
|||||||
|
|
||||||
FIXME: When disconnected to the menu, memory is not freed properly
|
FIXME: When disconnected to the menu, memory is not freed properly
|
||||||
|
|
||||||
|
TODO: Investigate how much the mesh generator thread gets used when
|
||||||
|
transferring map data
|
||||||
|
|
||||||
Server:
|
Server:
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@ -214,11 +236,20 @@ FIXME: Server sometimes goes into some infinite PeerNotFoundException loop
|
|||||||
|
|
||||||
FIXME: The new optimized map sending doesn't sometimes send enough blocks
|
FIXME: The new optimized map sending doesn't sometimes send enough blocks
|
||||||
from big caves and such
|
from big caves and such
|
||||||
|
FIXME: Block send distance configuration does not take effect for some reason
|
||||||
|
|
||||||
|
TODO: Map saving should be done by EmergeThread
|
||||||
|
|
||||||
|
SUGG: Map unloading based on sector reference is not very good, it keeps
|
||||||
|
unnecessary stuff in memory. I guess. Investigate this.
|
||||||
|
|
||||||
|
TODO: When block is placed and it has param_type==CPT_FACEDIR_SIMPLE, set
|
||||||
|
the direction accordingly.
|
||||||
|
|
||||||
Environment:
|
Environment:
|
||||||
------------
|
------------
|
||||||
|
|
||||||
TODO: A list of "active blocks" in which stuff happens.
|
TODO: A list of "active blocks" in which stuff happens. (+=done)
|
||||||
+ Add a never-resetted game timer to the server
|
+ Add a never-resetted game timer to the server
|
||||||
+ Add a timestamp value to blocks
|
+ Add a timestamp value to blocks
|
||||||
+ The simple rule: All blocks near some player are "active"
|
+ The simple rule: All blocks near some player are "active"
|
||||||
@ -260,31 +291,24 @@ SUGG: MovingObject::move and Player::move are basically the same.
|
|||||||
- NOTE: There is a simple move implementation now in collision.{h,cpp}
|
- NOTE: There is a simple move implementation now in collision.{h,cpp}
|
||||||
- NOTE: MovingObject will be deleted (MapBlockObject)
|
- NOTE: MovingObject will be deleted (MapBlockObject)
|
||||||
|
|
||||||
|
TODO: Add a long step function to objects that is called with the time
|
||||||
|
difference when block activates
|
||||||
|
|
||||||
Map:
|
Map:
|
||||||
----
|
----
|
||||||
|
|
||||||
TODO: Mineral and ground material properties
|
TODO: Mineral and ground material properties
|
||||||
- This way mineral ground toughness can be calculated with just
|
- This way mineral ground toughness can be calculated with just
|
||||||
some formula, as well as tool strengths
|
some formula, as well as tool strengths
|
||||||
|
- There are TODOs in appropriate files: material.h, content_mapnode.h
|
||||||
|
|
||||||
TODO: Flowing water to actually contain flow direction information
|
TODO: Flowing water to actually contain flow direction information
|
||||||
- There is a space for this - it just has to be implemented.
|
- There is a space for this - it just has to be implemented.
|
||||||
|
|
||||||
SUGG: Erosion simulation at map generation time
|
|
||||||
- Simulate water flows, which would carve out dirt fast and
|
|
||||||
then turn stone into gravel and sand and relocate it.
|
|
||||||
- How about relocating minerals, too? Coal and gold in
|
|
||||||
downstream sand and gravel would be kind of cool
|
|
||||||
- This would need a better way of handling minerals, mainly
|
|
||||||
to have mineral content as a separate field. the first
|
|
||||||
parameter field is free for this.
|
|
||||||
- Simulate rock falling from cliffs when water has removed
|
|
||||||
enough solid rock from the bottom
|
|
||||||
|
|
||||||
SUGG: Try out the notch way of generating maps, that is, make bunches
|
SUGG: Try out the notch way of generating maps, that is, make bunches
|
||||||
of low-res 3d noise and interpolate linearly.
|
of low-res 3d noise and interpolate linearly.
|
||||||
|
|
||||||
Mapgen v2:
|
Mapgen v2 (the current one):
|
||||||
* Possibly add some kind of erosion and other stuff
|
* Possibly add some kind of erosion and other stuff
|
||||||
* Better water generation (spread it to underwater caverns but don't
|
* Better water generation (spread it to underwater caverns but don't
|
||||||
fill dungeons that don't touch big water masses)
|
fill dungeons that don't touch big water masses)
|
||||||
@ -293,25 +317,66 @@ Mapgen v2:
|
|||||||
the other chunk making nasty straight walls when the other chunk
|
the other chunk making nasty straight walls when the other chunk
|
||||||
is generated. Fix it. Maybe just a special case if the ground is
|
is generated. Fix it. Maybe just a special case if the ground is
|
||||||
flat?
|
flat?
|
||||||
|
* Consider not updating this one and make a good mainly block-based
|
||||||
|
generator
|
||||||
|
|
||||||
|
SUGG: Make two "modified states", one that forces the block to be saved at
|
||||||
|
the next save event, and one that makes the block to be saved at exit
|
||||||
|
time.
|
||||||
|
|
||||||
|
TODO: Add a not_fully_generated flag to MapBlock, which would be set for
|
||||||
|
blocks that contain eg. trees from neighboring generations but haven't
|
||||||
|
been generated itself. This is required for the future generator.
|
||||||
|
|
||||||
Misc. stuff:
|
Misc. stuff:
|
||||||
------------
|
------------
|
||||||
* Move digging property stuff from material.{h,cpp} to mapnode.cpp
|
- Make sure server handles removing grass when a block is placed (etc)
|
||||||
- ...Or maybe move content_features to material.{h,cpp}?
|
- The client should not do it by itself
|
||||||
|
- Block cube placement around player's head
|
||||||
|
- Protocol version field
|
||||||
|
- Consider getting some textures from cisoun's texture pack
|
||||||
|
- Ask from Cisoun
|
||||||
|
- Make sure the fence implementation and data format is good
|
||||||
|
- Think about using same bits for material for fences and doors, for
|
||||||
|
example
|
||||||
|
- Finish the ActiveBlockModifier stuff and use it for something
|
||||||
|
- Move mineral to param2, increment map serialization version, add conversion
|
||||||
|
|
||||||
|
TODO: Add a per-sector database to store surface stuff as simple flags/values
|
||||||
|
- Light?
|
||||||
|
- A building?
|
||||||
|
And at some point make the server send this data to the client too,
|
||||||
|
instead of referring to the noise functions
|
||||||
|
- Ground height
|
||||||
|
- Surface ground type
|
||||||
|
- Trees?
|
||||||
|
|
||||||
|
TODO: Restart irrlicht completely when coming back to main menu from game.
|
||||||
|
- This gets rid of everything that is stored in irrlicht's caches.
|
||||||
|
|
||||||
|
TODO: Merge bahamada's audio stuff (clean patch available)
|
||||||
|
|
||||||
|
TODO: Merge spongie's chest/furnace direction (by hand)
|
||||||
|
|
||||||
|
TODO: Merge key configuration menu (no clean patch available)
|
||||||
|
|
||||||
Making it more portable:
|
Making it more portable:
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Stuff to do before release:
|
Stuff to do before release:
|
||||||
---------------------------
|
---------------------------
|
||||||
- Player default privileges and default password
|
|
||||||
- Chat privilege
|
Fixes to the current release:
|
||||||
- Some simple block-based dynamic stuff in the world (finish the
|
-----------------------------
|
||||||
ActiveBlockModifier stuff)
|
|
||||||
- Protocol version field
|
Stuff to do after release:
|
||||||
- Consider getting some textures from cisoun's texture pack
|
---------------------------
|
||||||
- Add a long step function to objects that is called with the time
|
|
||||||
difference when block activates
|
Doing currently:
|
||||||
|
----------------
|
||||||
|
|
||||||
|
TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
||||||
|
(on client and server)
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
@ -377,6 +442,9 @@ Settings g_settings;
|
|||||||
// This is located in defaultsettings.cpp
|
// This is located in defaultsettings.cpp
|
||||||
extern void set_default_settings();
|
extern void set_default_settings();
|
||||||
|
|
||||||
|
// Global profiler
|
||||||
|
Profiler g_profiler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Random stuff
|
Random stuff
|
||||||
*/
|
*/
|
||||||
@ -427,7 +495,14 @@ std::ostream *derr_client_ptr = &dstream;
|
|||||||
class TimeGetter
|
class TimeGetter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimeGetter(IrrlichtDevice *device):
|
virtual u32 getTime() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A precise irrlicht one
|
||||||
|
class IrrlichtTimeGetter: public TimeGetter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IrrlichtTimeGetter(IrrlichtDevice *device):
|
||||||
m_device(device)
|
m_device(device)
|
||||||
{}
|
{}
|
||||||
u32 getTime()
|
u32 getTime()
|
||||||
@ -439,8 +514,18 @@ public:
|
|||||||
private:
|
private:
|
||||||
IrrlichtDevice *m_device;
|
IrrlichtDevice *m_device;
|
||||||
};
|
};
|
||||||
|
// Not so precise one which works without irrlicht
|
||||||
|
class SimpleTimeGetter: public TimeGetter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
u32 getTime()
|
||||||
|
{
|
||||||
|
return porting::getTimeMs();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// A pointer to a global instance of the time getter
|
// A pointer to a global instance of the time getter
|
||||||
|
// TODO: why?
|
||||||
TimeGetter *g_timegetter = NULL;
|
TimeGetter *g_timegetter = NULL;
|
||||||
|
|
||||||
u32 getTimeMs()
|
u32 getTimeMs()
|
||||||
@ -994,6 +1079,15 @@ void drawMenuBackground(video::IVideoDriver* driver)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Initialization
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set locale. This is for forcing '.' as the decimal point.
|
||||||
|
std::locale::global(std::locale("C"));
|
||||||
|
// This enables printing all characters in bitmap font
|
||||||
|
setlocale(LC_CTYPE, "en_US");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parse command line
|
Parse command line
|
||||||
*/
|
*/
|
||||||
@ -1057,22 +1151,29 @@ int main(int argc, char *argv[])
|
|||||||
disable_stderr = true;
|
disable_stderr = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
porting::signal_handler_init();
|
||||||
|
bool &kill = *porting::signal_handler_killstatus();
|
||||||
|
|
||||||
|
// Initialize porting::path_data and porting::path_userdata
|
||||||
|
porting::initializePaths();
|
||||||
|
|
||||||
|
// Create user data directory
|
||||||
|
fs::CreateDir(porting::path_userdata);
|
||||||
|
|
||||||
// Initialize debug streams
|
// Initialize debug streams
|
||||||
debugstreams_init(disable_stderr, DEBUGFILE);
|
#ifdef RUN_IN_PLACE
|
||||||
|
std::string debugfile = DEBUGFILE;
|
||||||
|
#else
|
||||||
|
std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;
|
||||||
|
#endif
|
||||||
|
debugstreams_init(disable_stderr, debugfile.c_str());
|
||||||
// Initialize debug stacks
|
// Initialize debug stacks
|
||||||
debug_stacks_init();
|
debug_stacks_init();
|
||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
porting::signal_handler_init();
|
// Init material properties table
|
||||||
bool &kill = *porting::signal_handler_killstatus();
|
//initializeMaterialProperties();
|
||||||
|
|
||||||
porting::initializePaths();
|
|
||||||
// Create user data directory
|
|
||||||
fs::CreateDir(porting::path_userdata);
|
|
||||||
|
|
||||||
// C-style stuff initialization
|
|
||||||
initializeMaterialProperties();
|
|
||||||
|
|
||||||
// Debug handler
|
// Debug handler
|
||||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||||
@ -1090,19 +1191,10 @@ int main(int argc, char *argv[])
|
|||||||
// Initialize default settings
|
// Initialize default settings
|
||||||
set_default_settings();
|
set_default_settings();
|
||||||
|
|
||||||
// Set locale. This is for forcing '.' as the decimal point.
|
|
||||||
std::locale::global(std::locale("C"));
|
|
||||||
// This enables printing all characters in bitmap font
|
|
||||||
setlocale(LC_CTYPE, "en_US");
|
|
||||||
|
|
||||||
// Initialize sockets
|
// Initialize sockets
|
||||||
sockets_init();
|
sockets_init();
|
||||||
atexit(sockets_cleanup);
|
atexit(sockets_cleanup);
|
||||||
|
|
||||||
/*
|
|
||||||
Initialization
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read config file
|
Read config file
|
||||||
*/
|
*/
|
||||||
@ -1188,7 +1280,7 @@ int main(int argc, char *argv[])
|
|||||||
port = 30000;
|
port = 30000;
|
||||||
|
|
||||||
// Map directory
|
// Map directory
|
||||||
std::string map_dir = porting::path_userdata+"/map";
|
std::string map_dir = porting::path_userdata+"/world";
|
||||||
if(cmd_args.exists("map-dir"))
|
if(cmd_args.exists("map-dir"))
|
||||||
map_dir = cmd_args.get("map-dir");
|
map_dir = cmd_args.get("map-dir");
|
||||||
else if(g_settings.exists("map-dir"))
|
else if(g_settings.exists("map-dir"))
|
||||||
@ -1199,6 +1291,9 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
DSTACK("Dedicated server branch");
|
DSTACK("Dedicated server branch");
|
||||||
|
|
||||||
|
// Create time getter
|
||||||
|
g_timegetter = new SimpleTimeGetter();
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
Server server(map_dir.c_str());
|
Server server(map_dir.c_str());
|
||||||
server.start(port);
|
server.start(port);
|
||||||
@ -1281,7 +1376,7 @@ int main(int argc, char *argv[])
|
|||||||
device = device;
|
device = device;
|
||||||
|
|
||||||
// Create time getter
|
// Create time getter
|
||||||
g_timegetter = new TimeGetter(device);
|
g_timegetter = new IrrlichtTimeGetter(device);
|
||||||
|
|
||||||
// Create game callback for menus
|
// Create game callback for menus
|
||||||
g_gamecallback = new MainGameCallback(device);
|
g_gamecallback = new MainGameCallback(device);
|
||||||
@ -1349,7 +1444,6 @@ int main(int argc, char *argv[])
|
|||||||
Preload some textures and stuff
|
Preload some textures and stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init_content_inventory_texture_paths();
|
|
||||||
init_mapnode(); // Second call with g_texturesource set
|
init_mapnode(); // Second call with g_texturesource set
|
||||||
init_mineral();
|
init_mineral();
|
||||||
|
|
||||||
@ -1488,13 +1582,22 @@ int main(int argc, char *argv[])
|
|||||||
g_settings.set("creative_mode", itos(menudata.creative_mode));
|
g_settings.set("creative_mode", itos(menudata.creative_mode));
|
||||||
g_settings.set("enable_damage", itos(menudata.enable_damage));
|
g_settings.set("enable_damage", itos(menudata.enable_damage));
|
||||||
|
|
||||||
// Check for valid parameters, restart menu if invalid.
|
// NOTE: These are now checked server side; no need to do it
|
||||||
|
// here, so let's not do it here.
|
||||||
|
/*// Check for valid parameters, restart menu if invalid.
|
||||||
if(playername == "")
|
if(playername == "")
|
||||||
{
|
{
|
||||||
error_message = L"Name required.";
|
error_message = L"Name required.";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Check that name has only valid chars
|
||||||
|
if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
|
||||||
|
{
|
||||||
|
error_message = L"Characters allowed: "
|
||||||
|
+narrow_to_wide(PLAYERNAME_ALLOWED_CHARS);
|
||||||
|
continue;
|
||||||
|
}*/
|
||||||
|
|
||||||
// Save settings
|
// Save settings
|
||||||
g_settings.set("name", playername);
|
g_settings.set("name", playername);
|
||||||
g_settings.set("address", address);
|
g_settings.set("address", address);
|
||||||
|
@ -28,6 +28,10 @@ extern Settings g_settings;
|
|||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
extern ITextureSource *g_texturesource;
|
extern ITextureSource *g_texturesource;
|
||||||
|
|
||||||
|
// Global profiler
|
||||||
|
#include "profiler.h"
|
||||||
|
extern Profiler g_profiler;
|
||||||
|
|
||||||
// Debug streams
|
// Debug streams
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
3483
src/map.cpp
3483
src/map.cpp
File diff suppressed because it is too large
Load Diff
246
src/map.h
246
src/map.h
@ -41,13 +41,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "mapchunk.h"
|
#include "mapchunk.h"
|
||||||
#include "nodemetadata.h"
|
#include "nodemetadata.h"
|
||||||
|
|
||||||
|
namespace mapgen{
|
||||||
|
struct BlockMakeData;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
MapEditEvent
|
||||||
|
*/
|
||||||
|
|
||||||
#define MAPTYPE_BASE 0
|
#define MAPTYPE_BASE 0
|
||||||
#define MAPTYPE_SERVER 1
|
#define MAPTYPE_SERVER 1
|
||||||
#define MAPTYPE_CLIENT 2
|
#define MAPTYPE_CLIENT 2
|
||||||
|
|
||||||
enum MapEditEventType{
|
enum MapEditEventType{
|
||||||
|
// Node added (changed from air or something else to something)
|
||||||
MEET_ADDNODE,
|
MEET_ADDNODE,
|
||||||
|
// Node removed (changed to air)
|
||||||
MEET_REMOVENODE,
|
MEET_REMOVENODE,
|
||||||
|
// Node metadata of block changed (not knowing which node exactly)
|
||||||
|
// p stores block coordinate
|
||||||
|
MEET_BLOCK_NODE_METADATA_CHANGED,
|
||||||
|
// Anything else
|
||||||
MEET_OTHER
|
MEET_OTHER
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,7 +136,7 @@ public:
|
|||||||
|
|
||||||
// On failure returns NULL
|
// On failure returns NULL
|
||||||
MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
|
MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
|
||||||
// On failure returns NULL
|
// Same as the above (there exists no lock anymore)
|
||||||
MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
|
MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
|
||||||
// On failure throws InvalidPositionException
|
// On failure throws InvalidPositionException
|
||||||
MapSector * getSectorNoGenerate(v2s16 p2d);
|
MapSector * getSectorNoGenerate(v2s16 p2d);
|
||||||
@ -258,6 +272,9 @@ public:
|
|||||||
//bool updateChangedVisibleArea();
|
//bool updateChangedVisibleArea();
|
||||||
|
|
||||||
virtual void save(bool only_changed){assert(0);};
|
virtual void save(bool only_changed){assert(0);};
|
||||||
|
|
||||||
|
// Server implements this
|
||||||
|
virtual void saveBlock(MapBlock *block){};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Updates usage timers
|
Updates usage timers
|
||||||
@ -269,7 +286,7 @@ public:
|
|||||||
void deleteSectors(core::list<v2s16> &list, bool only_blocks);
|
void deleteSectors(core::list<v2s16> &list, bool only_blocks);
|
||||||
|
|
||||||
// Returns count of deleted sectors
|
// Returns count of deleted sectors
|
||||||
u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
|
u32 unloadUnusedData(float timeout, bool only_blocks=false,
|
||||||
core::list<v3s16> *deleted_blocks=NULL);
|
core::list<v3s16> *deleted_blocks=NULL);
|
||||||
|
|
||||||
// For debug printing
|
// For debug printing
|
||||||
@ -320,8 +337,6 @@ protected:
|
|||||||
This is the only map class that is able to generate map.
|
This is the only map class that is able to generate map.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ChunkMakeData;
|
|
||||||
|
|
||||||
class ServerMap : public Map
|
class ServerMap : public Map
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -336,160 +351,25 @@ public:
|
|||||||
return MAPTYPE_SERVER;
|
return MAPTYPE_SERVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Map generation
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Returns the position of the chunk where the sector is in
|
|
||||||
v2s16 sector_to_chunk(v2s16 sectorpos)
|
|
||||||
{
|
|
||||||
if(m_chunksize == 0)
|
|
||||||
return v2s16(0,0);
|
|
||||||
sectorpos.X += m_chunksize / 2;
|
|
||||||
sectorpos.Y += m_chunksize / 2;
|
|
||||||
v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
|
|
||||||
return chunkpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the position of the (0,0) sector of the chunk
|
|
||||||
v2s16 chunk_to_sector(v2s16 chunkpos)
|
|
||||||
{
|
|
||||||
if(m_chunksize == 0)
|
|
||||||
return v2s16(0,0);
|
|
||||||
v2s16 sectorpos(
|
|
||||||
chunkpos.X * m_chunksize,
|
|
||||||
chunkpos.Y * m_chunksize
|
|
||||||
);
|
|
||||||
sectorpos.X -= m_chunksize / 2;
|
|
||||||
sectorpos.Y -= m_chunksize / 2;
|
|
||||||
return sectorpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get a chunk.
|
|
||||||
*/
|
|
||||||
MapChunk *getChunk(v2s16 chunkpos)
|
|
||||||
{
|
|
||||||
core::map<v2s16, MapChunk*>::Node *n;
|
|
||||||
n = m_chunks.find(chunkpos);
|
|
||||||
if(n == NULL)
|
|
||||||
return NULL;
|
|
||||||
return n->getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
True if the chunk and its neighbors are fully generated.
|
|
||||||
It means the chunk will not be touched in the future by the
|
|
||||||
generator. If false, generateChunk will make it true.
|
|
||||||
*/
|
|
||||||
bool chunkNonVolatile(v2s16 chunkpos)
|
|
||||||
{
|
|
||||||
if(m_chunksize == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/*for(s16 x=-1; x<=1; x++)
|
|
||||||
for(s16 y=-1; y<=1; y++)*/
|
|
||||||
s16 x=0;
|
|
||||||
s16 y=0;
|
|
||||||
{
|
|
||||||
v2s16 chunkpos0 = chunkpos + v2s16(x,y);
|
|
||||||
MapChunk *chunk = getChunk(chunkpos);
|
|
||||||
if(chunk == NULL)
|
|
||||||
return false;
|
|
||||||
if(chunk->getGenLevel() != GENERATED_FULLY)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Returns true if any chunk is marked as modified
|
|
||||||
*/
|
|
||||||
bool anyChunkModified()
|
|
||||||
{
|
|
||||||
for(core::map<v2s16, MapChunk*>::Iterator
|
|
||||||
i = m_chunks.getIterator();
|
|
||||||
i.atEnd()==false; i++)
|
|
||||||
{
|
|
||||||
v2s16 p = i.getNode()->getKey();
|
|
||||||
MapChunk *chunk = i.getNode()->getValue();
|
|
||||||
if(chunk->isModified())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChunksNonModified()
|
|
||||||
{
|
|
||||||
for(core::map<v2s16, MapChunk*>::Iterator
|
|
||||||
i = m_chunks.getIterator();
|
|
||||||
i.atEnd()==false; i++)
|
|
||||||
{
|
|
||||||
v2s16 p = i.getNode()->getKey();
|
|
||||||
MapChunk *chunk = i.getNode()->getValue();
|
|
||||||
chunk->setModified(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Chunks are generated by using these and makeChunk().
|
|
||||||
*/
|
|
||||||
void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
|
|
||||||
MapChunk* finishChunkMake(ChunkMakeData &data,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Generate a chunk.
|
|
||||||
|
|
||||||
All chunks touching this one can be altered also.
|
|
||||||
*/
|
|
||||||
/*MapChunk* generateChunkRaw(v2s16 chunkpos,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
|
||||||
bool force=false);*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Generate a chunk and its neighbors so that it won't be touched
|
|
||||||
anymore.
|
|
||||||
*/
|
|
||||||
/*MapChunk* generateChunk(v2s16 chunkpos,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks);*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Generate a sector.
|
|
||||||
|
|
||||||
This is mainly called by generateChunkRaw.
|
|
||||||
*/
|
|
||||||
//ServerMapSector * generateSector(v2s16 p);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a sector from somewhere.
|
Get a sector from somewhere.
|
||||||
- Check memory
|
- Check memory
|
||||||
- Check disk (loads blocks also)
|
- Check disk (doesn't load blocks)
|
||||||
- Create blank one
|
- Create blank one
|
||||||
*/
|
*/
|
||||||
ServerMapSector * createSector(v2s16 p);
|
ServerMapSector * createSector(v2s16 p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a sector from somewhere.
|
Blocks are generated by using these and makeBlock().
|
||||||
- Check memory
|
|
||||||
- Check disk (loads blocks also)
|
|
||||||
- Generate chunk
|
|
||||||
*/
|
*/
|
||||||
/*MapSector * emergeSector(v2s16 p,
|
void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks);*/
|
MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
|
||||||
|
core::map<v3s16, MapBlock*> &changed_blocks);
|
||||||
|
|
||||||
/*MapSector * emergeSector(v2s16 p)
|
// A non-threaded wrapper to the above
|
||||||
{
|
|
||||||
core::map<v3s16, MapBlock*> changed_blocks;
|
|
||||||
return emergeSector(p, changed_blocks);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
MapBlock * generateBlock(
|
MapBlock * generateBlock(
|
||||||
v3s16 p,
|
v3s16 p,
|
||||||
MapBlock *original_dummy,
|
core::map<v3s16, MapBlock*> &modified_blocks
|
||||||
ServerMapSector *sector,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
|
||||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -498,37 +378,17 @@ public:
|
|||||||
- Create blank
|
- Create blank
|
||||||
*/
|
*/
|
||||||
MapBlock * createBlock(v3s16 p);
|
MapBlock * createBlock(v3s16 p);
|
||||||
|
|
||||||
/*
|
|
||||||
only_from_disk, changed_blocks and lighting_invalidated_blocks
|
|
||||||
are not properly used by the new map generator.
|
|
||||||
*/
|
|
||||||
MapBlock * emergeBlock(
|
|
||||||
v3s16 p,
|
|
||||||
bool only_from_disk,
|
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
|
||||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
|
||||||
);
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
|
NOTE: This comment might be outdated
|
||||||
|
|
||||||
Forcefully get a block from somewhere.
|
Forcefully get a block from somewhere.
|
||||||
|
|
||||||
Exceptions:
|
InvalidPositionException possible if only_from_disk==true
|
||||||
- InvalidPositionException: possible if only_from_disk==true
|
|
||||||
|
|
||||||
changed_blocks:
|
Parameters:
|
||||||
- All already existing blocks that were modified are added.
|
changed_blocks: Blocks that have been modified
|
||||||
- If found on disk, nothing will be added.
|
|
||||||
- If generated, the new block will not be included.
|
|
||||||
|
|
||||||
lighting_invalidated_blocks:
|
|
||||||
- All blocks that have heavy-to-calculate lighting changes
|
|
||||||
are added.
|
|
||||||
- updateLighting() should be called for these.
|
|
||||||
|
|
||||||
- A block that is in changed_blocks may not be in
|
|
||||||
lighting_invalidated_blocks.
|
|
||||||
*/
|
*/
|
||||||
MapBlock * emergeBlock(
|
MapBlock * emergeBlock(
|
||||||
v3s16 p,
|
v3s16 p,
|
||||||
@ -551,6 +411,7 @@ public:
|
|||||||
// dirname: final directory name
|
// dirname: final directory name
|
||||||
v2s16 getSectorPos(std::string dirname);
|
v2s16 getSectorPos(std::string dirname);
|
||||||
v3s16 getBlockPos(std::string sectordir, std::string blockfile);
|
v3s16 getBlockPos(std::string sectordir, std::string blockfile);
|
||||||
|
static std::string getBlockFilename(v3s16 p);
|
||||||
|
|
||||||
void save(bool only_changed);
|
void save(bool only_changed);
|
||||||
//void loadAll();
|
//void loadAll();
|
||||||
@ -559,8 +420,8 @@ public:
|
|||||||
void saveMapMeta();
|
void saveMapMeta();
|
||||||
void loadMapMeta();
|
void loadMapMeta();
|
||||||
|
|
||||||
void saveChunkMeta();
|
/*void saveChunkMeta();
|
||||||
void loadChunkMeta();
|
void loadChunkMeta();*/
|
||||||
|
|
||||||
// The sector mutex should be locked when calling most of these
|
// The sector mutex should be locked when calling most of these
|
||||||
|
|
||||||
@ -569,6 +430,7 @@ public:
|
|||||||
// DEPRECATED? Sectors have no metadata anymore.
|
// DEPRECATED? Sectors have no metadata anymore.
|
||||||
void saveSectorMeta(ServerMapSector *sector);
|
void saveSectorMeta(ServerMapSector *sector);
|
||||||
MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
|
MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
|
||||||
|
bool loadSectorMeta(v2s16 p2d);
|
||||||
|
|
||||||
// Full load of a sector including all blocks.
|
// Full load of a sector including all blocks.
|
||||||
// returns true on success, false on failure.
|
// returns true on success, false on failure.
|
||||||
@ -580,12 +442,15 @@ public:
|
|||||||
void saveBlock(MapBlock *block);
|
void saveBlock(MapBlock *block);
|
||||||
// This will generate a sector with getSector if not found.
|
// This will generate a sector with getSector if not found.
|
||||||
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
|
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
|
||||||
|
MapBlock* loadBlock(v3s16 p);
|
||||||
|
|
||||||
// For debug printing
|
// For debug printing
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
bool isSavingEnabled(){ return m_map_saving_enabled; }
|
bool isSavingEnabled(){ return m_map_saving_enabled; }
|
||||||
|
|
||||||
|
u64 getSeed(){ return m_seed; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Seed used for all kinds of randomness
|
// Seed used for all kinds of randomness
|
||||||
u64 m_seed;
|
u64 m_seed;
|
||||||
@ -593,11 +458,13 @@ private:
|
|||||||
std::string m_savedir;
|
std::string m_savedir;
|
||||||
bool m_map_saving_enabled;
|
bool m_map_saving_enabled;
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Chunk size in MapSectors
|
// Chunk size in MapSectors
|
||||||
// If 0, chunks are disabled.
|
// If 0, chunks are disabled.
|
||||||
s16 m_chunksize;
|
s16 m_chunksize;
|
||||||
// Chunks
|
// Chunks
|
||||||
core::map<v2s16, MapChunk*> m_chunks;
|
core::map<v2s16, MapChunk*> m_chunks;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Metadata is re-written on disk only if this is true.
|
Metadata is re-written on disk only if this is true.
|
||||||
@ -732,6 +599,12 @@ public:
|
|||||||
// For debug printing
|
// For debug printing
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
|
// Check if sector was drawn on last render()
|
||||||
|
bool sectorWasDrawn(v2s16 p)
|
||||||
|
{
|
||||||
|
return (m_last_drawn_sectors.find(p) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Client *m_client;
|
Client *m_client;
|
||||||
|
|
||||||
@ -746,7 +619,8 @@ private:
|
|||||||
v3f m_camera_position;
|
v3f m_camera_position;
|
||||||
v3f m_camera_direction;
|
v3f m_camera_direction;
|
||||||
JMutex m_camera_mutex;
|
JMutex m_camera_mutex;
|
||||||
|
|
||||||
|
core::map<v2s16, bool> m_last_drawn_sectors;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -796,29 +670,5 @@ protected:
|
|||||||
bool m_create_area;
|
bool m_create_area;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChunkMakeData
|
|
||||||
{
|
|
||||||
bool no_op;
|
|
||||||
ManualMapVoxelManipulator vmanip;
|
|
||||||
u64 seed;
|
|
||||||
v2s16 chunkpos;
|
|
||||||
s16 y_blocks_min;
|
|
||||||
s16 y_blocks_max;
|
|
||||||
v2s16 sectorpos_base;
|
|
||||||
s16 sectorpos_base_size;
|
|
||||||
v2s16 sectorpos_bigbase;
|
|
||||||
s16 sectorpos_bigbase_size;
|
|
||||||
s16 max_spread_amount;
|
|
||||||
UniqueQueue<v3s16> transforming_liquid;
|
|
||||||
|
|
||||||
ChunkMakeData():
|
|
||||||
no_op(false),
|
|
||||||
vmanip(NULL),
|
|
||||||
seed(0)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
void makeChunk(ChunkMakeData *data);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
1847
src/mapblock.cpp
1847
src/mapblock.cpp
File diff suppressed because it is too large
Load Diff
260
src/mapblock.h
260
src/mapblock.h
@ -33,10 +33,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "nodemetadata.h"
|
#include "nodemetadata.h"
|
||||||
#include "staticobject.h"
|
#include "staticobject.h"
|
||||||
|
#include "mapblock_nodemod.h"
|
||||||
|
#ifndef SERVER
|
||||||
|
#include "mapblock_mesh.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
|
#define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
|
||||||
|
|
||||||
// Named by looking towards z+
|
/*// Named by looking towards z+
|
||||||
enum{
|
enum{
|
||||||
FACE_BACK=0,
|
FACE_BACK=0,
|
||||||
FACE_TOP,
|
FACE_TOP,
|
||||||
@ -44,103 +49,37 @@ enum{
|
|||||||
FACE_FRONT,
|
FACE_FRONT,
|
||||||
FACE_BOTTOM,
|
FACE_BOTTOM,
|
||||||
FACE_LEFT
|
FACE_LEFT
|
||||||
};
|
};*/
|
||||||
|
|
||||||
struct FastFace
|
enum ModifiedState
|
||||||
{
|
{
|
||||||
TileSpec tile;
|
// Has not been modified.
|
||||||
video::S3DVertex vertices[4]; // Precalculated vertices
|
MOD_STATE_CLEAN = 0,
|
||||||
|
MOD_RESERVED1 = 1,
|
||||||
|
// Has been modified, and will be saved when being unloaded.
|
||||||
|
MOD_STATE_WRITE_AT_UNLOAD = 2,
|
||||||
|
MOD_RESERVED3 = 3,
|
||||||
|
// Has been modified, and will be saved as soon as possible.
|
||||||
|
MOD_STATE_WRITE_NEEDED = 4,
|
||||||
|
MOD_RESERVED5 = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum NodeModType
|
// NOTE: If this is enabled, set MapBlock to be initialized with
|
||||||
|
// CONTENT_IGNORE.
|
||||||
|
/*enum BlockGenerationStatus
|
||||||
{
|
{
|
||||||
NODEMOD_NONE,
|
// Completely non-generated (filled with CONTENT_IGNORE).
|
||||||
NODEMOD_CHANGECONTENT, //param is content id
|
BLOCKGEN_UNTOUCHED=0,
|
||||||
NODEMOD_CRACK // param is crack progression
|
// Trees or similar might have been blitted from other blocks to here.
|
||||||
};
|
// Otherwise, the block contains CONTENT_IGNORE
|
||||||
|
BLOCKGEN_FROM_NEIGHBORS=2,
|
||||||
struct NodeMod
|
// Has been generated, but some neighbors might put some stuff in here
|
||||||
{
|
// when they are generated.
|
||||||
NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0)
|
// Does not contain any CONTENT_IGNORE
|
||||||
{
|
BLOCKGEN_SELF_GENERATED=4,
|
||||||
type = a_type;
|
// The block and all its neighbors have been generated
|
||||||
param = a_param;
|
BLOCKGEN_FULLY_GENERATED=6
|
||||||
}
|
};*/
|
||||||
bool operator==(const NodeMod &other)
|
|
||||||
{
|
|
||||||
return (type == other.type && param == other.param);
|
|
||||||
}
|
|
||||||
enum NodeModType type;
|
|
||||||
u16 param;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NodeModMap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
returns true if the mod was different last time
|
|
||||||
*/
|
|
||||||
bool set(v3s16 p, const NodeMod &mod)
|
|
||||||
{
|
|
||||||
// See if old is different, cancel if it is not different.
|
|
||||||
core::map<v3s16, NodeMod>::Node *n = m_mods.find(p);
|
|
||||||
if(n)
|
|
||||||
{
|
|
||||||
NodeMod old = n->getValue();
|
|
||||||
if(old == mod)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n->setValue(mod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_mods.insert(p, mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Returns true if there was one
|
|
||||||
bool get(v3s16 p, NodeMod *mod)
|
|
||||||
{
|
|
||||||
core::map<v3s16, NodeMod>::Node *n;
|
|
||||||
n = m_mods.find(p);
|
|
||||||
if(n == NULL)
|
|
||||||
return false;
|
|
||||||
if(mod)
|
|
||||||
*mod = n->getValue();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool clear(v3s16 p)
|
|
||||||
{
|
|
||||||
if(m_mods.find(p))
|
|
||||||
{
|
|
||||||
m_mods.remove(p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool clear()
|
|
||||||
{
|
|
||||||
if(m_mods.size() == 0)
|
|
||||||
return false;
|
|
||||||
m_mods.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void copy(NodeModMap &dest)
|
|
||||||
{
|
|
||||||
dest.m_mods.clear();
|
|
||||||
|
|
||||||
for(core::map<v3s16, NodeMod>::Iterator
|
|
||||||
i = m_mods.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
dest.m_mods.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
core::map<v3s16, NodeMod> m_mods;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -170,35 +109,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Mesh making stuff
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MapBlock;
|
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
|
|
||||||
struct MeshMakeData
|
|
||||||
{
|
|
||||||
u32 m_daynight_ratio;
|
|
||||||
NodeModMap m_temp_mods;
|
|
||||||
VoxelManipulator m_vmanip;
|
|
||||||
v3s16 m_blockpos;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copy central data directly from block, and other data from
|
|
||||||
parent of block.
|
|
||||||
*/
|
|
||||||
void fill(u32 daynight_ratio, MapBlock *block);
|
|
||||||
};
|
|
||||||
|
|
||||||
scene::SMesh* makeMapBlockMesh(MeshMakeData *data);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
|
||||||
v3s16 face_dir);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MapBlock itself
|
MapBlock itself
|
||||||
*/
|
*/
|
||||||
@ -226,9 +136,10 @@ public:
|
|||||||
u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
||||||
data = new MapNode[l];
|
data = new MapNode[l];
|
||||||
for(u32 i=0; i<l; i++){
|
for(u32 i=0; i<l; i++){
|
||||||
data[i] = MapNode();
|
//data[i] = MapNode();
|
||||||
|
data[i] = MapNode(CONTENT_IGNORE);
|
||||||
}
|
}
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -250,19 +161,43 @@ public:
|
|||||||
modified, so that the block is saved and possibly not deleted from
|
modified, so that the block is saved and possibly not deleted from
|
||||||
memory.
|
memory.
|
||||||
*/
|
*/
|
||||||
|
// DEPRECATED, use *Modified()
|
||||||
void setChangedFlag()
|
void setChangedFlag()
|
||||||
{
|
{
|
||||||
changed = true;
|
//dstream<<"Deprecated setChangedFlag() called"<<std::endl;
|
||||||
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
|
// DEPRECATED, use *Modified()
|
||||||
void resetChangedFlag()
|
void resetChangedFlag()
|
||||||
{
|
{
|
||||||
changed = false;
|
//dstream<<"Deprecated resetChangedFlag() called"<<std::endl;
|
||||||
|
resetModified();
|
||||||
}
|
}
|
||||||
|
// DEPRECATED, use *Modified()
|
||||||
bool getChangedFlag()
|
bool getChangedFlag()
|
||||||
{
|
{
|
||||||
return changed;
|
//dstream<<"Deprecated getChangedFlag() called"<<std::endl;
|
||||||
|
if(getModified() == MOD_STATE_CLEAN)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// m_modified methods
|
||||||
|
void raiseModified(u32 mod)
|
||||||
|
{
|
||||||
|
m_modified = MYMAX(m_modified, mod);
|
||||||
|
}
|
||||||
|
u32 getModified()
|
||||||
|
{
|
||||||
|
return m_modified;
|
||||||
|
}
|
||||||
|
void resetModified()
|
||||||
|
{
|
||||||
|
m_modified = MOD_STATE_CLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is_underground getter/setter
|
||||||
bool getIsUnderground()
|
bool getIsUnderground()
|
||||||
{
|
{
|
||||||
return is_underground;
|
return is_underground;
|
||||||
@ -270,7 +205,7 @@ public:
|
|||||||
void setIsUnderground(bool a_is_underground)
|
void setIsUnderground(bool a_is_underground)
|
||||||
{
|
{
|
||||||
is_underground = a_is_underground;
|
is_underground = a_is_underground;
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
@ -288,22 +223,22 @@ public:
|
|||||||
void setLightingExpired(bool expired)
|
void setLightingExpired(bool expired)
|
||||||
{
|
{
|
||||||
m_lighting_expired = expired;
|
m_lighting_expired = expired;
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
bool getLightingExpired()
|
bool getLightingExpired()
|
||||||
{
|
{
|
||||||
return m_lighting_expired;
|
return m_lighting_expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bool isFullyGenerated()
|
bool isGenerated()
|
||||||
{
|
{
|
||||||
return !m_not_fully_generated;
|
return m_generated;
|
||||||
}
|
}
|
||||||
void setFullyGenerated(bool b)
|
void setGenerated(bool b)
|
||||||
{
|
{
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
m_not_fully_generated = !b;
|
m_generated = b;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
bool isValid()
|
bool isValid()
|
||||||
{
|
{
|
||||||
@ -381,7 +316,7 @@ public:
|
|||||||
if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||||
if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||||
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
|
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNode(v3s16 p, MapNode & n)
|
void setNode(v3s16 p, MapNode & n)
|
||||||
@ -410,7 +345,7 @@ public:
|
|||||||
if(data == NULL)
|
if(data == NULL)
|
||||||
throw InvalidPositionException();
|
throw InvalidPositionException();
|
||||||
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
|
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNodeNoCheck(v3s16 p, MapNode & n)
|
void setNodeNoCheck(v3s16 p, MapNode & n)
|
||||||
@ -474,8 +409,7 @@ public:
|
|||||||
|
|
||||||
// See comments in mapblock.cpp
|
// See comments in mapblock.cpp
|
||||||
bool propagateSunlight(core::map<v3s16, bool> & light_sources,
|
bool propagateSunlight(core::map<v3s16, bool> & light_sources,
|
||||||
bool remove_light=false, bool *black_air_left=NULL,
|
bool remove_light=false, bool *black_air_left=NULL);
|
||||||
bool grow_grass=false);
|
|
||||||
|
|
||||||
// Copies data to VoxelManipulator to getPosRelative()
|
// Copies data to VoxelManipulator to getPosRelative()
|
||||||
void copyTo(VoxelManipulator &dst);
|
void copyTo(VoxelManipulator &dst);
|
||||||
@ -487,36 +421,36 @@ public:
|
|||||||
DEPRECATED
|
DEPRECATED
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void serializeObjects(std::ostream &os, u8 version)
|
/*void serializeObjects(std::ostream &os, u8 version)
|
||||||
{
|
{
|
||||||
m_objects.serialize(os, version);
|
m_objects.serialize(os, version);
|
||||||
}
|
}*/
|
||||||
// If smgr!=NULL, new objects are added to the scene
|
// If smgr!=NULL, new objects are added to the scene
|
||||||
void updateObjects(std::istream &is, u8 version,
|
void updateObjects(std::istream &is, u8 version,
|
||||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
scene::ISceneManager *smgr, u32 daynight_ratio)
|
||||||
{
|
{
|
||||||
m_objects.update(is, version, smgr, daynight_ratio);
|
m_objects.update(is, version, smgr, daynight_ratio);
|
||||||
|
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
void clearObjects()
|
void clearObjects()
|
||||||
{
|
{
|
||||||
m_objects.clear();
|
m_objects.clear();
|
||||||
|
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
void addObject(MapBlockObject *object)
|
void addObject(MapBlockObject *object)
|
||||||
throw(ContainerFullException, AlreadyExistsException)
|
throw(ContainerFullException, AlreadyExistsException)
|
||||||
{
|
{
|
||||||
m_objects.add(object);
|
m_objects.add(object);
|
||||||
|
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
void removeObject(s16 id)
|
void removeObject(s16 id)
|
||||||
{
|
{
|
||||||
m_objects.remove(id);
|
m_objects.remove(id);
|
||||||
|
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
}
|
}
|
||||||
MapBlockObject * getObject(s16 id)
|
MapBlockObject * getObject(s16 id)
|
||||||
{
|
{
|
||||||
@ -626,12 +560,32 @@ public:
|
|||||||
void setTimestamp(u32 time)
|
void setTimestamp(u32 time)
|
||||||
{
|
{
|
||||||
m_timestamp = time;
|
m_timestamp = time;
|
||||||
setChangedFlag();
|
raiseModified(MOD_STATE_WRITE_AT_UNLOAD);
|
||||||
|
}
|
||||||
|
void setTimestampNoChangedFlag(u32 time)
|
||||||
|
{
|
||||||
|
m_timestamp = time;
|
||||||
}
|
}
|
||||||
u32 getTimestamp()
|
u32 getTimestamp()
|
||||||
{
|
{
|
||||||
return m_timestamp;
|
return m_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
See m_usage_timer
|
||||||
|
*/
|
||||||
|
void resetUsageTimer()
|
||||||
|
{
|
||||||
|
m_usage_timer = 0;
|
||||||
|
}
|
||||||
|
void incrementUsageTimer(float dtime)
|
||||||
|
{
|
||||||
|
m_usage_timer += dtime;
|
||||||
|
}
|
||||||
|
u32 getUsageTimer()
|
||||||
|
{
|
||||||
|
return m_usage_timer;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Serialization
|
Serialization
|
||||||
@ -698,10 +652,10 @@ private:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
- On the server, this is used for telling whether the
|
- On the server, this is used for telling whether the
|
||||||
block has been changed from the one on disk.
|
block has been modified from the one on disk.
|
||||||
- On the client, this is used for nothing.
|
- On the client, this is used for nothing.
|
||||||
*/
|
*/
|
||||||
bool changed;
|
u32 m_modified;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When propagating sunlight and the above block doesn't exist,
|
When propagating sunlight and the above block doesn't exist,
|
||||||
@ -724,6 +678,8 @@ private:
|
|||||||
|
|
||||||
// Whether day and night lighting differs
|
// Whether day and night lighting differs
|
||||||
bool m_day_night_differs;
|
bool m_day_night_differs;
|
||||||
|
|
||||||
|
bool m_generated;
|
||||||
|
|
||||||
// DEPRECATED
|
// DEPRECATED
|
||||||
MapBlockObjectList m_objects;
|
MapBlockObjectList m_objects;
|
||||||
@ -747,6 +703,12 @@ private:
|
|||||||
Value BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp.
|
Value BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp.
|
||||||
*/
|
*/
|
||||||
u32 m_timestamp;
|
u32 m_timestamp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
When the block is accessed, this is set to 0.
|
||||||
|
Map will unload the block when this reaches a timeout.
|
||||||
|
*/
|
||||||
|
float m_usage_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool blockpos_over_limit(v3s16 p)
|
inline bool blockpos_over_limit(v3s16 p)
|
||||||
|
791
src/mapblock_mesh.cpp
Normal file
791
src/mapblock_mesh.cpp
Normal file
@ -0,0 +1,791 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mapblock_mesh.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "main.h" // For g_settings and g_texturesource
|
||||||
|
#include "content_mapblock.h"
|
||||||
|
|
||||||
|
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
||||||
|
{
|
||||||
|
m_daynight_ratio = daynight_ratio;
|
||||||
|
m_blockpos = block->getPos();
|
||||||
|
|
||||||
|
v3s16 blockpos_nodes = m_blockpos*MAP_BLOCKSIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
There is no harm not copying the TempMods of the neighbors
|
||||||
|
because they are already copied to this block
|
||||||
|
*/
|
||||||
|
m_temp_mods.clear();
|
||||||
|
block->copyTempMods(m_temp_mods);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy data
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Allocate this block + neighbors
|
||||||
|
m_vmanip.clear();
|
||||||
|
m_vmanip.addArea(VoxelArea(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE,
|
||||||
|
blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1)));
|
||||||
|
|
||||||
|
{
|
||||||
|
//TimeTaker timer("copy central block data");
|
||||||
|
// 0ms
|
||||||
|
|
||||||
|
// Copy our data
|
||||||
|
block->copyTo(m_vmanip);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//TimeTaker timer("copy neighbor block data");
|
||||||
|
// 0ms
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy neighbors. This is lightning fast.
|
||||||
|
Copying only the borders would be *very* slow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Get map
|
||||||
|
NodeContainer *parentcontainer = block->getParent();
|
||||||
|
// This will only work if the parent is the map
|
||||||
|
assert(parentcontainer->nodeContainerId() == NODECONTAINER_ID_MAP);
|
||||||
|
// OK, we have the map!
|
||||||
|
Map *map = (Map*)parentcontainer;
|
||||||
|
|
||||||
|
for(u16 i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
const v3s16 &dir = g_6dirs[i];
|
||||||
|
v3s16 bp = m_blockpos + dir;
|
||||||
|
MapBlock *b = map->getBlockNoCreateNoEx(bp);
|
||||||
|
if(b)
|
||||||
|
b->copyTo(m_vmanip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
vertex_dirs: v3s16[4]
|
||||||
|
*/
|
||||||
|
void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If looked from outside the node towards the face, the corners are:
|
||||||
|
0: bottom-right
|
||||||
|
1: bottom-left
|
||||||
|
2: top-left
|
||||||
|
3: top-right
|
||||||
|
*/
|
||||||
|
if(dir == v3s16(0,0,1))
|
||||||
|
{
|
||||||
|
// If looking towards z+, this is the face that is behind
|
||||||
|
// the center point, facing towards z+.
|
||||||
|
vertex_dirs[0] = v3s16(-1,-1, 1);
|
||||||
|
vertex_dirs[1] = v3s16( 1,-1, 1);
|
||||||
|
vertex_dirs[2] = v3s16( 1, 1, 1);
|
||||||
|
vertex_dirs[3] = v3s16(-1, 1, 1);
|
||||||
|
}
|
||||||
|
else if(dir == v3s16(0,0,-1))
|
||||||
|
{
|
||||||
|
// faces towards Z-
|
||||||
|
vertex_dirs[0] = v3s16( 1,-1,-1);
|
||||||
|
vertex_dirs[1] = v3s16(-1,-1,-1);
|
||||||
|
vertex_dirs[2] = v3s16(-1, 1,-1);
|
||||||
|
vertex_dirs[3] = v3s16( 1, 1,-1);
|
||||||
|
}
|
||||||
|
else if(dir == v3s16(1,0,0))
|
||||||
|
{
|
||||||
|
// faces towards X+
|
||||||
|
vertex_dirs[0] = v3s16( 1,-1, 1);
|
||||||
|
vertex_dirs[1] = v3s16( 1,-1,-1);
|
||||||
|
vertex_dirs[2] = v3s16( 1, 1,-1);
|
||||||
|
vertex_dirs[3] = v3s16( 1, 1, 1);
|
||||||
|
}
|
||||||
|
else if(dir == v3s16(-1,0,0))
|
||||||
|
{
|
||||||
|
// faces towards X-
|
||||||
|
vertex_dirs[0] = v3s16(-1,-1,-1);
|
||||||
|
vertex_dirs[1] = v3s16(-1,-1, 1);
|
||||||
|
vertex_dirs[2] = v3s16(-1, 1, 1);
|
||||||
|
vertex_dirs[3] = v3s16(-1, 1,-1);
|
||||||
|
}
|
||||||
|
else if(dir == v3s16(0,1,0))
|
||||||
|
{
|
||||||
|
// faces towards Y+ (assume Z- as "down" in texture)
|
||||||
|
vertex_dirs[0] = v3s16( 1, 1,-1);
|
||||||
|
vertex_dirs[1] = v3s16(-1, 1,-1);
|
||||||
|
vertex_dirs[2] = v3s16(-1, 1, 1);
|
||||||
|
vertex_dirs[3] = v3s16( 1, 1, 1);
|
||||||
|
}
|
||||||
|
else if(dir == v3s16(0,-1,0))
|
||||||
|
{
|
||||||
|
// faces towards Y- (assume Z+ as "down" in texture)
|
||||||
|
vertex_dirs[0] = v3s16( 1,-1, 1);
|
||||||
|
vertex_dirs[1] = v3s16(-1,-1, 1);
|
||||||
|
vertex_dirs[2] = v3s16(-1,-1,-1);
|
||||||
|
vertex_dirs[3] = v3s16( 1,-1,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline video::SColor lightColor(u8 alpha, u8 light)
|
||||||
|
{
|
||||||
|
return video::SColor(alpha,light,light,light);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FastFace
|
||||||
|
{
|
||||||
|
TileSpec tile;
|
||||||
|
video::S3DVertex vertices[4]; // Precalculated vertices
|
||||||
|
};
|
||||||
|
|
||||||
|
void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p,
|
||||||
|
v3s16 dir, v3f scale, v3f posRelative_f,
|
||||||
|
core::array<FastFace> &dest)
|
||||||
|
{
|
||||||
|
FastFace face;
|
||||||
|
|
||||||
|
// Position is at the center of the cube.
|
||||||
|
v3f pos = p * BS;
|
||||||
|
posRelative_f *= BS;
|
||||||
|
|
||||||
|
v3f vertex_pos[4];
|
||||||
|
v3s16 vertex_dirs[4];
|
||||||
|
getNodeVertexDirs(dir, vertex_dirs);
|
||||||
|
for(u16 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
vertex_pos[i] = v3f(
|
||||||
|
BS/2*vertex_dirs[i].X,
|
||||||
|
BS/2*vertex_dirs[i].Y,
|
||||||
|
BS/2*vertex_dirs[i].Z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u16 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
vertex_pos[i].X *= scale.X;
|
||||||
|
vertex_pos[i].Y *= scale.Y;
|
||||||
|
vertex_pos[i].Z *= scale.Z;
|
||||||
|
vertex_pos[i] += pos + posRelative_f;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 abs_scale = 1.;
|
||||||
|
if (scale.X < 0.999 || scale.X > 1.001) abs_scale = scale.X;
|
||||||
|
else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y;
|
||||||
|
else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z;
|
||||||
|
|
||||||
|
v3f zerovector = v3f(0,0,0);
|
||||||
|
|
||||||
|
u8 alpha = tile.alpha;
|
||||||
|
/*u8 alpha = 255;
|
||||||
|
if(tile.id == TILE_WATER)
|
||||||
|
alpha = WATER_ALPHA;*/
|
||||||
|
|
||||||
|
float x0 = tile.texture.pos.X;
|
||||||
|
float y0 = tile.texture.pos.Y;
|
||||||
|
float w = tile.texture.size.X;
|
||||||
|
float h = tile.texture.size.Y;
|
||||||
|
|
||||||
|
/*video::SColor c = lightColor(alpha, li);
|
||||||
|
|
||||||
|
face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c,
|
||||||
|
core::vector2d<f32>(x0+w*abs_scale, y0+h));
|
||||||
|
face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), c,
|
||||||
|
core::vector2d<f32>(x0, y0+h));
|
||||||
|
face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), c,
|
||||||
|
core::vector2d<f32>(x0, y0));
|
||||||
|
face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), c,
|
||||||
|
core::vector2d<f32>(x0+w*abs_scale, y0));*/
|
||||||
|
|
||||||
|
face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0),
|
||||||
|
lightColor(alpha, li0),
|
||||||
|
core::vector2d<f32>(x0+w*abs_scale, y0+h));
|
||||||
|
face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0),
|
||||||
|
lightColor(alpha, li1),
|
||||||
|
core::vector2d<f32>(x0, y0+h));
|
||||||
|
face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0),
|
||||||
|
lightColor(alpha, li2),
|
||||||
|
core::vector2d<f32>(x0, y0));
|
||||||
|
face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0),
|
||||||
|
lightColor(alpha, li3),
|
||||||
|
core::vector2d<f32>(x0+w*abs_scale, y0));
|
||||||
|
|
||||||
|
face.tile = tile;
|
||||||
|
//DEBUG
|
||||||
|
//f->tile = TILE_STONE;
|
||||||
|
|
||||||
|
dest.push_back(face);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets node tile from any place relative to block.
|
||||||
|
Returns TILE_NODE if doesn't exist or should not be drawn.
|
||||||
|
*/
|
||||||
|
TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||||
|
NodeModMap &temp_mods)
|
||||||
|
{
|
||||||
|
TileSpec spec;
|
||||||
|
spec = mn.getTile(face_dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check temporary modifications on this node
|
||||||
|
*/
|
||||||
|
/*core::map<v3s16, NodeMod>::Node *n;
|
||||||
|
n = m_temp_mods.find(p);
|
||||||
|
// If modified
|
||||||
|
if(n != NULL)
|
||||||
|
{
|
||||||
|
struct NodeMod mod = n->getValue();*/
|
||||||
|
NodeMod mod;
|
||||||
|
if(temp_mods.get(p, &mod))
|
||||||
|
{
|
||||||
|
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||||
|
{
|
||||||
|
MapNode mn2(mod.param);
|
||||||
|
spec = mn2.getTile(face_dir);
|
||||||
|
}
|
||||||
|
if(mod.type == NODEMOD_CRACK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Get texture id, translate it to name, append stuff to
|
||||||
|
name, get texture id
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Get original texture name
|
||||||
|
u32 orig_id = spec.texture.id;
|
||||||
|
std::string orig_name = g_texturesource->getTextureName(orig_id);
|
||||||
|
|
||||||
|
// Create new texture name
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<orig_name<<"^[crack"<<mod.param;
|
||||||
|
|
||||||
|
// Get new texture
|
||||||
|
u32 new_id = g_texturesource->getTextureId(os.str());
|
||||||
|
|
||||||
|
/*dstream<<"MapBlock::getNodeTile(): Switching from "
|
||||||
|
<<orig_name<<" to "<<os.str()<<" ("
|
||||||
|
<<orig_id<<" to "<<new_id<<")"<<std::endl;*/
|
||||||
|
|
||||||
|
spec.texture = g_texturesource->getTexture(new_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Check temporary modifications on this node
|
||||||
|
*/
|
||||||
|
/*core::map<v3s16, NodeMod>::Node *n;
|
||||||
|
n = m_temp_mods.find(p);
|
||||||
|
// If modified
|
||||||
|
if(n != NULL)
|
||||||
|
{
|
||||||
|
struct NodeMod mod = n->getValue();*/
|
||||||
|
NodeMod mod;
|
||||||
|
if(temp_mods.get(p, &mod))
|
||||||
|
{
|
||||||
|
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||||
|
{
|
||||||
|
// Overrides content
|
||||||
|
return mod.param;
|
||||||
|
}
|
||||||
|
if(mod.type == NODEMOD_CRACK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Content doesn't change.
|
||||||
|
|
||||||
|
face_contents works just like it should, because
|
||||||
|
there should not be faces between differently cracked
|
||||||
|
nodes.
|
||||||
|
|
||||||
|
If a semi-transparent node is cracked in front an
|
||||||
|
another one, it really doesn't matter whether there
|
||||||
|
is a cracked face drawn in between or not.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mn.d;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 dirs8[8] = {
|
||||||
|
v3s16(0,0,0),
|
||||||
|
v3s16(0,0,1),
|
||||||
|
v3s16(0,1,0),
|
||||||
|
v3s16(0,1,1),
|
||||||
|
v3s16(1,0,0),
|
||||||
|
v3s16(1,1,0),
|
||||||
|
v3s16(1,0,1),
|
||||||
|
v3s16(1,1,1),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate lighting at the XYZ- corner of p
|
||||||
|
u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio)
|
||||||
|
{
|
||||||
|
u16 ambient_occlusion = 0;
|
||||||
|
u16 light = 0;
|
||||||
|
u16 light_count = 0;
|
||||||
|
for(u32 i=0; i<8; i++)
|
||||||
|
{
|
||||||
|
MapNode n = vmanip.getNodeNoEx(p - dirs8[i]);
|
||||||
|
if(content_features(n.d).param_type == CPT_LIGHT
|
||||||
|
// Fast-style leaves look better this way
|
||||||
|
&& content_features(n.d).solidness != 2)
|
||||||
|
{
|
||||||
|
light += decode_light(n.getLightBlend(daynight_ratio));
|
||||||
|
light_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(n.d != CONTENT_IGNORE)
|
||||||
|
ambient_occlusion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(light_count == 0)
|
||||||
|
return 255;
|
||||||
|
|
||||||
|
light /= light_count;
|
||||||
|
|
||||||
|
if(ambient_occlusion > 4)
|
||||||
|
{
|
||||||
|
ambient_occlusion -= 4;
|
||||||
|
light = (float)light / ((float)ambient_occlusion * 0.5 + 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate lighting at the given corner of p
|
||||||
|
u8 getSmoothLight(v3s16 p, v3s16 corner,
|
||||||
|
VoxelManipulator &vmanip, u32 daynight_ratio)
|
||||||
|
{
|
||||||
|
if(corner.X == 1) p.X += 1;
|
||||||
|
else assert(corner.X == -1);
|
||||||
|
if(corner.Y == 1) p.Y += 1;
|
||||||
|
else assert(corner.Y == -1);
|
||||||
|
if(corner.Z == 1) p.Z += 1;
|
||||||
|
else assert(corner.Z == -1);
|
||||||
|
|
||||||
|
return getSmoothLight(p, vmanip, daynight_ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getTileInfo(
|
||||||
|
// Input:
|
||||||
|
v3s16 blockpos_nodes,
|
||||||
|
v3s16 p,
|
||||||
|
v3s16 face_dir,
|
||||||
|
u32 daynight_ratio,
|
||||||
|
VoxelManipulator &vmanip,
|
||||||
|
NodeModMap &temp_mods,
|
||||||
|
bool smooth_lighting,
|
||||||
|
// Output:
|
||||||
|
bool &makes_face,
|
||||||
|
v3s16 &p_corrected,
|
||||||
|
v3s16 &face_dir_corrected,
|
||||||
|
u8 *lights,
|
||||||
|
TileSpec &tile
|
||||||
|
)
|
||||||
|
{
|
||||||
|
MapNode n0 = vmanip.getNodeNoEx(blockpos_nodes + p);
|
||||||
|
MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir);
|
||||||
|
TileSpec tile0 = getNodeTile(n0, p, face_dir, temp_mods);
|
||||||
|
TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods);
|
||||||
|
|
||||||
|
// This is hackish
|
||||||
|
u8 content0 = getNodeContent(p, n0, temp_mods);
|
||||||
|
u8 content1 = getNodeContent(p + face_dir, n1, temp_mods);
|
||||||
|
u8 mf = face_contents(content0, content1);
|
||||||
|
|
||||||
|
if(mf == 0)
|
||||||
|
{
|
||||||
|
makes_face = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
makes_face = true;
|
||||||
|
|
||||||
|
if(mf == 1)
|
||||||
|
{
|
||||||
|
tile = tile0;
|
||||||
|
p_corrected = p;
|
||||||
|
face_dir_corrected = face_dir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tile = tile1;
|
||||||
|
p_corrected = p + face_dir;
|
||||||
|
face_dir_corrected = -face_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(smooth_lighting == false)
|
||||||
|
{
|
||||||
|
lights[0] = lights[1] = lights[2] = lights[3] =
|
||||||
|
decode_light(getFaceLight(daynight_ratio, n0, n1, face_dir));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v3s16 vertex_dirs[4];
|
||||||
|
getNodeVertexDirs(face_dir_corrected, vertex_dirs);
|
||||||
|
for(u16 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
lights[i] = getSmoothLight(blockpos_nodes + p_corrected,
|
||||||
|
vertex_dirs[i], vmanip, daynight_ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
startpos:
|
||||||
|
translate_dir: unit vector with only one of x, y or z
|
||||||
|
face_dir: unit vector with only one of x, y or z
|
||||||
|
*/
|
||||||
|
void updateFastFaceRow(
|
||||||
|
u32 daynight_ratio,
|
||||||
|
v3f posRelative_f,
|
||||||
|
v3s16 startpos,
|
||||||
|
u16 length,
|
||||||
|
v3s16 translate_dir,
|
||||||
|
v3f translate_dir_f,
|
||||||
|
v3s16 face_dir,
|
||||||
|
v3f face_dir_f,
|
||||||
|
core::array<FastFace> &dest,
|
||||||
|
NodeModMap &temp_mods,
|
||||||
|
VoxelManipulator &vmanip,
|
||||||
|
v3s16 blockpos_nodes,
|
||||||
|
bool smooth_lighting)
|
||||||
|
{
|
||||||
|
v3s16 p = startpos;
|
||||||
|
|
||||||
|
u16 continuous_tiles_count = 0;
|
||||||
|
|
||||||
|
bool makes_face;
|
||||||
|
v3s16 p_corrected;
|
||||||
|
v3s16 face_dir_corrected;
|
||||||
|
u8 lights[4];
|
||||||
|
TileSpec tile;
|
||||||
|
getTileInfo(blockpos_nodes, p, face_dir, daynight_ratio,
|
||||||
|
vmanip, temp_mods, smooth_lighting,
|
||||||
|
makes_face, p_corrected, face_dir_corrected, lights, tile);
|
||||||
|
|
||||||
|
for(u16 j=0; j<length; j++)
|
||||||
|
{
|
||||||
|
// If tiling can be done, this is set to false in the next step
|
||||||
|
bool next_is_different = true;
|
||||||
|
|
||||||
|
v3s16 p_next;
|
||||||
|
|
||||||
|
bool next_makes_face = false;
|
||||||
|
v3s16 next_p_corrected;
|
||||||
|
v3s16 next_face_dir_corrected;
|
||||||
|
u8 next_lights[4] = {0,0,0,0};
|
||||||
|
TileSpec next_tile;
|
||||||
|
|
||||||
|
// If at last position, there is nothing to compare to and
|
||||||
|
// the face must be drawn anyway
|
||||||
|
if(j != length - 1)
|
||||||
|
{
|
||||||
|
p_next = p + translate_dir;
|
||||||
|
|
||||||
|
getTileInfo(blockpos_nodes, p_next, face_dir, daynight_ratio,
|
||||||
|
vmanip, temp_mods, smooth_lighting,
|
||||||
|
next_makes_face, next_p_corrected,
|
||||||
|
next_face_dir_corrected, next_lights,
|
||||||
|
next_tile);
|
||||||
|
|
||||||
|
if(next_makes_face == makes_face
|
||||||
|
&& next_p_corrected == p_corrected
|
||||||
|
&& next_face_dir_corrected == face_dir_corrected
|
||||||
|
&& next_lights[0] == lights[0]
|
||||||
|
&& next_lights[1] == lights[1]
|
||||||
|
&& next_lights[2] == lights[2]
|
||||||
|
&& next_lights[3] == lights[3]
|
||||||
|
&& next_tile == tile)
|
||||||
|
{
|
||||||
|
next_is_different = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continuous_tiles_count++;
|
||||||
|
|
||||||
|
// This is set to true if the texture doesn't allow more tiling
|
||||||
|
bool end_of_texture = false;
|
||||||
|
/*
|
||||||
|
If there is no texture, it can be tiled infinitely.
|
||||||
|
If tiled==0, it means the texture can be tiled infinitely.
|
||||||
|
Otherwise check tiled agains continuous_tiles_count.
|
||||||
|
*/
|
||||||
|
if(tile.texture.atlas != NULL && tile.texture.tiled != 0)
|
||||||
|
{
|
||||||
|
if(tile.texture.tiled <= continuous_tiles_count)
|
||||||
|
end_of_texture = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do this to disable tiling textures
|
||||||
|
//end_of_texture = true; //DEBUG
|
||||||
|
|
||||||
|
if(next_is_different || end_of_texture)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Create a face if there should be one
|
||||||
|
*/
|
||||||
|
if(makes_face)
|
||||||
|
{
|
||||||
|
// Floating point conversion of the position vector
|
||||||
|
v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
|
||||||
|
// Center point of face (kind of)
|
||||||
|
v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f;
|
||||||
|
v3f scale(1,1,1);
|
||||||
|
|
||||||
|
if(translate_dir.X != 0)
|
||||||
|
{
|
||||||
|
scale.X = continuous_tiles_count;
|
||||||
|
}
|
||||||
|
if(translate_dir.Y != 0)
|
||||||
|
{
|
||||||
|
scale.Y = continuous_tiles_count;
|
||||||
|
}
|
||||||
|
if(translate_dir.Z != 0)
|
||||||
|
{
|
||||||
|
scale.Z = continuous_tiles_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
|
||||||
|
sp, face_dir_corrected, scale,
|
||||||
|
posRelative_f, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
continuous_tiles_count = 0;
|
||||||
|
|
||||||
|
makes_face = next_makes_face;
|
||||||
|
p_corrected = next_p_corrected;
|
||||||
|
face_dir_corrected = next_face_dir_corrected;
|
||||||
|
lights[0] = next_lights[0];
|
||||||
|
lights[1] = next_lights[1];
|
||||||
|
lights[2] = next_lights[2];
|
||||||
|
lights[3] = next_lights[3];
|
||||||
|
tile = next_tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
|
||||||
|
{
|
||||||
|
// 4-21ms for MAP_BLOCKSIZE=16
|
||||||
|
// 24-155ms for MAP_BLOCKSIZE=32
|
||||||
|
//TimeTaker timer1("makeMapBlockMesh()");
|
||||||
|
|
||||||
|
core::array<FastFace> fastfaces_new;
|
||||||
|
|
||||||
|
v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;
|
||||||
|
|
||||||
|
// floating point conversion
|
||||||
|
v3f posRelative_f(blockpos_nodes.X, blockpos_nodes.Y, blockpos_nodes.Z);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Some settings
|
||||||
|
*/
|
||||||
|
//bool new_style_water = g_settings.getBool("new_style_water");
|
||||||
|
//bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||||
|
bool smooth_lighting = g_settings.getBool("smooth_lighting");
|
||||||
|
|
||||||
|
/*
|
||||||
|
We are including the faces of the trailing edges of the block.
|
||||||
|
This means that when something changes, the caller must
|
||||||
|
also update the meshes of the blocks at the leading edges.
|
||||||
|
|
||||||
|
NOTE: This is the slowest part of this method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
// 4-23ms for MAP_BLOCKSIZE=16
|
||||||
|
//TimeTaker timer2("updateMesh() collect");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Go through every y,z and get top(y+) faces in rows of x+
|
||||||
|
*/
|
||||||
|
for(s16 y=0; y<MAP_BLOCKSIZE; y++){
|
||||||
|
for(s16 z=0; z<MAP_BLOCKSIZE; z++){
|
||||||
|
updateFastFaceRow(data->m_daynight_ratio, posRelative_f,
|
||||||
|
v3s16(0,y,z), MAP_BLOCKSIZE,
|
||||||
|
v3s16(1,0,0), //dir
|
||||||
|
v3f (1,0,0),
|
||||||
|
v3s16(0,1,0), //face dir
|
||||||
|
v3f (0,1,0),
|
||||||
|
fastfaces_new,
|
||||||
|
data->m_temp_mods,
|
||||||
|
data->m_vmanip,
|
||||||
|
blockpos_nodes,
|
||||||
|
smooth_lighting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Go through every x,y and get right(x+) faces in rows of z+
|
||||||
|
*/
|
||||||
|
for(s16 x=0; x<MAP_BLOCKSIZE; x++){
|
||||||
|
for(s16 y=0; y<MAP_BLOCKSIZE; y++){
|
||||||
|
updateFastFaceRow(data->m_daynight_ratio, posRelative_f,
|
||||||
|
v3s16(x,y,0), MAP_BLOCKSIZE,
|
||||||
|
v3s16(0,0,1),
|
||||||
|
v3f (0,0,1),
|
||||||
|
v3s16(1,0,0),
|
||||||
|
v3f (1,0,0),
|
||||||
|
fastfaces_new,
|
||||||
|
data->m_temp_mods,
|
||||||
|
data->m_vmanip,
|
||||||
|
blockpos_nodes,
|
||||||
|
smooth_lighting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Go through every y,z and get back(z+) faces in rows of x+
|
||||||
|
*/
|
||||||
|
for(s16 z=0; z<MAP_BLOCKSIZE; z++){
|
||||||
|
for(s16 y=0; y<MAP_BLOCKSIZE; y++){
|
||||||
|
updateFastFaceRow(data->m_daynight_ratio, posRelative_f,
|
||||||
|
v3s16(0,y,z), MAP_BLOCKSIZE,
|
||||||
|
v3s16(1,0,0),
|
||||||
|
v3f (1,0,0),
|
||||||
|
v3s16(0,0,1),
|
||||||
|
v3f (0,0,1),
|
||||||
|
fastfaces_new,
|
||||||
|
data->m_temp_mods,
|
||||||
|
data->m_vmanip,
|
||||||
|
blockpos_nodes,
|
||||||
|
smooth_lighting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of slow part
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert FastFaces to SMesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
MeshCollector collector;
|
||||||
|
|
||||||
|
if(fastfaces_new.size() > 0)
|
||||||
|
{
|
||||||
|
// avg 0ms (100ms spikes when loading textures the first time)
|
||||||
|
//TimeTaker timer2("updateMesh() mesh building");
|
||||||
|
|
||||||
|
video::SMaterial material;
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
|
||||||
|
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
|
||||||
|
|
||||||
|
for(u32 i=0; i<fastfaces_new.size(); i++)
|
||||||
|
{
|
||||||
|
FastFace &f = fastfaces_new[i];
|
||||||
|
|
||||||
|
const u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
const u16 indices_alternate[] = {0,1,3,2,3,1};
|
||||||
|
|
||||||
|
video::ITexture *texture = f.tile.texture.atlas;
|
||||||
|
if(texture == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
material.setTexture(0, texture);
|
||||||
|
|
||||||
|
f.tile.applyMaterialOptions(material);
|
||||||
|
|
||||||
|
const u16 *indices_p = indices;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Revert triangles for nicer looking gradient if vertices
|
||||||
|
1 and 3 have same color or 0 and 2 have different color.
|
||||||
|
*/
|
||||||
|
if(f.vertices[0].Color != f.vertices[2].Color
|
||||||
|
|| f.vertices[1].Color == f.vertices[3].Color)
|
||||||
|
indices_p = indices_alternate;
|
||||||
|
|
||||||
|
collector.append(material, f.vertices, 4, indices_p, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add special graphics:
|
||||||
|
- torches
|
||||||
|
- flowing water
|
||||||
|
- fences
|
||||||
|
- whatever
|
||||||
|
*/
|
||||||
|
|
||||||
|
mapblock_mesh_generate_special(data, collector);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add stuff from collector to mesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
scene::SMesh *mesh_new = NULL;
|
||||||
|
mesh_new = new scene::SMesh();
|
||||||
|
|
||||||
|
collector.fillMesh(mesh_new);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Do some stuff to the mesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
mesh_new->recalculateBoundingBox();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete new mesh if it is empty
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(mesh_new->getMeshBufferCount() == 0)
|
||||||
|
{
|
||||||
|
mesh_new->drop();
|
||||||
|
mesh_new = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mesh_new)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// Usually 1-700 faces and 1-7 materials
|
||||||
|
std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
|
||||||
|
<<"and uses "<<mesh_new->getMeshBufferCount()
|
||||||
|
<<" materials (meshbuffers)"<<std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use VBO for mesh (this just would set this for ever buffer)
|
||||||
|
// This will lead to infinite memory usage because or irrlicht.
|
||||||
|
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: If that is enabled, some kind of a queue to the main
|
||||||
|
thread should be made which would call irrlicht to delete
|
||||||
|
the hardware buffer and then delete the mesh
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return mesh_new;
|
||||||
|
|
||||||
|
//std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
|
||||||
|
}
|
||||||
|
|
143
src/mapblock_mesh.h
Normal file
143
src/mapblock_mesh.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAPBLOCK_MESH_HEADER
|
||||||
|
#define MAPBLOCK_MESH_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include "mapblock_nodemod.h"
|
||||||
|
#include "voxel.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mesh making stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is used because CMeshBuffer::append() is very slow
|
||||||
|
*/
|
||||||
|
struct PreMeshBuffer
|
||||||
|
{
|
||||||
|
video::SMaterial material;
|
||||||
|
core::array<u16> indices;
|
||||||
|
core::array<video::S3DVertex> vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MeshCollector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void append(
|
||||||
|
video::SMaterial material,
|
||||||
|
const video::S3DVertex* const vertices,
|
||||||
|
u32 numVertices,
|
||||||
|
const u16* const indices,
|
||||||
|
u32 numIndices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PreMeshBuffer *p = NULL;
|
||||||
|
for(u32 i=0; i<m_prebuffers.size(); i++)
|
||||||
|
{
|
||||||
|
PreMeshBuffer &pp = m_prebuffers[i];
|
||||||
|
if(pp.material != material)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = &pp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p == NULL)
|
||||||
|
{
|
||||||
|
PreMeshBuffer pp;
|
||||||
|
pp.material = material;
|
||||||
|
m_prebuffers.push_back(pp);
|
||||||
|
p = &m_prebuffers[m_prebuffers.size()-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 vertex_count = p->vertices.size();
|
||||||
|
for(u32 i=0; i<numIndices; i++)
|
||||||
|
{
|
||||||
|
u32 j = indices[i] + vertex_count;
|
||||||
|
if(j > 65535)
|
||||||
|
{
|
||||||
|
dstream<<"FIXME: Meshbuffer ran out of indices"<<std::endl;
|
||||||
|
// NOTE: Fix is to just add an another MeshBuffer
|
||||||
|
}
|
||||||
|
p->indices.push_back(j);
|
||||||
|
}
|
||||||
|
for(u32 i=0; i<numVertices; i++)
|
||||||
|
{
|
||||||
|
p->vertices.push_back(vertices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillMesh(scene::SMesh *mesh)
|
||||||
|
{
|
||||||
|
/*dstream<<"Filling mesh with "<<m_prebuffers.size()
|
||||||
|
<<" meshbuffers"<<std::endl;*/
|
||||||
|
for(u32 i=0; i<m_prebuffers.size(); i++)
|
||||||
|
{
|
||||||
|
PreMeshBuffer &p = m_prebuffers[i];
|
||||||
|
|
||||||
|
/*dstream<<"p.vertices.size()="<<p.vertices.size()
|
||||||
|
<<", p.indices.size()="<<p.indices.size()
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
// Create meshbuffer
|
||||||
|
|
||||||
|
// This is a "Standard MeshBuffer",
|
||||||
|
// it's a typedeffed CMeshBuffer<video::S3DVertex>
|
||||||
|
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
// Set material
|
||||||
|
buf->Material = p.material;
|
||||||
|
//((scene::SMeshBuffer*)buf)->Material = p.material;
|
||||||
|
// Use VBO
|
||||||
|
//buf->setHardwareMappingHint(scene::EHM_STATIC);
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
// Mesh grabbed it
|
||||||
|
buf->drop();
|
||||||
|
|
||||||
|
buf->append(p.vertices.pointer(), p.vertices.size(),
|
||||||
|
p.indices.pointer(), p.indices.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::array<PreMeshBuffer> m_prebuffers;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MapBlock;
|
||||||
|
|
||||||
|
struct MeshMakeData
|
||||||
|
{
|
||||||
|
u32 m_daynight_ratio;
|
||||||
|
NodeModMap m_temp_mods;
|
||||||
|
VoxelManipulator m_vmanip;
|
||||||
|
v3s16 m_blockpos;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy central data directly from block, and other data from
|
||||||
|
parent of block.
|
||||||
|
*/
|
||||||
|
void fill(u32 daynight_ratio, MapBlock *block);
|
||||||
|
};
|
||||||
|
|
||||||
|
scene::SMesh* makeMapBlockMesh(MeshMakeData *data);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
114
src/mapblock_nodemod.h
Normal file
114
src/mapblock_nodemod.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(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 MAPBLOCK_NODEMOD_HEADER
|
||||||
|
#define MAPBLOCK_NODEMOD_HEADER
|
||||||
|
|
||||||
|
enum NodeModType
|
||||||
|
{
|
||||||
|
NODEMOD_NONE,
|
||||||
|
NODEMOD_CHANGECONTENT, //param is content id
|
||||||
|
NODEMOD_CRACK // param is crack progression
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NodeMod
|
||||||
|
{
|
||||||
|
NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0)
|
||||||
|
{
|
||||||
|
type = a_type;
|
||||||
|
param = a_param;
|
||||||
|
}
|
||||||
|
bool operator==(const NodeMod &other)
|
||||||
|
{
|
||||||
|
return (type == other.type && param == other.param);
|
||||||
|
}
|
||||||
|
enum NodeModType type;
|
||||||
|
u16 param;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NodeModMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
returns true if the mod was different last time
|
||||||
|
*/
|
||||||
|
bool set(v3s16 p, const NodeMod &mod)
|
||||||
|
{
|
||||||
|
// See if old is different, cancel if it is not different.
|
||||||
|
core::map<v3s16, NodeMod>::Node *n = m_mods.find(p);
|
||||||
|
if(n)
|
||||||
|
{
|
||||||
|
NodeMod old = n->getValue();
|
||||||
|
if(old == mod)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
n->setValue(mod);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_mods.insert(p, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Returns true if there was one
|
||||||
|
bool get(v3s16 p, NodeMod *mod)
|
||||||
|
{
|
||||||
|
core::map<v3s16, NodeMod>::Node *n;
|
||||||
|
n = m_mods.find(p);
|
||||||
|
if(n == NULL)
|
||||||
|
return false;
|
||||||
|
if(mod)
|
||||||
|
*mod = n->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool clear(v3s16 p)
|
||||||
|
{
|
||||||
|
if(m_mods.find(p))
|
||||||
|
{
|
||||||
|
m_mods.remove(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool clear()
|
||||||
|
{
|
||||||
|
if(m_mods.size() == 0)
|
||||||
|
return false;
|
||||||
|
m_mods.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void copy(NodeModMap &dest)
|
||||||
|
{
|
||||||
|
dest.m_mods.clear();
|
||||||
|
|
||||||
|
for(core::map<v3s16, NodeMod>::Iterator
|
||||||
|
i = m_mods.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
dest.m_mods.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::map<v3s16, NodeMod> m_mods;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
2007
src/mapgen.cpp
Normal file
2007
src/mapgen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
66
src/mapgen.h
Normal file
66
src/mapgen.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAPGEN_HEADER
|
||||||
|
#define MAPGEN_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include "utility.h" // UniqueQueue
|
||||||
|
|
||||||
|
struct BlockMakeData;
|
||||||
|
class MapBlock;
|
||||||
|
class ManualMapVoxelManipulator;
|
||||||
|
|
||||||
|
namespace mapgen
|
||||||
|
{
|
||||||
|
// Finds precise ground level at any position
|
||||||
|
s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
|
||||||
|
|
||||||
|
// Find out if block is completely underground
|
||||||
|
bool block_is_underground(u64 seed, v3s16 blockpos);
|
||||||
|
|
||||||
|
// Main map generation routine
|
||||||
|
void make_block(BlockMakeData *data);
|
||||||
|
|
||||||
|
// Add objects according to block content
|
||||||
|
void add_random_objects(MapBlock *block);
|
||||||
|
|
||||||
|
/*
|
||||||
|
These are used by FarMesh
|
||||||
|
*/
|
||||||
|
bool get_have_sand(u64 seed, v2s16 p2d);
|
||||||
|
double tree_amount_2d(u64 seed, v2s16 p);
|
||||||
|
|
||||||
|
|
||||||
|
struct BlockMakeData
|
||||||
|
{
|
||||||
|
bool no_op;
|
||||||
|
ManualMapVoxelManipulator *vmanip;
|
||||||
|
u64 seed;
|
||||||
|
v3s16 blockpos;
|
||||||
|
UniqueQueue<v3s16> transforming_liquid;
|
||||||
|
|
||||||
|
BlockMakeData();
|
||||||
|
~BlockMakeData();
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace mapgen
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
365
src/mapnode.cpp
365
src/mapnode.cpp
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "mineral.h"
|
#include "mineral.h"
|
||||||
// For g_settings
|
// For g_settings
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
#include "nodemetadata.h"
|
#include "nodemetadata.h"
|
||||||
|
|
||||||
ContentFeatures::~ContentFeatures()
|
ContentFeatures::~ContentFeatures()
|
||||||
@ -107,9 +108,9 @@ void init_mapnode()
|
|||||||
"g_texturesource!=NULL"<<std::endl;
|
"g_texturesource!=NULL"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read some settings
|
/*// Read some settings
|
||||||
bool new_style_water = g_settings.getBool("new_style_water");
|
bool new_style_water = g_settings.getBool("new_style_water");
|
||||||
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
bool new_style_leaves = g_settings.getBool("new_style_leaves");*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialize content feature table
|
Initialize content feature table
|
||||||
@ -131,313 +132,17 @@ void init_mapnode()
|
|||||||
{
|
{
|
||||||
ContentFeatures *f = &g_content_features[i];
|
ContentFeatures *f = &g_content_features[i];
|
||||||
// Re-initialize
|
// Re-initialize
|
||||||
*f = ContentFeatures();
|
f->reset();
|
||||||
|
|
||||||
for(u16 j=0; j<6; j++)
|
for(u16 j=0; j<6; j++)
|
||||||
f->tiles[j].material_type = initial_material_type;
|
f->tiles[j].material_type = initial_material_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 i;
|
|
||||||
ContentFeatures *f = NULL;
|
|
||||||
|
|
||||||
i = CONTENT_STONE;
|
/*
|
||||||
f = &g_content_features[i];
|
Initialize mapnode content
|
||||||
f->setAllTextures("stone.png");
|
*/
|
||||||
f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
|
content_mapnode_init();
|
||||||
f->param_type = CPT_MINERAL;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_GRASS;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("mud.png^grass_side.png");
|
|
||||||
f->setTexture(0, "grass.png");
|
|
||||||
f->setTexture(1, "mud.png");
|
|
||||||
f->param_type = CPT_MINERAL;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_GRASS_FOOTSTEPS;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("mud.png^grass_side.png");
|
|
||||||
f->setTexture(0, "grass_footsteps.png");
|
|
||||||
f->setTexture(1, "mud.png");
|
|
||||||
f->param_type = CPT_MINERAL;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_MUD;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("mud.png");
|
|
||||||
f->setInventoryTextureCube("mud.png", "mud.png", "mud.png");
|
|
||||||
f->param_type = CPT_MINERAL;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_SAND;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("sand.png");
|
|
||||||
f->param_type = CPT_MINERAL;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_SANDSTONE;
|
|
||||||
f = &g_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";
|
|
||||||
|
|
||||||
i = CONTENT_CLAY;
|
|
||||||
f = &g_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");
|
|
||||||
|
|
||||||
i = CONTENT_BRICK;
|
|
||||||
f = &g_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");
|
|
||||||
|
|
||||||
i = CONTENT_TREE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("tree.png");
|
|
||||||
f->setTexture(0, "tree_top.png");
|
|
||||||
f->setTexture(1, "tree_top.png");
|
|
||||||
f->param_type = CPT_MINERAL;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_LEAVES;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->light_propagates = true;
|
|
||||||
//f->param_type = CPT_MINERAL;
|
|
||||||
f->param_type = CPT_LIGHT;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
if(new_style_leaves)
|
|
||||||
{
|
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
|
||||||
f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f->setAllTextures("[noalpha:leaves.png");
|
|
||||||
}
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_CACTUS;
|
|
||||||
f = &g_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";
|
|
||||||
|
|
||||||
i = CONTENT_PAPYRUS;
|
|
||||||
f = &g_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;
|
|
||||||
|
|
||||||
i = CONTENT_BOOKSHELF;
|
|
||||||
f = &g_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;
|
|
||||||
|
|
||||||
i = CONTENT_GLASS;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
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->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
|
|
||||||
|
|
||||||
i = CONTENT_FENCE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setInventoryTexture("fence.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
|
|
||||||
|
|
||||||
i = CONTENT_RAIL;
|
|
||||||
f = &g_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;
|
|
||||||
|
|
||||||
// Deprecated
|
|
||||||
i = CONTENT_COALSTONE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
//f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
|
||||||
f->setAllTextures("stone.png^mineral_coal.png");
|
|
||||||
f->is_ground_content = true;
|
|
||||||
|
|
||||||
i = CONTENT_WOOD;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("wood.png");
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_MESE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("mese.png");
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_CLOUD;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("cloud.png");
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_AIR;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->param_type = CPT_LIGHT;
|
|
||||||
f->light_propagates = true;
|
|
||||||
f->sunlight_propagates = true;
|
|
||||||
f->solidness = 0;
|
|
||||||
f->walkable = false;
|
|
||||||
f->pointable = false;
|
|
||||||
f->diggable = false;
|
|
||||||
f->buildable_to = true;
|
|
||||||
f->air_equivalent = true;
|
|
||||||
|
|
||||||
i = CONTENT_WATER;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setInventoryTextureCube("water.png", "water.png", "water.png");
|
|
||||||
f->param_type = CPT_LIGHT;
|
|
||||||
f->light_propagates = true;
|
|
||||||
f->solidness = 0; // Drawn separately, makes no faces
|
|
||||||
f->walkable = false;
|
|
||||||
f->pointable = false;
|
|
||||||
f->diggable = false;
|
|
||||||
f->buildable_to = true;
|
|
||||||
f->liquid_type = LIQUID_FLOWING;
|
|
||||||
|
|
||||||
i = CONTENT_WATERSOURCE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setInventoryTexture("water.png");
|
|
||||||
if(new_style_water)
|
|
||||||
{
|
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
|
||||||
}
|
|
||||||
else // old style
|
|
||||||
{
|
|
||||||
f->solidness = 1;
|
|
||||||
|
|
||||||
TileSpec t;
|
|
||||||
if(g_texturesource)
|
|
||||||
t.texture = g_texturesource->getTexture("water.png");
|
|
||||||
|
|
||||||
t.alpha = WATER_ALPHA;
|
|
||||||
t.material_type = MATERIAL_ALPHA_VERTEX;
|
|
||||||
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
|
||||||
f->setAllTiles(t);
|
|
||||||
}
|
|
||||||
f->param_type = CPT_LIGHT;
|
|
||||||
f->light_propagates = true;
|
|
||||||
f->walkable = false;
|
|
||||||
f->pointable = false;
|
|
||||||
f->diggable = false;
|
|
||||||
f->buildable_to = true;
|
|
||||||
f->liquid_type = LIQUID_SOURCE;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_TORCH;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setInventoryTexture("torch_on_floor.png");
|
|
||||||
f->param_type = CPT_LIGHT;
|
|
||||||
f->light_propagates = true;
|
|
||||||
f->sunlight_propagates = true;
|
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
|
||||||
f->walkable = false;
|
|
||||||
f->wall_mounted = true;
|
|
||||||
f->air_equivalent = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_SIGN_WALL;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setInventoryTexture("sign_wall.png");
|
|
||||||
f->param_type = CPT_LIGHT;
|
|
||||||
f->light_propagates = true;
|
|
||||||
f->sunlight_propagates = true;
|
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
|
||||||
f->walkable = false;
|
|
||||||
f->wall_mounted = true;
|
|
||||||
f->air_equivalent = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
if(f->initial_metadata == NULL)
|
|
||||||
f->initial_metadata = new SignNodeMetadata("Some sign");
|
|
||||||
|
|
||||||
i = CONTENT_CHEST;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->param_type = CPT_FACEDIR_SIMPLE;
|
|
||||||
f->setAllTextures("chest_side.png");
|
|
||||||
f->setTexture(0, "chest_top.png");
|
|
||||||
f->setTexture(1, "chest_top.png");
|
|
||||||
f->setTexture(5, "chest_front.png"); // Z-
|
|
||||||
f->setInventoryTexture("chest_top.png");
|
|
||||||
//f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
if(f->initial_metadata == NULL)
|
|
||||||
f->initial_metadata = new ChestNodeMetadata();
|
|
||||||
|
|
||||||
i = CONTENT_FURNACE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->param_type = CPT_FACEDIR_SIMPLE;
|
|
||||||
f->setAllTextures("furnace_side.png");
|
|
||||||
f->setTexture(5, "furnace_front.png"); // Z-
|
|
||||||
f->setInventoryTexture("furnace_front.png");
|
|
||||||
//f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6";
|
|
||||||
if(f->initial_metadata == NULL)
|
|
||||||
f->initial_metadata = new FurnaceNodeMetadata();
|
|
||||||
|
|
||||||
i = CONTENT_COBBLE;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("cobble.png");
|
|
||||||
f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
|
|
||||||
f->param_type = CPT_NONE;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
i = CONTENT_STEEL;
|
|
||||||
f = &g_content_features[i];
|
|
||||||
f->setAllTextures("steel_block.png");
|
|
||||||
f->setInventoryTextureCube("steel_block.png", "steel_block.png",
|
|
||||||
"steel_block.png");
|
|
||||||
f->param_type = CPT_NONE;
|
|
||||||
f->is_ground_content = true;
|
|
||||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
|
||||||
|
|
||||||
// NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v3s16 facedir_rotate(u8 facedir, v3s16 dir)
|
v3s16 facedir_rotate(u8 facedir, v3s16 dir)
|
||||||
@ -525,16 +230,54 @@ u8 MapNode::getMineral()
|
|||||||
return MINERAL_NONE;
|
return MINERAL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointers to c_str()s g_content_features[i].inventory_image_path
|
/*
|
||||||
//const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
|
Gets lighting value at face of node
|
||||||
|
|
||||||
|
Parameters must consist of air and !air.
|
||||||
|
Order doesn't matter.
|
||||||
|
|
||||||
void init_content_inventory_texture_paths()
|
If either of the nodes doesn't exist, light is 0.
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
daynight_ratio: 0...1000
|
||||||
|
n: getNodeParent(p)
|
||||||
|
n2: getNodeParent(p + face_dir)
|
||||||
|
face_dir: axis oriented unit vector from p to p2
|
||||||
|
|
||||||
|
returns encoded light value.
|
||||||
|
*/
|
||||||
|
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
||||||
|
v3s16 face_dir)
|
||||||
{
|
{
|
||||||
dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
|
try{
|
||||||
/*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
u8 light;
|
||||||
|
u8 l1 = n.getLightBlend(daynight_ratio);
|
||||||
|
u8 l2 = n2.getLightBlend(daynight_ratio);
|
||||||
|
if(l1 > l2)
|
||||||
|
light = l1;
|
||||||
|
else
|
||||||
|
light = l2;
|
||||||
|
|
||||||
|
// Make some nice difference to different sides
|
||||||
|
|
||||||
|
// This makes light come from a corner
|
||||||
|
/*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
|
||||||
|
light = diminish_light(diminish_light(light));
|
||||||
|
else if(face_dir.X == -1 || face_dir.Z == -1)
|
||||||
|
light = diminish_light(light);*/
|
||||||
|
|
||||||
|
// All neighboring faces have different shade (like in minecraft)
|
||||||
|
if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
|
||||||
|
light = diminish_light(diminish_light(light));
|
||||||
|
else if(face_dir.Z == 1 || face_dir.Z == -1)
|
||||||
|
light = diminish_light(light);
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e)
|
||||||
{
|
{
|
||||||
g_content_inventory_texture_paths[i] =
|
return 0;
|
||||||
g_content_features[i].inventory_image_path.c_str();
|
}
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
181
src/mapnode.h
181
src/mapnode.h
@ -27,6 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
#include "materials.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Naming scheme:
|
||||||
|
- Material = irrlicht's Material class
|
||||||
|
- Content = (u8) content of a node
|
||||||
|
- Tile = TileSpec at some side of a node of some content type
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initializes all kind of stuff in here.
|
Initializes all kind of stuff in here.
|
||||||
@ -42,13 +50,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
void init_mapnode();
|
void init_mapnode();
|
||||||
|
|
||||||
// Initializes g_content_inventory_texture_paths
|
|
||||||
void init_content_inventory_texture_paths();
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE: This is not used appropriately everywhere.
|
|
||||||
#define MATERIALS_COUNT 256
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ignored node.
|
Ignored node.
|
||||||
|
|
||||||
@ -67,48 +68,6 @@ void init_content_inventory_texture_paths();
|
|||||||
*/
|
*/
|
||||||
#define CONTENT_AIR 254
|
#define CONTENT_AIR 254
|
||||||
|
|
||||||
/*
|
|
||||||
Suggested materials:
|
|
||||||
- Gravel
|
|
||||||
- Sand
|
|
||||||
|
|
||||||
New naming scheme:
|
|
||||||
- Material = irrlicht's Material class
|
|
||||||
- Content = (u8) content of a node
|
|
||||||
- Tile = (u16) Material ID at some side of a node
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CONTENT_STONE 0
|
|
||||||
#define CONTENT_GRASS 1
|
|
||||||
#define CONTENT_WATER 2
|
|
||||||
#define CONTENT_TORCH 3
|
|
||||||
#define CONTENT_TREE 4
|
|
||||||
#define CONTENT_LEAVES 5
|
|
||||||
#define CONTENT_GRASS_FOOTSTEPS 6
|
|
||||||
#define CONTENT_MESE 7
|
|
||||||
#define CONTENT_MUD 8
|
|
||||||
#define CONTENT_WATERSOURCE 9
|
|
||||||
// Pretty much useless, clouds won't be drawn this way
|
|
||||||
#define CONTENT_CLOUD 10
|
|
||||||
#define CONTENT_COALSTONE 11
|
|
||||||
#define CONTENT_WOOD 12
|
|
||||||
#define CONTENT_SAND 13
|
|
||||||
#define CONTENT_SIGN_WALL 14
|
|
||||||
#define CONTENT_CHEST 15
|
|
||||||
#define CONTENT_FURNACE 16
|
|
||||||
//#define CONTENT_WORKBENCH 17
|
|
||||||
#define CONTENT_COBBLE 18
|
|
||||||
#define CONTENT_STEEL 19
|
|
||||||
#define CONTENT_GLASS 20
|
|
||||||
#define CONTENT_FENCE 21
|
|
||||||
#define CONTENT_SANDSTONE 22
|
|
||||||
#define CONTENT_CACTUS 23
|
|
||||||
#define CONTENT_BRICK 24
|
|
||||||
#define CONTENT_CLAY 25
|
|
||||||
#define CONTENT_PAPYRUS 26
|
|
||||||
#define CONTENT_BOOKSHELF 27
|
|
||||||
#define CONTENT_RAIL 28
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Content feature list
|
Content feature list
|
||||||
*/
|
*/
|
||||||
@ -180,10 +139,20 @@ struct ContentFeatures
|
|||||||
|
|
||||||
// Initial metadata is cloned from this
|
// Initial metadata is cloned from this
|
||||||
NodeMetadata *initial_metadata;
|
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.
|
||||||
|
u8 liquid_alternative_flowing;
|
||||||
|
|
||||||
|
// Amount of light the node emits
|
||||||
|
u8 light_source;
|
||||||
|
|
||||||
|
// Digging properties for different tools
|
||||||
|
DiggingPropertiesList digging_properties;
|
||||||
|
|
||||||
|
// NOTE: Move relevant properties to here from elsewhere
|
||||||
|
|
||||||
//TODO: Move more properties here
|
void reset()
|
||||||
|
|
||||||
ContentFeatures()
|
|
||||||
{
|
{
|
||||||
translate_to = NULL;
|
translate_to = NULL;
|
||||||
param_type = CPT_NONE;
|
param_type = CPT_NONE;
|
||||||
@ -201,6 +170,14 @@ struct ContentFeatures
|
|||||||
air_equivalent = false;
|
air_equivalent = false;
|
||||||
dug_item = "";
|
dug_item = "";
|
||||||
initial_metadata = NULL;
|
initial_metadata = NULL;
|
||||||
|
liquid_alternative_flowing = CONTENT_IGNORE;
|
||||||
|
light_source = 0;
|
||||||
|
digging_properties.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentFeatures()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ContentFeatures();
|
~ContentFeatures();
|
||||||
@ -242,6 +219,11 @@ struct ContentFeatures
|
|||||||
*/
|
*/
|
||||||
ContentFeatures & content_features(u8 i);
|
ContentFeatures & content_features(u8 i);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here is a bunch of DEPRECATED functions.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If true, the material allows light propagation and brightness is stored
|
If true, the material allows light propagation and brightness is stored
|
||||||
in param.
|
in param.
|
||||||
@ -250,9 +232,7 @@ ContentFeatures & content_features(u8 i);
|
|||||||
inline bool light_propagates_content(u8 m)
|
inline bool light_propagates_content(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).light_propagates;
|
return content_features(m).light_propagates;
|
||||||
//return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If true, the material allows lossless sunlight propagation.
|
If true, the material allows lossless sunlight propagation.
|
||||||
NOTE: It doesn't seem to go through torches regardlessly of this
|
NOTE: It doesn't seem to go through torches regardlessly of this
|
||||||
@ -261,9 +241,7 @@ inline bool light_propagates_content(u8 m)
|
|||||||
inline bool sunlight_propagates_content(u8 m)
|
inline bool sunlight_propagates_content(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).sunlight_propagates;
|
return content_features(m).sunlight_propagates;
|
||||||
//return (m == CONTENT_AIR || m == CONTENT_TORCH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
On a node-node surface, the material of the node with higher solidness
|
On a node-node surface, the material of the node with higher solidness
|
||||||
is used for drawing.
|
is used for drawing.
|
||||||
@ -275,83 +253,54 @@ inline bool sunlight_propagates_content(u8 m)
|
|||||||
inline u8 content_solidness(u8 m)
|
inline u8 content_solidness(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).solidness;
|
return content_features(m).solidness;
|
||||||
/*// As of now, every pseudo node like torches are added to this
|
|
||||||
if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
|
|
||||||
return 0;
|
|
||||||
if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
|
|
||||||
return 1;
|
|
||||||
return 2;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Objects collide with walkable contents
|
// Objects collide with walkable contents
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_walkable(u8 m)
|
inline bool content_walkable(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).walkable;
|
return content_features(m).walkable;
|
||||||
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_liquid(u8 m)
|
inline bool content_liquid(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).liquid_type != LIQUID_NONE;
|
return content_features(m).liquid_type != LIQUID_NONE;
|
||||||
//return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_flowing_liquid(u8 m)
|
inline bool content_flowing_liquid(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).liquid_type == LIQUID_FLOWING;
|
return content_features(m).liquid_type == LIQUID_FLOWING;
|
||||||
//return (m == CONTENT_WATER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_liquid_source(u8 m)
|
inline bool content_liquid_source(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).liquid_type == LIQUID_SOURCE;
|
return content_features(m).liquid_type == LIQUID_SOURCE;
|
||||||
//return (m == CONTENT_WATERSOURCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
|
// CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
|
||||||
// CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
|
// CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
|
||||||
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline u8 make_liquid_flowing(u8 m)
|
inline u8 make_liquid_flowing(u8 m)
|
||||||
{
|
{
|
||||||
if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
|
u8 c = content_features(m).liquid_alternative_flowing;
|
||||||
return CONTENT_WATER;
|
assert(c != CONTENT_IGNORE);
|
||||||
assert(0);
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointable contents can be pointed to in the map
|
// Pointable contents can be pointed to in the map
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_pointable(u8 m)
|
inline bool content_pointable(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).pointable;
|
return content_features(m).pointable;
|
||||||
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_diggable(u8 m)
|
inline bool content_diggable(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).diggable;
|
return content_features(m).diggable;
|
||||||
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_buildable_to(u8 m)
|
inline bool content_buildable_to(u8 m)
|
||||||
{
|
{
|
||||||
return content_features(m).buildable_to;
|
return content_features(m).buildable_to;
|
||||||
//return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Returns true for contents that form the base ground that
|
|
||||||
follows the main heightmap
|
|
||||||
*/
|
|
||||||
/*inline bool is_ground_content(u8 m)
|
|
||||||
{
|
|
||||||
return content_features(m).is_ground_content;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Nodes make a face if contents differ and solidness differs.
|
Nodes make a face if contents differ and solidness differs.
|
||||||
Return value:
|
Return value:
|
||||||
@ -500,31 +449,25 @@ struct MapNode
|
|||||||
&& param == other.param
|
&& param == other.param
|
||||||
&& param2 == other.param2);
|
&& param2 == other.param2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
These four are DEPRECATED I guess. -c55
|
||||||
|
*/
|
||||||
bool light_propagates()
|
bool light_propagates()
|
||||||
{
|
{
|
||||||
return light_propagates_content(d);
|
return light_propagates_content(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sunlight_propagates()
|
bool sunlight_propagates()
|
||||||
{
|
{
|
||||||
return sunlight_propagates_content(d);
|
return sunlight_propagates_content(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 solidness()
|
u8 solidness()
|
||||||
{
|
{
|
||||||
return content_solidness(d);
|
return content_solidness(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 light_source()
|
u8 light_source()
|
||||||
{
|
{
|
||||||
/*
|
return content_features(d).light_source;
|
||||||
Note that a block that isn't light_propagates() can be a light source.
|
|
||||||
*/
|
|
||||||
if(d == CONTENT_TORCH)
|
|
||||||
return LIGHT_MAX;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 getLightBanksWithSource()
|
u8 getLightBanksWithSource()
|
||||||
@ -544,11 +487,6 @@ struct MapNode
|
|||||||
return (lightday&0x0f) | ((lightnight<<4)&0xf0);
|
return (lightday&0x0f) | ((lightnight<<4)&0xf0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLightBanks(u8 a_light)
|
|
||||||
{
|
|
||||||
param = a_light;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 getLight(enum LightBank bank)
|
u8 getLight(enum LightBank bank)
|
||||||
{
|
{
|
||||||
// Select the brightest of [light source, propagated light]
|
// Select the brightest of [light source, propagated light]
|
||||||
@ -613,13 +551,25 @@ struct MapNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In mapnode.cpp
|
// In mapnode.cpp
|
||||||
|
/*
|
||||||
|
Get tile of a face of the node.
|
||||||
|
dir: direction of face
|
||||||
|
Returns: TileSpec. Can contain miscellaneous texture coordinates,
|
||||||
|
which must be obeyed so that the texture atlas can be used.
|
||||||
|
*/
|
||||||
TileSpec getTile(v3s16 dir);
|
TileSpec getTile(v3s16 dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets mineral content of node, if there is any.
|
||||||
|
MINERAL_NONE if doesn't contain or isn't able to contain mineral.
|
||||||
|
*/
|
||||||
u8 getMineral();
|
u8 getMineral();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These serialization functions are used when informing client
|
These serialization functions are used when informing client
|
||||||
of a single node add
|
of a single node add.
|
||||||
|
|
||||||
|
NOTE: When loading a MapBlock, these are not used. Should they?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u32 serializedLength(u8 version)
|
static u32 serializedLength(u8 version)
|
||||||
@ -698,7 +648,24 @@ struct MapNode
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets lighting value at face of node
|
||||||
|
|
||||||
|
Parameters must consist of air and !air.
|
||||||
|
Order doesn't matter.
|
||||||
|
|
||||||
|
If either of the nodes doesn't exist, light is 0.
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
daynight_ratio: 0...1000
|
||||||
|
n: getNodeParent(p)
|
||||||
|
n2: getNodeParent(p + face_dir)
|
||||||
|
face_dir: axis oriented unit vector from p to p2
|
||||||
|
|
||||||
|
returns encoded light value.
|
||||||
|
*/
|
||||||
|
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
||||||
|
v3s16 face_dir);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
MapSector::MapSector(NodeContainer *parent, v2s16 pos):
|
MapSector::MapSector(NodeContainer *parent, v2s16 pos):
|
||||||
differs_from_disk(true),
|
differs_from_disk(true),
|
||||||
usage_timer(0.0),
|
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_pos(pos),
|
m_pos(pos),
|
||||||
m_block_cache(NULL)
|
m_block_cache(NULL)
|
||||||
|
@ -203,13 +203,6 @@ public:
|
|||||||
// Basically, this should be changed to true in every setter method
|
// Basically, this should be changed to true in every setter method
|
||||||
bool differs_from_disk;
|
bool differs_from_disk;
|
||||||
|
|
||||||
// Counts seconds from last usage.
|
|
||||||
// Sector can be deleted from memory after some time of inactivity.
|
|
||||||
// NOTE: It has to be made very sure no other thread is accessing
|
|
||||||
// the sector and it doesn't remain in any cache when
|
|
||||||
// deleting it.
|
|
||||||
float usage_timer;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The pile of MapBlocks
|
// The pile of MapBlocks
|
||||||
|
@ -1,119 +1,20 @@
|
|||||||
#include "materials.h"
|
#include "materials.h"
|
||||||
|
#include "mapnode.h"
|
||||||
|
|
||||||
#define MATERIAL_PROPERTIES_COUNT 256
|
// NOTE: DEPRECATED
|
||||||
|
|
||||||
// These correspond to the CONTENT_* constants
|
DiggingPropertiesList * getDiggingPropertiesList(u8 content)
|
||||||
MaterialProperties g_material_properties[MATERIAL_PROPERTIES_COUNT];
|
|
||||||
|
|
||||||
bool g_material_properties_initialized = false;
|
|
||||||
|
|
||||||
void setStoneLikeDiggingProperties(u8 material, float toughness)
|
|
||||||
{
|
{
|
||||||
g_material_properties[material].setDiggingProperties("",
|
return &content_features(content).digging_properties;
|
||||||
DiggingProperties(true, 15.0*toughness, 0));
|
|
||||||
|
|
||||||
g_material_properties[material].setDiggingProperties("WPick",
|
|
||||||
DiggingProperties(true, 1.3*toughness, 65535./30.*toughness));
|
|
||||||
g_material_properties[material].setDiggingProperties("STPick",
|
|
||||||
DiggingProperties(true, 0.75*toughness, 65535./100.*toughness));
|
|
||||||
g_material_properties[material].setDiggingProperties("SteelPick",
|
|
||||||
DiggingProperties(true, 0.50*toughness, 65535./333.*toughness));
|
|
||||||
|
|
||||||
/*g_material_properties[material].setDiggingProperties("MesePick",
|
|
||||||
DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDirtLikeDiggingProperties(u8 material, float toughness)
|
DiggingProperties getDiggingProperties(u8 content, const std::string &tool)
|
||||||
{
|
{
|
||||||
g_material_properties[material].setDiggingProperties("",
|
DiggingPropertiesList *mprop = getDiggingPropertiesList(content);
|
||||||
DiggingProperties(true, 0.75*toughness, 0));
|
|
||||||
|
|
||||||
g_material_properties[material].setDiggingProperties("WShovel",
|
|
||||||
DiggingProperties(true, 0.4*toughness, 65535./50.*toughness));
|
|
||||||
g_material_properties[material].setDiggingProperties("STShovel",
|
|
||||||
DiggingProperties(true, 0.2*toughness, 65535./150.*toughness));
|
|
||||||
g_material_properties[material].setDiggingProperties("SteelShovel",
|
|
||||||
DiggingProperties(true, 0.15*toughness, 65535./400.*toughness));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWoodLikeDiggingProperties(u8 material, float toughness)
|
|
||||||
{
|
|
||||||
g_material_properties[material].setDiggingProperties("",
|
|
||||||
DiggingProperties(true, 3.0*toughness, 0));
|
|
||||||
|
|
||||||
g_material_properties[material].setDiggingProperties("WAxe",
|
|
||||||
DiggingProperties(true, 1.5*toughness, 65535./30.*toughness));
|
|
||||||
g_material_properties[material].setDiggingProperties("STAxe",
|
|
||||||
DiggingProperties(true, 0.75*toughness, 65535./100.*toughness));
|
|
||||||
g_material_properties[material].setDiggingProperties("SteelAxe",
|
|
||||||
DiggingProperties(true, 0.5*toughness, 65535./333.*toughness));
|
|
||||||
}
|
|
||||||
|
|
||||||
void initializeMaterialProperties()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Now, the g_material_properties array is already initialized
|
|
||||||
by the constructors to such that no digging is possible.
|
|
||||||
|
|
||||||
Add some digging properties to them.
|
|
||||||
*/
|
|
||||||
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_STONE, 1.0);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_SANDSTONE, 1.0);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_BRICK, 3.0);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_MESE, 0.5);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_COALSTONE, 1.5);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_FURNACE, 3.0);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_COBBLE, 1.0);
|
|
||||||
setStoneLikeDiggingProperties(CONTENT_STEEL, 5.0);
|
|
||||||
|
|
||||||
setDirtLikeDiggingProperties(CONTENT_MUD, 1.0);
|
|
||||||
setDirtLikeDiggingProperties(CONTENT_GRASS, 1.0);
|
|
||||||
setDirtLikeDiggingProperties(CONTENT_GRASS_FOOTSTEPS, 1.0);
|
|
||||||
setDirtLikeDiggingProperties(CONTENT_SAND, 1.0);
|
|
||||||
setDirtLikeDiggingProperties(CONTENT_CLAY, 1.0);
|
|
||||||
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_TREE, 1.0);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_LEAVES, 0.15);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_CACTUS, 0.75);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_PAPYRUS, 0.25);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_GLASS, 0.15);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_FENCE, 0.75);
|
|
||||||
setDirtLikeDiggingProperties(CONTENT_RAIL, 0.75);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_WOOD, 0.75);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_BOOKSHELF, 0.75);
|
|
||||||
setWoodLikeDiggingProperties(CONTENT_CHEST, 1.0);
|
|
||||||
|
|
||||||
g_material_properties[CONTENT_SIGN_WALL].setDiggingProperties("",
|
|
||||||
DiggingProperties(true, 0.5, 0));
|
|
||||||
g_material_properties[CONTENT_TORCH].setDiggingProperties("",
|
|
||||||
DiggingProperties(true, 0.0, 0));
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add MesePick to everything
|
|
||||||
*/
|
|
||||||
for(u16 i=0; i<MATERIAL_PROPERTIES_COUNT; i++)
|
|
||||||
{
|
|
||||||
g_material_properties[i].setDiggingProperties("MesePick",
|
|
||||||
DiggingProperties(true, 0.0, 65535./1337));
|
|
||||||
}
|
|
||||||
|
|
||||||
g_material_properties_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialProperties * getMaterialProperties(u8 material)
|
|
||||||
{
|
|
||||||
assert(g_material_properties_initialized);
|
|
||||||
return &g_material_properties[material];
|
|
||||||
}
|
|
||||||
|
|
||||||
DiggingProperties getDiggingProperties(u8 material, const std::string &tool)
|
|
||||||
{
|
|
||||||
MaterialProperties *mprop = getMaterialProperties(material);
|
|
||||||
if(mprop == NULL)
|
if(mprop == NULL)
|
||||||
// Not diggable
|
// Not diggable
|
||||||
return DiggingProperties();
|
return DiggingProperties();
|
||||||
|
|
||||||
return mprop->getDiggingProperties(tool);
|
return mprop->get(tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "inventory.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct DiggingProperties
|
struct DiggingProperties
|
||||||
@ -49,20 +48,26 @@ struct DiggingProperties
|
|||||||
u16 wear;
|
u16 wear;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MaterialProperties
|
/*
|
||||||
|
This is a bad way of determining mining characteristics.
|
||||||
|
TODO: Get rid of this and set up some attributes like toughness,
|
||||||
|
fluffyness, and a funciton to calculate time and durability loss
|
||||||
|
(and sound? and whatever else) from them
|
||||||
|
*/
|
||||||
|
class DiggingPropertiesList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MaterialProperties()
|
DiggingPropertiesList()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDiggingProperties(const std::string toolname,
|
void set(const std::string toolname,
|
||||||
const DiggingProperties &prop)
|
const DiggingProperties &prop)
|
||||||
{
|
{
|
||||||
m_digging_properties[toolname] = prop;
|
m_digging_properties[toolname] = prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiggingProperties getDiggingProperties(const std::string toolname)
|
DiggingProperties get(const std::string toolname)
|
||||||
{
|
{
|
||||||
core::map<std::string, DiggingProperties>::Node *n;
|
core::map<std::string, DiggingProperties>::Node *n;
|
||||||
n = m_digging_properties.find(toolname);
|
n = m_digging_properties.find(toolname);
|
||||||
@ -80,16 +85,17 @@ public:
|
|||||||
return n->getValue();
|
return n->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_digging_properties.clear();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// toolname="": default properties (digging by hand)
|
// toolname="": default properties (digging by hand)
|
||||||
// Key is toolname
|
// Key is toolname
|
||||||
core::map<std::string, DiggingProperties> m_digging_properties;
|
core::map<std::string, DiggingProperties> m_digging_properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
void initializeMaterialProperties();
|
|
||||||
|
|
||||||
// Material correspond to the CONTENT_* constants
|
|
||||||
MaterialProperties * getMaterialProperties(u8 material);
|
|
||||||
// For getting the default properties, set tool=""
|
// For getting the default properties, set tool=""
|
||||||
DiggingProperties getDiggingProperties(u8 material, const std::string &tool);
|
DiggingProperties getDiggingProperties(u8 material, const std::string &tool);
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NodeMetadata
|
NodeMetadata
|
||||||
@ -96,268 +97,7 @@ void NodeMetadata::registerType(u16 id, Factory f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SignNodeMetadata
|
NodeMetadataList
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
SignNodeMetadata proto_SignNodeMetadata("");
|
|
||||||
|
|
||||||
SignNodeMetadata::SignNodeMetadata(std::string text):
|
|
||||||
m_text(text)
|
|
||||||
{
|
|
||||||
NodeMetadata::registerType(typeId(), create);
|
|
||||||
}
|
|
||||||
u16 SignNodeMetadata::typeId() const
|
|
||||||
{
|
|
||||||
return CONTENT_SIGN_WALL;
|
|
||||||
}
|
|
||||||
NodeMetadata* SignNodeMetadata::create(std::istream &is)
|
|
||||||
{
|
|
||||||
std::string text = deSerializeString(is);
|
|
||||||
return new SignNodeMetadata(text);
|
|
||||||
}
|
|
||||||
NodeMetadata* SignNodeMetadata::clone()
|
|
||||||
{
|
|
||||||
return new SignNodeMetadata(m_text);
|
|
||||||
}
|
|
||||||
void SignNodeMetadata::serializeBody(std::ostream &os)
|
|
||||||
{
|
|
||||||
os<<serializeString(m_text);
|
|
||||||
}
|
|
||||||
std::string SignNodeMetadata::infoText()
|
|
||||||
{
|
|
||||||
return std::string("\"")+m_text+"\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
ChestNodeMetadata
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
ChestNodeMetadata proto_ChestNodeMetadata;
|
|
||||||
|
|
||||||
ChestNodeMetadata::ChestNodeMetadata()
|
|
||||||
{
|
|
||||||
NodeMetadata::registerType(typeId(), create);
|
|
||||||
|
|
||||||
m_inventory = new Inventory();
|
|
||||||
m_inventory->addList("0", 8*4);
|
|
||||||
}
|
|
||||||
ChestNodeMetadata::~ChestNodeMetadata()
|
|
||||||
{
|
|
||||||
delete m_inventory;
|
|
||||||
}
|
|
||||||
u16 ChestNodeMetadata::typeId() const
|
|
||||||
{
|
|
||||||
return CONTENT_CHEST;
|
|
||||||
}
|
|
||||||
NodeMetadata* ChestNodeMetadata::create(std::istream &is)
|
|
||||||
{
|
|
||||||
ChestNodeMetadata *d = new ChestNodeMetadata();
|
|
||||||
d->m_inventory->deSerialize(is);
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
NodeMetadata* ChestNodeMetadata::clone()
|
|
||||||
{
|
|
||||||
ChestNodeMetadata *d = new ChestNodeMetadata();
|
|
||||||
*d->m_inventory = *m_inventory;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
void ChestNodeMetadata::serializeBody(std::ostream &os)
|
|
||||||
{
|
|
||||||
m_inventory->serialize(os);
|
|
||||||
}
|
|
||||||
std::string ChestNodeMetadata::infoText()
|
|
||||||
{
|
|
||||||
return "Chest";
|
|
||||||
}
|
|
||||||
bool ChestNodeMetadata::nodeRemovalDisabled()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Disable removal if chest contains something
|
|
||||||
*/
|
|
||||||
InventoryList *list = m_inventory->getList("0");
|
|
||||||
if(list == NULL)
|
|
||||||
return false;
|
|
||||||
if(list->getUsedSlots() == 0)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
FurnaceNodeMetadata
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prototype
|
|
||||||
FurnaceNodeMetadata proto_FurnaceNodeMetadata;
|
|
||||||
|
|
||||||
FurnaceNodeMetadata::FurnaceNodeMetadata()
|
|
||||||
{
|
|
||||||
NodeMetadata::registerType(typeId(), create);
|
|
||||||
|
|
||||||
m_inventory = new Inventory();
|
|
||||||
m_inventory->addList("fuel", 1);
|
|
||||||
m_inventory->addList("src", 1);
|
|
||||||
m_inventory->addList("dst", 4);
|
|
||||||
|
|
||||||
m_step_accumulator = 0;
|
|
||||||
m_fuel_totaltime = 0;
|
|
||||||
m_fuel_time = 0;
|
|
||||||
m_src_totaltime = 0;
|
|
||||||
m_src_time = 0;
|
|
||||||
}
|
|
||||||
FurnaceNodeMetadata::~FurnaceNodeMetadata()
|
|
||||||
{
|
|
||||||
delete m_inventory;
|
|
||||||
}
|
|
||||||
u16 FurnaceNodeMetadata::typeId() const
|
|
||||||
{
|
|
||||||
return CONTENT_FURNACE;
|
|
||||||
}
|
|
||||||
NodeMetadata* FurnaceNodeMetadata::clone()
|
|
||||||
{
|
|
||||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
|
|
||||||
*d->m_inventory = *m_inventory;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
NodeMetadata* FurnaceNodeMetadata::create(std::istream &is)
|
|
||||||
{
|
|
||||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
|
|
||||||
|
|
||||||
d->m_inventory->deSerialize(is);
|
|
||||||
|
|
||||||
int temp;
|
|
||||||
is>>temp;
|
|
||||||
d->m_fuel_totaltime = (float)temp/10;
|
|
||||||
is>>temp;
|
|
||||||
d->m_fuel_time = (float)temp/10;
|
|
||||||
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
void FurnaceNodeMetadata::serializeBody(std::ostream &os)
|
|
||||||
{
|
|
||||||
m_inventory->serialize(os);
|
|
||||||
os<<itos(m_fuel_totaltime*10)<<" ";
|
|
||||||
os<<itos(m_fuel_time*10)<<" ";
|
|
||||||
}
|
|
||||||
std::string FurnaceNodeMetadata::infoText()
|
|
||||||
{
|
|
||||||
//return "Furnace";
|
|
||||||
if(m_fuel_time >= m_fuel_totaltime)
|
|
||||||
{
|
|
||||||
InventoryList *src_list = m_inventory->getList("src");
|
|
||||||
assert(src_list);
|
|
||||||
InventoryItem *src_item = src_list->getItem(0);
|
|
||||||
|
|
||||||
if(src_item)
|
|
||||||
return "Furnace is out of fuel";
|
|
||||||
else
|
|
||||||
return "Furnace is inactive";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string s = "Furnace is active (";
|
|
||||||
s += itos(m_fuel_time/m_fuel_totaltime*100);
|
|
||||||
s += "%)";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void FurnaceNodeMetadata::inventoryModified()
|
|
||||||
{
|
|
||||||
dstream<<"Furnace inventory modification callback"<<std::endl;
|
|
||||||
}
|
|
||||||
bool FurnaceNodeMetadata::step(float dtime)
|
|
||||||
{
|
|
||||||
// Update at a fixed frequency
|
|
||||||
const float interval = 0.5;
|
|
||||||
m_step_accumulator += dtime;
|
|
||||||
if(m_step_accumulator < interval)
|
|
||||||
return false;
|
|
||||||
m_step_accumulator -= interval;
|
|
||||||
dtime = interval;
|
|
||||||
|
|
||||||
//dstream<<"Furnace step dtime="<<dtime<<std::endl;
|
|
||||||
|
|
||||||
InventoryList *dst_list = m_inventory->getList("dst");
|
|
||||||
assert(dst_list);
|
|
||||||
|
|
||||||
InventoryList *src_list = m_inventory->getList("src");
|
|
||||||
assert(src_list);
|
|
||||||
InventoryItem *src_item = src_list->getItem(0);
|
|
||||||
|
|
||||||
// Start only if there are free slots in dst, so that it can
|
|
||||||
// accomodate any result item
|
|
||||||
if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
|
|
||||||
{
|
|
||||||
m_src_totaltime = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_src_time = 0;
|
|
||||||
m_src_totaltime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_fuel_time < m_fuel_totaltime)
|
|
||||||
{
|
|
||||||
//dstream<<"Furnace is active"<<std::endl;
|
|
||||||
m_fuel_time += dtime;
|
|
||||||
m_src_time += dtime;
|
|
||||||
if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
|
|
||||||
&& src_item)
|
|
||||||
{
|
|
||||||
InventoryItem *cookresult = src_item->createCookResult();
|
|
||||||
dst_list->addItem(cookresult);
|
|
||||||
src_list->decrementMaterials(1);
|
|
||||||
m_src_time = 0;
|
|
||||||
m_src_totaltime = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(src_item == NULL || m_src_totaltime < 0.001)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
//dstream<<"Furnace is out of fuel"<<std::endl;
|
|
||||||
|
|
||||||
InventoryList *fuel_list = m_inventory->getList("fuel");
|
|
||||||
assert(fuel_list);
|
|
||||||
InventoryItem *fuel_item = fuel_list->getItem(0);
|
|
||||||
|
|
||||||
if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
|
|
||||||
{
|
|
||||||
m_fuel_totaltime = 10;
|
|
||||||
m_fuel_time = 0;
|
|
||||||
fuel_list->decrementMaterials(1);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
|
|
||||||
{
|
|
||||||
m_fuel_totaltime = 5;
|
|
||||||
m_fuel_time = 0;
|
|
||||||
fuel_list->decrementMaterials(1);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
|
|
||||||
{
|
|
||||||
m_fuel_totaltime = 10;
|
|
||||||
m_fuel_time = 0;
|
|
||||||
fuel_list->decrementMaterials(1);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//dstream<<"No fuel found"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
NodeMetadatalist
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void NodeMetadataList::serialize(std::ostream &os)
|
void NodeMetadataList::serialize(std::ostream &os)
|
||||||
@ -484,19 +224,6 @@ bool NodeMetadataList::step(float dtime)
|
|||||||
bool changed = meta->step(dtime);
|
bool changed = meta->step(dtime);
|
||||||
if(changed)
|
if(changed)
|
||||||
something_changed = true;
|
something_changed = true;
|
||||||
/*if(res.inventory_changed)
|
|
||||||
{
|
|
||||||
std::string inv_id;
|
|
||||||
inv_id += "nodemeta:";
|
|
||||||
inv_id += itos(p.X);
|
|
||||||
inv_id += ",";
|
|
||||||
inv_id += itos(p.Y);
|
|
||||||
inv_id += ",";
|
|
||||||
inv_id += itos(p.Z);
|
|
||||||
InventoryContext c;
|
|
||||||
c.current_player = NULL;
|
|
||||||
inv_mgr->inventoryModified(&c, inv_id);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
return something_changed;
|
return something_changed;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,9 @@ public:
|
|||||||
// A step in time. Returns true if metadata changed.
|
// A step in time. Returns true if metadata changed.
|
||||||
virtual bool step(float dtime) {return false;}
|
virtual bool step(float dtime) {return false;}
|
||||||
virtual bool nodeRemovalDisabled(){return false;}
|
virtual bool nodeRemovalDisabled(){return false;}
|
||||||
|
// Used to make custom inventory menus.
|
||||||
|
// See format in guiInventoryMenu.cpp.
|
||||||
|
virtual std::string getInventoryDrawSpecString(){return "";}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void registerType(u16 id, Factory f);
|
static void registerType(u16 id, Factory f);
|
||||||
@ -69,74 +72,10 @@ private:
|
|||||||
static core::map<u16, Factory> m_types;
|
static core::map<u16, Factory> m_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SignNodeMetadata : public NodeMetadata
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SignNodeMetadata(std::string text);
|
|
||||||
//~SignNodeMetadata();
|
|
||||||
|
|
||||||
virtual u16 typeId() const;
|
|
||||||
static NodeMetadata* create(std::istream &is);
|
|
||||||
virtual NodeMetadata* clone();
|
|
||||||
virtual void serializeBody(std::ostream &os);
|
|
||||||
virtual std::string infoText();
|
|
||||||
|
|
||||||
std::string getText(){ return m_text; }
|
|
||||||
void setText(std::string t){ m_text = t; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_text;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChestNodeMetadata : public NodeMetadata
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ChestNodeMetadata();
|
|
||||||
~ChestNodeMetadata();
|
|
||||||
|
|
||||||
virtual u16 typeId() const;
|
|
||||||
static NodeMetadata* create(std::istream &is);
|
|
||||||
virtual NodeMetadata* clone();
|
|
||||||
virtual void serializeBody(std::ostream &os);
|
|
||||||
virtual std::string infoText();
|
|
||||||
virtual Inventory* getInventory() {return m_inventory;}
|
|
||||||
|
|
||||||
virtual bool nodeRemovalDisabled();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Inventory *m_inventory;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FurnaceNodeMetadata : public NodeMetadata
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FurnaceNodeMetadata();
|
|
||||||
~FurnaceNodeMetadata();
|
|
||||||
|
|
||||||
virtual u16 typeId() const;
|
|
||||||
virtual NodeMetadata* clone();
|
|
||||||
static NodeMetadata* create(std::istream &is);
|
|
||||||
virtual void serializeBody(std::ostream &os);
|
|
||||||
virtual std::string infoText();
|
|
||||||
virtual Inventory* getInventory() {return m_inventory;}
|
|
||||||
virtual void inventoryModified();
|
|
||||||
virtual bool step(float dtime);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Inventory *m_inventory;
|
|
||||||
float m_step_accumulator;
|
|
||||||
float m_fuel_totaltime;
|
|
||||||
float m_fuel_time;
|
|
||||||
float m_src_totaltime;
|
|
||||||
float m_src_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
List of metadata of all the nodes of a block
|
List of metadata of all the nodes of a block
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class InventoryManager;
|
|
||||||
|
|
||||||
class NodeMetadataList
|
class NodeMetadataList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
111
src/noise.cpp
111
src/noise.cpp
@ -222,6 +222,49 @@ double noise3d_perlin_abs(double x, double y, double z, int seed,
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -1->0, 0->1, 1->0
|
||||||
|
double contour(double v)
|
||||||
|
{
|
||||||
|
v = fabs(v);
|
||||||
|
if(v >= 1.0)
|
||||||
|
return 0.0;
|
||||||
|
return (1.0-v);
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise3d_param(const NoiseParams ¶m, double x, double y, double z)
|
||||||
|
{
|
||||||
|
double s = param.pos_scale;
|
||||||
|
x /= s;
|
||||||
|
y /= s;
|
||||||
|
z /= s;
|
||||||
|
|
||||||
|
if(param.type == NOISE_PERLIN)
|
||||||
|
{
|
||||||
|
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
|
||||||
|
param.octaves,
|
||||||
|
param.persistence);
|
||||||
|
}
|
||||||
|
else if(param.type == NOISE_PERLIN_ABS)
|
||||||
|
{
|
||||||
|
return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed,
|
||||||
|
param.octaves,
|
||||||
|
param.persistence);
|
||||||
|
}
|
||||||
|
else if(param.type == NOISE_PERLIN_CONTOUR)
|
||||||
|
{
|
||||||
|
return contour(param.noise_scale*noise3d_perlin(x,y,z,
|
||||||
|
param.seed, param.octaves,
|
||||||
|
param.persistence));
|
||||||
|
}
|
||||||
|
else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ)
|
||||||
|
{
|
||||||
|
return contour(param.noise_scale*noise3d_perlin(x,z,y,
|
||||||
|
param.seed, param.octaves,
|
||||||
|
param.persistence));
|
||||||
|
}
|
||||||
|
else assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NoiseBuffer
|
NoiseBuffer
|
||||||
*/
|
*/
|
||||||
@ -246,8 +289,7 @@ void NoiseBuffer::clear()
|
|||||||
m_size_z = 0;
|
m_size_z = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseBuffer::create(int seed, int octaves, double persistence,
|
void NoiseBuffer::create(const NoiseParams ¶m,
|
||||||
double pos_scale,
|
|
||||||
double first_x, double first_y, double first_z,
|
double first_x, double first_y, double first_z,
|
||||||
double last_x, double last_y, double last_z,
|
double last_x, double last_y, double last_z,
|
||||||
double samplelength_x, double samplelength_y, double samplelength_z)
|
double samplelength_x, double samplelength_y, double samplelength_z)
|
||||||
@ -265,22 +307,54 @@ void NoiseBuffer::create(int seed, int octaves, double persistence,
|
|||||||
m_size_y = (last_y - m_start_y)/samplelength_y + 2;
|
m_size_y = (last_y - m_start_y)/samplelength_y + 2;
|
||||||
m_size_z = (last_z - m_start_z)/samplelength_z + 2;
|
m_size_z = (last_z - m_start_z)/samplelength_z + 2;
|
||||||
|
|
||||||
/*dstream<<"m_size_x="<<m_size_x<<", m_size_y="<<m_size_y
|
|
||||||
<<", m_size_z="<<m_size_z<<std::endl;*/
|
|
||||||
|
|
||||||
m_data = new double[m_size_x*m_size_y*m_size_z];
|
m_data = new double[m_size_x*m_size_y*m_size_z];
|
||||||
|
|
||||||
for(int x=0; x<m_size_x; x++)
|
for(int x=0; x<m_size_x; x++)
|
||||||
for(int y=0; y<m_size_y; y++)
|
for(int y=0; y<m_size_y; y++)
|
||||||
for(int z=0; z<m_size_z; z++)
|
for(int z=0; z<m_size_z; z++)
|
||||||
{
|
{
|
||||||
double xd = (m_start_x + (double)x*m_samplelength_x)/pos_scale;
|
double xd = (m_start_x + (double)x*m_samplelength_x);
|
||||||
double yd = (m_start_y + (double)y*m_samplelength_y)/pos_scale;
|
double yd = (m_start_y + (double)y*m_samplelength_y);
|
||||||
double zd = (m_start_z + (double)z*m_samplelength_z)/pos_scale;
|
double zd = (m_start_z + (double)z*m_samplelength_z);
|
||||||
intSet(x,y,z, noise3d_perlin(xd,yd,zd,seed,octaves,persistence));
|
double a = noise3d_param(param, xd,yd,zd);
|
||||||
|
intSet(x,y,z, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoiseBuffer::multiply(const NoiseParams ¶m)
|
||||||
|
{
|
||||||
|
assert(m_data != NULL);
|
||||||
|
|
||||||
|
for(int x=0; x<m_size_x; x++)
|
||||||
|
for(int y=0; y<m_size_y; y++)
|
||||||
|
for(int z=0; z<m_size_z; z++)
|
||||||
|
{
|
||||||
|
double xd = (m_start_x + (double)x*m_samplelength_x);
|
||||||
|
double yd = (m_start_y + (double)y*m_samplelength_y);
|
||||||
|
double zd = (m_start_z + (double)z*m_samplelength_z);
|
||||||
|
double a = noise3d_param(param, xd,yd,zd);
|
||||||
|
intMultiply(x,y,z, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
|
void NoiseBuffer::create(int seed, int octaves, double persistence,
|
||||||
|
bool abs,
|
||||||
|
double first_x, double first_y, double first_z,
|
||||||
|
double last_x, double last_y, double last_z,
|
||||||
|
double samplelength_x, double samplelength_y, double samplelength_z)
|
||||||
|
{
|
||||||
|
NoiseParams param;
|
||||||
|
param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
|
||||||
|
param.seed = seed;
|
||||||
|
param.octaves = octaves;
|
||||||
|
param.persistence = persistence;
|
||||||
|
|
||||||
|
create(param, first_x, first_y, first_z,
|
||||||
|
last_x, last_y, last_z,
|
||||||
|
samplelength_x, samplelength_y, samplelength_z);
|
||||||
|
}
|
||||||
|
|
||||||
void NoiseBuffer::intSet(int x, int y, int z, double d)
|
void NoiseBuffer::intSet(int x, int y, int z, double d)
|
||||||
{
|
{
|
||||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||||
@ -289,6 +363,14 @@ void NoiseBuffer::intSet(int x, int y, int z, double d)
|
|||||||
m_data[i] = d;
|
m_data[i] = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoiseBuffer::intMultiply(int x, int y, int z, double d)
|
||||||
|
{
|
||||||
|
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||||
|
assert(i >= 0);
|
||||||
|
assert(i < m_size_x*m_size_y*m_size_z);
|
||||||
|
m_data[i] = m_data[i] * d;
|
||||||
|
}
|
||||||
|
|
||||||
double NoiseBuffer::intGet(int x, int y, int z)
|
double NoiseBuffer::intGet(int x, int y, int z)
|
||||||
{
|
{
|
||||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||||
@ -326,3 +408,14 @@ double NoiseBuffer::get(double x, double y, double z)
|
|||||||
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
|
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*bool NoiseBuffer::contains(double x, double y, double z)
|
||||||
|
{
|
||||||
|
x -= m_start_x;
|
||||||
|
y -= m_start_y;
|
||||||
|
z -= m_start_z;
|
||||||
|
x /= m_samplelength_x;
|
||||||
|
y /= m_samplelength_y;
|
||||||
|
z /= m_samplelength_z;
|
||||||
|
if(x <= 0.0 || x >= m_size_x)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
81
src/noise.h
81
src/noise.h
@ -20,6 +20,45 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#ifndef NOISE_HEADER
|
#ifndef NOISE_HEADER
|
||||||
#define NOISE_HEADER
|
#define NOISE_HEADER
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
class PseudoRandom
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PseudoRandom(): m_next(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
PseudoRandom(int seed): m_next(seed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void seed(int seed)
|
||||||
|
{
|
||||||
|
m_next = seed;
|
||||||
|
}
|
||||||
|
// Returns 0...32767
|
||||||
|
int next()
|
||||||
|
{
|
||||||
|
m_next = m_next * 1103515245 + 12345;
|
||||||
|
return((unsigned)(m_next/65536) % 32768);
|
||||||
|
}
|
||||||
|
int range(int min, int max)
|
||||||
|
{
|
||||||
|
if(max-min > 32768/10)
|
||||||
|
{
|
||||||
|
//dstream<<"WARNING: PseudoRandom::range: max > 32767"<<std::endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
if(min > max)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
return (next()%(max-min+1))+min;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int m_next;
|
||||||
|
};
|
||||||
|
|
||||||
double easeCurve(double t);
|
double easeCurve(double t);
|
||||||
|
|
||||||
// Return value: -1 ... 1
|
// Return value: -1 ... 1
|
||||||
@ -41,6 +80,38 @@ double noise3d_perlin(double x, double y, double z, int seed,
|
|||||||
double noise3d_perlin_abs(double x, double y, double z, int seed,
|
double noise3d_perlin_abs(double x, double y, double z, int seed,
|
||||||
int octaves, double persistence);
|
int octaves, double persistence);
|
||||||
|
|
||||||
|
enum NoiseType
|
||||||
|
{
|
||||||
|
NOISE_PERLIN,
|
||||||
|
NOISE_PERLIN_ABS,
|
||||||
|
NOISE_PERLIN_CONTOUR,
|
||||||
|
NOISE_PERLIN_CONTOUR_FLIP_YZ
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NoiseParams
|
||||||
|
{
|
||||||
|
NoiseType type;
|
||||||
|
int seed;
|
||||||
|
int octaves;
|
||||||
|
double persistence;
|
||||||
|
double pos_scale;
|
||||||
|
double noise_scale; // Useful for contour noises
|
||||||
|
|
||||||
|
NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
|
||||||
|
int octaves_=3, double persistence_=0.5,
|
||||||
|
double pos_scale_=100.0, double noise_scale_=1.0):
|
||||||
|
type(type_),
|
||||||
|
seed(seed_),
|
||||||
|
octaves(octaves_),
|
||||||
|
persistence(persistence_),
|
||||||
|
pos_scale(pos_scale_),
|
||||||
|
noise_scale(noise_scale_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
double noise3d_param(const NoiseParams ¶m, double x, double y, double z);
|
||||||
|
|
||||||
class NoiseBuffer
|
class NoiseBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -48,15 +119,23 @@ public:
|
|||||||
~NoiseBuffer();
|
~NoiseBuffer();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
void create(const NoiseParams ¶m,
|
||||||
|
double first_x, double first_y, double first_z,
|
||||||
|
double last_x, double last_y, double last_z,
|
||||||
|
double samplelength_x, double samplelength_y, double samplelength_z);
|
||||||
|
void multiply(const NoiseParams ¶m);
|
||||||
|
// Deprecated
|
||||||
void create(int seed, int octaves, double persistence,
|
void create(int seed, int octaves, double persistence,
|
||||||
double pos_scale,
|
bool abs,
|
||||||
double first_x, double first_y, double first_z,
|
double first_x, double first_y, double first_z,
|
||||||
double last_x, double last_y, double last_z,
|
double last_x, double last_y, double last_z,
|
||||||
double samplelength_x, double samplelength_y, double samplelength_z);
|
double samplelength_x, double samplelength_y, double samplelength_z);
|
||||||
|
|
||||||
void intSet(int x, int y, int z, double d);
|
void intSet(int x, int y, int z, double d);
|
||||||
|
void intMultiply(int x, int y, int z, double d);
|
||||||
double intGet(int x, int y, int z);
|
double intGet(int x, int y, int z);
|
||||||
double get(double x, double y, double z);
|
double get(double x, double y, double z);
|
||||||
|
//bool contains(double x, double y, double z);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double *m_data;
|
double *m_data;
|
||||||
|
@ -23,58 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
// Convert a privileges value into a human-readable string,
|
|
||||||
// with each component separated by a comma.
|
|
||||||
std::wstring privsToString(u64 privs)
|
|
||||||
{
|
|
||||||
std::wostringstream os(std::ios_base::binary);
|
|
||||||
if(privs & PRIV_BUILD)
|
|
||||||
os<<L"build,";
|
|
||||||
if(privs & PRIV_TELEPORT)
|
|
||||||
os<<L"teleport,";
|
|
||||||
if(privs & PRIV_SETTIME)
|
|
||||||
os<<L"settime,";
|
|
||||||
if(privs & PRIV_PRIVS)
|
|
||||||
os<<L"privs,";
|
|
||||||
if(privs & PRIV_SHOUT)
|
|
||||||
os<<L"shout,";
|
|
||||||
if(os.tellp())
|
|
||||||
{
|
|
||||||
// Drop the trailing comma. (Why on earth can't
|
|
||||||
// you truncate a C++ stream anyway???)
|
|
||||||
std::wstring tmp = os.str();
|
|
||||||
return tmp.substr(0, tmp.length() -1);
|
|
||||||
}
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a comma-seperated list of privilege values into a
|
|
||||||
// privileges value. The reverse of privsToString(). Returns
|
|
||||||
// PRIV_INVALID if there is anything wrong with the input.
|
|
||||||
u64 stringToPrivs(std::wstring str)
|
|
||||||
{
|
|
||||||
u64 privs=0;
|
|
||||||
std::vector<std::wstring> pr;
|
|
||||||
pr=str_split(str, ',');
|
|
||||||
for(std::vector<std::wstring>::iterator i = pr.begin();
|
|
||||||
i != pr.end(); ++i)
|
|
||||||
{
|
|
||||||
if(*i == L"build")
|
|
||||||
privs |= PRIV_BUILD;
|
|
||||||
else if(*i == L"teleport")
|
|
||||||
privs |= PRIV_TELEPORT;
|
|
||||||
else if(*i == L"settime")
|
|
||||||
privs |= PRIV_SETTIME;
|
|
||||||
else if(*i == L"privs")
|
|
||||||
privs |= PRIV_PRIVS;
|
|
||||||
else if(*i == L"shout")
|
|
||||||
privs |= PRIV_SHOUT;
|
|
||||||
else
|
|
||||||
return PRIV_INVALID;
|
|
||||||
}
|
|
||||||
return privs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Player::Player():
|
Player::Player():
|
||||||
touching_ground(false),
|
touching_ground(false),
|
||||||
@ -83,7 +31,6 @@ Player::Player():
|
|||||||
swimming_up(false),
|
swimming_up(false),
|
||||||
craftresult_is_preview(true),
|
craftresult_is_preview(true),
|
||||||
hp(20),
|
hp(20),
|
||||||
privs(PRIV_DEFAULT),
|
|
||||||
peer_id(PEER_ID_INEXISTENT),
|
peer_id(PEER_ID_INEXISTENT),
|
||||||
m_pitch(0),
|
m_pitch(0),
|
||||||
m_yaw(0),
|
m_yaw(0),
|
||||||
@ -91,7 +38,6 @@ Player::Player():
|
|||||||
m_position(0,0,0)
|
m_position(0,0,0)
|
||||||
{
|
{
|
||||||
updateName("<not set>");
|
updateName("<not set>");
|
||||||
updatePassword("");
|
|
||||||
resetInventory();
|
resetInventory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +96,12 @@ void Player::serialize(std::ostream &os)
|
|||||||
Settings args;
|
Settings args;
|
||||||
args.setS32("version", 1);
|
args.setS32("version", 1);
|
||||||
args.set("name", m_name);
|
args.set("name", m_name);
|
||||||
args.set("password", m_password);
|
//args.set("password", m_password);
|
||||||
args.setFloat("pitch", m_pitch);
|
args.setFloat("pitch", m_pitch);
|
||||||
args.setFloat("yaw", m_yaw);
|
args.setFloat("yaw", m_yaw);
|
||||||
args.setV3F("position", m_position);
|
args.setV3F("position", m_position);
|
||||||
args.setBool("craftresult_is_preview", craftresult_is_preview);
|
args.setBool("craftresult_is_preview", craftresult_is_preview);
|
||||||
args.setS32("hp", hp);
|
args.setS32("hp", hp);
|
||||||
args.setU64("privs", privs);
|
|
||||||
|
|
||||||
args.writeLines(os);
|
args.writeLines(os);
|
||||||
|
|
||||||
@ -185,10 +130,10 @@ void Player::deSerialize(std::istream &is)
|
|||||||
//args.getS32("version");
|
//args.getS32("version");
|
||||||
std::string name = args.get("name");
|
std::string name = args.get("name");
|
||||||
updateName(name.c_str());
|
updateName(name.c_str());
|
||||||
std::string password = "";
|
/*std::string password = "";
|
||||||
if(args.exists("password"))
|
if(args.exists("password"))
|
||||||
password = args.get("password");
|
password = args.get("password");
|
||||||
updatePassword(password.c_str());
|
updatePassword(password.c_str());*/
|
||||||
m_pitch = args.getFloat("pitch");
|
m_pitch = args.getFloat("pitch");
|
||||||
m_yaw = args.getFloat("yaw");
|
m_yaw = args.getFloat("yaw");
|
||||||
m_position = args.getV3F("position");
|
m_position = args.getV3F("position");
|
||||||
@ -202,7 +147,7 @@ void Player::deSerialize(std::istream &is)
|
|||||||
}catch(SettingNotFoundException &e){
|
}catch(SettingNotFoundException &e){
|
||||||
hp = 20;
|
hp = 20;
|
||||||
}
|
}
|
||||||
try{
|
/*try{
|
||||||
std::string sprivs = args.get("privs");
|
std::string sprivs = args.get("privs");
|
||||||
if(sprivs == "all")
|
if(sprivs == "all")
|
||||||
{
|
{
|
||||||
@ -215,7 +160,7 @@ void Player::deSerialize(std::istream &is)
|
|||||||
}
|
}
|
||||||
}catch(SettingNotFoundException &e){
|
}catch(SettingNotFoundException &e){
|
||||||
privs = PRIV_DEFAULT;
|
privs = PRIV_DEFAULT;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
inventory.deSerialize(is);
|
inventory.deSerialize(is);
|
||||||
}
|
}
|
||||||
|
47
src/player.h
47
src/player.h
@ -25,39 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
|
|
||||||
#define PLAYERNAME_SIZE 20
|
#define PLAYERNAME_SIZE 20
|
||||||
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
|
|
||||||
// base64-encoded SHA-1.
|
|
||||||
|
|
||||||
#define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,"
|
#define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
||||||
|
|
||||||
// Player privileges. These form a bitmask stored in the privs field
|
|
||||||
// of the player, and define things they're allowed to do. See also
|
|
||||||
// the static methods Player::privsToString and stringToPrivs that
|
|
||||||
// convert these to human-readable form.
|
|
||||||
const u64 PRIV_BUILD = 1; // Can build - i.e. modify the world
|
|
||||||
const u64 PRIV_TELEPORT = 2; // Can teleport
|
|
||||||
const u64 PRIV_SETTIME = 4; // Can set the time
|
|
||||||
const u64 PRIV_PRIVS = 8; // Can grant and revoke privileges
|
|
||||||
const u64 PRIV_SERVER = 16; // Can manage the server (e.g. shutodwn
|
|
||||||
// ,settings)
|
|
||||||
const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all
|
|
||||||
// players
|
|
||||||
|
|
||||||
// Default privileges - these can be overriden for new players using the
|
|
||||||
// config option "default_privs" - however, this value still applies for
|
|
||||||
// players that existed before the privileges system was added.
|
|
||||||
const u64 PRIV_DEFAULT = PRIV_BUILD|PRIV_SHOUT;
|
|
||||||
const u64 PRIV_ALL = 0x7FFFFFFFFFFFFFFFULL;
|
|
||||||
const u64 PRIV_INVALID = 0x8000000000000000ULL;
|
|
||||||
|
|
||||||
// Convert a privileges value into a human-readable string,
|
|
||||||
// with each component separated by a comma.
|
|
||||||
std::wstring privsToString(u64 privs);
|
|
||||||
|
|
||||||
// Converts a comma-seperated list of privilege values into a
|
|
||||||
// privileges value. The reverse of privsToString(). Returns
|
|
||||||
// PRIV_INVALID if there is anything wrong with the input.
|
|
||||||
u64 stringToPrivs(std::wstring str);
|
|
||||||
|
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
@ -128,16 +97,6 @@ public:
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updatePassword(const char *password)
|
|
||||||
{
|
|
||||||
snprintf(m_password, PASSWORD_SIZE, "%s", password);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * getPassword()
|
|
||||||
{
|
|
||||||
return m_password;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool isLocal() const = 0;
|
virtual bool isLocal() const = 0;
|
||||||
|
|
||||||
virtual void updateLight(u8 light_at_pos) {};
|
virtual void updateLight(u8 light_at_pos) {};
|
||||||
@ -167,14 +126,10 @@ public:
|
|||||||
|
|
||||||
u16 hp;
|
u16 hp;
|
||||||
|
|
||||||
// Player's privileges - a bitmaps of PRIV_xxxx.
|
|
||||||
u64 privs;
|
|
||||||
|
|
||||||
u16 peer_id;
|
u16 peer_id;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char m_name[PLAYERNAME_SIZE];
|
char m_name[PLAYERNAME_SIZE];
|
||||||
char m_password[PASSWORD_SIZE];
|
|
||||||
f32 m_pitch;
|
f32 m_pitch;
|
||||||
f32 m_yaw;
|
f32 m_yaw;
|
||||||
v3f m_speed;
|
v3f m_speed;
|
||||||
|
@ -27,6 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "CoreFoundation/CoreFoundation.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace porting
|
namespace porting
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -215,9 +219,26 @@ void initializePaths()
|
|||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Code based on
|
||||||
|
// http://stackoverflow.com/questions/516200/relative-paths-not-working-in-xcode-c
|
||||||
|
CFBundleRef main_bundle = CFBundleGetMainBundle();
|
||||||
|
CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(main_bundle);
|
||||||
|
char path[PATH_MAX];
|
||||||
|
if(CFURLGetFileSystemRepresentation(resources_url, TRUE, (UInt8 *)path, PATH_MAX))
|
||||||
|
{
|
||||||
|
dstream<<"Bundle resource path: "<<path<<std::endl;
|
||||||
|
//chdir(path);
|
||||||
|
path_data = std::string(path) + "/data";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// error!
|
||||||
|
dstream<<"WARNING: Could not determine bundle resource path"<<std::endl;
|
||||||
|
}
|
||||||
|
CFRelease(resources_url);
|
||||||
|
|
||||||
path_userdata = std::string(getenv("HOME")) + "/Library/Application Support/" + APPNAME;
|
path_userdata = std::string(getenv("HOME")) + "/Library/Application Support/" + APPNAME;
|
||||||
path_data = std::string("minetest-mac.app/Contents/Resources/data/");
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // RUN_IN_PLACE
|
#endif // RUN_IN_PLACE
|
||||||
|
131
src/profiler.h
Normal file
131
src/profiler.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROFILER_HEADER
|
||||||
|
#define PROFILER_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include <string>
|
||||||
|
#include "utility.h"
|
||||||
|
#include <jmutex.h>
|
||||||
|
#include <jmutexautolock.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Time profiler
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Profiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Profiler()
|
||||||
|
{
|
||||||
|
m_mutex.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const std::string &name, u32 duration)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
core::map<std::string, u32>::Node *n = m_data.find(name);
|
||||||
|
if(n == NULL)
|
||||||
|
{
|
||||||
|
m_data[name] = duration;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n->setValue(n->getValue()+duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
for(core::map<std::string, u32>::Iterator
|
||||||
|
i = m_data.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
i.getNode()->setValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(std::ostream &o)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
for(core::map<std::string, u32>::Iterator
|
||||||
|
i = m_data.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
std::string name = i.getNode()->getKey();
|
||||||
|
o<<name<<": ";
|
||||||
|
s32 clampsize = 40;
|
||||||
|
s32 space = clampsize-name.size();
|
||||||
|
for(s32 j=0; j<space; j++)
|
||||||
|
{
|
||||||
|
if(j%2 == 0 && j < space - 1)
|
||||||
|
o<<"-";
|
||||||
|
else
|
||||||
|
o<<" ";
|
||||||
|
}
|
||||||
|
o<<i.getNode()->getValue();
|
||||||
|
o<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JMutex m_mutex;
|
||||||
|
core::map<std::string, u32> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopeProfiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScopeProfiler(Profiler *profiler, const std::string &name):
|
||||||
|
m_profiler(profiler),
|
||||||
|
m_name(name),
|
||||||
|
m_timer(NULL)
|
||||||
|
{
|
||||||
|
if(m_profiler)
|
||||||
|
m_timer = new TimeTaker(m_name.c_str());
|
||||||
|
}
|
||||||
|
// name is copied
|
||||||
|
ScopeProfiler(Profiler *profiler, const char *name):
|
||||||
|
m_profiler(profiler),
|
||||||
|
m_name(name),
|
||||||
|
m_timer(NULL)
|
||||||
|
{
|
||||||
|
if(m_profiler)
|
||||||
|
m_timer = new TimeTaker(m_name.c_str());
|
||||||
|
}
|
||||||
|
~ScopeProfiler()
|
||||||
|
{
|
||||||
|
if(m_timer)
|
||||||
|
{
|
||||||
|
u32 duration = m_timer->stop(true);
|
||||||
|
if(m_profiler)
|
||||||
|
m_profiler->add(m_name, duration);
|
||||||
|
delete m_timer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Profiler *m_profiler;
|
||||||
|
std::string m_name;
|
||||||
|
TimeTaker *m_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -128,7 +128,7 @@ void decompressZlib(std::istream &is, std::ostream &os)
|
|||||||
|
|
||||||
ret = inflateInit(&z);
|
ret = inflateInit(&z);
|
||||||
if(ret != Z_OK)
|
if(ret != Z_OK)
|
||||||
throw SerializationError("compressZlib: inflateInit failed");
|
throw SerializationError("dcompressZlib: inflateInit failed");
|
||||||
|
|
||||||
z.avail_in = 0;
|
z.avail_in = 0;
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ void decompressZlib(std::istream &is, std::ostream &os)
|
|||||||
|| status == Z_MEM_ERROR)
|
|| status == Z_MEM_ERROR)
|
||||||
{
|
{
|
||||||
zerr(status);
|
zerr(status);
|
||||||
throw SerializationError("compressZlib: inflate failed");
|
throw SerializationError("decompressZlib: inflate failed");
|
||||||
}
|
}
|
||||||
int count = bufsize - z.avail_out;
|
int count = bufsize - z.avail_out;
|
||||||
//dstream<<"count="<<count<<std::endl;
|
//dstream<<"count="<<count<<std::endl;
|
||||||
@ -182,7 +182,7 @@ void decompressZlib(std::istream &is, std::ostream &os)
|
|||||||
{
|
{
|
||||||
dstream<<"unget #"<<i<<" failed"<<std::endl;
|
dstream<<"unget #"<<i<<" failed"<<std::endl;
|
||||||
dstream<<"fail="<<is.fail()<<" bad="<<is.bad()<<std::endl;
|
dstream<<"fail="<<is.fail()<<" bad="<<is.bad()<<std::endl;
|
||||||
throw SerializationError("compressZlib: unget failed");
|
throw SerializationError("decompressZlib: unget failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,11 +53,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
15: StaticObjects
|
15: StaticObjects
|
||||||
16: larger maximum size of node metadata, and compression
|
16: larger maximum size of node metadata, and compression
|
||||||
17: MapBlocks contain timestamp
|
17: MapBlocks contain timestamp
|
||||||
|
18: sqlite/new generator/whatever
|
||||||
*/
|
*/
|
||||||
// This represents an uninitialized or invalid format
|
// This represents an uninitialized or invalid format
|
||||||
#define SER_FMT_VER_INVALID 255
|
#define SER_FMT_VER_INVALID 255
|
||||||
// Highest supported serialization version
|
// Highest supported serialization version
|
||||||
#define SER_FMT_VER_HIGHEST 17
|
#define SER_FMT_VER_HIGHEST 18
|
||||||
// Lowest supported serialization version
|
// Lowest supported serialization version
|
||||||
#define SER_FMT_VER_LOWEST 0
|
#define SER_FMT_VER_LOWEST 0
|
||||||
|
|
||||||
|
1192
src/server.cpp
1192
src/server.cpp
File diff suppressed because it is too large
Load Diff
50
src/server.h
50
src/server.h
@ -17,10 +17,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
(c) 2010 Perttu Ahola <celeron55@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERVER_HEADER
|
#ifndef SERVER_HEADER
|
||||||
#define SERVER_HEADER
|
#define SERVER_HEADER
|
||||||
|
|
||||||
@ -32,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some random functions
|
Some random functions
|
||||||
@ -423,7 +420,29 @@ public:
|
|||||||
|
|
||||||
// Envlock and conlock should be locked when calling this
|
// Envlock and conlock should be locked when calling this
|
||||||
void SendMovePlayer(Player *player);
|
void SendMovePlayer(Player *player);
|
||||||
|
|
||||||
|
u64 getPlayerAuthPrivs(const std::string &name)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
return m_authmanager.getPrivs(name);
|
||||||
|
}
|
||||||
|
catch(AuthNotFoundException &e)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Auth not found for "<<name<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPlayerAuthPrivs(const std::string &name, u64 privs)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
return m_authmanager.setPrivs(name, privs);
|
||||||
|
}
|
||||||
|
catch(AuthNotFoundException &e)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Auth not found for "<<name<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -438,7 +457,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
|
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
|
||||||
static void SendAccessDenied(con::Connection &con, u16 peer_id);
|
static void SendAccessDenied(con::Connection &con, u16 peer_id,
|
||||||
|
const std::wstring &reason);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Non-static send methods
|
Non-static send methods
|
||||||
@ -456,15 +476,17 @@ private:
|
|||||||
Additionally, if far_players!=NULL, players further away than
|
Additionally, if far_players!=NULL, players further away than
|
||||||
far_d_nodes are ignored and their peer_ids are added to far_players
|
far_d_nodes are ignored and their peer_ids are added to far_players
|
||||||
*/
|
*/
|
||||||
|
// Envlock and conlock should be locked when calling these
|
||||||
void sendRemoveNode(v3s16 p, u16 ignore_id=0,
|
void sendRemoveNode(v3s16 p, u16 ignore_id=0,
|
||||||
core::list<u16> *far_players=NULL, float far_d_nodes=100);
|
core::list<u16> *far_players=NULL, float far_d_nodes=100);
|
||||||
void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
|
void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
|
||||||
core::list<u16> *far_players=NULL, float far_d_nodes=100);
|
core::list<u16> *far_players=NULL, float far_d_nodes=100);
|
||||||
|
void setBlockNotSent(v3s16 p);
|
||||||
|
|
||||||
// Environment and Connection must be locked when called
|
// Environment and Connection must be locked when called
|
||||||
void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
|
void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
|
||||||
|
|
||||||
// Sends blocks to clients
|
// Sends blocks to clients (locks env and con on its own)
|
||||||
void SendBlocks(float dtime);
|
void SendBlocks(float dtime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -476,6 +498,15 @@ private:
|
|||||||
// When called, connection mutex should be locked
|
// When called, connection mutex should be locked
|
||||||
RemoteClient* getClient(u16 peer_id);
|
RemoteClient* getClient(u16 peer_id);
|
||||||
|
|
||||||
|
// When called, environment mutex should be locked
|
||||||
|
std::string getPlayerName(u16 peer_id)
|
||||||
|
{
|
||||||
|
Player *player = m_env.getPlayer(peer_id);
|
||||||
|
if(player == NULL)
|
||||||
|
return "[id="+itos(peer_id);
|
||||||
|
return player->getName();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a player from memory or creates one.
|
Get a player from memory or creates one.
|
||||||
If player is already connected, return NULL
|
If player is already connected, return NULL
|
||||||
@ -491,6 +522,8 @@ private:
|
|||||||
void handlePeerChange(PeerChange &c);
|
void handlePeerChange(PeerChange &c);
|
||||||
void handlePeerChanges();
|
void handlePeerChanges();
|
||||||
|
|
||||||
|
u64 getPlayerPrivs(Player *player);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Variables
|
Variables
|
||||||
*/
|
*/
|
||||||
@ -514,6 +547,9 @@ private:
|
|||||||
JMutex m_con_mutex;
|
JMutex m_con_mutex;
|
||||||
// Connected clients (behind the con mutex)
|
// Connected clients (behind the con mutex)
|
||||||
core::map<u16, RemoteClient*> m_clients;
|
core::map<u16, RemoteClient*> m_clients;
|
||||||
|
|
||||||
|
// User authentication
|
||||||
|
AuthManager m_authmanager;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Threads
|
Threads
|
||||||
@ -598,6 +634,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
u16 m_ignore_map_edit_events_peer_id;
|
u16 m_ignore_map_edit_events_peer_id;
|
||||||
|
|
||||||
|
Profiler *m_profiler;
|
||||||
|
|
||||||
friend class EmergeThread;
|
friend class EmergeThread;
|
||||||
friend class RemoteClient;
|
friend class RemoteClient;
|
||||||
};
|
};
|
||||||
|
@ -1,24 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Part of Minetest-c55
|
||||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
it under the terms of the GNU General Public License as published by
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
copyright notice and this permission notice appear in all copies.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
GNU General Public License for more details.
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
You should have received a copy of the GNU General Public License along
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "servercommand.h"
|
#include "servercommand.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
@ -35,7 +32,8 @@ void cmd_privs(std::wostringstream &os,
|
|||||||
{
|
{
|
||||||
// Show our own real privs, without any adjustments
|
// Show our own real privs, without any adjustments
|
||||||
// made for admin status
|
// made for admin status
|
||||||
os<<L"-!- " + privsToString(ctx->player->privs);
|
os<<L"-!- " + narrow_to_wide(privsToString(
|
||||||
|
ctx->server->getPlayerAuthPrivs(ctx->player->getName())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +50,7 @@ void cmd_privs(std::wostringstream &os,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
os<<L"-!- " + privsToString(tp->privs);
|
os<<L"-!- " + narrow_to_wide(privsToString(ctx->server->getPlayerAuthPrivs(tp->getName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_grantrevoke(std::wostringstream &os,
|
void cmd_grantrevoke(std::wostringstream &os,
|
||||||
@ -70,7 +68,7 @@ void cmd_grantrevoke(std::wostringstream &os,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 newprivs = stringToPrivs(ctx->parms[2]);
|
u64 newprivs = stringToPrivs(wide_to_narrow(ctx->parms[2]));
|
||||||
if(newprivs == PRIV_INVALID)
|
if(newprivs == PRIV_INVALID)
|
||||||
{
|
{
|
||||||
os<<L"-!- Invalid privileges specified";
|
os<<L"-!- Invalid privileges specified";
|
||||||
@ -83,14 +81,19 @@ void cmd_grantrevoke(std::wostringstream &os,
|
|||||||
os<<L"-!- No such player";
|
os<<L"-!- No such player";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string playername = wide_to_narrow(ctx->parms[1]);
|
||||||
|
u64 privs = ctx->server->getPlayerAuthPrivs(playername);
|
||||||
|
|
||||||
if(ctx->parms[0] == L"grant")
|
if(ctx->parms[0] == L"grant")
|
||||||
tp->privs |= newprivs;
|
privs |= newprivs;
|
||||||
else
|
else
|
||||||
tp->privs &= ~newprivs;
|
privs &= ~newprivs;
|
||||||
|
|
||||||
|
ctx->server->setPlayerAuthPrivs(playername, privs);
|
||||||
|
|
||||||
os<<L"-!- Privileges change to ";
|
os<<L"-!- Privileges change to ";
|
||||||
os<<privsToString(tp->privs);
|
os<<narrow_to_wide(privsToString(privs));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_time(std::wostringstream &os,
|
void cmd_time(std::wostringstream &os,
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Part of Minetest-c55
|
||||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
it under the terms of the GNU General Public License as published by
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
copyright notice and this permission notice appear in all copies.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
GNU General Public License for more details.
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
You should have received a copy of the GNU General Public License along
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SERVERCOMMAND_HEADER
|
#ifndef SERVERCOMMAND_HEADER
|
||||||
|
@ -69,6 +69,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "materials.h"
|
#include "materials.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "mineral.h"
|
#include "mineral.h"
|
||||||
|
#include "filesys.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Settings.
|
Settings.
|
||||||
@ -79,6 +80,9 @@ Settings g_settings;
|
|||||||
|
|
||||||
extern void set_default_settings();
|
extern void set_default_settings();
|
||||||
|
|
||||||
|
// Global profiler
|
||||||
|
Profiler g_profiler;
|
||||||
|
|
||||||
// A dummy thing
|
// A dummy thing
|
||||||
ITextureSource *g_texturesource = NULL;
|
ITextureSource *g_texturesource = NULL;
|
||||||
|
|
||||||
@ -112,6 +116,15 @@ u32 getTimeMs()
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Initialization
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set locale. This is for forcing '.' as the decimal point.
|
||||||
|
std::locale::global(std::locale("C"));
|
||||||
|
// This enables printing all characters in bitmap font
|
||||||
|
setlocale(LC_CTYPE, "en_US");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Low-level initialization
|
Low-level initialization
|
||||||
*/
|
*/
|
||||||
@ -121,20 +134,31 @@ int main(int argc, char *argv[])
|
|||||||
disable_stderr = true;
|
disable_stderr = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
porting::signal_handler_init();
|
||||||
|
bool &kill = *porting::signal_handler_killstatus();
|
||||||
|
|
||||||
|
// Initialize porting::path_data and porting::path_userdata
|
||||||
|
porting::initializePaths();
|
||||||
|
|
||||||
|
// Create user data directory
|
||||||
|
fs::CreateDir(porting::path_userdata);
|
||||||
|
|
||||||
// Initialize debug streams
|
// Initialize debug streams
|
||||||
debugstreams_init(disable_stderr, DEBUGFILE);
|
#ifdef RUN_IN_PLACE
|
||||||
|
std::string debugfile = DEBUGFILE;
|
||||||
|
#else
|
||||||
|
std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;
|
||||||
|
#endif
|
||||||
|
debugstreams_init(disable_stderr, debugfile.c_str());
|
||||||
// Initialize debug stacks
|
// Initialize debug stacks
|
||||||
debug_stacks_init();
|
debug_stacks_init();
|
||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
porting::signal_handler_init();
|
// Init material properties table
|
||||||
bool &kill = *porting::signal_handler_killstatus();
|
//initializeMaterialProperties();
|
||||||
|
|
||||||
porting::initializePaths();
|
|
||||||
|
|
||||||
initializeMaterialProperties();
|
|
||||||
|
|
||||||
|
// Debug handler
|
||||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||||
|
|
||||||
// Print startup message
|
// Print startup message
|
||||||
@ -199,19 +223,10 @@ int main(int argc, char *argv[])
|
|||||||
// Initialize default settings
|
// Initialize default settings
|
||||||
set_default_settings();
|
set_default_settings();
|
||||||
|
|
||||||
// Set locale. This is for forcing '.' as the decimal point.
|
|
||||||
std::locale::global(std::locale("C"));
|
|
||||||
// This enables printing all characters in bitmap font
|
|
||||||
setlocale(LC_CTYPE, "en_US");
|
|
||||||
|
|
||||||
// Initialize sockets
|
// Initialize sockets
|
||||||
sockets_init();
|
sockets_init();
|
||||||
atexit(sockets_cleanup);
|
atexit(sockets_cleanup);
|
||||||
|
|
||||||
/*
|
|
||||||
Initialization
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read config file
|
Read config file
|
||||||
*/
|
*/
|
||||||
@ -301,7 +316,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out path to map
|
// Figure out path to map
|
||||||
std::string map_dir = porting::path_userdata+"/map";
|
std::string map_dir = porting::path_userdata+"/world";
|
||||||
if(cmd_args.exists("map-dir"))
|
if(cmd_args.exists("map-dir"))
|
||||||
map_dir = cmd_args.get("map-dir");
|
map_dir = cmd_args.get("map-dir");
|
||||||
else if(g_settings.exists("map-dir"))
|
else if(g_settings.exists("map-dir"))
|
||||||
|
16
src/sqlite/CMakeLists.txt
Normal file
16
src/sqlite/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
if( UNIX )
|
||||||
|
set(sqlite3_SRCS sqlite3.c)
|
||||||
|
set(sqlite3_platform_LIBS "")
|
||||||
|
else( UNIX )
|
||||||
|
set(sqlite3_SRCS sqlite3.c)
|
||||||
|
set(sqlite3_platform_LIBS "")
|
||||||
|
endif( UNIX )
|
||||||
|
|
||||||
|
add_library(sqlite3 ${sqlite3_SRCS})
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
sqlite3
|
||||||
|
${sqlite3_platform_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
125968
src/sqlite/sqlite3.c
Normal file
125968
src/sqlite/sqlite3.c
Normal file
File diff suppressed because it is too large
Load Diff
6464
src/sqlite/sqlite3.h
Normal file
6464
src/sqlite/sqlite3.h
Normal file
File diff suppressed because it is too large
Load Diff
16
src/test.cpp
16
src/test.cpp
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Asserts that the exception occurs
|
Asserts that the exception occurs
|
||||||
@ -424,16 +425,27 @@ struct TestMapBlock
|
|||||||
assert(b.getChangedFlag() == false);
|
assert(b.getChangedFlag() == false);
|
||||||
|
|
||||||
// All nodes should have been set to
|
// All nodes should have been set to
|
||||||
// .d=CONTENT_AIR and .getLight() = 0
|
// .d=CONTENT_IGNORE and .getLight() = 0
|
||||||
for(u16 z=0; z<MAP_BLOCKSIZE; z++)
|
for(u16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||||
for(u16 y=0; y<MAP_BLOCKSIZE; y++)
|
for(u16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||||
for(u16 x=0; x<MAP_BLOCKSIZE; x++)
|
for(u16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||||
{
|
{
|
||||||
assert(b.getNode(v3s16(x,y,z)).d == CONTENT_AIR);
|
//assert(b.getNode(v3s16(x,y,z)).d == CONTENT_AIR);
|
||||||
|
assert(b.getNode(v3s16(x,y,z)).d == CONTENT_IGNORE);
|
||||||
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0);
|
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0);
|
||||||
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0);
|
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MapNode n(CONTENT_AIR);
|
||||||
|
for(u16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||||
|
for(u16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||||
|
for(u16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||||
|
{
|
||||||
|
b.setNode(v3s16(x,y,z), n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parent fetch functions
|
Parent fetch functions
|
||||||
*/
|
*/
|
||||||
|
11
src/tile.cpp
11
src/tile.cpp
@ -506,22 +506,17 @@ void TextureSource::buildMainAtlas()
|
|||||||
sourcelist.push_back("stone.png");
|
sourcelist.push_back("stone.png");
|
||||||
sourcelist.push_back("mud.png");
|
sourcelist.push_back("mud.png");
|
||||||
sourcelist.push_back("sand.png");
|
sourcelist.push_back("sand.png");
|
||||||
sourcelist.push_back("sandstone.png");
|
|
||||||
sourcelist.push_back("clay.png");
|
|
||||||
sourcelist.push_back("brick.png");
|
|
||||||
sourcelist.push_back("grass.png");
|
sourcelist.push_back("grass.png");
|
||||||
sourcelist.push_back("grass_footsteps.png");
|
sourcelist.push_back("grass_footsteps.png");
|
||||||
sourcelist.push_back("tree.png");
|
sourcelist.push_back("tree.png");
|
||||||
sourcelist.push_back("tree_top.png");
|
sourcelist.push_back("tree_top.png");
|
||||||
sourcelist.push_back("water.png");
|
sourcelist.push_back("water.png");
|
||||||
sourcelist.push_back("leaves.png");
|
sourcelist.push_back("leaves.png");
|
||||||
sourcelist.push_back("cactus_side.png");
|
|
||||||
sourcelist.push_back("cactus_top.png");
|
|
||||||
sourcelist.push_back("papyrus.png");
|
|
||||||
sourcelist.push_back("bookshelf.png");
|
|
||||||
sourcelist.push_back("glass.png");
|
sourcelist.push_back("glass.png");
|
||||||
sourcelist.push_back("mud.png^grass_side.png");
|
sourcelist.push_back("mud.png^grass_side.png");
|
||||||
sourcelist.push_back("cobble.png");
|
sourcelist.push_back("cobble.png");
|
||||||
|
sourcelist.push_back("mossycobble.png");
|
||||||
|
sourcelist.push_back("gravel.png");
|
||||||
|
|
||||||
sourcelist.push_back("stone.png^mineral_coal.png");
|
sourcelist.push_back("stone.png^mineral_coal.png");
|
||||||
sourcelist.push_back("stone.png^mineral_iron.png");
|
sourcelist.push_back("stone.png^mineral_iron.png");
|
||||||
@ -1092,7 +1087,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||||||
imagename_right, device);
|
imagename_right, device);
|
||||||
assert(img_top && img_left && img_right);
|
assert(img_top && img_left && img_right);
|
||||||
|
|
||||||
// FIXME: Create textures from left and right images
|
// TODO: Create textures from images
|
||||||
video::ITexture *texture_top = driver->addTexture(
|
video::ITexture *texture_top = driver->addTexture(
|
||||||
(imagename_top + "__temp__").c_str(), img_top);
|
(imagename_top + "__temp__").c_str(), img_top);
|
||||||
assert(texture_top);
|
assert(texture_top);
|
||||||
|
@ -229,10 +229,10 @@ std::string translatePassword(std::string playername, std::wstring password)
|
|||||||
if(password.length() == 0)
|
if(password.length() == 0)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
std::string slt=playername + wide_to_narrow(password);
|
std::string slt = playername + wide_to_narrow(password);
|
||||||
SHA1 *sha1 = new SHA1();
|
SHA1 sha1;
|
||||||
sha1->addBytes(slt.c_str(), slt.length());
|
sha1.addBytes(slt.c_str(), slt.length());
|
||||||
unsigned char *digest = sha1->getDigest();
|
unsigned char *digest = sha1.getDigest();
|
||||||
std::string pwd = base64_encode(digest, 20);
|
std::string pwd = base64_encode(digest, 20);
|
||||||
free(digest);
|
free(digest);
|
||||||
return pwd;
|
return pwd;
|
||||||
|
@ -244,6 +244,9 @@ inline f32 readF1000(std::istream &is)
|
|||||||
{
|
{
|
||||||
char buf[2];
|
char buf[2];
|
||||||
is.read(buf, 2);
|
is.read(buf, 2);
|
||||||
|
// TODO: verify if this gets rid of the valgrind warning
|
||||||
|
//if(is.gcount() != 2)
|
||||||
|
// return 0;
|
||||||
return readF1000((u8*)buf);
|
return readF1000((u8*)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1738,6 +1741,11 @@ void mysrand(unsigned seed);
|
|||||||
|
|
||||||
inline int myrand_range(int min, int max)
|
inline int myrand_range(int min, int max)
|
||||||
{
|
{
|
||||||
|
if(max-min > MYRAND_MAX)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
if(min > max)
|
if(min > max)
|
||||||
{
|
{
|
||||||
assert(0);
|
assert(0);
|
||||||
@ -1984,17 +1992,23 @@ inline std::string serializeString(const std::string &plain)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*// Reads a string with the length as the first two bytes
|
// Creates a string with the length as the first two bytes from wide string
|
||||||
inline std::string deSerializeString(const std::string encoded)
|
inline std::string serializeWideString(const std::wstring &plain)
|
||||||
{
|
{
|
||||||
u16 s_size = readU16((u8*)&encoded.c_str()[0]);
|
//assert(plain.size() <= 65535);
|
||||||
if(s_size > encoded.length() - 2)
|
if(plain.size() > 65535)
|
||||||
return "";
|
throw SerializationError("String too long for serializeString");
|
||||||
|
char buf[2];
|
||||||
|
writeU16((u8*)buf, plain.size());
|
||||||
std::string s;
|
std::string s;
|
||||||
s.reserve(s_size);
|
s.append(buf, 2);
|
||||||
s.append(&encoded.c_str()[2], s_size);
|
for(u32 i=0; i<plain.size(); i++)
|
||||||
|
{
|
||||||
|
writeU16((u8*)buf, plain[i]);
|
||||||
|
s.append(buf, 2);
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
// Reads a string with the length as the first two bytes
|
// Reads a string with the length as the first two bytes
|
||||||
inline std::string deSerializeString(std::istream &is)
|
inline std::string deSerializeString(std::istream &is)
|
||||||
@ -2014,6 +2028,27 @@ inline std::string deSerializeString(std::istream &is)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reads a wide string with the length as the first two bytes
|
||||||
|
inline std::wstring deSerializeWideString(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[2];
|
||||||
|
is.read(buf, 2);
|
||||||
|
if(is.gcount() != 2)
|
||||||
|
throw SerializationError("deSerializeString: size not read");
|
||||||
|
u16 s_size = readU16((u8*)buf);
|
||||||
|
if(s_size == 0)
|
||||||
|
return L"";
|
||||||
|
std::wstring s;
|
||||||
|
s.reserve(s_size);
|
||||||
|
for(u32 i=0; i<s_size; i++)
|
||||||
|
{
|
||||||
|
is.read(&buf[0], 2);
|
||||||
|
wchar_t c16 = readU16((u8*)buf);
|
||||||
|
s.append(&c16, 1);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a string with the length as the first four bytes
|
// Creates a string with the length as the first four bytes
|
||||||
inline std::string serializeLongString(const std::string &plain)
|
inline std::string serializeLongString(const std::string &plain)
|
||||||
{
|
{
|
||||||
@ -2025,18 +2060,6 @@ inline std::string serializeLongString(const std::string &plain)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*// Reads a string with the length as the first four bytes
|
|
||||||
inline std::string deSerializeLongString(const std::string encoded)
|
|
||||||
{
|
|
||||||
u32 s_size = readU32((u8*)&encoded.c_str()[0]);
|
|
||||||
if(s_size > encoded.length() - 4)
|
|
||||||
return "";
|
|
||||||
std::string s;
|
|
||||||
s.reserve(s_size);
|
|
||||||
s.append(&encoded.c_str()[4], s_size);
|
|
||||||
return s;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Reads a string with the length as the first four bytes
|
// Reads a string with the length as the first four bytes
|
||||||
inline std::string deSerializeLongString(std::istream &is)
|
inline std::string deSerializeLongString(std::istream &is)
|
||||||
{
|
{
|
||||||
|
@ -19,10 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "utility.h" // For TimeTaker
|
||||||
// For TimeTaker
|
|
||||||
#include "utility.h"
|
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Debug stuff
|
Debug stuff
|
||||||
|
@ -384,6 +384,14 @@ public:
|
|||||||
|
|
||||||
return m_data[m_area.index(p)];
|
return m_data[m_area.index(p)];
|
||||||
}
|
}
|
||||||
|
MapNode getNodeNoExNoEmerge(v3s16 p)
|
||||||
|
{
|
||||||
|
if(m_area.contains(p) == false)
|
||||||
|
return MapNode(CONTENT_IGNORE);
|
||||||
|
if(m_flags[m_area.index(p)] & VOXELFLAG_INEXISTENT)
|
||||||
|
return MapNode(CONTENT_IGNORE);
|
||||||
|
return m_data[m_area.index(p)];
|
||||||
|
}
|
||||||
MapNode & getNodeRef(v3s16 p)
|
MapNode & getNodeRef(v3s16 p)
|
||||||
{
|
{
|
||||||
emerge(p);
|
emerge(p);
|
||||||
|
21
util/colors.txt
Normal file
21
util/colors.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
0 128 128 128
|
||||||
|
1 107 134 51
|
||||||
|
2 39 66 106
|
||||||
|
3 255 255 0
|
||||||
|
4 86 58 31
|
||||||
|
5 48 95 8
|
||||||
|
6 102 129 38
|
||||||
|
7 178 178 0
|
||||||
|
8 101 84 36
|
||||||
|
9 39 66 106
|
||||||
|
12 104 78 42
|
||||||
|
13 210 194 156
|
||||||
|
14 117 86 41
|
||||||
|
15 128 79 0
|
||||||
|
16 118 118 118
|
||||||
|
18 123 123 123
|
||||||
|
19 199 199 199
|
||||||
|
20 183 183 222
|
||||||
|
21 103 78 42
|
||||||
|
22 108 138 108
|
||||||
|
23 90 90 90
|
271
util/genmap.py
Executable file
271
util/genmap.py
Executable file
@ -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
|
444
util/minetestmapper.py
Executable file
444
util/minetestmapper.py
Executable file
@ -0,0 +1,444 @@
|
|||||||
|
#!/usr/bin/python2
|
||||||
|
# -*- coding: windows-1252 -*-
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# COPYING for more details.
|
||||||
|
|
||||||
|
# Made by Jogge, modified by celeron55
|
||||||
|
# 2011-05-29: j0gge: initial release
|
||||||
|
# 2011-05-30: celeron55: simultaneous support for sectors/sectors2, removed
|
||||||
|
# 2011-06-02: j0gge: command line parameters, coordinates, players, ...
|
||||||
|
# 2011-06-04: celeron55: added #!/usr/bin/python2 and converted \r\n to \n
|
||||||
|
# to make it easily executable on Linux
|
||||||
|
|
||||||
|
# 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, ImageFont, ImageColor
|
||||||
|
import os
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
import getopt
|
||||||
|
import sys
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print "TODO: Help"
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "hi:o:", ["help", "input=", "output=", "bgcolor=", "scalecolor=", "origincolor=", "playercolor=", "draworigin", "drawplayers", "drawscale"])
|
||||||
|
except getopt.GetoptError, err:
|
||||||
|
# print help information and exit:
|
||||||
|
print str(err) # will print something like "option -a not recognized"
|
||||||
|
usage()
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
path = "../world/"
|
||||||
|
output = "uloste.png"
|
||||||
|
border = 0
|
||||||
|
scalecolor = "black"
|
||||||
|
bgcolor = "white"
|
||||||
|
origincolor = "red"
|
||||||
|
playercolor = "red"
|
||||||
|
drawscale = False
|
||||||
|
drawplayers = False
|
||||||
|
draworigin = False
|
||||||
|
|
||||||
|
sector_xmin = -1500 / 16
|
||||||
|
sector_xmax = 1500 / 16
|
||||||
|
sector_zmin = -1500 / 16
|
||||||
|
sector_zmax = 1500 / 16
|
||||||
|
|
||||||
|
for o, a in opts:
|
||||||
|
if o in ("-h", "--help"):
|
||||||
|
usage()
|
||||||
|
sys.exit()
|
||||||
|
elif o in ("-i", "--input"):
|
||||||
|
path = a
|
||||||
|
elif o in ("-o", "--output"):
|
||||||
|
output = a
|
||||||
|
elif o == "--bgcolor":
|
||||||
|
bgcolor = ImageColor.getrgb(a)
|
||||||
|
elif o == "--scalecolor":
|
||||||
|
scalecolor = ImageColor.getrgb(a)
|
||||||
|
elif o == "--playercolor":
|
||||||
|
playercolor = ImageColor.getrgb(a)
|
||||||
|
elif o == "--origincolor":
|
||||||
|
origincolor = ImageColor.getrgb(a)
|
||||||
|
elif o == "--drawscale":
|
||||||
|
drawscale = True
|
||||||
|
border = 40
|
||||||
|
elif o == "--drawplayers":
|
||||||
|
drawplayers = True
|
||||||
|
elif o == "--draworigin":
|
||||||
|
draworigin = True
|
||||||
|
else:
|
||||||
|
assert False, "unhandled option"
|
||||||
|
|
||||||
|
if path[-1:]!="/" and path[-1:]!="\\":
|
||||||
|
path = path + "/"
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
try:
|
||||||
|
for filename in os.listdir(path + "sectors2"):
|
||||||
|
for filename2 in os.listdir(path + "sectors2/" + filename):
|
||||||
|
x = hex_to_int(filename)
|
||||||
|
z = hex_to_int(filename2)
|
||||||
|
if x < sector_xmin or x > sector_xmax:
|
||||||
|
continue
|
||||||
|
if z < sector_zmin or z > sector_zmax:
|
||||||
|
continue
|
||||||
|
xlist.append(x)
|
||||||
|
zlist.append(z)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
for filename in os.listdir(path + "sectors"):
|
||||||
|
x = hex4_to_int(filename[:4])
|
||||||
|
z = hex4_to_int(filename[-4:])
|
||||||
|
if x < sector_xmin or x > sector_xmax:
|
||||||
|
continue
|
||||||
|
if z < sector_zmin or z > sector_zmax:
|
||||||
|
continue
|
||||||
|
xlist.append(x)
|
||||||
|
zlist.append(z)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
minx = min(xlist)
|
||||||
|
minz = min(zlist)
|
||||||
|
maxx = max(xlist)
|
||||||
|
maxz = max(zlist)
|
||||||
|
|
||||||
|
w = (maxx - minx) * 16 + 16
|
||||||
|
h = (maxz - minz) * 16 + 16
|
||||||
|
|
||||||
|
print "w="+str(w)+" h="+str(h)
|
||||||
|
|
||||||
|
im = Image.new("RGB", (w + border, h + border), bgcolor)
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
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
|
||||||
|
try:
|
||||||
|
n_per_second = 1.0 * n / dtime
|
||||||
|
except ZeroDivisionError:
|
||||||
|
n_per_second = 0
|
||||||
|
if n_per_second != 0:
|
||||||
|
seconds_per_n = 1.0 / n_per_second
|
||||||
|
time_guess = seconds_per_n * len(xlist)
|
||||||
|
remaining_s = time_guess - dtime
|
||||||
|
remaining_minutes = int(remaining_s / 60)
|
||||||
|
remaining_s -= remaining_minutes * 60;
|
||||||
|
print("Processing sector "+str(n)+" of "+str(len(xlist))
|
||||||
|
+" ("+str(round(100.0*n/len(xlist), 1))+"%)"
|
||||||
|
+" (ETA: "+str(remaining_minutes)+"m "
|
||||||
|
+str(int(remaining_s))+"s)")
|
||||||
|
|
||||||
|
xpos = xlist[n]
|
||||||
|
zpos = zlist[n]
|
||||||
|
|
||||||
|
xhex = int_to_hex3(xpos)
|
||||||
|
zhex = int_to_hex3(zpos)
|
||||||
|
xhex4 = int_to_hex4(xpos)
|
||||||
|
zhex4 = int_to_hex4(zpos)
|
||||||
|
|
||||||
|
sector1 = xhex4.lower() + zhex4.lower()
|
||||||
|
sector2 = xhex.lower() + "/" + zhex.lower()
|
||||||
|
|
||||||
|
ylist = []
|
||||||
|
|
||||||
|
sectortype = ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
for filename in os.listdir(path + "sectors/" + sector1):
|
||||||
|
if(filename != "meta"):
|
||||||
|
pos = int(filename, 16)
|
||||||
|
if(pos > 32767):
|
||||||
|
pos -= 65536
|
||||||
|
ylist.append(pos)
|
||||||
|
sectortype = "old"
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if sectortype != "old":
|
||||||
|
try:
|
||||||
|
for filename in os.listdir(path + "sectors2/" + sector2):
|
||||||
|
if(filename != "meta"):
|
||||||
|
pos = int(filename, 16)
|
||||||
|
if(pos > 32767):
|
||||||
|
pos -= 65536
|
||||||
|
ylist.append(pos)
|
||||||
|
sectortype = "new"
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if sectortype == "":
|
||||||
|
continue
|
||||||
|
|
||||||
|
ylist.sort()
|
||||||
|
|
||||||
|
# Make a list of pixels of the sector that are to be looked for.
|
||||||
|
pixellist = []
|
||||||
|
water = {}
|
||||||
|
for x in range(16):
|
||||||
|
for z in range(16):
|
||||||
|
pixellist.append((x, z))
|
||||||
|
water[(x, z)] = 0
|
||||||
|
|
||||||
|
# Go through the Y axis from top to bottom.
|
||||||
|
ylist2=[]
|
||||||
|
for ypos in reversed(ylist):
|
||||||
|
|
||||||
|
yhex = int_to_hex4(ypos)
|
||||||
|
|
||||||
|
filename = ""
|
||||||
|
if sectortype == "old":
|
||||||
|
filename = path + "sectors/" + sector1 + "/" + yhex.lower()
|
||||||
|
else:
|
||||||
|
filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
|
||||||
|
|
||||||
|
f = file(filename, "rb")
|
||||||
|
|
||||||
|
version = f.read(1)
|
||||||
|
flags = f.read(1)
|
||||||
|
|
||||||
|
# Checking day and night differs -flag
|
||||||
|
if not ord(flags) & 2:
|
||||||
|
ylist2.append((ypos,filename))
|
||||||
|
f.close()
|
||||||
|
continue
|
||||||
|
|
||||||
|
dec_o = zlib.decompressobj()
|
||||||
|
try:
|
||||||
|
mapdata = dec_o.decompress(f.read())
|
||||||
|
except:
|
||||||
|
mapdata = []
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
if(len(mapdata) < 4096):
|
||||||
|
print "bad: " + xhex + "/" + zhex + "/" + yhex + " " + str(len(mapdata))
|
||||||
|
else:
|
||||||
|
chunkxpos = xpos * 16
|
||||||
|
chunkypos = ypos * 16
|
||||||
|
chunkzpos = zpos * 16
|
||||||
|
for (x, z) in reversed(pixellist):
|
||||||
|
for y in reversed(range(16)):
|
||||||
|
datapos = x + y * 16 + z * 256
|
||||||
|
if(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) in colors):
|
||||||
|
if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9):
|
||||||
|
water[(x, z)] += 1
|
||||||
|
# Add dummy stuff for drawing sea without seabed
|
||||||
|
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
|
||||||
|
else:
|
||||||
|
pixellist.remove((x, z))
|
||||||
|
# Memorize information on the type and height of the block and for drawing the picture.
|
||||||
|
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
|
||||||
|
break
|
||||||
|
elif(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) not in colors):
|
||||||
|
print "strange block: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos]))
|
||||||
|
|
||||||
|
# After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis.
|
||||||
|
if(len(pixellist) == 0):
|
||||||
|
break
|
||||||
|
|
||||||
|
if len(pixellist) > 0:
|
||||||
|
for (ypos, filename) in ylist2:
|
||||||
|
f = file(filename, "rb")
|
||||||
|
|
||||||
|
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 + " " + str(len(mapdata))
|
||||||
|
else:
|
||||||
|
chunkxpos = xpos * 16
|
||||||
|
chunkypos = ypos * 16
|
||||||
|
chunkzpos = zpos * 16
|
||||||
|
for (x, z) in reversed(pixellist):
|
||||||
|
for y in reversed(range(16)):
|
||||||
|
datapos = x + y * 16 + z * 256
|
||||||
|
if(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) in colors):
|
||||||
|
if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9):
|
||||||
|
water[(x, z)] += 1
|
||||||
|
# Add dummy stuff for drawing sea without seabed
|
||||||
|
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
|
||||||
|
else:
|
||||||
|
pixellist.remove((x, z))
|
||||||
|
# Memorize information on the type and height of the block and for drawing the picture.
|
||||||
|
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
|
||||||
|
break
|
||||||
|
elif(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) not in colors):
|
||||||
|
print "outo palikka: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos]))
|
||||||
|
|
||||||
|
# After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis.
|
||||||
|
if(len(pixellist) == 0):
|
||||||
|
break
|
||||||
|
|
||||||
|
print "Drawing image"
|
||||||
|
# Drawing the picture
|
||||||
|
starttime = time.time()
|
||||||
|
n = 0
|
||||||
|
for (x, z) in stuff.iterkeys():
|
||||||
|
if n % 500000 == 0:
|
||||||
|
nowtime = time.time()
|
||||||
|
dtime = nowtime - starttime
|
||||||
|
try:
|
||||||
|
n_per_second = 1.0 * n / dtime
|
||||||
|
except ZeroDivisionError:
|
||||||
|
n_per_second = 0
|
||||||
|
if n_per_second != 0:
|
||||||
|
listlen = len(stuff)
|
||||||
|
seconds_per_n = 1.0 / n_per_second
|
||||||
|
time_guess = seconds_per_n * listlen
|
||||||
|
remaining_s = time_guess - dtime
|
||||||
|
remaining_minutes = int(remaining_s / 60)
|
||||||
|
remaining_s -= remaining_minutes * 60;
|
||||||
|
print("Drawing pixel "+str(n)+" of "+str(listlen)
|
||||||
|
+" ("+str(round(100.0*n/listlen, 1))+"%)"
|
||||||
|
+" (ETA: "+str(remaining_minutes)+"m "
|
||||||
|
+str(int(remaining_s))+"s)")
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
(r, g, b) = colors[stuff[(x,z)][1]]
|
||||||
|
# Comparing heights of a couple of adjacent blocks and changing brightness accordingly.
|
||||||
|
try:
|
||||||
|
c1 = stuff[(x - 1, z)][1]
|
||||||
|
c2 = stuff[(x, z + 1)][1]
|
||||||
|
c = stuff[(x, z)][1]
|
||||||
|
if c1 != 2 and c1 != 9 and c2 != 2 and c2 != 9 and c != 2 and c != 9:
|
||||||
|
y1 = stuff[(x - 1, z)][0]
|
||||||
|
y2 = stuff[(x, z + 1)][0]
|
||||||
|
y = stuff[(x, z)][0]
|
||||||
|
|
||||||
|
d = ((y - y1) + (y - y2)) * 12
|
||||||
|
else:
|
||||||
|
d = 0
|
||||||
|
|
||||||
|
if(d > 36):
|
||||||
|
d = 36
|
||||||
|
|
||||||
|
r = limit(r + d, 0, 255)
|
||||||
|
g = limit(g + d, 0, 255)
|
||||||
|
b = limit(b + d, 0, 255)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Water
|
||||||
|
if(stuff[(x,z)][2] > 0):
|
||||||
|
r=int(r * .15 + colors[2][0] * .85)
|
||||||
|
g=int(g * .15 + colors[2][1] * .85)
|
||||||
|
b=int(b * .15 + colors[2][2] * .85)
|
||||||
|
|
||||||
|
impix[x - minx * 16 + border, h - 1 - (z - minz * 16) + border] = (r, g, b)
|
||||||
|
|
||||||
|
|
||||||
|
if draworigin:
|
||||||
|
draw.ellipse((minx * -16 - 5 + border, h - minz * -16 - 6 + border, minx * -16 + 5 + border, h - minz * -16 + 4 + border), outline = origincolor)
|
||||||
|
|
||||||
|
font = ImageFont.load_default()
|
||||||
|
|
||||||
|
if drawscale:
|
||||||
|
draw.text((24, 0), "X", font = font, fill = scalecolor)
|
||||||
|
draw.text((2, 24), "Z", font = font, fill = scalecolor)
|
||||||
|
|
||||||
|
for n in range(int(minx / -4) * -4, maxx, 4):
|
||||||
|
draw.text((minx * -16 + n * 16 + 2 + border, 0), str(n * 16), font = font, fill = scalecolor)
|
||||||
|
draw.line((minx * -16 + n * 16 + border, 0, minx * -16 + n * 16 + border, border - 1), fill = scalecolor)
|
||||||
|
|
||||||
|
for n in range(int(maxz / 4) * 4, minz, -4):
|
||||||
|
draw.text((2, h - 1 - (n * 16 - minz * 16) + border), str(n * 16), font = font, fill = scalecolor)
|
||||||
|
draw.line((0, h - 1 - (n * 16 - minz * 16) + border, border - 1, h - 1 - (n * 16 - minz * 16) + border), fill = scalecolor)
|
||||||
|
|
||||||
|
if drawplayers:
|
||||||
|
try:
|
||||||
|
for filename in os.listdir(path + "players"):
|
||||||
|
f = file(path + "players/" + filename)
|
||||||
|
lines = f.readlines()
|
||||||
|
name=""
|
||||||
|
position=[]
|
||||||
|
for line in lines:
|
||||||
|
p = string.split(line)
|
||||||
|
if p[0] == "name":
|
||||||
|
name = p[2]
|
||||||
|
print filename + ": name = " + name
|
||||||
|
if p[0] == "position":
|
||||||
|
position = string.split(p[2][1:-1], ",")
|
||||||
|
print filename + ": position = " + p[2]
|
||||||
|
if len(name) > 0 and len(position) == 3:
|
||||||
|
x=(int(float(position[0]) / 10 - minx * 16))
|
||||||
|
z=int(h - (float(position[2]) / 10 - minz * 16))
|
||||||
|
draw.ellipse((x - 2 + border, z - 2 + border, x + 2 + border, z + 2 + border), outline = playercolor)
|
||||||
|
draw.text((x + 2 + border, z + 2 + border), name, font = font, fill = playercolor)
|
||||||
|
f.close()
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print "Saving"
|
||||||
|
im.save(output)
|
102
util/pnoise.py
Normal file
102
util/pnoise.py
Normal file
@ -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)))
|
Loading…
Reference in New Issue
Block a user