Compare commits
9 Commits
stable-0.3
...
0.2.201109
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f446fbf017 | ||
|
|
960009d619 | ||
|
|
5ca877b836 | ||
|
|
b0c2c83861 | ||
|
|
1a63c6e016 | ||
|
|
fd7c8706ce | ||
|
|
aefa3b630b | ||
|
|
d5281eaa2e | ||
|
|
7504a748d0 |
@@ -7,14 +7,11 @@ endif(${CMAKE_VERSION} STREQUAL "2.8.2")
|
||||
# This can be read from ${PROJECT_NAME} after project() is called
|
||||
project(minetest)
|
||||
|
||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 3)
|
||||
set(VERSION_PATCH 3)
|
||||
set(VERSION_MINOR 2)
|
||||
set(VERSION_PATCH 20110922_3)
|
||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
|
||||
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
||||
|
||||
# Configuration options
|
||||
|
||||
if(WIN32)
|
||||
@@ -66,7 +63,7 @@ elseif(UNIX) # Linux, BSD etc
|
||||
set(EXAMPLE_CONF_DIR "share/doc/${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
install(FILES "README.txt" DESTINATION "${DOCDIR}")
|
||||
install(FILES "doc/README.txt" DESTINATION "${DOCDIR}")
|
||||
install(FILES "doc/changelog.txt" DESTINATION "${DOCDIR}")
|
||||
install(FILES "minetest.conf.example" DESTINATION "${DOCDIR}")
|
||||
|
||||
|
||||
49
README.txt
@@ -54,12 +54,12 @@ Compiling on GNU/Linux:
|
||||
-----------------------
|
||||
|
||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev
|
||||
|
||||
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
||||
$ wget https://github.com/celeron55/minetest/tarball/master -O master.tar.gz
|
||||
$ tar xf master.tar.gz
|
||||
$ cd celeron55-minetest-286edd4 (or similar)
|
||||
$ 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
|
||||
@@ -73,7 +73,7 @@ $ ./minetest
|
||||
- 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>
|
||||
- Debug build is slower, but gives much more useful output in a debugger
|
||||
- Note that the Debug build is considerably slower
|
||||
|
||||
Compiling on Windows:
|
||||
---------------------
|
||||
@@ -90,18 +90,16 @@ Compiling on Windows:
|
||||
http://www.winimage.com/zLibDll/index.html
|
||||
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
|
||||
http://www.winimage.com/zLibDll/index.html
|
||||
* Optional: gettext bibrary and tools:
|
||||
* gettext bibrary and tools:
|
||||
http://gnuwin32.sourceforge.net/downlinks/gettext.php
|
||||
- This is used for other UI languages. Feel free to leave it out.
|
||||
* 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.
|
||||
("extract here", not "extract to packagename/")
|
||||
- All those packages contain a nice base directory in them, which
|
||||
should end up being the direct subdirectories of DIR.
|
||||
- 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
|
||||
@@ -121,7 +119,7 @@ Compiling on Windows:
|
||||
+ lib
|
||||
+ include
|
||||
...
|
||||
+ gettext (optional)
|
||||
+ gettext
|
||||
+bin
|
||||
+include
|
||||
+lib
|
||||
@@ -165,8 +163,7 @@ Compiling on Windows:
|
||||
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
|
||||
and might not even work at all)
|
||||
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
|
||||
@@ -179,30 +176,6 @@ Compiling on Windows:
|
||||
- You should now have a working game with the executable in
|
||||
DIR/minetest/bin/minetest.exe
|
||||
|
||||
Windows releases of minetest are built using a bat script like this:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
set installpath="C:\tmp\minetest_install"
|
||||
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
|
||||
|
||||
set sourcedir=%CD%
|
||||
set builddir=%sourcedir%\bvc10
|
||||
mkdir %builddir%
|
||||
pushd %builddir%
|
||||
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=1 -DCMAKE_INSTALL_PREFIX=%installpath%
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
|
||||
popd
|
||||
|
||||
License of Minetest-c55 textures
|
||||
--------------------------------
|
||||
|
||||
This does not apply to texture packs made by others.
|
||||
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
License of Minetest-c55
|
||||
-----------------------
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 224 B |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 603 B |
BIN
data/sapling.png
|
Before Width: | Height: | Size: 502 B |
|
Before Width: | Height: | Size: 927 B After Width: | Height: | Size: 209 B |
|
Before Width: | Height: | Size: 931 B After Width: | Height: | Size: 193 B |
|
Before Width: | Height: | Size: 927 B After Width: | Height: | Size: 190 B |
238
doc/README.txt
Normal file
@@ -0,0 +1,238 @@
|
||||
Minetest-c55
|
||||
---------------
|
||||
An InfiniMiner/Minecraft inspired game.
|
||||
Copyright (c) 2010-2011 Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
Further documentation:
|
||||
----------------------
|
||||
- Website: http://celeron.55.lt/~celeron55/minetest/
|
||||
- Wiki: http://celeron.55.lt/~celeron55/minetest/wiki/
|
||||
- Forum: http://celeron.55.lt/~celeron55/minetest/forum/
|
||||
|
||||
This is a development version:
|
||||
------------------------------
|
||||
- Don't expect it to work as well as a finished game will.
|
||||
- Please report any bugs to me. That way I can fix them to the next release.
|
||||
- debug.txt is useful when the game crashes.
|
||||
|
||||
Controls:
|
||||
---------
|
||||
- See the in-game pause menu
|
||||
- Settable in the configuration file, see the section below.
|
||||
|
||||
Map directory:
|
||||
--------------
|
||||
- Map is stored in a directory, which can be removed to generate a new map.
|
||||
- There is a command-line option for it: --map-dir
|
||||
- For a RUN_IN_PLACE build, it is located in:
|
||||
../map
|
||||
- Otherwise something like this:
|
||||
Windows: C:\Documents and Settings\user\Application Data\minetest\map
|
||||
Linux: ~/.minetest/map
|
||||
OS X: ~/Library/Application Support/minetest/map
|
||||
|
||||
Configuration file:
|
||||
-------------------
|
||||
- An optional configuration file can be used. See minetest.conf.example.
|
||||
- Path to file can be passed as a parameter to the executable:
|
||||
--config <path-to-file>
|
||||
- Defaults:
|
||||
- If built with -DRUN_IN_PLACE=1:
|
||||
../minetest.conf
|
||||
../../minetest.conf
|
||||
- Otherwise something like this:
|
||||
Windows: C:\Documents and Settings\user\Application Data\minetest\minetest.conf
|
||||
Linux: ~/.minetest/minetest.conf
|
||||
OS X: ~/Library/Application Support/minetest.conf
|
||||
|
||||
Command-line options:
|
||||
---------------------
|
||||
- Use --help
|
||||
|
||||
Compiling on GNU/Linux:
|
||||
-----------------------
|
||||
|
||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev
|
||||
|
||||
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
||||
$ wget https://bitbucket.org/celeron55/minetest/get/tip.tar.gz
|
||||
$ tar xf tip.tar.gz
|
||||
$ cd minetest
|
||||
|
||||
Build a version that runs directly from the source directory:
|
||||
$ cmake . -DRUN_IN_PLACE=1
|
||||
$ make -j2
|
||||
|
||||
Run it:
|
||||
$ cd bin
|
||||
$ ./minetest
|
||||
|
||||
- Use cmake . -LH to see all CMake options and their current state
|
||||
- If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0
|
||||
- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
|
||||
- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=<Debug or Release>
|
||||
- Note that the Debug build is considerably slower
|
||||
|
||||
Compiling on Windows:
|
||||
---------------------
|
||||
|
||||
- You need:
|
||||
* CMake:
|
||||
http://www.cmake.org/cmake/resources/software.html
|
||||
* MinGW or Visual Studio
|
||||
http://www.mingw.org/
|
||||
http://msdn.microsoft.com/en-us/vstudio/default
|
||||
* Irrlicht SDK 1.7:
|
||||
http://irrlicht.sourceforge.net/downloads.html
|
||||
* Zlib headers (zlib125.zip)
|
||||
http://www.winimage.com/zLibDll/index.html
|
||||
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
|
||||
http://www.winimage.com/zLibDll/index.html
|
||||
* And, of course, Minetest-c55:
|
||||
http://celeron.55.lt/~celeron55/minetest/download
|
||||
- Steps:
|
||||
- Select a directory called DIR hereafter in which you will operate.
|
||||
- Make sure you have CMake and a compiler installed.
|
||||
- Download all the other stuff to DIR and extract them into there. All those
|
||||
packages contain a nice base directory in them, which should end up being
|
||||
the direct subdirectories of DIR.
|
||||
- You will end up with a directory structure like this (+=dir, -=file):
|
||||
-----------------
|
||||
+ DIR
|
||||
- zlib-1.2.5.tar.gz
|
||||
- zlib125dll.zip
|
||||
- irrlicht-1.7.1.zip
|
||||
- 110214175330.zip (or whatever, this is the minetest source)
|
||||
+ zlib-1.2.5
|
||||
- zlib.h
|
||||
+ win32
|
||||
...
|
||||
+ zlib125dll
|
||||
- readme.txt
|
||||
+ dll32
|
||||
...
|
||||
+ irrlicht-1.7.1
|
||||
+ lib
|
||||
+ include
|
||||
...
|
||||
+ minetest
|
||||
+ src
|
||||
+ doc
|
||||
- CMakeLists.txt
|
||||
...
|
||||
-----------------
|
||||
- Start up the CMake GUI
|
||||
- Select "Browse Source..." and select DIR/minetest
|
||||
- Now, if using MSVC:
|
||||
- Select "Browse Build..." and select DIR/minetest-build
|
||||
- Else if using MinGW:
|
||||
- Select "Browse Build..." and select DIR/minetest
|
||||
- Select "Configure"
|
||||
- Select your compiler
|
||||
- It will warn about missing stuff, ignore that at this point. (later don't)
|
||||
- Make sure the configuration is as follows
|
||||
(note that the versions may differ for you):
|
||||
-----------------
|
||||
BUILD_CLIENT [X]
|
||||
BUILD_SERVER [ ]
|
||||
CMAKE_BUILD_TYPE Release
|
||||
CMAKE_INSTALL_PREFIX DIR/minetest-install
|
||||
IRRLICHT_SOURCE_DIR DIR/irrlicht-1.7.1
|
||||
RUN_IN_PLACE [X]
|
||||
WARN_ALL [ ]
|
||||
ZLIB_DLL DIR/zlib125dll/dll32/zlibwapi.dll
|
||||
ZLIB_INCLUDE_DIR DIR/zlib-1.2.5
|
||||
ZLIB_LIBRARIES DIR/zlib125dll/dll32/zlibwapi.lib
|
||||
-----------------
|
||||
- Hit "Configure"
|
||||
- Hit "Generate"
|
||||
If using MSVC:
|
||||
- Open the generated minetest.sln
|
||||
- The project defaults to the "Debug" configuration. Make very sure to
|
||||
select "Release", unless you want to debug some stuff (it's slower)
|
||||
- Build the ALL_BUILD project
|
||||
- Build the INSTALL project
|
||||
- You should now have a working game with the executable in
|
||||
DIR/minetest-install/bin/minetest.exe
|
||||
- Additionally you may create a zip package by building the PACKAGE
|
||||
project.
|
||||
If using MinGW:
|
||||
- Using the command line, browse to the build directory and run 'make'
|
||||
(or mingw32-make or whatever it happens to be)
|
||||
- You should now have a working game with the executable in
|
||||
DIR/minetest/bin/minetest.exe
|
||||
|
||||
License of Minetest-c55
|
||||
-----------------------
|
||||
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Irrlicht
|
||||
---------------
|
||||
|
||||
This program uses the Irrlicht Engine. http://irrlicht.sourceforge.net/
|
||||
|
||||
The Irrlicht Engine License
|
||||
|
||||
Copyright © 2002-2005 Nikolaus Gebhardt
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute
|
||||
it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
|
||||
JThread
|
||||
---------------
|
||||
|
||||
This program uses the JThread library. License for JThread follows:
|
||||
|
||||
Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
|
||||
@@ -3,42 +3,9 @@ Minetest-c55 changelog
|
||||
This should contain all the major changes.
|
||||
For minor stuff, refer to the commit log of the repository.
|
||||
|
||||
0.3.3: (tagged on 2013-03-05)
|
||||
- Fix a password-related vulnerability (late backport from some early 0.4)
|
||||
|
||||
0.3.2: (tagged on 2012-05-12)
|
||||
- Include unistd.h in filesys.cpp
|
||||
- Add wooden planks to creative inventory
|
||||
|
||||
0.3.1: (released on 2011-11-09)
|
||||
- Fix frustum culling (previous versions have rendered too much stuff that is not actually visible (about 180 degrees, while should have been more like 100.))
|
||||
- Add occlusion culling (improves performance a lot)
|
||||
- Add “3d clouds” on/off checkbox in main menu
|
||||
- Add “opaque water” on/off checkbox
|
||||
- Fix some random minor stuff
|
||||
- Turn mipmapping off (This makes far-away textures a bit noisier but better looking)
|
||||
- Add Command-line signal handler for Windows (contributed by SpeedProg)
|
||||
- Fix network layer segmentation fault introduced in 0.3.dev-20111021
|
||||
- Fix water-glass and water-lava and lava-glass surfaces
|
||||
|
||||
0.3.0: (released on 2011-11-01)
|
||||
- Some small fixes
|
||||
0.3.dev-20111021:
|
||||
- Modify dungeon masters to only try to shoot players
|
||||
- Fix object duplication bug at block load/unload bug
|
||||
- Improve network layer
|
||||
0.3.dev-20111016:
|
||||
- Locked chest (contributed)
|
||||
- Server user limit setting (max_users)
|
||||
- Wielded tool is shown in HUD (contributed)
|
||||
- View bobbing (contributed)
|
||||
- Saplings that drop from leaf blocks and when placed on ground will grow to trees (contributed)
|
||||
- Optimized map saving (does not re-save everything all the time)
|
||||
- New mob system and new mob: dungeon master
|
||||
- Death/respawn screen
|
||||
|
||||
0.2.20110922_3:
|
||||
- Fix the build for MSVC2010; also released for windows using MSVC2010.
|
||||
0.2.20110922_2:
|
||||
- Move PLATFORM_LIBS around to make sqlite3 link with libdl on some distros
|
||||
- sectors2sqlite.py and minetestmapper.py fixes
|
||||
|
||||
0.2.20110922_1:
|
||||
- Make client report a newer version number to the server than 2011-07-31 does and make server disallow old clients
|
||||
|
||||
@@ -85,10 +85,5 @@ Furnace metadata:
|
||||
Chest metadata:
|
||||
TBD
|
||||
|
||||
Locking Chest metadata:
|
||||
u16 string_len
|
||||
u8[string_len] string
|
||||
TBD
|
||||
|
||||
// END
|
||||
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
#keymap_jump = KEY_SPACE
|
||||
#keymap_sneak = KEY_LSHIFT
|
||||
#keymap_inventory = KEY_KEY_I
|
||||
# Go down ladder / go down in fly mode / go fast in fast mode
|
||||
#keymap_special1 = KEY_KEY_E
|
||||
#keymap_chat = KEY_KEY_T
|
||||
#keymap_rangeselect = KEY_KEY_R
|
||||
#keymap_freemove = KEY_KEY_K
|
||||
@@ -48,6 +46,7 @@
|
||||
#keymap_frametime_graph = KEY_F1
|
||||
#keymap_screenshot = KEY_F12
|
||||
# Some (temporary) keys for debugging
|
||||
#keymap_special1 = KEY_KEY_E
|
||||
#keymap_print_debug_stacks = KEY_KEY_P
|
||||
|
||||
# The desired FPS
|
||||
@@ -59,8 +58,8 @@
|
||||
#viewing_range_nodes_max = 300
|
||||
#viewing_range_nodes_min = 25
|
||||
# Initial window size
|
||||
#screenW = 800
|
||||
#screenH = 600
|
||||
screenW# = 800
|
||||
screenH# = 600
|
||||
# Address to connect to (#blank = start local server)
|
||||
#address =
|
||||
# Enable random user input, for testing
|
||||
@@ -104,54 +103,41 @@
|
||||
#invisible_stone = false
|
||||
# Path for screenshots
|
||||
#screenshot_path = .
|
||||
# Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double)
|
||||
#view_bobbing_amount = 1.0
|
||||
|
||||
#
|
||||
# Server stuff
|
||||
#
|
||||
|
||||
# Map directory (everything in the world is stored here)
|
||||
#map-dir = /custom/map
|
||||
#map-#dir = /custom/map
|
||||
# Message of the Day
|
||||
#motd = Welcome to this awesome Minetest server!
|
||||
# Maximum number of players connected simultaneously
|
||||
#max_users = 20
|
||||
# Set to false to allow old clients to connect
|
||||
#strict_protocol_version_checking = true
|
||||
# Set to true to enable creative mode (unlimited inventory)
|
||||
#creative_mode = false
|
||||
# Enable players getting damage and dying
|
||||
#enable_damage = false
|
||||
# Despawn all non-peaceful mobs
|
||||
#only_peaceful_mobs = false
|
||||
# A chosen map seed for a new map, leave empty for random
|
||||
#fixed_map_seed =
|
||||
# Gives some stuff to players at the beginning
|
||||
#give_initial_stuff = false
|
||||
# New users need to input this password
|
||||
#default_password =
|
||||
# Available privileges: build, teleport, settime, privs, shout
|
||||
#default_privs = build, shout
|
||||
|
||||
# Set to true to enable experimental features or stuff that is tested
|
||||
# (varies from version to version, usually not useful at all)
|
||||
#enable_experimental = false
|
||||
# Profiler data print interval. #0 = disable.
|
||||
#profiler_print_interval = 0
|
||||
#enable_mapgen_debug_info = false
|
||||
# Player and object positions are sent at intervals specified by this
|
||||
#objectdata_interval = 0.2
|
||||
#active_object_send_range_blocks = 3
|
||||
#active_block_range = 2
|
||||
#active_object_range = 2
|
||||
#max_simultaneous_block_sends_per_client = 2
|
||||
#max_simultaneous_block_sends_server_total = 8
|
||||
#max_block_send_distance = 7
|
||||
#max_block_generate_distance = 5
|
||||
#max_block_send_distance = 8
|
||||
#max_block_generate_distance = 8
|
||||
#time_send_interval = 20
|
||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
||||
#time_speed = 72
|
||||
#server_unload_unused_data_timeout = 60
|
||||
#server_map_save_interval = 60
|
||||
#full_block_send_enable_min_time_from_building = 2.0
|
||||
# Set to true to enable experimental features or stuff that is tested
|
||||
# (varies from version to version, usually not useful at all)
|
||||
#enable_experimental = false
|
||||
|
||||
|
||||
@@ -90,12 +90,12 @@ configure_file(
|
||||
)
|
||||
|
||||
set(common_SRCS
|
||||
log.cpp
|
||||
content_sao.cpp
|
||||
mapgen.cpp
|
||||
content_inventory.cpp
|
||||
content_nodemeta.cpp
|
||||
content_craft.cpp
|
||||
content_mapblock.cpp
|
||||
content_mapnode.cpp
|
||||
auth.cpp
|
||||
collision.cpp
|
||||
@@ -108,6 +108,7 @@ set(common_SRCS
|
||||
defaultsettings.cpp
|
||||
mapnode.cpp
|
||||
voxel.cpp
|
||||
mapblockobject.cpp
|
||||
inventory.cpp
|
||||
debug.cpp
|
||||
serialization.cpp
|
||||
@@ -130,28 +131,17 @@ set(common_SRCS
|
||||
)
|
||||
|
||||
# This gives us the icon
|
||||
if(WIN32)
|
||||
if(MINGW)
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
||||
COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-i${CMAKE_CURRENT_SOURCE_DIR}/winresource.rc
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
|
||||
SET(common_SRCS ${common_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
|
||||
else(MINGW) # Probably MSVC
|
||||
set(common_SRCS ${common_SRCS} winresource.rc)
|
||||
endif(MINGW)
|
||||
if(WIN32 AND MSVC)
|
||||
set(common_SRCS ${common_SRCS} winresource.rc)
|
||||
endif()
|
||||
|
||||
# Client sources
|
||||
set(minetest_SRCS
|
||||
${common_SRCS}
|
||||
MyBillboardSceneNode.cpp
|
||||
content_mapblock.cpp
|
||||
content_cao.cpp
|
||||
mapblock_mesh.cpp
|
||||
farmesh.cpp
|
||||
keycode.cpp
|
||||
camera.cpp
|
||||
clouds.cpp
|
||||
clientobject.cpp
|
||||
guiMainMenu.cpp
|
||||
@@ -161,7 +151,6 @@ set(minetest_SRCS
|
||||
guiInventoryMenu.cpp
|
||||
guiPauseMenu.cpp
|
||||
guiPasswordChange.cpp
|
||||
guiDeathScreen.cpp
|
||||
client.cpp
|
||||
tile.cpp
|
||||
game.cpp
|
||||
@@ -238,7 +227,7 @@ if(MSVC)
|
||||
# Flags for C files (sqlite)
|
||||
# /MT = Link statically with standard library stuff
|
||||
set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /MT")
|
||||
|
||||
|
||||
if(BUILD_SERVER)
|
||||
set_target_properties(${PROJECT_NAME}server PROPERTIES
|
||||
COMPILE_DEFINITIONS "SERVER")
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
// Copyright (C) 2002-2010 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "MyBillboardSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
MyBillboardSceneNode::MyBillboardSceneNode(ISceneNode* parent,
|
||||
ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size)
|
||||
: IBillboardSceneNode(parent, mgr, id, position)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("MyBillboardSceneNode");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
|
||||
indices[0] = 0;
|
||||
indices[1] = 2;
|
||||
indices[2] = 1;
|
||||
indices[3] = 0;
|
||||
indices[4] = 3;
|
||||
indices[5] = 2;
|
||||
|
||||
video::SColor colorTop = video::SColor(0xFFFFFFFF);
|
||||
video::SColor colorBottom = video::SColor(0xFFFFFFFF);
|
||||
|
||||
vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
vertices[0].Color = colorBottom;
|
||||
|
||||
vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
vertices[1].Color = colorTop;
|
||||
|
||||
vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
vertices[2].Color = colorTop;
|
||||
|
||||
vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void MyBillboardSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void MyBillboardSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||
|
||||
if (!camera || !driver)
|
||||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
core::vector3df target = camera->getTarget();
|
||||
core::vector3df up = camera->getUpVector();
|
||||
core::vector3df view = target - campos;
|
||||
view.normalize();
|
||||
|
||||
core::vector3df horizontal = up.crossProduct(view);
|
||||
if ( horizontal.getLength() == 0 )
|
||||
{
|
||||
horizontal.set(up.Y,up.X,up.Z);
|
||||
}
|
||||
horizontal.normalize();
|
||||
horizontal *= 0.5f * Size.Width;
|
||||
|
||||
core::vector3df vertical = horizontal.crossProduct(view);
|
||||
vertical.normalize();
|
||||
vertical *= 0.5f * Size.Height;
|
||||
|
||||
view *= -1.0f;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
vertices[0].Pos = pos + horizontal + vertical;
|
||||
vertices[1].Pos = pos + horizontal - vertical;
|
||||
vertices[2].Pos = pos - horizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
// draw
|
||||
|
||||
if ( DebugDataVisible & scene::EDS_BBOX )
|
||||
{
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->draw3DBox(BBox, video::SColor(0,208,195,152));
|
||||
}
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
|
||||
driver->setMaterial(Material);
|
||||
|
||||
driver->drawIndexedTriangleList(vertices, 4, indices, 2);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& MyBillboardSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BBox;
|
||||
}
|
||||
|
||||
|
||||
//! sets the size of the billboard
|
||||
void MyBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
||||
if (Size.Width == 0.0f)
|
||||
Size.Width = 1.0f;
|
||||
|
||||
if (Size.Height == 0.0f )
|
||||
Size.Height = 1.0f;
|
||||
|
||||
f32 avg = (size.Width + size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
video::SMaterial& MyBillboardSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Material;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 MyBillboardSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! gets the size of the billboard
|
||||
const core::dimension2d<f32>& MyBillboardSceneNode::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
void MyBillboardSceneNode::setColor(const video::SColor & overallColor)
|
||||
{
|
||||
for(u32 vertex = 0; vertex < 4; ++vertex)
|
||||
vertices[vertex].Color = overallColor;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
void MyBillboardSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor)
|
||||
{
|
||||
vertices[0].Color = bottomColor;
|
||||
vertices[1].Color = topColor;
|
||||
vertices[2].Color = topColor;
|
||||
vertices[3].Color = bottomColor;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
void MyBillboardSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const
|
||||
{
|
||||
bottomColor = vertices[0].Color;
|
||||
topColor = vertices[1].Color;
|
||||
}
|
||||
|
||||
void MyBillboardSceneNode::setTCoords(u32 i, core::vector2d<f32> c)
|
||||
{
|
||||
vertices[i].TCoords = c;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright (C) 2002-2010 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "S3DVertex.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||
//! which always looks to the camera.
|
||||
class MyBillboardSceneNode : virtual public IBillboardSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
MyBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size);
|
||||
|
||||
//! pre render event
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! render
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! sets the size of the billboard
|
||||
virtual void setSize(const core::dimension2d<f32>& size);
|
||||
|
||||
//! gets the size of the billboard
|
||||
virtual const core::dimension2d<f32>& getSize() const;
|
||||
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
virtual void setColor(const video::SColor & overallColor);
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor);
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const;
|
||||
|
||||
virtual void setTCoords(u32 i, core::vector2d<f32> c);
|
||||
|
||||
private:
|
||||
|
||||
core::dimension2d<f32> Size;
|
||||
core::aabbox3d<f32> BBox;
|
||||
video::SMaterial Material;
|
||||
|
||||
video::S3DVertex vertices[4];
|
||||
u16 indices[6];
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,13 +38,6 @@ static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
bool base64_is_valid(std::string const& s)
|
||||
{
|
||||
for(int i=0; i<s.size(); i++)
|
||||
if(!is_base64(s[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <string>
|
||||
|
||||
bool base64_is_valid(std::string const& s);
|
||||
std::string base64_encode(unsigned char const* , unsigned int len);
|
||||
std::string base64_decode(std::string const& s);
|
||||
|
||||
903
src/camera.cpp
@@ -1,903 +0,0 @@
|
||||
/*
|
||||
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 "camera.h"
|
||||
#include "debug.h"
|
||||
#include "client.h"
|
||||
#include "main.h" // for g_settings
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include <cmath>
|
||||
#include <SAnimatedMesh.h>
|
||||
#include "settings.h"
|
||||
|
||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
|
||||
m_smgr(smgr),
|
||||
m_playernode(NULL),
|
||||
m_headnode(NULL),
|
||||
m_cameranode(NULL),
|
||||
|
||||
m_wieldmgr(NULL),
|
||||
m_wieldnode(NULL),
|
||||
|
||||
m_draw_control(draw_control),
|
||||
m_viewing_range_min(5.0),
|
||||
m_viewing_range_max(5.0),
|
||||
|
||||
m_camera_position(0,0,0),
|
||||
m_camera_direction(0,0,0),
|
||||
|
||||
m_aspect(1.0),
|
||||
m_fov_x(1.0),
|
||||
m_fov_y(1.0),
|
||||
|
||||
m_wanted_frametime(0.0),
|
||||
m_added_frametime(0),
|
||||
m_added_frames(0),
|
||||
m_range_old(0),
|
||||
m_frametime_old(0),
|
||||
m_frametime_counter(0),
|
||||
m_time_per_range(30. / 50), // a sane default of 30ms per 50 nodes of range
|
||||
|
||||
m_view_bobbing_anim(0),
|
||||
m_view_bobbing_state(0),
|
||||
m_view_bobbing_speed(0),
|
||||
|
||||
m_digging_anim(0),
|
||||
m_digging_button(-1)
|
||||
{
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
|
||||
// note: making the camera node a child of the player node
|
||||
// would lead to unexpected behaviour, so we don't do that.
|
||||
m_playernode = smgr->addEmptySceneNode(smgr->getRootSceneNode());
|
||||
m_headnode = smgr->addEmptySceneNode(m_playernode);
|
||||
m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode());
|
||||
m_cameranode->bindTargetAndRotation(true);
|
||||
|
||||
// This needs to be in its own scene manager. It is drawn after
|
||||
// all other 3D scene nodes and before the GUI.
|
||||
m_wieldmgr = smgr->createNewSceneManager();
|
||||
m_wieldmgr->addCameraSceneNode();
|
||||
m_wieldnode = new ExtrudedSpriteSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr);
|
||||
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
m_wieldmgr->drop();
|
||||
m_wieldnode->drop();
|
||||
}
|
||||
|
||||
bool Camera::successfullyCreated(std::wstring& error_message)
|
||||
{
|
||||
if (m_playernode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the player scene node";
|
||||
return false;
|
||||
}
|
||||
if (m_headnode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the head scene node";
|
||||
return false;
|
||||
}
|
||||
if (m_cameranode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the camera scene node";
|
||||
return false;
|
||||
}
|
||||
if (m_wieldmgr == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the wielded item scene manager";
|
||||
return false;
|
||||
}
|
||||
if (m_wieldnode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the wielded item scene node";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the fractional part of x
|
||||
inline f32 my_modf(f32 x)
|
||||
{
|
||||
double dummy;
|
||||
return modf(x, &dummy);
|
||||
}
|
||||
|
||||
void Camera::step(f32 dtime)
|
||||
{
|
||||
if (m_view_bobbing_state != 0)
|
||||
{
|
||||
//f32 offset = dtime * m_view_bobbing_speed * 0.035;
|
||||
f32 offset = dtime * m_view_bobbing_speed * 0.030;
|
||||
if (m_view_bobbing_state == 2)
|
||||
{
|
||||
#if 0
|
||||
// Animation is getting turned off
|
||||
if (m_view_bobbing_anim < 0.5)
|
||||
m_view_bobbing_anim -= offset;
|
||||
else
|
||||
m_view_bobbing_anim += offset;
|
||||
if (m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1)
|
||||
{
|
||||
m_view_bobbing_anim = 0;
|
||||
m_view_bobbing_state = 0;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
// Animation is getting turned off
|
||||
if(m_view_bobbing_anim < 0.25){
|
||||
m_view_bobbing_anim -= offset;
|
||||
} else if(m_view_bobbing_anim > 0.75){
|
||||
m_view_bobbing_anim += offset;
|
||||
} if(m_view_bobbing_anim < 0.5){
|
||||
m_view_bobbing_anim += offset;
|
||||
if(m_view_bobbing_anim > 0.5)
|
||||
m_view_bobbing_anim = 0.5;
|
||||
} else {
|
||||
m_view_bobbing_anim -= offset;
|
||||
if(m_view_bobbing_anim < 0.5)
|
||||
m_view_bobbing_anim = 0.5;
|
||||
}
|
||||
if(m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1 ||
|
||||
fabs(m_view_bobbing_anim - 0.5) < 0.01)
|
||||
{
|
||||
m_view_bobbing_anim = 0;
|
||||
m_view_bobbing_state = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
m_view_bobbing_anim = my_modf(m_view_bobbing_anim + offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 offset = dtime * 3.5;
|
||||
m_digging_anim += offset;
|
||||
if (m_digging_anim >= 1)
|
||||
{
|
||||
m_digging_anim = 0;
|
||||
m_digging_button = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
|
||||
{
|
||||
// Set player node transformation
|
||||
m_playernode->setPosition(player->getPosition());
|
||||
m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
|
||||
m_playernode->updateAbsolutePosition();
|
||||
|
||||
// Set head node transformation
|
||||
m_headnode->setPosition(player->getEyeOffset());
|
||||
m_headnode->setRotation(v3f(player->getPitch(), 0, 0));
|
||||
m_headnode->updateAbsolutePosition();
|
||||
|
||||
// Compute relative camera position and target
|
||||
v3f rel_cam_pos = v3f(0,0,0);
|
||||
v3f rel_cam_target = v3f(0,0,1);
|
||||
v3f rel_cam_up = v3f(0,1,0);
|
||||
|
||||
if (m_view_bobbing_anim != 0)
|
||||
{
|
||||
f32 bobfrac = my_modf(m_view_bobbing_anim * 2);
|
||||
f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0;
|
||||
|
||||
#if 1
|
||||
f32 bobknob = 1.2;
|
||||
f32 bobtmp = sin(pow(bobfrac, bobknob) * PI);
|
||||
//f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI);
|
||||
|
||||
v3f bobvec = v3f(
|
||||
0.3 * bobdir * sin(bobfrac * PI),
|
||||
-0.28 * bobtmp * bobtmp,
|
||||
0.);
|
||||
|
||||
//rel_cam_pos += 0.2 * bobvec;
|
||||
//rel_cam_target += 0.03 * bobvec;
|
||||
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI);
|
||||
float f = 1.0;
|
||||
f *= g_settings->getFloat("view_bobbing_amount");
|
||||
rel_cam_pos += bobvec * f;
|
||||
//rel_cam_target += 0.995 * bobvec * f;
|
||||
rel_cam_target += bobvec * f;
|
||||
rel_cam_target.Z -= 0.005 * bobvec.Z * f;
|
||||
//rel_cam_target.X -= 0.005 * bobvec.X * f;
|
||||
//rel_cam_target.Y -= 0.005 * bobvec.Y * f;
|
||||
rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f);
|
||||
#else
|
||||
f32 angle_deg = 1 * bobdir * sin(bobfrac * PI);
|
||||
f32 angle_rad = angle_deg * PI / 180;
|
||||
f32 r = 0.05;
|
||||
v3f off = v3f(
|
||||
r * sin(angle_rad),
|
||||
r * (cos(angle_rad) - 1),
|
||||
0);
|
||||
rel_cam_pos += off;
|
||||
//rel_cam_target += off;
|
||||
rel_cam_up.rotateXYBy(angle_deg);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Compute absolute camera position and target
|
||||
m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos);
|
||||
m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos);
|
||||
|
||||
v3f abs_cam_up;
|
||||
m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up);
|
||||
|
||||
// Set camera node transformation
|
||||
m_cameranode->setPosition(m_camera_position);
|
||||
m_cameranode->setUpVector(abs_cam_up);
|
||||
// *100.0 helps in large map coordinates
|
||||
m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction);
|
||||
|
||||
// FOV and and aspect ratio
|
||||
m_aspect = (f32)screensize.X / (f32) screensize.Y;
|
||||
m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y));
|
||||
m_cameranode->setAspectRatio(m_aspect);
|
||||
m_cameranode->setFOV(m_fov_y);
|
||||
// Just so big a value that everything rendered is visible
|
||||
// Some more allowance that m_viewing_range_max * BS because of active objects etc.
|
||||
m_cameranode->setFarValue(m_viewing_range_max * BS * 10);
|
||||
|
||||
// Position the wielded item
|
||||
v3f wield_position = v3f(45, -35, 65);
|
||||
v3f wield_rotation = v3f(-100, 110, -100);
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 digfrac = m_digging_anim;
|
||||
wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI);
|
||||
wield_position.Y += 15 * sin(digfrac * 2 * PI);
|
||||
wield_position.Z += 5 * digfrac;
|
||||
|
||||
// Euler angles are PURE EVIL, so why not use quaternions?
|
||||
core::quaternion quat_begin(wield_rotation * core::DEGTORAD);
|
||||
core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD);
|
||||
core::quaternion quat_slerp;
|
||||
quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI));
|
||||
quat_slerp.toEuler(wield_rotation);
|
||||
wield_rotation *= core::RADTODEG;
|
||||
}
|
||||
else {
|
||||
f32 bobfrac = my_modf(m_view_bobbing_anim);
|
||||
wield_position.X -= sin(bobfrac*PI*2.0) * 3.0;
|
||||
wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0;
|
||||
}
|
||||
m_wieldnode->setPosition(wield_position);
|
||||
m_wieldnode->setRotation(wield_rotation);
|
||||
m_wieldnode->updateLight(player->light);
|
||||
|
||||
// Render distance feedback loop
|
||||
updateViewingRange(frametime);
|
||||
|
||||
// If the player seems to be walking on solid ground,
|
||||
// view bobbing is enabled and free_move is off,
|
||||
// start (or continue) the view bobbing animation.
|
||||
v3f speed = player->getSpeed();
|
||||
if ((hypot(speed.X, speed.Z) > BS) &&
|
||||
(player->touching_ground) &&
|
||||
(g_settings->getBool("view_bobbing") == true) &&
|
||||
(g_settings->getBool("free_move") == false))
|
||||
{
|
||||
// Start animation
|
||||
m_view_bobbing_state = 1;
|
||||
m_view_bobbing_speed = MYMIN(speed.getLength(), 40);
|
||||
}
|
||||
else if (m_view_bobbing_state == 1)
|
||||
{
|
||||
// Stop animation
|
||||
m_view_bobbing_state = 2;
|
||||
m_view_bobbing_speed = 60;
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::updateViewingRange(f32 frametime_in)
|
||||
{
|
||||
if (m_draw_control.range_all)
|
||||
return;
|
||||
|
||||
m_added_frametime += frametime_in;
|
||||
m_added_frames += 1;
|
||||
|
||||
// Actually this counter kind of sucks because frametime is busytime
|
||||
m_frametime_counter -= frametime_in;
|
||||
if (m_frametime_counter > 0)
|
||||
return;
|
||||
m_frametime_counter = 0.2;
|
||||
|
||||
/*dstream<<__FUNCTION_NAME
|
||||
<<": Collected "<<m_added_frames<<" frames, total of "
|
||||
<<m_added_frametime<<"s."<<std::endl;
|
||||
|
||||
dstream<<"m_draw_control.blocks_drawn="
|
||||
<<m_draw_control.blocks_drawn
|
||||
<<", m_draw_control.blocks_would_have_drawn="
|
||||
<<m_draw_control.blocks_would_have_drawn
|
||||
<<std::endl;*/
|
||||
|
||||
m_draw_control.wanted_min_range = m_viewing_range_min;
|
||||
m_draw_control.wanted_max_blocks = (2.0*m_draw_control.blocks_would_have_drawn)+1;
|
||||
if (m_draw_control.wanted_max_blocks < 10)
|
||||
m_draw_control.wanted_max_blocks = 10;
|
||||
|
||||
f32 block_draw_ratio = 1.0;
|
||||
if (m_draw_control.blocks_would_have_drawn != 0)
|
||||
{
|
||||
block_draw_ratio = (f32)m_draw_control.blocks_drawn
|
||||
/ (f32)m_draw_control.blocks_would_have_drawn;
|
||||
}
|
||||
|
||||
// Calculate the average frametime in the case that all wanted
|
||||
// blocks had been drawn
|
||||
f32 frametime = m_added_frametime / m_added_frames / block_draw_ratio;
|
||||
|
||||
m_added_frametime = 0.0;
|
||||
m_added_frames = 0;
|
||||
|
||||
f32 wanted_frametime_change = m_wanted_frametime - frametime;
|
||||
//dstream<<"wanted_frametime_change="<<wanted_frametime_change<<std::endl;
|
||||
|
||||
// If needed frametime change is small, just return
|
||||
// This value was 0.4 for many months until 2011-10-18 by c55;
|
||||
// Let's see how this works out.
|
||||
if (fabs(wanted_frametime_change) < m_wanted_frametime*0.33)
|
||||
{
|
||||
//dstream<<"ignoring small wanted_frametime_change"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
f32 range = m_draw_control.wanted_range;
|
||||
f32 new_range = range;
|
||||
|
||||
f32 d_range = range - m_range_old;
|
||||
f32 d_frametime = frametime - m_frametime_old;
|
||||
if (d_range != 0)
|
||||
{
|
||||
m_time_per_range = d_frametime / d_range;
|
||||
}
|
||||
|
||||
// The minimum allowed calculated frametime-range derivative:
|
||||
// Practically this sets the maximum speed of changing the range.
|
||||
// The lower this value, the higher the maximum changing speed.
|
||||
// A low value here results in wobbly range (0.001)
|
||||
// A high value here results in slow changing range (0.0025)
|
||||
// SUGG: This could be dynamically adjusted so that when
|
||||
// the camera is turning, this is lower
|
||||
//f32 min_time_per_range = 0.0015;
|
||||
f32 min_time_per_range = 0.0010;
|
||||
//f32 min_time_per_range = 0.05 / range;
|
||||
if(m_time_per_range < min_time_per_range)
|
||||
{
|
||||
m_time_per_range = min_time_per_range;
|
||||
//dstream<<"m_time_per_range="<<m_time_per_range<<" (min)"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
//dstream<<"m_time_per_range="<<m_time_per_range<<std::endl;
|
||||
}
|
||||
|
||||
f32 wanted_range_change = wanted_frametime_change / m_time_per_range;
|
||||
// Dampen the change a bit to kill oscillations
|
||||
//wanted_range_change *= 0.9;
|
||||
//wanted_range_change *= 0.75;
|
||||
wanted_range_change *= 0.5;
|
||||
//dstream<<"wanted_range_change="<<wanted_range_change<<std::endl;
|
||||
|
||||
// If needed range change is very small, just return
|
||||
if(fabs(wanted_range_change) < 0.001)
|
||||
{
|
||||
//dstream<<"ignoring small wanted_range_change"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
new_range += wanted_range_change;
|
||||
|
||||
//f32 new_range_unclamped = new_range;
|
||||
new_range = MYMAX(new_range, m_viewing_range_min);
|
||||
new_range = MYMIN(new_range, m_viewing_range_max);
|
||||
/*dstream<<"new_range="<<new_range_unclamped
|
||||
<<", clamped to "<<new_range<<std::endl;*/
|
||||
|
||||
m_draw_control.wanted_range = new_range;
|
||||
|
||||
m_range_old = new_range;
|
||||
m_frametime_old = frametime;
|
||||
}
|
||||
|
||||
void Camera::updateSettings()
|
||||
{
|
||||
m_viewing_range_min = g_settings->getS16("viewing_range_nodes_min");
|
||||
m_viewing_range_min = MYMAX(5.0, m_viewing_range_min);
|
||||
|
||||
m_viewing_range_max = g_settings->getS16("viewing_range_nodes_max");
|
||||
m_viewing_range_max = MYMAX(m_viewing_range_min, m_viewing_range_max);
|
||||
|
||||
f32 fov_degrees = g_settings->getFloat("fov");
|
||||
fov_degrees = MYMAX(fov_degrees, 10.0);
|
||||
fov_degrees = MYMIN(fov_degrees, 170.0);
|
||||
m_fov_y = fov_degrees * PI / 180.0;
|
||||
|
||||
f32 wanted_fps = g_settings->getFloat("wanted_fps");
|
||||
wanted_fps = MYMAX(wanted_fps, 1.0);
|
||||
m_wanted_frametime = 1.0 / wanted_fps;
|
||||
}
|
||||
|
||||
void Camera::wield(const InventoryItem* item)
|
||||
{
|
||||
if (item != NULL)
|
||||
{
|
||||
bool isCube = false;
|
||||
|
||||
// Try to make a MaterialItem cube.
|
||||
if (std::string(item->getName()) == "MaterialItem")
|
||||
{
|
||||
// A block-type material
|
||||
MaterialItem* mat_item = (MaterialItem*) item;
|
||||
content_t content = mat_item->getMaterial();
|
||||
if (content_features(content).solidness || content_features(content).visual_solidness)
|
||||
{
|
||||
m_wieldnode->setCube(content_features(content).tiles);
|
||||
m_wieldnode->setScale(v3f(30));
|
||||
isCube = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, make an extruded sprite.
|
||||
if (!isCube)
|
||||
{
|
||||
m_wieldnode->setSprite(item->getImageRaw());
|
||||
m_wieldnode->setScale(v3f(40));
|
||||
}
|
||||
|
||||
m_wieldnode->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bare hands
|
||||
m_wieldnode->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::setDigging(s32 button)
|
||||
{
|
||||
if (m_digging_button == -1)
|
||||
m_digging_button = button;
|
||||
}
|
||||
|
||||
void Camera::drawWieldedTool()
|
||||
{
|
||||
m_wieldmgr->getVideoDriver()->clearZBuffer();
|
||||
|
||||
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
|
||||
cam->setAspectRatio(m_cameranode->getAspectRatio());
|
||||
cam->setFOV(m_cameranode->getFOV());
|
||||
cam->setNearValue(0.1);
|
||||
cam->setFarValue(100);
|
||||
m_wieldmgr->drawAll();
|
||||
}
|
||||
|
||||
|
||||
ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id,
|
||||
const v3f& position,
|
||||
const v3f& rotation,
|
||||
const v3f& scale
|
||||
):
|
||||
ISceneNode(parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
|
||||
m_thickness = 0.1;
|
||||
m_cubemesh = NULL;
|
||||
m_is_cube = false;
|
||||
m_light = LIGHT_MAX;
|
||||
}
|
||||
|
||||
ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
|
||||
{
|
||||
removeChild(m_meshnode);
|
||||
if (m_cubemesh)
|
||||
m_cubemesh->drop();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
|
||||
{
|
||||
if (texture == NULL)
|
||||
{
|
||||
m_meshnode->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
io::path name = getExtrudedName(texture);
|
||||
scene::IMeshCache* cache = SceneManager->getMeshCache();
|
||||
scene::IAnimatedMesh* mesh = cache->getMeshByName(name);
|
||||
if (mesh != NULL)
|
||||
{
|
||||
// Extruded texture has been found in cache.
|
||||
m_meshnode->setMesh(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Texture was not yet extruded, do it now and save in cache
|
||||
mesh = extrude(texture);
|
||||
if (mesh == NULL)
|
||||
{
|
||||
dstream << "Warning: failed to extrude sprite" << std::endl;
|
||||
m_meshnode->setVisible(false);
|
||||
return;
|
||||
}
|
||||
cache->addMesh(name, mesh);
|
||||
m_meshnode->setMesh(mesh);
|
||||
mesh->drop();
|
||||
}
|
||||
|
||||
m_meshnode->setScale(v3f(1, 1, m_thickness));
|
||||
m_meshnode->getMaterial(0).setTexture(0, texture);
|
||||
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
|
||||
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
m_meshnode->setVisible(true);
|
||||
m_is_cube = false;
|
||||
updateLight(m_light);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
|
||||
{
|
||||
if (m_cubemesh == NULL)
|
||||
m_cubemesh = createCubeMesh();
|
||||
|
||||
m_meshnode->setMesh(m_cubemesh);
|
||||
m_meshnode->setScale(v3f(1));
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// Get the tile texture and atlas transformation
|
||||
video::ITexture* atlas = tiles[i].texture.atlas;
|
||||
v2f pos = tiles[i].texture.pos;
|
||||
v2f size = tiles[i].texture.size;
|
||||
|
||||
// Set material flags and texture
|
||||
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
tiles[i].applyMaterialOptions(material);
|
||||
material.setTexture(0, atlas);
|
||||
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||
}
|
||||
m_meshnode->setVisible(true);
|
||||
m_is_cube = true;
|
||||
updateLight(m_light);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::updateLight(u8 light)
|
||||
{
|
||||
m_light = light;
|
||||
|
||||
u8 li = decode_light(light);
|
||||
// Set brightness one lower than incoming light
|
||||
diminish_light(li);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_meshnode->getMesh(), color);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
|
||||
{
|
||||
scene::IMeshCache* cache = SceneManager->getMeshCache();
|
||||
scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture));
|
||||
if (mesh != NULL)
|
||||
cache->removeMesh(mesh);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness)
|
||||
{
|
||||
m_thickness = thickness;
|
||||
if (!m_is_cube)
|
||||
m_meshnode->setScale(v3f(1, 1, thickness));
|
||||
}
|
||||
|
||||
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
|
||||
{
|
||||
return m_meshnode->getBoundingBox();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
|
||||
{
|
||||
io::path path = texture->getName();
|
||||
path.append("/[extruded]");
|
||||
return path;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height, u8* data)
|
||||
{
|
||||
const s32 argb_wstep = 4 * width;
|
||||
const s32 alpha_threshold = 1;
|
||||
|
||||
scene::IMeshBuffer* buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
|
||||
// Front and back
|
||||
{
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,+1, c, 1,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,+1, c, 1,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,+1, c, 0,0),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,+1, c, 0,1),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
}
|
||||
|
||||
// "Interior"
|
||||
// (add faces where a solid pixel is next to a transparent one)
|
||||
u8* solidity = new u8[(width+2) * (height+2)];
|
||||
u32 wstep = width + 2;
|
||||
for (u32 y = 0; y < height + 2; ++y)
|
||||
{
|
||||
u8* scanline = solidity + y * wstep;
|
||||
if (y == 0 || y == height + 1)
|
||||
{
|
||||
for (u32 x = 0; x < width + 2; ++x)
|
||||
scanline[x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanline[0] = 0;
|
||||
u8* argb_scanline = data + (y - 1) * argb_wstep;
|
||||
for (u32 x = 0; x < width; ++x)
|
||||
scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold);
|
||||
scanline[width + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// without this, there would be occasional "holes" in the mesh
|
||||
f32 eps = 0.01;
|
||||
|
||||
for (u32 y = 0; y <= height; ++y)
|
||||
{
|
||||
u8* scanline = solidity + y * wstep + 1;
|
||||
for (u32 x = 0; x <= width; ++x)
|
||||
{
|
||||
if (scanline[x] && !scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (scanline[xx] && !scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) width - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) width - 0.5;
|
||||
f32 vy = 0.5 - (y - eps) / (f32) height;
|
||||
f32 tx1 = x / (f32) width;
|
||||
f32 tx2 = xx / (f32) width;
|
||||
f32 ty = (y - 0.5) / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
if (!scanline[x] && scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (!scanline[xx] && scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) width - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) width - 0.5;
|
||||
f32 vy = 0.5 - (y + eps) / (f32) height;
|
||||
f32 tx1 = x / (f32) width;
|
||||
f32 tx2 = xx / (f32) width;
|
||||
f32 ty = (y + 0.5) / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 x = 0; x <= width; ++x)
|
||||
{
|
||||
u8* scancol = solidity + x + wstep;
|
||||
for (u32 y = 0; y <= height; ++y)
|
||||
{
|
||||
if (scancol[y * wstep] && !scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (scancol[yy * wstep] && !scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x - eps) / (f32) width - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) height;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) height;
|
||||
f32 tx = (x - 0.5) / (f32) width;
|
||||
f32 ty1 = y / (f32) height;
|
||||
f32 ty2 = yy / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
if (!scancol[y * wstep] && scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (!scancol[yy * wstep] && scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x + eps) / (f32) width - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) height;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) height;
|
||||
f32 tx = (x + 0.5) / (f32) width;
|
||||
f32 ty1 = y / (f32) height;
|
||||
f32 ty2 = yy / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mesh
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
buf->recalculateBoundingBox();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
mesh->recalculateBoundingBox();
|
||||
scene::SAnimatedMesh* anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture)
|
||||
{
|
||||
scene::IAnimatedMesh* mesh = NULL;
|
||||
core::dimension2d<u32> size = texture->getSize();
|
||||
video::ECOLOR_FORMAT format = texture->getColorFormat();
|
||||
if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
// Texture is in the correct color format, we can pass it
|
||||
// to extrudeARGB right away.
|
||||
void* data = texture->lock(true);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
|
||||
texture->unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(true));
|
||||
if (img1 == NULL)
|
||||
return NULL;
|
||||
|
||||
// img1 is in the texture's color format, convert to 8-bit ARGB
|
||||
video::IImage* img2 = driver->createImage(video::ECF_A8R8G8B8, size);
|
||||
if (img2 != NULL)
|
||||
{
|
||||
img1->copyTo(img2);
|
||||
img1->drop();
|
||||
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
|
||||
img2->unlock();
|
||||
img2->drop();
|
||||
}
|
||||
img1->drop();
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
scene::IMesh* ExtrudedSpriteSceneNode::createCubeMesh()
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer* buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
buf->recalculateBoundingBox();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
mesh->recalculateBoundingBox();
|
||||
return mesh;
|
||||
}
|
||||
233
src/camera.h
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
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 CAMERA_HEADER
|
||||
#define CAMERA_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "inventory.h"
|
||||
#include "tile.h"
|
||||
#include "utility.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <IMeshCache.h>
|
||||
#include <IAnimatedMesh.h>
|
||||
|
||||
class LocalPlayer;
|
||||
class MapDrawControl;
|
||||
class ExtrudedSpriteSceneNode;
|
||||
|
||||
/*
|
||||
Client camera class, manages the player and camera scene nodes, the viewing distance
|
||||
and performs view bobbing etc. It also displays the wielded tool in front of the
|
||||
first-person camera.
|
||||
*/
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control);
|
||||
~Camera();
|
||||
|
||||
// Get player scene node.
|
||||
// This node is positioned at the player's torso (without any view bobbing),
|
||||
// as given by Player::m_position. Yaw is applied but not pitch.
|
||||
inline scene::ISceneNode* getPlayerNode() const
|
||||
{
|
||||
return m_playernode;
|
||||
}
|
||||
|
||||
// Get head scene node.
|
||||
// It has the eye transformation and pitch applied,
|
||||
// but no view bobbing.
|
||||
inline scene::ISceneNode* getHeadNode() const
|
||||
{
|
||||
return m_headnode;
|
||||
}
|
||||
|
||||
// Get camera scene node.
|
||||
// It has the eye transformation, pitch and view bobbing applied.
|
||||
inline scene::ICameraSceneNode* getCameraNode() const
|
||||
{
|
||||
return m_cameranode;
|
||||
}
|
||||
|
||||
// Get the camera position (in absolute scene coordinates).
|
||||
// This has view bobbing applied.
|
||||
inline v3f getPosition() const
|
||||
{
|
||||
return m_camera_position;
|
||||
}
|
||||
|
||||
// Get the camera direction (in absolute camera coordinates).
|
||||
// This has view bobbing applied.
|
||||
inline v3f getDirection() const
|
||||
{
|
||||
return m_camera_direction;
|
||||
}
|
||||
|
||||
// Horizontal field of view
|
||||
inline f32 getFovX() const
|
||||
{
|
||||
return m_fov_x;
|
||||
}
|
||||
|
||||
// Vertical field of view
|
||||
inline f32 getFovY() const
|
||||
{
|
||||
return m_fov_y;
|
||||
}
|
||||
|
||||
// Get maximum of getFovX() and getFovY()
|
||||
inline f32 getFovMax() const
|
||||
{
|
||||
return MYMAX(m_fov_x, m_fov_y);
|
||||
}
|
||||
|
||||
// Checks if the constructor was able to create the scene nodes
|
||||
bool successfullyCreated(std::wstring& error_message);
|
||||
|
||||
// Step the camera: updates the viewing range and view bobbing.
|
||||
void step(f32 dtime);
|
||||
|
||||
// Update the camera from the local player's position.
|
||||
// frametime is used to adjust the viewing range.
|
||||
void update(LocalPlayer* player, f32 frametime, v2u32 screensize);
|
||||
|
||||
// Render distance feedback loop
|
||||
void updateViewingRange(f32 frametime_in);
|
||||
|
||||
// Update settings from g_settings
|
||||
void updateSettings();
|
||||
|
||||
// Replace the wielded item mesh
|
||||
void wield(const InventoryItem* item);
|
||||
|
||||
// Start digging animation
|
||||
// Pass 0 for left click, 1 for right click
|
||||
void setDigging(s32 button);
|
||||
|
||||
// Draw the wielded tool.
|
||||
// This has to happen *after* the main scene is drawn.
|
||||
// Warning: This clears the Z buffer.
|
||||
void drawWieldedTool();
|
||||
|
||||
private:
|
||||
// Scene manager and nodes
|
||||
scene::ISceneManager* m_smgr;
|
||||
scene::ISceneNode* m_playernode;
|
||||
scene::ISceneNode* m_headnode;
|
||||
scene::ICameraSceneNode* m_cameranode;
|
||||
|
||||
scene::ISceneManager* m_wieldmgr;
|
||||
ExtrudedSpriteSceneNode* m_wieldnode;
|
||||
|
||||
// draw control
|
||||
MapDrawControl& m_draw_control;
|
||||
|
||||
// viewing_range_min_nodes setting
|
||||
f32 m_viewing_range_min;
|
||||
// viewing_range_max_nodes setting
|
||||
f32 m_viewing_range_max;
|
||||
|
||||
// Absolute camera position
|
||||
v3f m_camera_position;
|
||||
// Absolute camera direction
|
||||
v3f m_camera_direction;
|
||||
|
||||
// Field of view and aspect ratio stuff
|
||||
f32 m_aspect;
|
||||
f32 m_fov_x;
|
||||
f32 m_fov_y;
|
||||
|
||||
// Stuff for viewing range calculations
|
||||
f32 m_wanted_frametime;
|
||||
f32 m_added_frametime;
|
||||
s16 m_added_frames;
|
||||
f32 m_range_old;
|
||||
f32 m_frametime_old;
|
||||
f32 m_frametime_counter;
|
||||
f32 m_time_per_range;
|
||||
|
||||
// View bobbing animation frame (0 <= m_view_bobbing_anim < 1)
|
||||
f32 m_view_bobbing_anim;
|
||||
// If 0, view bobbing is off (e.g. player is standing).
|
||||
// If 1, view bobbing is on (player is walking).
|
||||
// If 2, view bobbing is getting switched off.
|
||||
s32 m_view_bobbing_state;
|
||||
// Speed of view bobbing animation
|
||||
f32 m_view_bobbing_speed;
|
||||
|
||||
// Digging animation frame (0 <= m_digging_anim < 1)
|
||||
f32 m_digging_anim;
|
||||
// If -1, no digging animation
|
||||
// If 0, left-click digging animation
|
||||
// If 1, right-click digging animation
|
||||
s32 m_digging_button;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A scene node that displays a 2D mesh extruded into the third dimension,
|
||||
to add an illusion of depth.
|
||||
|
||||
Since this class was created to display the wielded tool of the local
|
||||
player, and only tools and items are rendered like this (but not solid
|
||||
content like stone and mud, which are shown as cubes), the option to
|
||||
draw a textured cube instead is provided.
|
||||
*/
|
||||
class ExtrudedSpriteSceneNode: public scene::ISceneNode
|
||||
{
|
||||
public:
|
||||
ExtrudedSpriteSceneNode(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id = -1,
|
||||
const v3f& position = v3f(0,0,0),
|
||||
const v3f& rotation = v3f(0,0,0),
|
||||
const v3f& scale = v3f(1,1,1));
|
||||
~ExtrudedSpriteSceneNode();
|
||||
|
||||
void setSprite(video::ITexture* texture);
|
||||
void setCube(const TileSpec tiles[6]);
|
||||
|
||||
f32 getSpriteThickness() const { return m_thickness; }
|
||||
void setSpriteThickness(f32 thickness);
|
||||
|
||||
void updateLight(u8 light);
|
||||
|
||||
void removeSpriteFromCache(video::ITexture* texture);
|
||||
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
virtual void OnRegisterSceneNode();
|
||||
virtual void render();
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode* m_meshnode;
|
||||
f32 m_thickness;
|
||||
scene::IMesh* m_cubemesh;
|
||||
bool m_is_cube;
|
||||
u8 m_light;
|
||||
|
||||
// internal extrusion helper methods
|
||||
io::path getExtrudedName(video::ITexture* texture);
|
||||
scene::IAnimatedMesh* extrudeARGB(u32 width, u32 height, u8* data);
|
||||
scene::IAnimatedMesh* extrude(video::ITexture* texture);
|
||||
scene::IMesh* createCubeMesh();
|
||||
};
|
||||
|
||||
#endif
|
||||
518
src/client.cpp
54
src/client.h
@@ -113,8 +113,7 @@ enum ClientEventType
|
||||
{
|
||||
CE_NONE,
|
||||
CE_PLAYER_DAMAGE,
|
||||
CE_PLAYER_FORCE_MOVE,
|
||||
CE_DEATHSCREEN,
|
||||
CE_PLAYER_FORCE_MOVE
|
||||
};
|
||||
|
||||
struct ClientEvent
|
||||
@@ -130,12 +129,6 @@ struct ClientEvent
|
||||
f32 pitch;
|
||||
f32 yaw;
|
||||
} player_force_move;
|
||||
struct{
|
||||
bool set_camera_point_target;
|
||||
f32 camera_point_target_x;
|
||||
f32 camera_point_target_y;
|
||||
f32 camera_point_target_z;
|
||||
} deathscreen;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -190,31 +183,32 @@ class Client : public con::PeerHandler, public InventoryManager
|
||||
|
||||
void groundAction(u8 action, v3s16 nodepos_undersurface,
|
||||
v3s16 nodepos_oversurface, u16 item);
|
||||
void clickActiveObject(u8 button, u16 id, u16 item_i);
|
||||
void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item);
|
||||
void clickActiveObject(u8 button, u16 id, u16 item);
|
||||
|
||||
void sendSignText(v3s16 blockpos, s16 id, std::string text);
|
||||
void sendSignNodeText(v3s16 p, std::string text);
|
||||
void sendInventoryAction(InventoryAction *a);
|
||||
void sendChatMessage(const std::wstring &message);
|
||||
void sendChangePassword(const std::wstring oldpassword,
|
||||
const std::wstring newpassword);
|
||||
void sendDamage(u8 damage);
|
||||
void sendRespawn();
|
||||
|
||||
// locks envlock
|
||||
void removeNode(v3s16 p);
|
||||
// locks envlock
|
||||
void addNode(v3s16 p, MapNode n);
|
||||
|
||||
void updateCamera(v3f pos, v3f dir, f32 fov);
|
||||
|
||||
void renderPostFx();
|
||||
void updateCamera(v3f pos, v3f dir);
|
||||
|
||||
// Returns InvalidPositionException if not found
|
||||
MapNode getNode(v3s16 p);
|
||||
// Wrapper to Map
|
||||
NodeMetadata* getNodeMetadata(v3s16 p);
|
||||
|
||||
LocalPlayer* getLocalPlayer();
|
||||
// Get the player position, and optionally put the
|
||||
// eye position in *eye_position
|
||||
v3f getPlayerPosition(v3f *eye_position=NULL);
|
||||
|
||||
void setPlayerControl(PlayerControl &control);
|
||||
|
||||
@@ -231,6 +225,14 @@ class Client : public con::PeerHandler, public InventoryManager
|
||||
Inventory* getInventory(InventoryContext *c, std::string id);
|
||||
void inventoryAction(InventoryAction *a);
|
||||
|
||||
// Gets closest object pointed by the shootline
|
||||
// Returns NULL if not found
|
||||
MapBlockObject * getSelectedObject(
|
||||
f32 max_d,
|
||||
v3f from_pos_f_on_map,
|
||||
core::line3d<f32> shootline_on_map
|
||||
);
|
||||
|
||||
// Gets closest object pointed by the shootline
|
||||
// Returns NULL if not found
|
||||
ClientActiveObject * getSelectedActiveObject(
|
||||
@@ -251,11 +253,11 @@ class Client : public con::PeerHandler, public InventoryManager
|
||||
|
||||
float getAvgRtt()
|
||||
{
|
||||
try{
|
||||
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
||||
} catch(con::PeerNotFoundException){
|
||||
return 1337;
|
||||
}
|
||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||
con::Peer *peer = m_con.GetPeerNoEx(PEER_ID_SERVER);
|
||||
if(peer == NULL)
|
||||
return 0.0;
|
||||
return peer->avg_rtt;
|
||||
}
|
||||
|
||||
bool getChatMessage(std::wstring &message)
|
||||
@@ -300,8 +302,15 @@ class Client : public con::PeerHandler, public InventoryManager
|
||||
{
|
||||
return m_access_denied_reason;
|
||||
}
|
||||
|
||||
float getRTT(void);
|
||||
|
||||
/*
|
||||
This should only be used for calling the special drawing stuff in
|
||||
ClientEnvironment
|
||||
*/
|
||||
ClientEnvironment * getEnv()
|
||||
{
|
||||
return &m_env;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -333,6 +342,9 @@ class Client : public con::PeerHandler, public InventoryManager
|
||||
|
||||
IrrlichtDevice *m_device;
|
||||
|
||||
v3f camera_position;
|
||||
v3f camera_direction;
|
||||
|
||||
// Server serialization version
|
||||
u8 m_server_ser_ver;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ ClientActiveObject* ClientActiveObject::create(u8 type)
|
||||
{
|
||||
// If factory is not found, just return.
|
||||
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
||||
<<(int)type<<std::endl;
|
||||
<<type<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ class ClientActiveObject : public ActiveObject
|
||||
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
|
||||
virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;}
|
||||
virtual v3f getPosition(){return v3f(0,0,0);}
|
||||
virtual bool doShowSelectionBox(){return true;}
|
||||
|
||||
// Step object in time
|
||||
virtual void step(float dtime, ClientEnvironment *env){}
|
||||
@@ -60,7 +59,7 @@ class ClientActiveObject : public ActiveObject
|
||||
virtual void processMessage(const std::string &data){}
|
||||
|
||||
virtual std::string infoText() {return "";}
|
||||
|
||||
|
||||
/*
|
||||
This takes the return value of
|
||||
ServerActiveObject::getClientInitializationData
|
||||
@@ -70,10 +69,6 @@ class ClientActiveObject : public ActiveObject
|
||||
// Create a certain type of ClientActiveObject
|
||||
static ClientActiveObject* create(u8 type);
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
virtual bool directReportPunch(const std::string &toolname, v3f dir)
|
||||
{ return false; }
|
||||
|
||||
protected:
|
||||
// Used for creating objects based on type
|
||||
typedef ClientActiveObject* (*Factory)();
|
||||
|
||||
@@ -22,8 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
#define PROTOCOL_VERSION 3
|
||||
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
|
||||
@@ -174,13 +172,6 @@ enum ToClientCommand
|
||||
string serialized item
|
||||
}
|
||||
*/
|
||||
|
||||
TOCLIENT_DEATHSCREEN = 0x37,
|
||||
/*
|
||||
u16 command
|
||||
u8 bool set camera point target
|
||||
v3f1000 camera point target (to point the death cause or whatever)
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
@@ -329,11 +320,7 @@ enum ToServerCommand
|
||||
[0] u16 TOSERVER_PLAYERITEM
|
||||
[2] u16 item
|
||||
*/
|
||||
|
||||
TOSERVER_RESPAWN=0x38,
|
||||
/*
|
||||
u16 TOSERVER_RESPAWN
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
|
||||
|
||||
@@ -21,9 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "noise.h"
|
||||
#include "constants.h"
|
||||
#include "debug.h"
|
||||
#include "main.h" // For g_profiler and g_settings
|
||||
#include "profiler.h"
|
||||
#include "settings.h"
|
||||
|
||||
Clouds::Clouds(
|
||||
scene::ISceneNode* parent,
|
||||
@@ -79,12 +76,6 @@ void Clouds::render()
|
||||
if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
|
||||
return;
|
||||
|
||||
ScopeProfiler sp(g_profiler, "Rendering of clouds, avg", SPT_AVG);
|
||||
|
||||
int num_faces_to_draw = 1;
|
||||
if(g_settings->getBool("enable_3d_clouds"))
|
||||
num_faces_to_draw = 6;
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
driver->setMaterial(m_material);
|
||||
|
||||
@@ -153,7 +144,7 @@ void Clouds::render()
|
||||
f32 ry = 8*BS;
|
||||
f32 rz = cloud_size;
|
||||
|
||||
for(int i=0; i<num_faces_to_draw; i++)
|
||||
for(int i=0;i<6;i++)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
|
||||
@@ -23,26 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\
|
||||
video::SColor(255,30,30,30));d->endScene();}
|
||||
|
||||
#include <irrTypes.h>
|
||||
#include <vector2d.h>
|
||||
#include <vector3d.h>
|
||||
#include <irrMap.h>
|
||||
#include <irrList.h>
|
||||
#include <irrArray.h>
|
||||
#include <aabbox3d.h>
|
||||
#ifndef SERVER
|
||||
#include <SColor.h>
|
||||
#include <IMesh.h>
|
||||
#include <IImage.h>
|
||||
#include <IrrlichtDevice.h>
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <SMesh.h>
|
||||
#include <ISceneManager.h>
|
||||
#include <IMeshBuffer.h>
|
||||
#include <SMeshBuffer.h>
|
||||
#include <IGUIElement.h>
|
||||
#include <IGUIEnvironment.h>
|
||||
#endif
|
||||
#include <irrlicht.h>
|
||||
using namespace irr;
|
||||
typedef core::vector3df v3f;
|
||||
typedef core::vector3d<s16> v3s16;
|
||||
|
||||
1405
src/connection.cpp
283
src/connection.h
@@ -319,6 +319,28 @@ struct Channel
|
||||
{
|
||||
Channel();
|
||||
~Channel();
|
||||
/*
|
||||
Processes a packet with the basic header stripped out.
|
||||
Parameters:
|
||||
packetdata: Data in packet (with no base headers)
|
||||
con: The connection to which the channel is associated
|
||||
(used for sending back stuff (ACKs))
|
||||
peer_id: peer id of the sender of the packet in question
|
||||
channelnum: channel on which the packet was sent
|
||||
reliable: true if recursing into a reliable packet
|
||||
*/
|
||||
SharedBuffer<u8> ProcessPacket(
|
||||
SharedBuffer<u8> packetdata,
|
||||
Connection *con,
|
||||
u16 peer_id,
|
||||
u8 channelnum,
|
||||
bool reliable=false);
|
||||
|
||||
// Returns next data from a buffer if possible
|
||||
// throws a NoIncomingDataException if no data is available
|
||||
// If found, sets peer_id
|
||||
SharedBuffer<u8> CheckIncomingBuffers(Connection *con,
|
||||
u16 &peer_id);
|
||||
|
||||
u16 next_outgoing_seqnum;
|
||||
u16 next_incoming_seqnum;
|
||||
@@ -390,237 +412,78 @@ class Peer
|
||||
// with the id we have given to it
|
||||
bool has_sent_with_id;
|
||||
|
||||
float m_sendtime_accu;
|
||||
float m_max_packets_per_second;
|
||||
int m_num_sent;
|
||||
int m_max_num_sent;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
/*
|
||||
Connection
|
||||
*/
|
||||
|
||||
struct OutgoingPacket
|
||||
{
|
||||
u16 peer_id;
|
||||
u8 channelnum;
|
||||
SharedBuffer<u8> data;
|
||||
bool reliable;
|
||||
|
||||
OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
|
||||
bool reliable_):
|
||||
peer_id(peer_id_),
|
||||
channelnum(channelnum_),
|
||||
data(data_),
|
||||
reliable(reliable_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
enum ConnectionEventType{
|
||||
CONNEVENT_NONE,
|
||||
CONNEVENT_DATA_RECEIVED,
|
||||
CONNEVENT_PEER_ADDED,
|
||||
CONNEVENT_PEER_REMOVED,
|
||||
};
|
||||
|
||||
struct ConnectionEvent
|
||||
{
|
||||
enum ConnectionEventType type;
|
||||
u16 peer_id;
|
||||
Buffer<u8> data;
|
||||
bool timeout;
|
||||
Address address;
|
||||
|
||||
ConnectionEvent(): type(CONNEVENT_NONE) {}
|
||||
|
||||
std::string describe()
|
||||
{
|
||||
switch(type){
|
||||
case CONNEVENT_NONE:
|
||||
return "CONNEVENT_NONE";
|
||||
case CONNEVENT_DATA_RECEIVED:
|
||||
return "CONNEVENT_DATA_RECEIVED";
|
||||
case CONNEVENT_PEER_ADDED:
|
||||
return "CONNEVENT_PEER_ADDED";
|
||||
case CONNEVENT_PEER_REMOVED:
|
||||
return "CONNEVENT_PEER_REMOVED";
|
||||
}
|
||||
return "Invalid ConnectionEvent";
|
||||
}
|
||||
|
||||
void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
|
||||
{
|
||||
type = CONNEVENT_DATA_RECEIVED;
|
||||
peer_id = peer_id_;
|
||||
data = data_;
|
||||
}
|
||||
void peerAdded(u16 peer_id_, Address address_)
|
||||
{
|
||||
type = CONNEVENT_PEER_ADDED;
|
||||
peer_id = peer_id_;
|
||||
address = address_;
|
||||
}
|
||||
void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
|
||||
{
|
||||
type = CONNEVENT_PEER_REMOVED;
|
||||
peer_id = peer_id_;
|
||||
timeout = timeout_;
|
||||
address = address_;
|
||||
}
|
||||
};
|
||||
|
||||
enum ConnectionCommandType{
|
||||
CONNCMD_NONE,
|
||||
CONNCMD_SERVE,
|
||||
CONNCMD_CONNECT,
|
||||
CONNCMD_DISCONNECT,
|
||||
CONNCMD_SEND,
|
||||
CONNCMD_SEND_TO_ALL,
|
||||
CONNCMD_DELETE_PEER,
|
||||
};
|
||||
|
||||
struct ConnectionCommand
|
||||
{
|
||||
enum ConnectionCommandType type;
|
||||
u16 port;
|
||||
Address address;
|
||||
u16 peer_id;
|
||||
u8 channelnum;
|
||||
Buffer<u8> data;
|
||||
bool reliable;
|
||||
|
||||
ConnectionCommand(): type(CONNCMD_NONE) {}
|
||||
|
||||
void serve(u16 port_)
|
||||
{
|
||||
type = CONNCMD_SERVE;
|
||||
port = port_;
|
||||
}
|
||||
void connect(Address address_)
|
||||
{
|
||||
type = CONNCMD_CONNECT;
|
||||
address = address_;
|
||||
}
|
||||
void disconnect()
|
||||
{
|
||||
type = CONNCMD_DISCONNECT;
|
||||
}
|
||||
void send(u16 peer_id_, u8 channelnum_,
|
||||
SharedBuffer<u8> data_, bool reliable_)
|
||||
{
|
||||
type = CONNCMD_SEND;
|
||||
peer_id = peer_id_;
|
||||
channelnum = channelnum_;
|
||||
data = data_;
|
||||
reliable = reliable_;
|
||||
}
|
||||
void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_)
|
||||
{
|
||||
type = CONNCMD_SEND_TO_ALL;
|
||||
channelnum = channelnum_;
|
||||
data = data_;
|
||||
reliable = reliable_;
|
||||
}
|
||||
void deletePeer(u16 peer_id_)
|
||||
{
|
||||
type = CONNCMD_DELETE_PEER;
|
||||
peer_id = peer_id_;
|
||||
}
|
||||
};
|
||||
|
||||
class Connection: public SimpleThread
|
||||
class Connection
|
||||
{
|
||||
public:
|
||||
Connection(u32 protocol_id, u32 max_packet_size, float timeout);
|
||||
Connection(u32 protocol_id, u32 max_packet_size, float timeout,
|
||||
PeerHandler *peerhandler);
|
||||
Connection(
|
||||
u32 protocol_id,
|
||||
u32 max_packet_size,
|
||||
float timeout,
|
||||
PeerHandler *peerhandler
|
||||
);
|
||||
~Connection();
|
||||
void * Thread();
|
||||
|
||||
/* Interface */
|
||||
|
||||
ConnectionEvent getEvent();
|
||||
ConnectionEvent waitEvent(u32 timeout_ms);
|
||||
void putCommand(ConnectionCommand &c);
|
||||
|
||||
void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; }
|
||||
void setTimeoutMs(int timeout){ m_socket.setTimeoutMs(timeout); }
|
||||
// Start being a server
|
||||
void Serve(unsigned short port);
|
||||
// Connect to a server
|
||||
void Connect(Address address);
|
||||
bool Connected();
|
||||
|
||||
void Disconnect();
|
||||
u32 Receive(u16 &peer_id, SharedBuffer<u8> &data);
|
||||
|
||||
// Sets peer_id
|
||||
SharedBuffer<u8> GetFromBuffers(u16 &peer_id);
|
||||
|
||||
// The peer_id of sender is stored in peer_id
|
||||
// Return value: I guess this always throws an exception or
|
||||
// actually gets data
|
||||
// May call PeerHandler methods
|
||||
u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
|
||||
|
||||
// These will automatically package the data as an original or split
|
||||
void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||
void RunTimeouts(float dtime); // dummy
|
||||
u16 GetPeerID(){ return m_peer_id; }
|
||||
Address GetPeerAddress(u16 peer_id);
|
||||
float GetPeerAvgRTT(u16 peer_id);
|
||||
void DeletePeer(u16 peer_id);
|
||||
|
||||
private:
|
||||
void putEvent(ConnectionEvent &e);
|
||||
void processCommand(ConnectionCommand &c);
|
||||
void send(float dtime);
|
||||
void receive();
|
||||
void runTimeouts(float dtime);
|
||||
void serve(u16 port);
|
||||
void connect(Address address);
|
||||
void disconnect();
|
||||
void sendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||
void send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||
void sendAsPacket(u16 peer_id, u8 channelnum,
|
||||
// Send data as a packet; it will be wrapped in base header and
|
||||
// optionally to a reliable packet.
|
||||
void SendAsPacket(u16 peer_id, u8 channelnum,
|
||||
SharedBuffer<u8> data, bool reliable);
|
||||
void rawSendAsPacket(u16 peer_id, u8 channelnum,
|
||||
SharedBuffer<u8> data, bool reliable);
|
||||
void rawSend(const BufferedPacket &packet);
|
||||
Peer* getPeer(u16 peer_id);
|
||||
Peer* getPeerNoEx(u16 peer_id);
|
||||
core::list<Peer*> getPeers();
|
||||
bool getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst);
|
||||
// Returns next data from a buffer if possible
|
||||
// If found, returns true; if not, false.
|
||||
// If found, sets peer_id and dst
|
||||
bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
|
||||
SharedBuffer<u8> &dst);
|
||||
/*
|
||||
Processes a packet with the basic header stripped out.
|
||||
Parameters:
|
||||
packetdata: Data in packet (with no base headers)
|
||||
peer_id: peer id of the sender of the packet in question
|
||||
channelnum: channel on which the packet was sent
|
||||
reliable: true if recursing into a reliable packet
|
||||
*/
|
||||
SharedBuffer<u8> processPacket(Channel *channel,
|
||||
SharedBuffer<u8> packetdata, u16 peer_id,
|
||||
u8 channelnum, bool reliable);
|
||||
bool deletePeer(u16 peer_id, bool timeout);
|
||||
// Sends a raw packet
|
||||
void RawSend(const BufferedPacket &packet);
|
||||
|
||||
Queue<OutgoingPacket> m_outgoing_queue;
|
||||
MutexedQueue<ConnectionEvent> m_event_queue;
|
||||
MutexedQueue<ConnectionCommand> m_command_queue;
|
||||
|
||||
u32 m_protocol_id;
|
||||
u32 m_max_packet_size;
|
||||
float m_timeout;
|
||||
UDPSocket m_socket;
|
||||
u16 m_peer_id;
|
||||
|
||||
core::map<u16, Peer*> m_peers;
|
||||
JMutex m_peers_mutex;
|
||||
// May call PeerHandler methods
|
||||
void RunTimeouts(float dtime);
|
||||
|
||||
// Backwards compatibility
|
||||
PeerHandler *m_bc_peerhandler;
|
||||
int m_bc_receive_timeout;
|
||||
// Can throw a PeerNotFoundException
|
||||
Peer* GetPeer(u16 peer_id);
|
||||
// returns NULL if failed
|
||||
Peer* GetPeerNoEx(u16 peer_id);
|
||||
core::list<Peer*> GetPeers();
|
||||
|
||||
// Calls PeerHandler::deletingPeer
|
||||
// Returns false if peer was not found
|
||||
bool deletePeer(u16 peer_id, bool timeout);
|
||||
|
||||
void SetPeerID(u16 id){ m_peer_id = id; }
|
||||
u16 GetPeerID(){ return m_peer_id; }
|
||||
u32 GetProtocolID(){ return m_protocol_id; }
|
||||
|
||||
// For debug printing
|
||||
void PrintInfo(std::ostream &out);
|
||||
void PrintInfo();
|
||||
std::string getDesc();
|
||||
u16 m_indentation;
|
||||
|
||||
private:
|
||||
u32 m_protocol_id;
|
||||
float m_timeout;
|
||||
PeerHandler *m_peerhandler;
|
||||
core::map<u16, Peer*> m_peers;
|
||||
u16 m_peer_id;
|
||||
//bool m_waiting_new_peer_id;
|
||||
u32 m_max_packet_size;
|
||||
UDPSocket m_socket;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -44,6 +44,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#define PI 3.14159
|
||||
|
||||
// This is the same as in minecraft and everything else
|
||||
#define FOV_ANGLE (PI/2.5)
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's
|
||||
// going near the limit or not, so this is lower.
|
||||
|
||||
@@ -20,8 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_cao.h"
|
||||
#include "tile.h"
|
||||
#include "environment.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
|
||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||
|
||||
@@ -116,7 +114,7 @@ void TestCAO::step(float dtime, ClientEnvironment *env)
|
||||
if(m_node)
|
||||
{
|
||||
v3f rot = m_node->getRotation();
|
||||
//infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||
rot.Y += dtime * 180;
|
||||
m_node->setRotation(rot);
|
||||
}
|
||||
@@ -124,7 +122,7 @@ void TestCAO::step(float dtime, ClientEnvironment *env)
|
||||
|
||||
void TestCAO::processMessage(const std::string &data)
|
||||
{
|
||||
infostream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||
dstream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
u16 cmd;
|
||||
is>>cmd;
|
||||
@@ -208,35 +206,6 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr)
|
||||
// This is needed for changing the texture in the future
|
||||
m_node->setReadOnlyMaterials(true);
|
||||
updateNodePos();
|
||||
|
||||
/*
|
||||
Update image of node
|
||||
*/
|
||||
|
||||
// Create an inventory item to see what is its image
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
video::ITexture *texture = NULL;
|
||||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(is);
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
if(item)
|
||||
{
|
||||
texture = item->getImage();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": error deSerializing inventorystring \""
|
||||
<<m_inventorystring<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
// Set meshbuffer texture
|
||||
buf->getMaterial().setTexture(0, texture);
|
||||
}
|
||||
|
||||
void ItemCAO::removeFromScene()
|
||||
@@ -255,7 +224,22 @@ void ItemCAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v3s16 ItemCAO::getLightPosition()
|
||||
@@ -288,7 +272,7 @@ void ItemCAO::step(float dtime, ClientEnvironment *env)
|
||||
|
||||
void ItemCAO::processMessage(const std::string &data)
|
||||
{
|
||||
infostream<<"ItemCAO: Got message"<<std::endl;
|
||||
dstream<<"ItemCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
@@ -302,7 +286,7 @@ void ItemCAO::processMessage(const std::string &data)
|
||||
|
||||
void ItemCAO::initialize(const std::string &data)
|
||||
{
|
||||
infostream<<"ItemCAO: Got init data"<<std::endl;
|
||||
dstream<<"ItemCAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
@@ -318,6 +302,49 @@ void ItemCAO::initialize(const std::string &data)
|
||||
}
|
||||
|
||||
updateNodePos();
|
||||
|
||||
/*
|
||||
Update image of node
|
||||
*/
|
||||
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
|
||||
|
||||
if(buf == NULL)
|
||||
return;
|
||||
|
||||
// Create an inventory item to see what is its image
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
video::ITexture *texture = NULL;
|
||||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(is);
|
||||
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
if(item)
|
||||
{
|
||||
texture = item->getImage();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": error deSerializing inventorystring \""
|
||||
<<m_inventorystring<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
// Set meshbuffer texture
|
||||
buf->getMaterial().setTexture(0, texture);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -403,7 +430,22 @@ void RatCAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v3s16 RatCAO::getLightPosition()
|
||||
@@ -432,7 +474,7 @@ void RatCAO::step(float dtime, ClientEnvironment *env)
|
||||
|
||||
void RatCAO::processMessage(const std::string &data)
|
||||
{
|
||||
//infostream<<"RatCAO: Got message"<<std::endl;
|
||||
//dstream<<"RatCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
@@ -449,7 +491,7 @@ void RatCAO::processMessage(const std::string &data)
|
||||
|
||||
void RatCAO::initialize(const std::string &data)
|
||||
{
|
||||
//infostream<<"RatCAO: Got init data"<<std::endl;
|
||||
//dstream<<"RatCAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
@@ -559,7 +601,22 @@ void Oerkki1CAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v3s16 Oerkki1CAO::getLightPosition()
|
||||
@@ -592,7 +649,7 @@ void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
||||
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||
|
||||
if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
|
||||
if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
|
||||
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
|
||||
{
|
||||
if(m_attack_interval.step(dtime, 0.5))
|
||||
@@ -656,7 +713,7 @@ void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
||||
|
||||
void Oerkki1CAO::processMessage(const std::string &data)
|
||||
{
|
||||
//infostream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
@@ -671,14 +728,14 @@ void Oerkki1CAO::processMessage(const std::string &data)
|
||||
}
|
||||
else if(cmd == 1)
|
||||
{
|
||||
//u16 damage = readU8(is);
|
||||
u16 damage = readU8(is);
|
||||
m_damage_visual_timer = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
void Oerkki1CAO::initialize(const std::string &data)
|
||||
{
|
||||
//infostream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
@@ -695,18 +752,6 @@ void Oerkki1CAO::initialize(const std::string &data)
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
|
||||
{
|
||||
m_damage_visual_timer = 1.0;
|
||||
|
||||
m_position += dir * BS;
|
||||
pos_translator.sharpen();
|
||||
pos_translator.update(m_position);
|
||||
updateNodePos();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
FireflyCAO
|
||||
*/
|
||||
@@ -788,7 +833,22 @@ void FireflyCAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = 255;
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v3s16 FireflyCAO::getLightPosition()
|
||||
@@ -817,7 +877,7 @@ void FireflyCAO::step(float dtime, ClientEnvironment *env)
|
||||
|
||||
void FireflyCAO::processMessage(const std::string &data)
|
||||
{
|
||||
//infostream<<"FireflyCAO: Got message"<<std::endl;
|
||||
//dstream<<"FireflyCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
@@ -834,7 +894,7 @@ void FireflyCAO::processMessage(const std::string &data)
|
||||
|
||||
void FireflyCAO::initialize(const std::string &data)
|
||||
{
|
||||
//infostream<<"FireflyCAO: Got init data"<<std::endl;
|
||||
//dstream<<"FireflyCAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
@@ -850,417 +910,3 @@ void FireflyCAO::initialize(const std::string &data)
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
/*
|
||||
MobV2CAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
MobV2CAO proto_MobV2CAO;
|
||||
|
||||
MobV2CAO::MobV2CAO():
|
||||
ClientActiveObject(0),
|
||||
m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
m_yaw(0),
|
||||
m_walking(false),
|
||||
m_walking_unset_timer(0),
|
||||
m_walk_timer(0),
|
||||
m_walk_frame(0),
|
||||
m_damage_visual_timer(0),
|
||||
m_last_light(0),
|
||||
m_shooting(0),
|
||||
m_shooting_unset_timer(0),
|
||||
m_sprite_size(BS,BS),
|
||||
m_sprite_y(0),
|
||||
m_bright_shooting(false),
|
||||
m_lock_full_brightness(false),
|
||||
m_player_hit_timer(0)
|
||||
{
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
|
||||
m_properties = new Settings;
|
||||
}
|
||||
|
||||
MobV2CAO::~MobV2CAO()
|
||||
{
|
||||
delete m_properties;
|
||||
}
|
||||
|
||||
ClientActiveObject* MobV2CAO::create()
|
||||
{
|
||||
return new MobV2CAO();
|
||||
}
|
||||
|
||||
void MobV2CAO::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
/*infostream<<"MobV2CAO::addToScene using texture_name="<<
|
||||
m_texture_name<<std::endl;*/
|
||||
std::string texture_string = "[makealpha2:128,0,0;128,128,0:";
|
||||
texture_string += m_texture_name;
|
||||
|
||||
scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
|
||||
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
||||
bill->setMaterialTexture(0, g_texturesource->getTextureRaw(texture_string));
|
||||
bill->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||
bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||
bill->setColor(video::SColor(255,0,0,0));
|
||||
bill->setVisible(false); /* Set visible when brightness is known */
|
||||
bill->setSize(m_sprite_size);
|
||||
if(m_sprite_type == "humanoid_1"){
|
||||
const float txp = 1./192;
|
||||
const float txs = txp*32;
|
||||
const float typ = 1./240;
|
||||
const float tys = typ*48;
|
||||
bill->setTCoords(0, v2f(txs*1, tys*1));
|
||||
bill->setTCoords(1, v2f(txs*1, tys*0));
|
||||
bill->setTCoords(2, v2f(txs*0, tys*0));
|
||||
bill->setTCoords(3, v2f(txs*0, tys*1));
|
||||
} else if(m_sprite_type == "simple"){
|
||||
const float txs = 1.0;
|
||||
const float tys = 1.0 / m_simple_anim_frames;
|
||||
bill->setTCoords(0, v2f(txs*1, tys*1));
|
||||
bill->setTCoords(1, v2f(txs*1, tys*0));
|
||||
bill->setTCoords(2, v2f(txs*0, tys*0));
|
||||
bill->setTCoords(3, v2f(txs*0, tys*1));
|
||||
} else {
|
||||
infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
m_node = bill;
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
void MobV2CAO::removeFromScene()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->drop();
|
||||
m_node->remove();
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
void MobV2CAO::updateLight(u8 light_at_pos)
|
||||
{
|
||||
if(m_lock_full_brightness)
|
||||
light_at_pos = 15;
|
||||
|
||||
m_last_light = light_at_pos;
|
||||
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
if(m_damage_visual_timer > 0)
|
||||
return;
|
||||
|
||||
if(m_shooting && m_bright_shooting)
|
||||
return;
|
||||
|
||||
/*if(light_at_pos <= 2){
|
||||
m_node->setVisible(false);
|
||||
return;
|
||||
}*/
|
||||
|
||||
m_node->setVisible(true);
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
m_node->setColor(color);
|
||||
}
|
||||
|
||||
v3s16 MobV2CAO::getLightPosition()
|
||||
{
|
||||
return floatToInt(m_position+v3f(0,0,0), BS);
|
||||
}
|
||||
|
||||
void MobV2CAO::updateNodePos()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
|
||||
}
|
||||
|
||||
void MobV2CAO::step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
scene::MyBillboardSceneNode *bill = m_node;
|
||||
if(!bill)
|
||||
return;
|
||||
|
||||
pos_translator.translate(dtime);
|
||||
|
||||
if(m_sprite_type == "humanoid_1"){
|
||||
scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
|
||||
if(!camera)
|
||||
return;
|
||||
v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
|
||||
cam_to_mob.normalize();
|
||||
int col = 0;
|
||||
if(cam_to_mob.Y > 0.75)
|
||||
col = 5;
|
||||
else if(cam_to_mob.Y < -0.75)
|
||||
col = 4;
|
||||
else{
|
||||
float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
|
||||
float dir = mob_dir - m_yaw;
|
||||
dir = wrapDegrees_180(dir);
|
||||
//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||
if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
|
||||
col = 2;
|
||||
else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
|
||||
col = 3;
|
||||
else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
|
||||
col = 0;
|
||||
else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
|
||||
col = 1;
|
||||
else
|
||||
col = 4;
|
||||
}
|
||||
|
||||
int row = 0;
|
||||
if(m_shooting){
|
||||
row = 3;
|
||||
} else if(m_walking){
|
||||
m_walk_timer += dtime;
|
||||
if(m_walk_timer >= 0.5){
|
||||
m_walk_frame = (m_walk_frame + 1) % 2;
|
||||
m_walk_timer = 0;
|
||||
}
|
||||
if(m_walk_frame == 0)
|
||||
row = 1;
|
||||
else
|
||||
row = 2;
|
||||
}
|
||||
|
||||
const float txp = 1./192;
|
||||
const float txs = txp*32;
|
||||
const float typ = 1./240;
|
||||
const float tys = typ*48;
|
||||
bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||
bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||
bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||
bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||
} else if(m_sprite_type == "simple"){
|
||||
m_walk_timer += dtime;
|
||||
if(m_walk_timer >= m_simple_anim_frametime){
|
||||
m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
|
||||
m_walk_timer = 0;
|
||||
}
|
||||
int col = 0;
|
||||
int row = m_walk_frame;
|
||||
const float txs = 1.0;
|
||||
const float tys = 1.0 / m_simple_anim_frames;
|
||||
bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||
bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||
bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||
bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||
} else {
|
||||
infostream<<"MobV2CAO::step(): Unknown sprite type \""
|
||||
<<m_sprite_type<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
updateNodePos();
|
||||
|
||||
/* Damage local player */
|
||||
if(m_player_hit_damage && m_player_hit_timer <= 0.0){
|
||||
LocalPlayer *player = env->getLocalPlayer();
|
||||
assert(player);
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||
|
||||
if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
|
||||
objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
|
||||
{
|
||||
env->damageLocalPlayer(m_player_hit_damage);
|
||||
m_player_hit_timer = m_player_hit_interval;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run timers */
|
||||
|
||||
m_player_hit_timer -= dtime;
|
||||
|
||||
if(m_damage_visual_timer >= 0){
|
||||
m_damage_visual_timer -= dtime;
|
||||
if(m_damage_visual_timer <= 0){
|
||||
infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_walking_unset_timer += dtime;
|
||||
if(m_walking_unset_timer >= 1.0){
|
||||
m_walking = false;
|
||||
}
|
||||
|
||||
m_shooting_unset_timer -= dtime;
|
||||
if(m_shooting_unset_timer <= 0.0){
|
||||
if(m_bright_shooting){
|
||||
u8 li = decode_light(m_last_light);
|
||||
video::SColor color(255,li,li,li);
|
||||
bill->setColor(color);
|
||||
m_bright_shooting = false;
|
||||
}
|
||||
m_shooting = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MobV2CAO::processMessage(const std::string &data)
|
||||
{
|
||||
//infostream<<"MobV2CAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
|
||||
// Move
|
||||
if(cmd == 0)
|
||||
{
|
||||
// pos
|
||||
m_position = readV3F1000(is);
|
||||
pos_translator.update(m_position);
|
||||
// yaw
|
||||
m_yaw = readF1000(is);
|
||||
|
||||
m_walking = true;
|
||||
m_walking_unset_timer = 0;
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
// Damage
|
||||
else if(cmd == 1)
|
||||
{
|
||||
//u16 damage = readU16(is);
|
||||
|
||||
/*u8 li = decode_light(m_last_light);
|
||||
if(li >= 100)
|
||||
li = 30;
|
||||
else
|
||||
li = 255;*/
|
||||
|
||||
/*video::SColor color(255,255,0,0);
|
||||
m_node->setColor(color);
|
||||
|
||||
m_damage_visual_timer = 0.2;*/
|
||||
}
|
||||
// Trigger shooting
|
||||
else if(cmd == 2)
|
||||
{
|
||||
// length
|
||||
m_shooting_unset_timer = readF1000(is);
|
||||
// bright?
|
||||
m_bright_shooting = readU8(is);
|
||||
if(m_bright_shooting){
|
||||
u8 li = 255;
|
||||
video::SColor color(255,li,li,li);
|
||||
m_node->setColor(color);
|
||||
}
|
||||
|
||||
m_shooting = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MobV2CAO::initialize(const std::string &data)
|
||||
{
|
||||
//infostream<<"MobV2CAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// version
|
||||
u8 version = readU8(is);
|
||||
// check version
|
||||
if(version != 0){
|
||||
infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
decompressZlib(is, tmp_os);
|
||||
std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
|
||||
m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
|
||||
|
||||
infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
|
||||
m_properties->writeLines(infostream);
|
||||
|
||||
m_properties->setDefault("looks", "dummy_default");
|
||||
m_properties->setDefault("yaw", "0");
|
||||
m_properties->setDefault("pos", "(0,0,0)");
|
||||
m_properties->setDefault("player_hit_damage", "0");
|
||||
m_properties->setDefault("player_hit_distance", "1.5");
|
||||
m_properties->setDefault("player_hit_interval", "1.5");
|
||||
|
||||
setLooks(m_properties->get("looks"));
|
||||
m_yaw = m_properties->getFloat("yaw");
|
||||
m_position = m_properties->getV3F("pos");
|
||||
m_player_hit_damage = m_properties->getS32("player_hit_damage");
|
||||
m_player_hit_distance = m_properties->getFloat("player_hit_distance");
|
||||
m_player_hit_interval = m_properties->getFloat("player_hit_interval");
|
||||
|
||||
pos_translator.init(m_position);
|
||||
}
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
|
||||
{
|
||||
video::SColor color(255,255,0,0);
|
||||
m_node->setColor(color);
|
||||
|
||||
m_damage_visual_timer = 0.05;
|
||||
|
||||
m_position += dir * BS;
|
||||
pos_translator.sharpen();
|
||||
pos_translator.update(m_position);
|
||||
updateNodePos();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MobV2CAO::setLooks(const std::string &looks)
|
||||
{
|
||||
v2f selection_size = v2f(0.4, 0.4) * BS;
|
||||
float selection_y = 0 * BS;
|
||||
|
||||
if(looks == "dungeon_master"){
|
||||
m_texture_name = "dungeon_master.png";
|
||||
m_sprite_type = "humanoid_1";
|
||||
m_sprite_size = v2f(2, 3) * BS;
|
||||
m_sprite_y = 0.85 * BS;
|
||||
selection_size = v2f(0.4, 2.6) * BS;
|
||||
selection_y = -0.4 * BS;
|
||||
}
|
||||
else if(looks == "fireball"){
|
||||
m_texture_name = "fireball.png";
|
||||
m_sprite_type = "simple";
|
||||
m_sprite_size = v2f(1, 1) * BS;
|
||||
m_simple_anim_frames = 3;
|
||||
m_simple_anim_frametime = 0.1;
|
||||
m_lock_full_brightness = true;
|
||||
}
|
||||
else{
|
||||
m_texture_name = "stone.png";
|
||||
m_sprite_type = "simple";
|
||||
m_sprite_size = v2f(1, 1) * BS;
|
||||
m_simple_anim_frames = 3;
|
||||
m_simple_anim_frametime = 0.333;
|
||||
selection_size = v2f(0.4, 0.4) * BS;
|
||||
selection_y = 0 * BS;
|
||||
}
|
||||
|
||||
m_selection_box = core::aabbox3d<f32>(
|
||||
-selection_size.X, selection_y, -selection_size.X,
|
||||
selection_size.X, selection_y+selection_size.Y,
|
||||
selection_size.X);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "clientobject.h"
|
||||
#include "content_object.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
class Settings;
|
||||
#include "MyBillboardSceneNode.h"
|
||||
|
||||
/*
|
||||
SmoothTranslator
|
||||
@@ -33,19 +31,19 @@ class Settings;
|
||||
struct SmoothTranslator
|
||||
{
|
||||
v3f vect_old;
|
||||
v3f vect_show;
|
||||
v3f vect_aim;
|
||||
f32 anim_counter;
|
||||
f32 anim_time;
|
||||
f32 anim_time_counter;
|
||||
v3f vect_show;
|
||||
v3f vect_aim;
|
||||
|
||||
SmoothTranslator():
|
||||
vect_old(0,0,0),
|
||||
vect_show(0,0,0),
|
||||
vect_aim(0,0,0),
|
||||
anim_counter(0),
|
||||
anim_time(0),
|
||||
anim_time_counter(0)
|
||||
anim_time_counter(0),
|
||||
vect_show(0,0,0),
|
||||
vect_aim(0,0,0)
|
||||
{}
|
||||
|
||||
void init(v3f vect)
|
||||
@@ -53,14 +51,6 @@ struct SmoothTranslator
|
||||
vect_old = vect;
|
||||
vect_show = vect;
|
||||
vect_aim = vect;
|
||||
anim_counter = 0;
|
||||
anim_time = 0;
|
||||
anim_time_counter = 0;
|
||||
}
|
||||
|
||||
void sharpen()
|
||||
{
|
||||
init(vect_show);
|
||||
}
|
||||
|
||||
void update(v3f vect_new)
|
||||
@@ -84,16 +74,11 @@ struct SmoothTranslator
|
||||
if(anim_time > 0.001)
|
||||
moveratio = anim_time_counter / anim_time;
|
||||
// Move a bit less than should, to avoid oscillation
|
||||
moveratio = moveratio * 0.5;
|
||||
moveratio = moveratio * 0.8;
|
||||
if(moveratio > 1.5)
|
||||
moveratio = 1.5;
|
||||
vect_show = vect_old + vect_move * moveratio;
|
||||
}
|
||||
|
||||
bool is_moving()
|
||||
{
|
||||
return ((anim_time_counter / anim_time) < 1.4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -248,9 +233,6 @@ class Oerkki1CAO : public ClientActiveObject
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
@@ -304,78 +286,6 @@ class FireflyCAO : public ClientActiveObject
|
||||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
MobV2CAO
|
||||
*/
|
||||
|
||||
class MobV2CAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
MobV2CAO();
|
||||
virtual ~MobV2CAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_MOBV2;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create();
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
bool doShowSelectionBox(){return false;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
void setLooks(const std::string &looks);
|
||||
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::MyBillboardSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_texture_name;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
bool m_walking;
|
||||
float m_walking_unset_timer;
|
||||
float m_walk_timer;
|
||||
int m_walk_frame;
|
||||
float m_damage_visual_timer;
|
||||
u8 m_last_light;
|
||||
bool m_shooting;
|
||||
float m_shooting_unset_timer;
|
||||
v2f m_sprite_size;
|
||||
float m_sprite_y;
|
||||
bool m_bright_shooting;
|
||||
std::string m_sprite_type;
|
||||
int m_simple_anim_frames;
|
||||
float m_simple_anim_frametime;
|
||||
bool m_lock_full_brightness;
|
||||
int m_player_hit_damage;
|
||||
float m_player_hit_distance;
|
||||
float m_player_hit_interval;
|
||||
float m_player_hit_timer;
|
||||
|
||||
Settings *m_properties;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -297,24 +297,6 @@ InventoryItem *craft_get_result(InventoryItem **items)
|
||||
}
|
||||
}
|
||||
|
||||
// Locking 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[4] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||
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_LOCKABLE_CHEST, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Furnace
|
||||
{
|
||||
ItemSpec specs[9];
|
||||
@@ -505,7 +487,6 @@ void craft_set_creative_inventory(Player *player)
|
||||
CONTENT_CLAY,
|
||||
CONTENT_BRICK,
|
||||
CONTENT_TREE,
|
||||
CONTENT_WOOD,
|
||||
CONTENT_LEAVES,
|
||||
CONTENT_CACTUS,
|
||||
CONTENT_PAPYRUS,
|
||||
|
||||
@@ -72,8 +72,8 @@ std::string item_craft_get_image_name(const std::string &subname)
|
||||
else if(subname == "firefly")
|
||||
return "firefly.png";
|
||||
else if(subname == "apple")
|
||||
return "apple.png^[forcesingle";
|
||||
else if(subname == "apple_iron")
|
||||
return "apple.png";
|
||||
else if(subname == "apple_iron")
|
||||
return "apple_iron.png";
|
||||
else
|
||||
return "cloud.png"; // just something
|
||||
|
||||
@@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "main.h" // For g_settings and g_texturesource
|
||||
#include "mineral.h"
|
||||
#include "mapblock_mesh.h" // For MapBlock_LightColor()
|
||||
#include "settings.h"
|
||||
|
||||
#ifndef SERVER
|
||||
// Create a cuboid.
|
||||
@@ -129,10 +128,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
/*
|
||||
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");
|
||||
bool invisible_stone = g_settings->getBool("invisible_stone");
|
||||
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");
|
||||
bool invisible_stone = g_settings.getBool("invisible_stone");
|
||||
|
||||
float node_liquid_level = 1.0;
|
||||
if(new_style_water)
|
||||
@@ -143,6 +142,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
// New-style leaves material
|
||||
video::SMaterial material_leaves1;
|
||||
material_leaves1.setFlag(video::EMF_LIGHTING, false);
|
||||
//material_leaves1.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
@@ -199,18 +199,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
g_texturesource->getTextureId("apple.png"));
|
||||
material_apple.setTexture(0, pa_apple.atlas);
|
||||
|
||||
|
||||
// Sapling material
|
||||
video::SMaterial material_sapling;
|
||||
material_sapling.setFlag(video::EMF_LIGHTING, false);
|
||||
material_sapling.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_sapling.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_sapling.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
AtlasPointer pa_sapling = g_texturesource->getTexture(
|
||||
g_texturesource->getTextureId("sapling.png"));
|
||||
material_sapling.setTexture(0, pa_sapling.atlas);
|
||||
|
||||
|
||||
// junglegrass material
|
||||
video::SMaterial material_junglegrass;
|
||||
material_junglegrass.setFlag(video::EMF_LIGHTING, false);
|
||||
@@ -228,54 +216,25 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
v3s16 p(x,y,z);
|
||||
|
||||
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes+p);
|
||||
|
||||
|
||||
/*
|
||||
Add torches to mesh
|
||||
*/
|
||||
if(n.getContent() == CONTENT_TORCH)
|
||||
{
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
|
||||
const char *texturename = "torch.png";
|
||||
if(dir == v3s16(0,-1,0)){
|
||||
texturename = "torch_on_floor.png";
|
||||
} else if(dir == v3s16(0,1,0)){
|
||||
texturename = "torch_on_ceiling.png";
|
||||
// For backwards compatibility
|
||||
} else if(dir == v3s16(0,0,0)){
|
||||
texturename = "torch_on_floor.png";
|
||||
} else {
|
||||
texturename = "torch.png";
|
||||
}
|
||||
|
||||
AtlasPointer ap = g_texturesource->getTexture(texturename);
|
||||
|
||||
// Set material
|
||||
video::SMaterial material;
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialType
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material.setTexture(0, ap.atlas);
|
||||
|
||||
video::SColor c(255,255,255,255);
|
||||
|
||||
// Wall at X+ of node
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
||||
ap.x0(), ap.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
||||
ap.x1(), ap.y1()),
|
||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
|
||||
ap.x1(), ap.y0()),
|
||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
|
||||
ap.x0(), ap.y0()),
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
|
||||
for(s32 i=0; i<4; i++)
|
||||
{
|
||||
if(dir == v3s16(1,0,0))
|
||||
@@ -294,6 +253,29 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
// Set material
|
||||
video::SMaterial material;
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialType
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
if(dir == v3s16(0,-1,0))
|
||||
material.setTexture(0,
|
||||
g_texturesource->getTextureRaw("torch_on_floor.png"));
|
||||
else if(dir == v3s16(0,1,0))
|
||||
material.setTexture(0,
|
||||
g_texturesource->getTextureRaw("torch_on_ceiling.png"));
|
||||
// For backwards compatibility
|
||||
else if(dir == v3s16(0,0,0))
|
||||
material.setTexture(0,
|
||||
g_texturesource->getTextureRaw("torch_on_floor.png"));
|
||||
else
|
||||
material.setTexture(0,
|
||||
g_texturesource->getTextureRaw("torch.png"));
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material, vertices, 4, indices, 6);
|
||||
@@ -303,18 +285,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
*/
|
||||
else if(n.getContent() == CONTENT_SIGN_WALL)
|
||||
{
|
||||
AtlasPointer ap = g_texturesource->getTexture("sign_wall.png");
|
||||
|
||||
// Set material
|
||||
video::SMaterial material;
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material.MaterialType
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material.setTexture(0, ap.atlas);
|
||||
|
||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
@@ -322,14 +292,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
// Wall at X+ of node
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y1()),
|
||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y1()),
|
||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y0()),
|
||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y0()),
|
||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
|
||||
};
|
||||
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
@@ -352,6 +318,19 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
// Set material
|
||||
video::SMaterial material;
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialType
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
material.setTexture(0,
|
||||
g_texturesource->getTextureRaw("sign_wall.png"));
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material, vertices, 4, indices, 6);
|
||||
@@ -364,9 +343,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
assert(content_features(n).special_material);
|
||||
video::SMaterial &liquid_material =
|
||||
*content_features(n).special_material;
|
||||
video::SMaterial &liquid_material_bfculled =
|
||||
*content_features(n).special_material2;
|
||||
|
||||
assert(content_features(n).special_atlas);
|
||||
AtlasPointer &pa_liquid1 =
|
||||
*content_features(n).special_atlas;
|
||||
@@ -519,10 +495,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
continue;
|
||||
|
||||
content_t neighbor_content = neighbor_contents[dir];
|
||||
ContentFeatures &n_feat = content_features(neighbor_content);
|
||||
|
||||
// Don't draw face if neighbor is blocking the view
|
||||
if(n_feat.solidness == 2)
|
||||
// Don't draw face if neighbor is not air or liquid
|
||||
if(neighbor_content != CONTENT_AIR
|
||||
&& content_liquid(neighbor_content) == false)
|
||||
continue;
|
||||
|
||||
bool neighbor_is_same_liquid = (neighbor_content == c_source
|
||||
@@ -533,15 +509,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
if(neighbor_is_same_liquid == true
|
||||
&& top_is_same_liquid == false)
|
||||
continue;
|
||||
|
||||
// Use backface culled material if neighbor doesn't have a
|
||||
// solidness of 0
|
||||
video::SMaterial *current_material = &liquid_material;
|
||||
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
|
||||
current_material = &liquid_material_bfculled;
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||
pa_liquid1.x0(), pa_liquid1.y1()),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||
@@ -602,17 +576,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
|
||||
// Do this to not cause glitches when two liquids are
|
||||
// side-by-side
|
||||
/*if(neighbor_is_same_liquid == false){
|
||||
if(neighbor_is_same_liquid == false){
|
||||
vertices[j].Pos.X *= 0.98;
|
||||
vertices[j].Pos.Z *= 0.98;
|
||||
}*/
|
||||
}
|
||||
|
||||
vertices[j].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(*current_material, vertices, 4, indices, 6);
|
||||
collector.append(liquid_material, vertices, 4, indices, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -623,6 +597,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||
pa_liquid1.x0(), pa_liquid1.y1()),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||
@@ -677,6 +655,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||
pa_liquid1.x0(), pa_liquid1.y1()),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||
@@ -710,6 +692,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
pa_leaves1.x0(), pa_leaves1.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
@@ -928,6 +914,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
@@ -1031,13 +1021,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
||||
pa_junglegrass.x0(), pa_junglegrass.y1()),
|
||||
pa_papyrus.x0(), pa_papyrus.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
||||
pa_junglegrass.x1(), pa_junglegrass.y1()),
|
||||
pa_papyrus.x1(), pa_papyrus.y1()),
|
||||
video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
|
||||
pa_junglegrass.x1(), pa_junglegrass.y0()),
|
||||
pa_papyrus.x1(), pa_papyrus.y0()),
|
||||
video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
|
||||
pa_junglegrass.x0(), pa_junglegrass.y0()),
|
||||
pa_papyrus.x0(), pa_papyrus.y0()),
|
||||
};
|
||||
|
||||
if(j == 0)
|
||||
@@ -1074,6 +1064,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
}
|
||||
else if(n.getContent() == CONTENT_RAIL)
|
||||
{
|
||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
bool is_rail_x [] = { false, false }; /* x-1, x+1 */
|
||||
bool is_rail_z [] = { false, false }; /* z-1, z+1 */
|
||||
|
||||
@@ -1091,25 +1084,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
if(n_plus_z.getContent() == CONTENT_RAIL)
|
||||
is_rail_z[1] = true;
|
||||
|
||||
int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
|
||||
|
||||
// Assign textures
|
||||
const char *texturename = "rail.png";
|
||||
if(adjacencies < 2)
|
||||
texturename = "rail.png";
|
||||
else if(adjacencies == 2)
|
||||
float d = (float)BS/16;
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
|
||||
texturename = "rail.png";
|
||||
else
|
||||
texturename = "rail_curved.png";
|
||||
}
|
||||
else if(adjacencies == 3)
|
||||
texturename = "rail_t_junction.png";
|
||||
else if(adjacencies == 4)
|
||||
texturename = "rail_crossing.png";
|
||||
|
||||
AtlasPointer ap = g_texturesource->getTexture(texturename);
|
||||
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
||||
0, 1),
|
||||
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
||||
1, 1),
|
||||
video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
||||
1, 0),
|
||||
video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
||||
0, 0),
|
||||
};
|
||||
|
||||
video::SMaterial material_rail;
|
||||
material_rail.setFlag(video::EMF_LIGHTING, false);
|
||||
@@ -1118,23 +1104,23 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
material_rail.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_rail.MaterialType
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material_rail.setTexture(0, ap.atlas);
|
||||
|
||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
|
||||
|
||||
float d = (float)BS/16;
|
||||
video::S3DVertex vertices[4] =
|
||||
// Assign textures
|
||||
if(adjacencies < 2)
|
||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
|
||||
else if(adjacencies == 2)
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y0()),
|
||||
video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y0()),
|
||||
};
|
||||
if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
|
||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
|
||||
else
|
||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_curved.png"));
|
||||
}
|
||||
else if(adjacencies == 3)
|
||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_t_junction.png"));
|
||||
else if(adjacencies == 4)
|
||||
material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_crossing.png"));
|
||||
|
||||
// Rotate textures
|
||||
int angle = 0;
|
||||
@@ -1181,17 +1167,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
collector.append(material_rail, vertices, 4, indices, 6);
|
||||
}
|
||||
else if (n.getContent() == CONTENT_LADDER) {
|
||||
AtlasPointer ap = g_texturesource->getTexture("ladder.png");
|
||||
|
||||
// Set material
|
||||
video::SMaterial material_ladder;
|
||||
material_ladder.setFlag(video::EMF_LIGHTING, false);
|
||||
material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material_ladder.setTexture(0, ap.atlas);
|
||||
|
||||
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
|
||||
video::SColor c(255,l,l,l);
|
||||
|
||||
@@ -1200,14 +1175,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
// Assume wall is at X+
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y1()),
|
||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y1()),
|
||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y0()),
|
||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y0()),
|
||||
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
|
||||
};
|
||||
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
@@ -1230,6 +1201,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
video::SMaterial material_ladder;
|
||||
material_ladder.setFlag(video::EMF_LIGHTING, false);
|
||||
material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material_ladder.setTexture(0, g_texturesource->getTextureRaw("ladder.png"));
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material_ladder, vertices, 4, indices, 6);
|
||||
@@ -1284,55 +1263,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
collector.append(material_apple, vertices, 4, indices, 6);
|
||||
}
|
||||
}
|
||||
else if(n.getContent() == CONTENT_SAPLING) {
|
||||
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
for(u32 j=0; j<4; j++)
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
||||
pa_sapling.x0(), pa_sapling.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
||||
pa_sapling.x1(), pa_sapling.y1()),
|
||||
video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
|
||||
pa_sapling.x1(), pa_sapling.y0()),
|
||||
video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
|
||||
pa_sapling.x0(), pa_sapling.y0()),
|
||||
};
|
||||
|
||||
if(j == 0)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(45);
|
||||
}
|
||||
else if(j == 1)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(-45);
|
||||
}
|
||||
else if(j == 2)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(135);
|
||||
}
|
||||
else if(j == 3)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(-135);
|
||||
}
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material_sapling, vertices, 4, indices, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_mapnode.h"
|
||||
#include "mapnode.h"
|
||||
#include "content_nodemeta.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define WATER_ALPHA 160
|
||||
|
||||
@@ -104,10 +103,9 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
|
||||
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");
|
||||
bool opaque_water = g_settings->getBool("opaque_water");
|
||||
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");
|
||||
|
||||
content_t i;
|
||||
ContentFeatures *f = NULL;
|
||||
@@ -118,7 +116,6 @@ void content_mapnode_init()
|
||||
f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
f->often_contains_mineral = true;
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
if(invisible_stone)
|
||||
@@ -221,7 +218,6 @@ void content_mapnode_init()
|
||||
i = CONTENT_JUNGLEGRASS;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("junglegrass.png");
|
||||
f->used_texturenames["junglegrass.png"] = true;
|
||||
f->light_propagates = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
//f->is_ground_content = true;
|
||||
@@ -240,16 +236,12 @@ void content_mapnode_init()
|
||||
if(new_style_leaves)
|
||||
{
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->visual_solidness = 1;
|
||||
f->setAllTextures("leaves.png");
|
||||
f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
f->setAllTextures("[noalpha:leaves.png");
|
||||
}
|
||||
f->extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
|
||||
f->extra_dug_item_rarity = 20;
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
|
||||
|
||||
@@ -267,7 +259,6 @@ void content_mapnode_init()
|
||||
i = CONTENT_PAPYRUS;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("papyrus.png");
|
||||
f->used_texturenames["papyrus.png"] = true;
|
||||
f->light_propagates = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->is_ground_content = true;
|
||||
@@ -296,8 +287,6 @@ void content_mapnode_init()
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->visual_solidness = 1;
|
||||
f->setAllTextures("glass.png");
|
||||
f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
|
||||
|
||||
@@ -310,13 +299,11 @@ void content_mapnode_init()
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->air_equivalent = true; // grass grows underneath
|
||||
f->setInventoryTexture("fence.png");
|
||||
f->used_texturenames["fence.png"] = true;
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
|
||||
|
||||
i = CONTENT_RAIL;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("rail.png");
|
||||
f->used_texturenames["rail.png"] = true;
|
||||
f->light_propagates = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->is_ground_content = true;
|
||||
@@ -329,7 +316,6 @@ void content_mapnode_init()
|
||||
i = CONTENT_LADDER;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("ladder.png");
|
||||
f->used_texturenames["ladder.png"] = true;
|
||||
f->light_propagates = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->is_ground_content = true;
|
||||
@@ -398,10 +384,7 @@ void content_mapnode_init()
|
||||
f->liquid_alternative_flowing = CONTENT_WATER;
|
||||
f->liquid_alternative_source = CONTENT_WATERSOURCE;
|
||||
f->liquid_viscosity = WATER_VISC;
|
||||
#ifndef SERVER
|
||||
if(!opaque_water)
|
||||
f->vertex_alpha = WATER_ALPHA;
|
||||
f->post_effect_color = video::SColor(64, 100, 100, 200);
|
||||
f->vertex_alpha = WATER_ALPHA;
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// Flowing water material
|
||||
@@ -410,20 +393,12 @@ void content_mapnode_init()
|
||||
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
|
||||
if(!opaque_water)
|
||||
f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||
f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||
AtlasPointer *pa_water1 = new AtlasPointer(g_texturesource->getTexture(
|
||||
g_texturesource->getTextureId("water.png")));
|
||||
f->special_material->setTexture(0, pa_water1->atlas);
|
||||
|
||||
// Flowing water material, backface culled
|
||||
f->special_material2 = new video::SMaterial;
|
||||
*f->special_material2 = *f->special_material;
|
||||
f->special_material2->setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||
|
||||
f->special_atlas = pa_water1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_WATERSOURCE;
|
||||
f = &content_features(i);
|
||||
@@ -436,18 +411,15 @@ void content_mapnode_init()
|
||||
else // old style
|
||||
{
|
||||
f->solidness = 1;
|
||||
#ifndef SERVER
|
||||
|
||||
TileSpec t;
|
||||
if(g_texturesource)
|
||||
t.texture = g_texturesource->getTexture("water.png");
|
||||
|
||||
if(!opaque_water){
|
||||
t.alpha = WATER_ALPHA;
|
||||
t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||
}
|
||||
t.alpha = WATER_ALPHA;
|
||||
t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
f->setAllTiles(t);
|
||||
#endif
|
||||
}
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
@@ -460,13 +432,10 @@ void content_mapnode_init()
|
||||
f->liquid_alternative_flowing = CONTENT_WATER;
|
||||
f->liquid_alternative_source = CONTENT_WATERSOURCE;
|
||||
f->liquid_viscosity = WATER_VISC;
|
||||
#ifndef SERVER
|
||||
if(!opaque_water)
|
||||
f->vertex_alpha = WATER_ALPHA;
|
||||
f->post_effect_color = video::SColor(64, 100, 100, 200);
|
||||
f->vertex_alpha = WATER_ALPHA;
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// New-style water source material (mostly unused)
|
||||
// Flowing water material
|
||||
f->special_material = new video::SMaterial;
|
||||
f->special_material->setFlag(video::EMF_LIGHTING, false);
|
||||
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
@@ -478,17 +447,15 @@ void content_mapnode_init()
|
||||
f->special_material->setTexture(0, pa_water1->atlas);
|
||||
f->special_atlas = pa_water1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_LAVA;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
||||
f->used_texturenames["lava.png"] = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = false;
|
||||
f->light_source = LIGHT_MAX-1;
|
||||
f->solidness = 0; // Drawn separately, makes no faces
|
||||
f->visual_solidness = 1; // Does not completely cover block boundaries
|
||||
f->visual_solidness = 2;
|
||||
f->walkable = false;
|
||||
f->pointable = false;
|
||||
f->diggable = false;
|
||||
@@ -498,8 +465,6 @@ void content_mapnode_init()
|
||||
f->liquid_alternative_source = CONTENT_LAVASOURCE;
|
||||
f->liquid_viscosity = LAVA_VISC;
|
||||
f->damage_per_second = 4*2;
|
||||
#ifndef SERVER
|
||||
f->post_effect_color = video::SColor(192, 255, 64, 0);
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// Flowing lava material
|
||||
@@ -509,25 +474,16 @@ void content_mapnode_init()
|
||||
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
|
||||
f->special_material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
AtlasPointer *pa_lava1 = new AtlasPointer(
|
||||
g_texturesource->getTexture(
|
||||
g_texturesource->getTextureId("lava.png")));
|
||||
f->special_material->setTexture(0, pa_lava1->atlas);
|
||||
|
||||
// Flowing lava material, backface culled
|
||||
f->special_material2 = new video::SMaterial;
|
||||
*f->special_material2 = *f->special_material;
|
||||
f->special_material2->setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||
|
||||
f->special_atlas = pa_lava1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_LAVASOURCE;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
||||
f->used_texturenames["ladder.png"] = true;
|
||||
if(new_style_water)
|
||||
{
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
@@ -535,7 +491,7 @@ void content_mapnode_init()
|
||||
else // old style
|
||||
{
|
||||
f->solidness = 2;
|
||||
#ifndef SERVER
|
||||
|
||||
TileSpec t;
|
||||
if(g_texturesource)
|
||||
t.texture = g_texturesource->getTexture("lava.png");
|
||||
@@ -544,7 +500,6 @@ void content_mapnode_init()
|
||||
//t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||
//t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
f->setAllTiles(t);
|
||||
#endif
|
||||
}
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = false;
|
||||
@@ -559,11 +514,9 @@ void content_mapnode_init()
|
||||
f->liquid_alternative_source = CONTENT_LAVASOURCE;
|
||||
f->liquid_viscosity = LAVA_VISC;
|
||||
f->damage_per_second = 4*2;
|
||||
#ifndef SERVER
|
||||
f->post_effect_color = video::SColor(192, 255, 64, 0);
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// New-style lava source material (mostly unused)
|
||||
// Flowing lava material
|
||||
f->special_material = new video::SMaterial;
|
||||
f->special_material->setFlag(video::EMF_LIGHTING, false);
|
||||
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
@@ -574,18 +527,12 @@ void content_mapnode_init()
|
||||
g_texturesource->getTexture(
|
||||
g_texturesource->getTextureId("lava.png")));
|
||||
f->special_material->setTexture(0, pa_lava1->atlas);
|
||||
|
||||
f->special_atlas = pa_lava1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_TORCH;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("torch_on_floor.png");
|
||||
f->used_texturenames["torch_on_floor.png"] = true;
|
||||
f->used_texturenames["torch_on_ceiling.png"] = true;
|
||||
f->used_texturenames["torch_on_floor.png"] = true;
|
||||
f->used_texturenames["torch.png"] = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
f->sunlight_propagates = true;
|
||||
@@ -600,7 +547,6 @@ void content_mapnode_init()
|
||||
i = CONTENT_SIGN_WALL;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("sign_wall.png");
|
||||
f->used_texturenames["sign_wall.png"] = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
f->sunlight_propagates = true;
|
||||
@@ -627,20 +573,6 @@ void content_mapnode_init()
|
||||
f->initial_metadata = new ChestNodeMetadata();
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
|
||||
i = CONTENT_LOCKABLE_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_lock.png"); // Z-
|
||||
f->setInventoryTexture("chest_lock.png");
|
||||
//f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
if(f->initial_metadata == NULL)
|
||||
f->initial_metadata = new LockingChestNodeMetadata();
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
|
||||
i = CONTENT_FURNACE;
|
||||
f = &content_features(i);
|
||||
f->param_type = CPT_FACEDIR_SIMPLE;
|
||||
@@ -697,24 +629,10 @@ void content_mapnode_init()
|
||||
f->setInventoryTexture("nc_rb.png");
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 3.0);
|
||||
|
||||
i = CONTENT_SAPLING;
|
||||
f = &content_features(i);
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->setAllTextures("sapling.png");
|
||||
f->setInventoryTexture("sapling.png");
|
||||
f->used_texturenames["sapling.png"] = true;
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f->light_propagates = true;
|
||||
f->air_equivalent = false;
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->walkable = false;
|
||||
f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
|
||||
|
||||
i = CONTENT_APPLE;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("apple.png");
|
||||
f->used_texturenames["apple.png"] = true;
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
f->sunlight_propagates = true;
|
||||
|
||||
@@ -48,7 +48,6 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
|
||||
#define CONTENT_SIGN_WALL 14
|
||||
#define CONTENT_CHEST 15
|
||||
#define CONTENT_FURNACE 16
|
||||
#define CONTENT_LOCKABLE_CHEST 17
|
||||
|
||||
#define CONTENT_FENCE 21
|
||||
|
||||
@@ -85,7 +84,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
|
||||
#define CONTENT_NC 0x817
|
||||
#define CONTENT_NC_RB 0x818
|
||||
#define CONTENT_APPLE 0x819
|
||||
#define CONTENT_SAPLING 0x820
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_nodemeta.h"
|
||||
#include "inventory.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
SignNodeMetadata
|
||||
@@ -118,70 +117,6 @@ std::string ChestNodeMetadata::getInventoryDrawSpecString()
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
|
||||
/*
|
||||
LockingChestNodeMetadata
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
LockingChestNodeMetadata proto_LockingChestNodeMetadata;
|
||||
|
||||
LockingChestNodeMetadata::LockingChestNodeMetadata()
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), create);
|
||||
|
||||
m_inventory = new Inventory();
|
||||
m_inventory->addList("0", 8*4);
|
||||
}
|
||||
LockingChestNodeMetadata::~LockingChestNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
u16 LockingChestNodeMetadata::typeId() const
|
||||
{
|
||||
return CONTENT_LOCKABLE_CHEST;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::create(std::istream &is)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata();
|
||||
d->setOwner(deSerializeString(is));
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::clone()
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata();
|
||||
*d->m_inventory = *m_inventory;
|
||||
return d;
|
||||
}
|
||||
void LockingChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
os<<serializeString(m_text);
|
||||
m_inventory->serialize(os);
|
||||
}
|
||||
std::string LockingChestNodeMetadata::infoText()
|
||||
{
|
||||
return "Locking Chest";
|
||||
}
|
||||
bool LockingChestNodeMetadata::nodeRemovalDisabled()
|
||||
{
|
||||
/*
|
||||
Disable removal if chest contains something
|
||||
*/
|
||||
InventoryList *list = m_inventory->getList("0");
|
||||
if(list == NULL)
|
||||
return false;
|
||||
if(list->getUsedSlots() == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
|
||||
{
|
||||
return
|
||||
"invsize[8,9;]"
|
||||
"list[current_name;0;0,0;8,4;]"
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
|
||||
/*
|
||||
FurnaceNodeMetadata
|
||||
*/
|
||||
@@ -288,12 +223,12 @@ bool FurnaceNodeMetadata::nodeRemovalDisabled()
|
||||
}
|
||||
void FurnaceNodeMetadata::inventoryModified()
|
||||
{
|
||||
infostream<<"Furnace inventory modification callback"<<std::endl;
|
||||
dstream<<"Furnace inventory modification callback"<<std::endl;
|
||||
}
|
||||
bool FurnaceNodeMetadata::step(float dtime)
|
||||
{
|
||||
if(dtime > 60.0)
|
||||
infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
|
||||
dstream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
|
||||
// Update at a fixed frequency
|
||||
const float interval = 2.0;
|
||||
m_step_accumulator += dtime;
|
||||
@@ -303,7 +238,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
||||
m_step_accumulator -= interval;
|
||||
dtime = interval;
|
||||
|
||||
//infostream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||
//dstream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||
|
||||
InventoryList *dst_list = m_inventory->getList("dst");
|
||||
assert(dst_list);
|
||||
@@ -335,7 +270,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
||||
*/
|
||||
if(m_fuel_time < m_fuel_totaltime)
|
||||
{
|
||||
//infostream<<"Furnace is active"<<std::endl;
|
||||
//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
|
||||
@@ -370,7 +305,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
||||
break;
|
||||
}
|
||||
|
||||
//infostream<<"Furnace is out of fuel"<<std::endl;
|
||||
//dstream<<"Furnace is out of fuel"<<std::endl;
|
||||
|
||||
InventoryList *fuel_list = m_inventory->getList("fuel");
|
||||
assert(fuel_list);
|
||||
@@ -455,7 +390,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
||||
}
|
||||
else
|
||||
{
|
||||
//infostream<<"No fuel found"<<std::endl;
|
||||
//dstream<<"No fuel found"<<std::endl;
|
||||
// No fuel, stop loop.
|
||||
m_step_accumulator = 0;
|
||||
break;
|
||||
|
||||
@@ -62,29 +62,6 @@ class ChestNodeMetadata : public NodeMetadata
|
||||
Inventory *m_inventory;
|
||||
};
|
||||
|
||||
class LockingChestNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
LockingChestNodeMetadata();
|
||||
~LockingChestNodeMetadata();
|
||||
|
||||
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();
|
||||
|
||||
virtual std::string getOwner(){ return m_text; }
|
||||
virtual void setOwner(std::string t){ m_text = t; }
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
std::string m_text;
|
||||
};
|
||||
|
||||
class FurnaceNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define ACTIVEOBJECT_TYPE_RAT 3
|
||||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
||||
#define ACTIVEOBJECT_TYPE_MOBV2 6
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,30 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_sao.h"
|
||||
#include "collision.h"
|
||||
#include "environment.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
/* Some helper functions */
|
||||
|
||||
// Y is copied, X and Z change is limited
|
||||
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
||||
{
|
||||
v3f d_wanted = target_speed - speed;
|
||||
d_wanted.Y = 0;
|
||||
f32 dl_wanted = d_wanted.getLength();
|
||||
f32 dl = dl_wanted;
|
||||
if(dl > max_increase)
|
||||
dl = max_increase;
|
||||
|
||||
v3f d = d_wanted.normalize() * dl;
|
||||
|
||||
speed.X += d.X;
|
||||
speed.Z += d.Z;
|
||||
speed.Y = target_speed.Y;
|
||||
}
|
||||
|
||||
/*
|
||||
TestSAO
|
||||
*/
|
||||
@@ -85,6 +64,7 @@ void TestSAO::step(float dtime, bool send_recommended)
|
||||
if(m_timer1 < 0.0)
|
||||
{
|
||||
m_timer1 += 0.125;
|
||||
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
|
||||
|
||||
std::string data;
|
||||
|
||||
@@ -131,15 +111,13 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
if(version != 0)
|
||||
return NULL;
|
||||
std::string inventorystring = deSerializeString(is);
|
||||
infostream<<"ItemSAO::create(): Creating item \""
|
||||
dstream<<"ItemSAO::create(): Creating item \""
|
||||
<<inventorystring<<"\""<<std::endl;
|
||||
return new ItemSAO(env, id, pos, inventorystring);
|
||||
}
|
||||
|
||||
void ItemSAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG);
|
||||
|
||||
assert(m_env);
|
||||
|
||||
const float interval = 0.2;
|
||||
@@ -208,7 +186,7 @@ std::string ItemSAO::getClientInitializationData()
|
||||
|
||||
std::string ItemSAO::getStaticData()
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
dstream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[1];
|
||||
// version
|
||||
@@ -224,14 +202,14 @@ InventoryItem * ItemSAO::createInventoryItem()
|
||||
try{
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
return item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<": serialization error: "
|
||||
dstream<<__FUNCTION_NAME<<": serialization error: "
|
||||
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
@@ -239,7 +217,7 @@ InventoryItem * ItemSAO::createInventoryItem()
|
||||
|
||||
void ItemSAO::rightClick(Player *player)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
dstream<<__FUNCTION_NAME<<std::endl;
|
||||
InventoryItem *item = createInventoryItem();
|
||||
if(item == NULL)
|
||||
return;
|
||||
@@ -294,8 +272,6 @@ ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
|
||||
void RatSAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
ScopeProfiler sp2(g_profiler, "RatSAO::step avg", SPT_AVG);
|
||||
|
||||
assert(m_env);
|
||||
|
||||
if(m_is_active == false)
|
||||
@@ -428,7 +404,7 @@ std::string RatSAO::getClientInitializationData()
|
||||
|
||||
std::string RatSAO::getStaticData()
|
||||
{
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
@@ -446,6 +422,23 @@ InventoryItem* RatSAO::createPickedUpItem()
|
||||
Oerkki1SAO
|
||||
*/
|
||||
|
||||
// Y is copied, X and Z change is limited
|
||||
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
||||
{
|
||||
v3f d_wanted = target_speed - speed;
|
||||
d_wanted.Y = 0;
|
||||
f32 dl_wanted = d_wanted.getLength();
|
||||
f32 dl = dl_wanted;
|
||||
if(dl > max_increase)
|
||||
dl = max_increase;
|
||||
|
||||
v3f d = d_wanted.normalize() * dl;
|
||||
|
||||
speed.X += d.X;
|
||||
speed.Z += d.Z;
|
||||
speed.Y = target_speed.Y;
|
||||
}
|
||||
|
||||
// Prototype
|
||||
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
||||
|
||||
@@ -485,8 +478,6 @@ ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
|
||||
void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
ScopeProfiler sp2(g_profiler, "Oerkki1SAO::step avg", SPT_AVG);
|
||||
|
||||
assert(m_env);
|
||||
|
||||
if(m_is_active == false)
|
||||
@@ -529,14 +520,13 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||
Player *player = *i;
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||
if(dist < BS*0.6)
|
||||
if(dist < BS*1.45)
|
||||
{
|
||||
m_removed = true;
|
||||
return;
|
||||
player_is_too_close = true;
|
||||
near_player_pos = playerpos;
|
||||
break;
|
||||
}
|
||||
else if(dist < BS*15.0 && !player_is_too_close)
|
||||
else if(dist < BS*15.0)
|
||||
{
|
||||
player_is_close = true;
|
||||
near_player_pos = playerpos;
|
||||
@@ -627,7 +617,7 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||
m_touching_ground = moveresult.touching_ground;
|
||||
|
||||
// Do collision damage
|
||||
float tolerance = BS*30;
|
||||
float tolerance = BS*12;
|
||||
float factor = BS*0.5;
|
||||
v3f speed_diff = old_speed - m_speed_f;
|
||||
// Increase effect in X and Z
|
||||
@@ -675,7 +665,7 @@ std::string Oerkki1SAO::getClientInitializationData()
|
||||
|
||||
std::string Oerkki1SAO::getStaticData()
|
||||
{
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
@@ -684,32 +674,18 @@ std::string Oerkki1SAO::getStaticData()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername)
|
||||
u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir)
|
||||
{
|
||||
m_speed_f += dir*12*BS;
|
||||
|
||||
u16 amount = 5;
|
||||
/* See tool names in inventory.h */
|
||||
if(toolname == "WSword")
|
||||
amount = 10;
|
||||
if(toolname == "STSword")
|
||||
amount = 12;
|
||||
if(toolname == "SteelSword")
|
||||
amount = 16;
|
||||
if(toolname == "STAxe")
|
||||
amount = 7;
|
||||
if(toolname == "SteelAxe")
|
||||
amount = 9;
|
||||
if(toolname == "SteelPick")
|
||||
amount = 7;
|
||||
doDamage(amount);
|
||||
return 65536/100;
|
||||
}
|
||||
|
||||
void Oerkki1SAO::doDamage(u16 d)
|
||||
{
|
||||
infostream<<"oerkki damage: "<<d<<std::endl;
|
||||
dstream<<"oerkki damage: "<<d<<std::endl;
|
||||
|
||||
if(d < m_hp)
|
||||
{
|
||||
@@ -773,8 +749,6 @@ ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
|
||||
void FireflySAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
ScopeProfiler sp2(g_profiler, "FireflySAO::step avg", SPT_AVG);
|
||||
|
||||
assert(m_env);
|
||||
|
||||
if(m_is_active == false)
|
||||
@@ -899,7 +873,7 @@ std::string FireflySAO::getClientInitializationData()
|
||||
|
||||
std::string FireflySAO::getStaticData()
|
||||
{
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
@@ -912,581 +886,3 @@ InventoryItem* FireflySAO::createPickedUpItem()
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
MobV2SAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL);
|
||||
|
||||
MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||
Settings *init_properties):
|
||||
ServerActiveObject(env, id, pos),
|
||||
m_move_type("ground_nodes"),
|
||||
m_speed(0,0,0),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_oldpos(0,0,0),
|
||||
m_yaw(0),
|
||||
m_counter1(0),
|
||||
m_counter2(0),
|
||||
m_age(0),
|
||||
m_touching_ground(false),
|
||||
m_hp(10),
|
||||
m_walk_around(false),
|
||||
m_walk_around_timer(0),
|
||||
m_next_pos_exists(false),
|
||||
m_shoot_reload_timer(0),
|
||||
m_shooting(false),
|
||||
m_shooting_timer(0),
|
||||
m_falling(false),
|
||||
m_disturb_timer(100000),
|
||||
m_random_disturb_timer(0),
|
||||
m_shoot_y(0)
|
||||
{
|
||||
ServerActiveObject::registerType(getType(), create);
|
||||
|
||||
m_properties = new Settings();
|
||||
if(init_properties)
|
||||
m_properties->update(*init_properties);
|
||||
|
||||
m_properties->setV3F("pos", pos);
|
||||
|
||||
setPropertyDefaults();
|
||||
readProperties();
|
||||
}
|
||||
|
||||
MobV2SAO::~MobV2SAO()
|
||||
{
|
||||
delete m_properties;
|
||||
}
|
||||
|
||||
ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data)
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
Settings properties;
|
||||
properties.parseConfigLines(is, "MobArgsEnd");
|
||||
MobV2SAO *o = new MobV2SAO(env, id, pos, &properties);
|
||||
return o;
|
||||
}
|
||||
|
||||
std::string MobV2SAO::getStaticData()
|
||||
{
|
||||
updateProperties();
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
m_properties->writeLines(os);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string MobV2SAO::getClientInitializationData()
|
||||
{
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
|
||||
updateProperties();
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
|
||||
Settings client_properties;
|
||||
|
||||
/*client_properties.set("version", "0");
|
||||
client_properties.updateValue(*m_properties, "pos");
|
||||
client_properties.updateValue(*m_properties, "yaw");
|
||||
client_properties.updateValue(*m_properties, "hp");*/
|
||||
|
||||
// Just send everything for simplicity
|
||||
client_properties.update(*m_properties);
|
||||
|
||||
std::ostringstream os2(std::ios::binary);
|
||||
client_properties.writeLines(os2);
|
||||
compressZlib(os2.str(), os);
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bool checkFreePosition(Map *map, v3s16 p0, v3s16 size)
|
||||
{
|
||||
for(int dx=0; dx<size.X; dx++)
|
||||
for(int dy=0; dy<size.Y; dy++)
|
||||
for(int dz=0; dz<size.Z; dz++){
|
||||
v3s16 dp(dx, dy, dz);
|
||||
v3s16 p = p0 + dp;
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() != CONTENT_AIR)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkWalkablePosition(Map *map, v3s16 p0)
|
||||
{
|
||||
v3s16 p = p0 + v3s16(0,-1,0);
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() != CONTENT_AIR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size)
|
||||
{
|
||||
if(!checkFreePosition(map, p0, size))
|
||||
return false;
|
||||
if(!checkWalkablePosition(map, p0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void get_random_u32_array(u32 a[], u32 len)
|
||||
{
|
||||
u32 i, n;
|
||||
for(i=0; i<len; i++)
|
||||
a[i] = i;
|
||||
n = len;
|
||||
while(n > 1){
|
||||
u32 k = myrand() % n;
|
||||
n--;
|
||||
u32 temp = a[n];
|
||||
a[n] = a[k];
|
||||
a[k] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
static void explodeSquare(Map *map, v3s16 p0, v3s16 size)
|
||||
{
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
|
||||
for(int dx=0; dx<size.X; dx++)
|
||||
for(int dy=0; dy<size.Y; dy++)
|
||||
for(int dz=0; dz<size.Z; dz++){
|
||||
v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2);
|
||||
v3s16 p = p0 + dp;
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() == CONTENT_IGNORE)
|
||||
continue;
|
||||
//map->removeNodeWithEvent(p);
|
||||
map->removeNodeAndUpdate(p, modified_blocks);
|
||||
}
|
||||
|
||||
// Send a MEET_OTHER event
|
||||
MapEditEvent event;
|
||||
event.type = MEET_OTHER;
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
event.modified_blocks.insert(p, true);
|
||||
}
|
||||
map->dispatchEvent(&event);
|
||||
}
|
||||
|
||||
void MobV2SAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
ScopeProfiler sp2(g_profiler, "MobV2SAO::step avg", SPT_AVG);
|
||||
|
||||
assert(m_env);
|
||||
Map *map = &m_env->getMap();
|
||||
|
||||
m_age += dtime;
|
||||
|
||||
if(m_die_age >= 0.0 && m_age >= m_die_age){
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_random_disturb_timer += dtime;
|
||||
if(m_random_disturb_timer >= 5.0)
|
||||
{
|
||||
m_random_disturb_timer = 0;
|
||||
// Check connected players
|
||||
core::list<Player*> players = m_env->getPlayers(true);
|
||||
core::list<Player*>::Iterator i;
|
||||
for(i = players.begin();
|
||||
i != players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||
if(dist < BS*16)
|
||||
{
|
||||
if(myrand_range(0,3) == 0){
|
||||
actionstream<<"Mob id="<<m_id<<" at "
|
||||
<<PP(m_base_position/BS)
|
||||
<<" got randomly disturbed by "
|
||||
<<player->getName()<<std::endl;
|
||||
m_disturbing_player = player->getName();
|
||||
m_disturb_timer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player *disturbing_player =
|
||||
m_env->getPlayer(m_disturbing_player.c_str());
|
||||
v3f disturbing_player_off = v3f(0,1,0);
|
||||
v3f disturbing_player_norm = v3f(0,1,0);
|
||||
float disturbing_player_distance = 1000000;
|
||||
float disturbing_player_dir = 0;
|
||||
if(disturbing_player){
|
||||
disturbing_player_off =
|
||||
disturbing_player->getPosition() - m_base_position;
|
||||
disturbing_player_distance = disturbing_player_off.getLength();
|
||||
disturbing_player_norm = disturbing_player_off;
|
||||
disturbing_player_norm.normalize();
|
||||
disturbing_player_dir = 180./PI*atan2(disturbing_player_norm.Z,
|
||||
disturbing_player_norm.X);
|
||||
}
|
||||
|
||||
m_disturb_timer += dtime;
|
||||
|
||||
if(!m_falling)
|
||||
{
|
||||
m_shooting_timer -= dtime;
|
||||
if(m_shooting_timer <= 0.0 && m_shooting){
|
||||
m_shooting = false;
|
||||
|
||||
std::string shoot_type = m_properties->get("shoot_type");
|
||||
v3f shoot_pos(0,0,0);
|
||||
shoot_pos.Y += m_properties->getFloat("shoot_y") * BS;
|
||||
if(shoot_type == "fireball"){
|
||||
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||
dir.Y = m_shoot_y;
|
||||
dir.normalize();
|
||||
v3f speed = dir * BS * 10.0;
|
||||
v3f pos = m_base_position + shoot_pos;
|
||||
infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
|
||||
<<" shooting fireball from "<<PP(pos)
|
||||
<<" at speed "<<PP(speed)<<std::endl;
|
||||
Settings properties;
|
||||
properties.set("looks", "fireball");
|
||||
properties.setV3F("speed", speed);
|
||||
properties.setFloat("die_age", 5.0);
|
||||
properties.set("move_type", "constant_speed");
|
||||
properties.setFloat("hp", 1000);
|
||||
properties.set("lock_full_brightness", "true");
|
||||
properties.set("player_hit_damage", "9");
|
||||
properties.set("player_hit_distance", "2");
|
||||
properties.set("player_hit_interval", "1");
|
||||
ServerActiveObject *obj = new MobV2SAO(m_env, 0,
|
||||
pos, &properties);
|
||||
//m_env->addActiveObjectAsStatic(obj);
|
||||
m_env->addActiveObject(obj);
|
||||
} else {
|
||||
infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
|
||||
<<": Unknown shoot_type="<<shoot_type
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_shoot_reload_timer += dtime;
|
||||
|
||||
float reload_time = 15.0;
|
||||
if(m_disturb_timer <= 15.0)
|
||||
reload_time = 3.0;
|
||||
|
||||
bool shoot_without_player = false;
|
||||
if(m_properties->getBool("mindless_rage"))
|
||||
shoot_without_player = true;
|
||||
|
||||
if(!m_shooting && m_shoot_reload_timer >= reload_time &&
|
||||
!m_next_pos_exists &&
|
||||
(m_disturb_timer <= 60.0 || shoot_without_player))
|
||||
{
|
||||
m_shoot_y = 0;
|
||||
if(m_disturb_timer < 60.0 && disturbing_player &&
|
||||
disturbing_player_distance < 16*BS &&
|
||||
fabs(disturbing_player_norm.Y) < 0.8){
|
||||
m_yaw = disturbing_player_dir;
|
||||
sendPosition();
|
||||
m_shoot_y += disturbing_player_norm.Y;
|
||||
} else {
|
||||
m_shoot_y = 0.01 * myrand_range(-30,10);
|
||||
}
|
||||
m_shoot_reload_timer = 0.0;
|
||||
m_shooting = true;
|
||||
m_shooting_timer = 1.5;
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (2 = shooting)
|
||||
writeU8(os, 2);
|
||||
// time
|
||||
writeF1000(os, m_shooting_timer + 0.1);
|
||||
// bright?
|
||||
writeU8(os, true);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_move_type == "ground_nodes")
|
||||
{
|
||||
if(!m_shooting){
|
||||
m_walk_around_timer -= dtime;
|
||||
if(m_walk_around_timer <= 0.0){
|
||||
m_walk_around = !m_walk_around;
|
||||
if(m_walk_around)
|
||||
m_walk_around_timer = 0.1*myrand_range(10,50);
|
||||
else
|
||||
m_walk_around_timer = 0.1*myrand_range(30,70);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move */
|
||||
if(m_next_pos_exists){
|
||||
v3f pos_f = m_base_position;
|
||||
v3f next_pos_f = intToFloat(m_next_pos_i, BS);
|
||||
|
||||
v3f v = next_pos_f - pos_f;
|
||||
m_yaw = atan2(v.Z, v.X) / PI * 180;
|
||||
|
||||
v3f diff = next_pos_f - pos_f;
|
||||
v3f dir = diff;
|
||||
dir.normalize();
|
||||
float speed = BS * 0.5;
|
||||
if(m_falling)
|
||||
speed = BS * 3.0;
|
||||
dir *= dtime * speed;
|
||||
bool arrived = false;
|
||||
if(dir.getLength() > diff.getLength()){
|
||||
dir = diff;
|
||||
arrived = true;
|
||||
}
|
||||
pos_f += dir;
|
||||
m_base_position = pos_f;
|
||||
|
||||
if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
|
||||
m_next_pos_exists = false;
|
||||
}
|
||||
}
|
||||
|
||||
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if(m_size.X >= 2.5){
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
|
||||
if(!m_next_pos_exists){
|
||||
/* Check whether to drop down */
|
||||
if(checkFreePosition(map,
|
||||
pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){
|
||||
m_next_pos_i = pos_i + v3s16(0,-1,0);
|
||||
m_next_pos_exists = true;
|
||||
m_falling = true;
|
||||
} else {
|
||||
m_falling = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_walk_around)
|
||||
{
|
||||
if(!m_next_pos_exists){
|
||||
/* Find some position where to go next */
|
||||
v3s16 dps[3*3*3];
|
||||
int num_dps = 0;
|
||||
for(int dx=-1; dx<=1; dx++)
|
||||
for(int dy=-1; dy<=1; dy++)
|
||||
for(int dz=-1; dz<=1; dz++){
|
||||
if(dx == 0 && dy == 0)
|
||||
continue;
|
||||
if(dx != 0 && dz != 0 && dy != 0)
|
||||
continue;
|
||||
dps[num_dps++] = v3s16(dx,dy,dz);
|
||||
}
|
||||
u32 order[3*3*3];
|
||||
get_random_u32_array(order, num_dps);
|
||||
for(int i=0; i<num_dps; i++){
|
||||
v3s16 p = dps[order[i]] + pos_i;
|
||||
bool is_free = checkFreeAndWalkablePosition(map,
|
||||
p + pos_size_off, size_blocks);
|
||||
if(!is_free)
|
||||
continue;
|
||||
m_next_pos_i = p;
|
||||
m_next_pos_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_move_type == "constant_speed")
|
||||
{
|
||||
m_base_position += m_speed * dtime;
|
||||
|
||||
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if(m_size.X >= 2.5){
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
|
||||
if(!free){
|
||||
explodeSquare(map, pos_i, v3s16(3,3,3));
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorstream<<"MobV2SAO::step(): id="<<m_id<<" unknown move_type=\""
|
||||
<<m_move_type<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
|
||||
if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||
{
|
||||
sendPosition();
|
||||
}
|
||||
}
|
||||
|
||||
u16 MobV2SAO::punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername)
|
||||
{
|
||||
assert(m_env);
|
||||
Map *map = &m_env->getMap();
|
||||
|
||||
actionstream<<playername<<" punches mob id="<<m_id
|
||||
<<" with a \""<<toolname<<"\" at "
|
||||
<<PP(m_base_position/BS)<<std::endl;
|
||||
|
||||
m_disturb_timer = 0;
|
||||
m_disturbing_player = playername;
|
||||
m_next_pos_exists = false; // Cancel moving immediately
|
||||
|
||||
m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.);
|
||||
v3f new_base_position = m_base_position + dir * BS;
|
||||
{
|
||||
v3s16 pos_i = floatToInt(new_base_position, BS);
|
||||
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if(m_size.X >= 2.5){
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
|
||||
if(free)
|
||||
m_base_position = new_base_position;
|
||||
}
|
||||
sendPosition();
|
||||
|
||||
u16 amount = 2;
|
||||
/* See tool names in inventory.h */
|
||||
if(toolname == "WSword")
|
||||
amount = 4;
|
||||
if(toolname == "STSword")
|
||||
amount = 6;
|
||||
if(toolname == "SteelSword")
|
||||
amount = 8;
|
||||
if(toolname == "STAxe")
|
||||
amount = 3;
|
||||
if(toolname == "SteelAxe")
|
||||
amount = 4;
|
||||
if(toolname == "SteelPick")
|
||||
amount = 3;
|
||||
doDamage(amount);
|
||||
return 65536/100;
|
||||
}
|
||||
|
||||
bool MobV2SAO::isPeaceful()
|
||||
{
|
||||
return m_properties->getBool("is_peaceful");
|
||||
}
|
||||
|
||||
void MobV2SAO::sendPosition()
|
||||
{
|
||||
m_last_sent_position = m_base_position;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (0 = update position)
|
||||
writeU8(os, 0);
|
||||
// pos
|
||||
writeV3F1000(os, m_base_position);
|
||||
// yaw
|
||||
writeF1000(os, m_yaw);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
void MobV2SAO::setPropertyDefaults()
|
||||
{
|
||||
m_properties->setDefault("is_peaceful", "false");
|
||||
m_properties->setDefault("move_type", "ground_nodes");
|
||||
m_properties->setDefault("speed", "(0,0,0)");
|
||||
m_properties->setDefault("age", "0");
|
||||
m_properties->setDefault("yaw", "0");
|
||||
m_properties->setDefault("pos", "(0,0,0)");
|
||||
m_properties->setDefault("hp", "0");
|
||||
m_properties->setDefault("die_age", "-1");
|
||||
m_properties->setDefault("size", "(1,2)");
|
||||
m_properties->setDefault("shoot_type", "fireball");
|
||||
m_properties->setDefault("shoot_y", "0");
|
||||
m_properties->setDefault("mindless_rage", "false");
|
||||
}
|
||||
void MobV2SAO::readProperties()
|
||||
{
|
||||
m_move_type = m_properties->get("move_type");
|
||||
m_speed = m_properties->getV3F("speed");
|
||||
m_age = m_properties->getFloat("age");
|
||||
m_yaw = m_properties->getFloat("yaw");
|
||||
m_base_position = m_properties->getV3F("pos");
|
||||
m_hp = m_properties->getS32("hp");
|
||||
m_die_age = m_properties->getFloat("die_age");
|
||||
m_size = m_properties->getV2F("size");
|
||||
}
|
||||
void MobV2SAO::updateProperties()
|
||||
{
|
||||
m_properties->set("move_type", m_move_type);
|
||||
m_properties->setV3F("speed", m_speed);
|
||||
m_properties->setFloat("age", m_age);
|
||||
m_properties->setFloat("yaw", m_yaw);
|
||||
m_properties->setV3F("pos", m_base_position);
|
||||
m_properties->setS32("hp", m_hp);
|
||||
m_properties->setFloat("die_age", m_die_age);
|
||||
m_properties->setV2F("size", m_size);
|
||||
|
||||
m_properties->setS32("version", 0);
|
||||
}
|
||||
|
||||
void MobV2SAO::doDamage(u16 d)
|
||||
{
|
||||
infostream<<"MobV2 hp="<<m_hp<<" damage="<<d<<std::endl;
|
||||
|
||||
if(d < m_hp)
|
||||
{
|
||||
m_hp -= d;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionstream<<"A "<<(isPeaceful()?"peaceful":"non-peaceful")
|
||||
<<" mob id="<<m_id<<" dies at "<<PP(m_base_position)<<std::endl;
|
||||
// Die
|
||||
m_hp = 0;
|
||||
m_removed = true;
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (1 = damage)
|
||||
writeU8(os, 1);
|
||||
// amount
|
||||
writeU16(os, d);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -96,9 +96,7 @@ class Oerkki1SAO : public ServerActiveObject
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createPickedUpItem(){return NULL;}
|
||||
u16 punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername);
|
||||
bool isPeaceful(){return false;}
|
||||
u16 punch(const std::string &toolname, v3f dir);
|
||||
private:
|
||||
void doDamage(u16 d);
|
||||
|
||||
@@ -141,59 +139,5 @@ class FireflySAO : public ServerActiveObject
|
||||
bool m_touching_ground;
|
||||
};
|
||||
|
||||
class Settings;
|
||||
|
||||
class MobV2SAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||
Settings *init_properties);
|
||||
virtual ~MobV2SAO();
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_MOBV2;}
|
||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data);
|
||||
std::string getStaticData();
|
||||
std::string getClientInitializationData();
|
||||
void step(float dtime, bool send_recommended);
|
||||
InventoryItem* createPickedUpItem(){return NULL;}
|
||||
u16 punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername);
|
||||
bool isPeaceful();
|
||||
private:
|
||||
void sendPosition();
|
||||
void setPropertyDefaults();
|
||||
void readProperties();
|
||||
void updateProperties();
|
||||
void doDamage(u16 d);
|
||||
|
||||
std::string m_move_type;
|
||||
v3f m_speed;
|
||||
v3f m_last_sent_position;
|
||||
v3f m_oldpos;
|
||||
float m_yaw;
|
||||
float m_counter1;
|
||||
float m_counter2;
|
||||
float m_age;
|
||||
bool m_touching_ground;
|
||||
int m_hp;
|
||||
bool m_walk_around;
|
||||
float m_walk_around_timer;
|
||||
bool m_next_pos_exists;
|
||||
v3s16 m_next_pos_i;
|
||||
float m_shoot_reload_timer;
|
||||
bool m_shooting;
|
||||
float m_shooting_timer;
|
||||
float m_die_age;
|
||||
v2f m_size;
|
||||
bool m_falling;
|
||||
float m_disturb_timer;
|
||||
std::string m_disturbing_player;
|
||||
float m_random_disturb_timer;
|
||||
float m_shoot_y;
|
||||
|
||||
Settings *m_properties;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
19
src/debug.h
@@ -235,9 +235,10 @@ class PacketCounter
|
||||
|
||||
#if CATCH_UNHANDLED_EXCEPTIONS == 1
|
||||
#define BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER try{
|
||||
#define END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)\
|
||||
#define END_PORTABLE_DEBUG_EXCEPTION_HANDLER\
|
||||
}catch(std::exception &e){\
|
||||
logstream<<"ERROR: An unhandled exception occurred: "\
|
||||
dstream<<std::endl<<DTIME\
|
||||
<<"ERROR: An unhandled exception occurred: "\
|
||||
<<e.what()<<std::endl;\
|
||||
assert(0);\
|
||||
}
|
||||
@@ -256,24 +257,24 @@ class FatalSystemException : public BaseException
|
||||
BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER\
|
||||
_set_se_translator(se_trans_func);
|
||||
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream) \
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#define END_DEBUG_EXCEPTION_HANDLER \
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#else // Probably mingw
|
||||
#define BEGIN_DEBUG_EXCEPTION_HANDLER\
|
||||
BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream)\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#define END_DEBUG_EXCEPTION_HANDLER\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#endif
|
||||
#else // Posix
|
||||
#define BEGIN_DEBUG_EXCEPTION_HANDLER\
|
||||
BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream)\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#define END_DEBUG_EXCEPTION_HANDLER\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#endif
|
||||
#else
|
||||
// Dummy ones
|
||||
#define BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#define END_DEBUG_EXCEPTION_HANDLER
|
||||
#endif
|
||||
|
||||
#endif // DEBUG_HEADER
|
||||
|
||||
@@ -17,99 +17,89 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "settings.h"
|
||||
#include "utility.h"
|
||||
|
||||
void set_default_settings(Settings *settings)
|
||||
extern Settings g_settings;
|
||||
|
||||
void set_default_settings()
|
||||
{
|
||||
// Client and server
|
||||
|
||||
settings->setDefault("port", "");
|
||||
settings->setDefault("name", "");
|
||||
settings->setDefault("footprints", "false");
|
||||
g_settings.setDefault("port", "");
|
||||
g_settings.setDefault("name", "");
|
||||
g_settings.setDefault("footprints", "false");
|
||||
|
||||
// Client stuff
|
||||
|
||||
settings->setDefault("keymap_forward", "KEY_KEY_W");
|
||||
settings->setDefault("keymap_backward", "KEY_KEY_S");
|
||||
settings->setDefault("keymap_left", "KEY_KEY_A");
|
||||
settings->setDefault("keymap_right", "KEY_KEY_D");
|
||||
settings->setDefault("keymap_jump", "KEY_SPACE");
|
||||
settings->setDefault("keymap_sneak", "KEY_LSHIFT");
|
||||
settings->setDefault("keymap_inventory", "KEY_KEY_I");
|
||||
settings->setDefault("keymap_special1", "KEY_KEY_E");
|
||||
settings->setDefault("keymap_chat", "KEY_KEY_T");
|
||||
settings->setDefault("keymap_cmd", "/");
|
||||
settings->setDefault("keymap_rangeselect", "KEY_KEY_R");
|
||||
settings->setDefault("keymap_freemove", "KEY_KEY_K");
|
||||
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||
settings->setDefault("keymap_frametime_graph", "KEY_F1");
|
||||
settings->setDefault("keymap_screenshot", "KEY_F12");
|
||||
settings->setDefault("keymap_toggle_profiler", "KEY_F2");
|
||||
settings->setDefault("keymap_toggle_force_fog_off", "KEY_F3");
|
||||
settings->setDefault("keymap_toggle_update_camera", "KEY_F4");
|
||||
g_settings.setDefault("keymap_forward", "KEY_KEY_W");
|
||||
g_settings.setDefault("keymap_backward", "KEY_KEY_S");
|
||||
g_settings.setDefault("keymap_left", "KEY_KEY_A");
|
||||
g_settings.setDefault("keymap_right", "KEY_KEY_D");
|
||||
g_settings.setDefault("keymap_jump", "KEY_SPACE");
|
||||
g_settings.setDefault("keymap_sneak", "KEY_LSHIFT");
|
||||
g_settings.setDefault("keymap_inventory", "KEY_KEY_I");
|
||||
g_settings.setDefault("keymap_chat", "KEY_KEY_T");
|
||||
g_settings.setDefault("keymap_cmd", "/");
|
||||
g_settings.setDefault("keymap_rangeselect", "KEY_KEY_R");
|
||||
g_settings.setDefault("keymap_freemove", "KEY_KEY_K");
|
||||
g_settings.setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||
g_settings.setDefault("keymap_frametime_graph", "KEY_F1");
|
||||
g_settings.setDefault("keymap_screenshot", "KEY_F12");
|
||||
// Some (temporary) keys for debugging
|
||||
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||
g_settings.setDefault("keymap_special1", "KEY_KEY_E");
|
||||
g_settings.setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||
|
||||
settings->setDefault("wanted_fps", "30");
|
||||
settings->setDefault("fps_max", "60");
|
||||
settings->setDefault("viewing_range_nodes_max", "300");
|
||||
settings->setDefault("viewing_range_nodes_min", "15");
|
||||
settings->setDefault("screenW", "800");
|
||||
settings->setDefault("screenH", "600");
|
||||
settings->setDefault("address", "");
|
||||
settings->setDefault("random_input", "false");
|
||||
settings->setDefault("client_unload_unused_data_timeout", "600");
|
||||
settings->setDefault("enable_fog", "true");
|
||||
settings->setDefault("fov", "72");
|
||||
settings->setDefault("view_bobbing", "true");
|
||||
settings->setDefault("new_style_water", "false");
|
||||
settings->setDefault("new_style_leaves", "false");
|
||||
settings->setDefault("smooth_lighting", "true");
|
||||
settings->setDefault("frametime_graph", "false");
|
||||
settings->setDefault("enable_texture_atlas", "true");
|
||||
settings->setDefault("texture_path", "");
|
||||
settings->setDefault("video_driver", "opengl");
|
||||
settings->setDefault("free_move", "false");
|
||||
settings->setDefault("continuous_forward", "false");
|
||||
settings->setDefault("fast_move", "false");
|
||||
settings->setDefault("invert_mouse", "false");
|
||||
settings->setDefault("enable_farmesh", "false");
|
||||
settings->setDefault("enable_clouds", "true");
|
||||
settings->setDefault("invisible_stone", "false");
|
||||
settings->setDefault("screenshot_path", ".");
|
||||
settings->setDefault("view_bobbing_amount", "1.0");
|
||||
settings->setDefault("enable_3d_clouds", "false");
|
||||
settings->setDefault("opaque_water", "false");
|
||||
g_settings.setDefault("wanted_fps", "30");
|
||||
g_settings.setDefault("fps_max", "60");
|
||||
g_settings.setDefault("viewing_range_nodes_max", "300");
|
||||
g_settings.setDefault("viewing_range_nodes_min", "15");
|
||||
g_settings.setDefault("screenW", "800");
|
||||
g_settings.setDefault("screenH", "600");
|
||||
g_settings.setDefault("address", "");
|
||||
g_settings.setDefault("random_input", "false");
|
||||
g_settings.setDefault("client_unload_unused_data_timeout", "600");
|
||||
g_settings.setDefault("enable_fog", "true");
|
||||
g_settings.setDefault("new_style_water", "false");
|
||||
g_settings.setDefault("new_style_leaves", "true");
|
||||
g_settings.setDefault("smooth_lighting", "true");
|
||||
g_settings.setDefault("frametime_graph", "false");
|
||||
g_settings.setDefault("enable_texture_atlas", "true");
|
||||
g_settings.setDefault("texture_path", "");
|
||||
g_settings.setDefault("video_driver", "opengl");
|
||||
g_settings.setDefault("free_move", "false");
|
||||
g_settings.setDefault("continuous_forward", "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");
|
||||
g_settings.setDefault("screenshot_path", ".");
|
||||
|
||||
// Server stuff
|
||||
// "map-dir" doesn't exist by default.
|
||||
settings->setDefault("motd", "");
|
||||
settings->setDefault("max_users", "20");
|
||||
settings->setDefault("strict_protocol_version_checking", "true");
|
||||
settings->setDefault("creative_mode", "false");
|
||||
settings->setDefault("enable_damage", "true");
|
||||
settings->setDefault("only_peaceful_mobs", "false");
|
||||
settings->setDefault("fixed_map_seed", "");
|
||||
settings->setDefault("give_initial_stuff", "false");
|
||||
settings->setDefault("default_password", "");
|
||||
settings->setDefault("default_privs", "build, shout");
|
||||
g_settings.setDefault("motd", "");
|
||||
g_settings.setDefault("enable_experimental", "false");
|
||||
g_settings.setDefault("creative_mode", "false");
|
||||
g_settings.setDefault("enable_damage", "true");
|
||||
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("enable_mapgen_debug_info", "false");
|
||||
g_settings.setDefault("fixed_map_seed", "");
|
||||
|
||||
settings->setDefault("profiler_print_interval", "0");
|
||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||
settings->setDefault("objectdata_interval", "0.2");
|
||||
settings->setDefault("active_object_send_range_blocks", "3");
|
||||
settings->setDefault("active_block_range", "2");
|
||||
//settings->setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
g_settings.setDefault("objectdata_interval", "0.2");
|
||||
g_settings.setDefault("active_object_range", "2");
|
||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
// This causes frametime jitter on client side, or does it?
|
||||
settings->setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||
settings->setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||
settings->setDefault("max_block_send_distance", "7");
|
||||
settings->setDefault("max_block_generate_distance", "5");
|
||||
settings->setDefault("time_send_interval", "20");
|
||||
settings->setDefault("time_speed", "96");
|
||||
settings->setDefault("server_unload_unused_data_timeout", "60");
|
||||
settings->setDefault("server_map_save_interval", "10");
|
||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
settings->setDefault("enable_experimental", "false");
|
||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||
g_settings.setDefault("max_block_send_distance", "8");
|
||||
g_settings.setDefault("max_block_generate_distance", "8");
|
||||
g_settings.setDefault("time_send_interval", "20");
|
||||
g_settings.setDefault("time_speed", "96");
|
||||
g_settings.setDefault("server_unload_unused_data_timeout", "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("dungeon_rarity", "0.025");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DEFAULTSETTINGS_HEADER
|
||||
#define DEFAULTSETTINGS_HEADER
|
||||
|
||||
class Settings;
|
||||
|
||||
void set_default_settings(Settings *settings);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -175,14 +175,6 @@ class ServerEnvironment : public Environment
|
||||
*/
|
||||
u16 addActiveObject(ServerActiveObject *object);
|
||||
|
||||
/*
|
||||
Add an active object as a static object to the corresponding
|
||||
MapBlock.
|
||||
Caller allocates memory, ServerEnvironment frees memory.
|
||||
Return value: true if succeeded, false if failed.
|
||||
*/
|
||||
bool addActiveObjectAsStatic(ServerActiveObject *object);
|
||||
|
||||
/*
|
||||
Find out what new objects have been added to
|
||||
inside a radius around a position
|
||||
@@ -218,11 +210,6 @@ class ServerEnvironment : public Environment
|
||||
|
||||
void addActiveBlockModifier(ActiveBlockModifier *abm);
|
||||
|
||||
/* Other stuff */
|
||||
|
||||
// Clear all objects, loading and going through every MapBlock
|
||||
void clearAllObjects();
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
@@ -419,6 +406,9 @@ class ClientEnvironment : public Environment
|
||||
|
||||
// Get event from queue. CEE_NONE is returned if queue is empty.
|
||||
ClientEnvEvent getClientEvent();
|
||||
|
||||
// Post effects
|
||||
void drawPostFx(video::IVideoDriver* driver, v3f camera_pos);
|
||||
|
||||
private:
|
||||
ClientMap *m_map;
|
||||
|
||||
@@ -171,7 +171,6 @@ bool RecursiveDelete(std::string path)
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
std::vector<DirListNode> GetDirListing(std::string pathstring)
|
||||
{
|
||||
@@ -280,7 +279,7 @@ bool RecursiveDeleteContent(std::string path)
|
||||
{
|
||||
if(trim(list[i].name) == "." || trim(list[i].name) == "..")
|
||||
continue;
|
||||
std::string childpath = path + DIR_DELIM + list[i].name;
|
||||
std::string childpath = path + "/" + list[i].name;
|
||||
bool r = RecursiveDelete(childpath);
|
||||
if(r == false)
|
||||
{
|
||||
@@ -300,7 +299,7 @@ bool CreateAllDirs(std::string path)
|
||||
while(!PathExists(basepath))
|
||||
{
|
||||
tocreate.push_back(basepath);
|
||||
pos = basepath.rfind(DIR_DELIM_C);
|
||||
pos = basepath.rfind('/');
|
||||
if(pos == std::string::npos)
|
||||
return false;
|
||||
basepath = basepath.substr(0,pos);
|
||||
|
||||
@@ -24,14 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <vector>
|
||||
#include "exceptions.h"
|
||||
|
||||
#ifdef _WIN32 // WINDOWS
|
||||
#define DIR_DELIM "\\"
|
||||
#define DIR_DELIM_C '\\'
|
||||
#else // POSIX
|
||||
#define DIR_DELIM "/"
|
||||
#define DIR_DELIM_C '/'
|
||||
#endif
|
||||
|
||||
namespace fs
|
||||
{
|
||||
|
||||
|
||||
800
src/game.cpp
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "guiDeathScreen.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "gettext.h"
|
||||
#include "client.h"
|
||||
|
||||
GUIDeathScreen::GUIDeathScreen(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr, IRespawnInitiator *respawner
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_respawner(respawner),
|
||||
m_screensize(1,1)
|
||||
{
|
||||
}
|
||||
|
||||
GUIDeathScreen::~GUIDeathScreen()
|
||||
{
|
||||
removeChildren();
|
||||
delete m_respawner;
|
||||
}
|
||||
|
||||
void GUIDeathScreen::removeChildren()
|
||||
{
|
||||
const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for(core::list<gui::IGUIElement*>::ConstIterator
|
||||
i = children.begin(); i != children.end(); i++)
|
||||
{
|
||||
children_copy.push_back(*i);
|
||||
}
|
||||
for(core::list<gui::IGUIElement*>::Iterator
|
||||
i = children_copy.begin();
|
||||
i != children_copy.end(); i++)
|
||||
{
|
||||
(*i)->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIDeathScreen::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
m_screensize = screensize;
|
||||
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
core::rect<s32> rect(
|
||||
screensize.X/2 - 500/2,
|
||||
screensize.Y/2 - 200/2,
|
||||
screensize.X/2 + 500/2,
|
||||
screensize.Y/2 + 200/2
|
||||
);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = rect.getSize();
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
changeCtype("");
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 400, 50);
|
||||
rect = rect + v2s32(size.X/2-400/2, size.Y/2-50/2-25);
|
||||
Environment->addStaticText(wgettext("You died."), rect, false,
|
||||
true, this, 256);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, 30);
|
||||
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
|
||||
gui::IGUIElement *e =
|
||||
Environment->addButton(rect, this, 257,
|
||||
wgettext("Respawn"));
|
||||
Environment->setFocus(e);
|
||||
}
|
||||
changeCtype("C");
|
||||
}
|
||||
|
||||
void GUIDeathScreen::drawMenu()
|
||||
{
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
{
|
||||
video::SColor color(180,50,0,0);
|
||||
driver->draw2DRectangle(color,
|
||||
core::rect<s32>(0,0,m_screensize.X,m_screensize.Y), NULL);
|
||||
}
|
||||
{
|
||||
video::SColor bgcolor(50,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIDeathScreen::OnEvent(const SEvent& event)
|
||||
{
|
||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
||||
{
|
||||
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
|
||||
{
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
|
||||
{
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.EventType==EET_GUI_EVENT)
|
||||
{
|
||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
||||
&& isVisible())
|
||||
{
|
||||
if(!canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
dstream<<"GUIDeathScreen: Not allowing focus change."
|
||||
<<std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
||||
{
|
||||
switch(event.GUIEvent.Caller->getID())
|
||||
{
|
||||
case 257:
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
void GUIDeathScreen::respawn()
|
||||
{
|
||||
m_respawner->respawn();
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GUIMESSAGEMENU_HEADER
|
||||
#define GUIMESSAGEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
class IRespawnInitiator
|
||||
{
|
||||
public:
|
||||
virtual void respawn() = 0;
|
||||
};
|
||||
|
||||
class GUIDeathScreen : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIDeathScreen(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr, IRespawnInitiator *respawner);
|
||||
~GUIDeathScreen();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent& event);
|
||||
|
||||
void respawn();
|
||||
|
||||
private:
|
||||
IRespawnInitiator *m_respawner;
|
||||
v2u32 m_screensize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,12 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "constants.h"
|
||||
#include "keycode.h"
|
||||
#include "strfnd.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "log.h"
|
||||
|
||||
void drawInventoryItem(video::IVideoDriver *driver,
|
||||
gui::IGUIFont *font,
|
||||
@@ -327,11 +321,11 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
if(amount >= 0)
|
||||
{
|
||||
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
||||
//infostream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||
//dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||
ItemSpec s = getItemAtPos(p);
|
||||
if(s.isValid())
|
||||
{
|
||||
infostream<<"Mouse down on "<<s.inventoryname
|
||||
dstream<<"Mouse down on "<<s.inventoryname
|
||||
<<"/"<<s.listname<<" "<<s.i<<std::endl;
|
||||
if(m_selected_item)
|
||||
{
|
||||
@@ -346,15 +340,15 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
InventoryList *list_to =
|
||||
inv_to->getList(s.listname);
|
||||
if(list_from == NULL)
|
||||
infostream<<"from list doesn't exist"<<std::endl;
|
||||
dstream<<"from list doesn't exist"<<std::endl;
|
||||
if(list_to == NULL)
|
||||
infostream<<"to list doesn't exist"<<std::endl;
|
||||
dstream<<"to list doesn't exist"<<std::endl;
|
||||
// Indicates whether source slot completely empties
|
||||
bool source_empties = false;
|
||||
if(list_from && list_to
|
||||
&& list_from->getItem(m_selected_item->i) != NULL)
|
||||
{
|
||||
infostream<<"Handing IACTION_MOVE to manager"<<std::endl;
|
||||
dstream<<"Handing IACTION_MOVE to manager"<<std::endl;
|
||||
IMoveAction *a = new IMoveAction();
|
||||
a->count = amount;
|
||||
a->from_inv = m_selected_item->inventoryname;
|
||||
@@ -409,7 +403,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
if(!canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
infostream<<"GUIInventoryMenu: Not allowing focus change."
|
||||
dstream<<"GUIInventoryMenu: Not allowing focus change."
|
||||
<<std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
@@ -475,7 +469,7 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
while(f.atend() == false)
|
||||
{
|
||||
std::string type = trim(f.next("["));
|
||||
//infostream<<"type="<<type<<std::endl;
|
||||
//dstream<<"type="<<type<<std::endl;
|
||||
if(type == "list")
|
||||
{
|
||||
std::string name = f.next(";");
|
||||
@@ -486,7 +480,7 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
s32 pos_y = stoi(f.next(";"));
|
||||
s32 geom_x = stoi(f.next(","));
|
||||
s32 geom_y = stoi(f.next(";"));
|
||||
infostream<<"list name="<<name<<", subname="<<subname
|
||||
dstream<<"list name="<<name<<", subname="<<subname
|
||||
<<", pos=("<<pos_x<<","<<pos_y<<")"
|
||||
<<", geom=("<<geom_x<<","<<geom_y<<")"
|
||||
<<std::endl;
|
||||
@@ -499,14 +493,14 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
{
|
||||
invsize.X = stoi(f.next(","));
|
||||
invsize.Y = stoi(f.next(";"));
|
||||
infostream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||
dstream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||
f.next("]");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore others
|
||||
std::string ts = f.next("]");
|
||||
infostream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\""
|
||||
dstream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
#include "serialization.h"
|
||||
#include "main.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "settings.h"
|
||||
|
||||
GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
|
||||
@@ -346,20 +340,20 @@ void GUIKeyChangeMenu::drawMenu()
|
||||
|
||||
bool GUIKeyChangeMenu::acceptInput()
|
||||
{
|
||||
g_settings->set("keymap_forward", key_forward.sym());
|
||||
g_settings->set("keymap_backward", key_backward.sym());
|
||||
g_settings->set("keymap_left", key_left.sym());
|
||||
g_settings->set("keymap_right", key_right.sym());
|
||||
g_settings->set("keymap_jump", key_jump.sym());
|
||||
g_settings->set("keymap_sneak", key_sneak.sym());
|
||||
g_settings->set("keymap_inventory", key_inventory.sym());
|
||||
g_settings->set("keymap_chat", key_chat.sym());
|
||||
g_settings->set("keymap_cmd", key_cmd.sym());
|
||||
g_settings->set("keymap_rangeselect", key_range.sym());
|
||||
g_settings->set("keymap_freemove", key_fly.sym());
|
||||
g_settings->set("keymap_fastmove", key_fast.sym());
|
||||
g_settings->set("keymap_special1", key_use.sym());
|
||||
g_settings->set("keymap_print_debug_stacks", key_dump.sym());
|
||||
g_settings.set("keymap_forward", key_forward.sym());
|
||||
g_settings.set("keymap_backward", key_backward.sym());
|
||||
g_settings.set("keymap_left", key_left.sym());
|
||||
g_settings.set("keymap_right", key_right.sym());
|
||||
g_settings.set("keymap_jump", key_jump.sym());
|
||||
g_settings.set("keymap_sneak", key_sneak.sym());
|
||||
g_settings.set("keymap_inventory", key_inventory.sym());
|
||||
g_settings.set("keymap_chat", key_chat.sym());
|
||||
g_settings.set("keymap_cmd", key_cmd.sym());
|
||||
g_settings.set("keymap_rangeselect", key_range.sym());
|
||||
g_settings.set("keymap_freemove", key_fly.sym());
|
||||
g_settings.set("keymap_fastmove", key_fast.sym());
|
||||
g_settings.set("keymap_special1", key_use.sym());
|
||||
g_settings.set("keymap_print_debug_stacks", key_dump.sym());
|
||||
clearKeyCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,11 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
|
||||
|
||||
#include "gettext.h"
|
||||
@@ -80,8 +76,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
bool enable_damage;
|
||||
bool fancy_trees;
|
||||
bool smooth_lighting;
|
||||
bool clouds_3d;
|
||||
bool opaque_water;
|
||||
|
||||
// Client options
|
||||
{
|
||||
@@ -119,20 +113,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
else
|
||||
smooth_lighting = m_data->smooth_lighting;
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
else
|
||||
clouds_3d = m_data->clouds_3d;
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
else
|
||||
opaque_water = m_data->opaque_water;
|
||||
}
|
||||
|
||||
// Server options
|
||||
{
|
||||
@@ -258,22 +238,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 250, 30);
|
||||
rect += topleft_client + v2s32(35, 150+20);
|
||||
rect += topleft_client + v2s32(35, 150+30);
|
||||
Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB,
|
||||
wgettext("Smooth Lighting"));
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 250, 30);
|
||||
rect += topleft_client + v2s32(35, 150+40);
|
||||
Environment->addCheckBox(clouds_3d, rect, this, GUI_ID_3D_CLOUDS_CB,
|
||||
wgettext("3D Clouds"));
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 250, 30);
|
||||
rect += topleft_client + v2s32(35, 150+60);
|
||||
Environment->addCheckBox(opaque_water, rect, this, GUI_ID_OPAQUE_WATER_CB,
|
||||
wgettext("Opaque water"));
|
||||
}
|
||||
// Start game button
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 180, 30);
|
||||
@@ -390,25 +358,15 @@ void GUIMainMenu::acceptInput()
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
m_data->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
m_data->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
m_data->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
m_data->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
|
||||
m_accepted = true;
|
||||
|
||||
@@ -35,8 +35,6 @@ enum
|
||||
GUI_ID_PORT_INPUT,
|
||||
GUI_ID_FANCYTREE_CB,
|
||||
GUI_ID_SMOOTH_LIGHTING_CB,
|
||||
GUI_ID_3D_CLOUDS_CB,
|
||||
GUI_ID_OPAQUE_WATER_CB,
|
||||
GUI_ID_DAMAGE_CB,
|
||||
GUI_ID_CREATIVE_CB,
|
||||
GUI_ID_JOIN_GAME_BUTTON,
|
||||
@@ -66,8 +64,6 @@ struct MainMenuData
|
||||
std::wstring password;
|
||||
bool fancy_trees;
|
||||
bool smooth_lighting;
|
||||
bool clouds_3d;
|
||||
bool opaque_water;
|
||||
// Server options
|
||||
bool creative_mode;
|
||||
bool enable_damage;
|
||||
|
||||
@@ -21,11 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
||||
@@ -20,11 +20,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
||||
@@ -23,11 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "porting.h"
|
||||
#include "config.h"
|
||||
#include "main.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
||||
@@ -21,11 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_inventory.h"
|
||||
#include "content_sao.h"
|
||||
#include "player.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
InventoryItem
|
||||
@@ -98,7 +97,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
||||
{
|
||||
std::string inventorystring;
|
||||
std::getline(is, inventorystring, '|');
|
||||
throw SerializationError("MBOItem not supported anymore");
|
||||
return new MapBlockObjectItem(inventorystring);
|
||||
}
|
||||
else if(name == "CraftItem")
|
||||
{
|
||||
@@ -118,7 +117,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
|
||||
dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
|
||||
throw SerializationError("Unknown InventoryItem name");
|
||||
}
|
||||
}
|
||||
@@ -159,7 +158,7 @@ InventoryItem *MaterialItem::createCookResult() const
|
||||
*/
|
||||
|
||||
#ifndef SERVER
|
||||
video::ITexture * CraftItem::getImage() const
|
||||
video::ITexture * CraftItem::getImage()
|
||||
{
|
||||
if(g_texturesource == NULL)
|
||||
return NULL;
|
||||
@@ -220,6 +219,77 @@ bool CraftItem::use(ServerEnvironment *env, Player *player)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
MapBlockObjectItem DEPRECATED
|
||||
TODO: Remove
|
||||
*/
|
||||
#ifndef SERVER
|
||||
video::ITexture * MapBlockObjectItem::getImage()
|
||||
{
|
||||
if(m_inventorystring.substr(0,3) == "Rat")
|
||||
return g_texturesource->getTextureRaw("rat.png");
|
||||
|
||||
if(m_inventorystring.substr(0,4) == "Sign")
|
||||
return g_texturesource->getTextureRaw("sign.png");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
std::string MapBlockObjectItem::getText()
|
||||
{
|
||||
if(m_inventorystring.substr(0,3) == "Rat")
|
||||
return "";
|
||||
|
||||
if(m_inventorystring.substr(0,4) == "Sign")
|
||||
return "";
|
||||
|
||||
return "obj";
|
||||
}
|
||||
|
||||
MapBlockObject * MapBlockObjectItem::createObject
|
||||
(v3f pos, f32 player_yaw, f32 player_pitch)
|
||||
{
|
||||
std::istringstream is(m_inventorystring);
|
||||
std::string name;
|
||||
std::getline(is, name, ' ');
|
||||
|
||||
if(name == "None")
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if(name == "Sign")
|
||||
{
|
||||
std::string text;
|
||||
std::getline(is, text, '|');
|
||||
SignObject *obj = new SignObject(NULL, -1, pos);
|
||||
obj->setText(text);
|
||||
obj->setYaw(-player_yaw);
|
||||
return obj;
|
||||
}
|
||||
else if(name == "Rat")
|
||||
{
|
||||
RatObject *obj = new RatObject(NULL, -1, pos);
|
||||
return obj;
|
||||
}
|
||||
else if(name == "ItemObj")
|
||||
{
|
||||
/*
|
||||
Now we are an inventory item containing the serialization
|
||||
string of an object that contains the serialization
|
||||
string of an inventory item. Fuck this.
|
||||
*/
|
||||
//assert(0);
|
||||
dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj "
|
||||
<<"because an item-object should never be inside "
|
||||
<<"an object-item."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Inventory
|
||||
*/
|
||||
@@ -739,56 +809,51 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
|
||||
return a;
|
||||
}
|
||||
|
||||
static std::string describeC(const struct InventoryContext *c)
|
||||
{
|
||||
if(c->current_player == NULL)
|
||||
return "current_player=NULL";
|
||||
else
|
||||
return std::string("current_player=") + c->current_player->getName();
|
||||
}
|
||||
|
||||
void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||
{
|
||||
#if 1
|
||||
|
||||
/*dstream<<"from_inv="<<from_inv<<" to_inv="<<to_inv<<std::endl;
|
||||
dstream<<"from_list="<<from_list<<" to_list="<<to_list<<std::endl;
|
||||
dstream<<"from_i="<<from_i<<" to_i="<<to_i<<std::endl;*/
|
||||
|
||||
Inventory *inv_from = mgr->getInventory(c, from_inv);
|
||||
Inventory *inv_to = mgr->getInventory(c, to_inv);
|
||||
|
||||
if(!inv_from){
|
||||
infostream<<"IMoveAction::apply(): FAIL: source inventory not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", to_inv=\""<<to_inv<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(!inv_to){
|
||||
infostream<<"IMoveAction::apply(): FAIL: destination inventory not found: "
|
||||
"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", to_inv=\""<<to_inv<<"\""<<std::endl;
|
||||
|
||||
if(!inv_from || !inv_to)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(inventories not found)"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryList *list_from = inv_from->getList(from_list);
|
||||
InventoryList *list_to = inv_to->getList(to_list);
|
||||
|
||||
/*dstream<<"list_from="<<list_from<<" list_to="<<list_to
|
||||
<<std::endl;*/
|
||||
/*if(list_from)
|
||||
dstream<<" list_from->getItem(from_i)="<<list_from->getItem(from_i)
|
||||
<<std::endl;
|
||||
if(list_to)
|
||||
dstream<<" list_to->getItem(to_i)="<<list_to->getItem(to_i)
|
||||
<<std::endl;*/
|
||||
|
||||
/*
|
||||
If a list doesn't exist or the source item doesn't exist
|
||||
*/
|
||||
if(!list_from){
|
||||
infostream<<"IMoveAction::apply(): FAIL: source list not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", from_list=\""<<from_list<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(!list_to){
|
||||
infostream<<"IMoveAction::apply(): FAIL: destination list not found: "
|
||||
<<"context=["<<describeC(c)<<"], to_inv=\""<<to_inv<<"\""
|
||||
<<", to_list=\""<<to_list<<"\""<<std::endl;
|
||||
if(!list_from || !list_to)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(a list doesn't exist)"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(list_from->getItem(from_i) == NULL)
|
||||
{
|
||||
infostream<<"IMoveAction::apply(): FAIL: source item not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", from_list=\""<<from_list<<"\""
|
||||
<<" from_i="<<from_i<<std::endl;
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(the source item doesn't exist)"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@@ -796,9 +861,8 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||
*/
|
||||
if(inv_from == inv_to && list_from == list_to && from_i == to_i)
|
||||
{
|
||||
infostream<<"IMoveAction::apply(): FAIL: source and destination slots "
|
||||
<<"are the same: inv=\""<<from_inv<<"\" list=\""<<from_list
|
||||
<<"\" i="<<from_i<<std::endl;
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(source and the destination slots are the same)"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -839,16 +903,7 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||
mgr->inventoryModified(c, from_inv);
|
||||
if(from_inv != to_inv)
|
||||
mgr->inventoryModified(c, to_inv);
|
||||
|
||||
infostream<<"IMoveAction::apply(): moved at "
|
||||
<<"["<<describeC(c)<<"]"
|
||||
<<" from inv=\""<<from_inv<<"\""
|
||||
<<" list=\""<<from_list<<"\""
|
||||
<<" i="<<from_i
|
||||
<<" to inv=\""<<to_inv<<"\""
|
||||
<<" list=\""<<to_list<<"\""
|
||||
<<" i="<<to_i
|
||||
<<std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
135
src/inventory.h
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <string>
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
#include "mapblockobject.h"
|
||||
#include "main.h" // For g_materials
|
||||
#include "mapnode.h" // For content_t
|
||||
|
||||
@@ -52,12 +53,8 @@ class InventoryItem
|
||||
// Shall make an exact clone of the item
|
||||
virtual InventoryItem* clone() = 0;
|
||||
#ifndef SERVER
|
||||
// Return the name of the image for this item
|
||||
virtual std::string getBasename() const { return ""; }
|
||||
// Shall return an image of the item (or NULL)
|
||||
virtual video::ITexture * getImage() const { return NULL; }
|
||||
// Shall return an image of the item without embellishments (or NULL)
|
||||
virtual video::ITexture * getImageRaw() const { return getImage(); }
|
||||
// Shall return an image to show in the GUI (or NULL)
|
||||
virtual video::ITexture * getImage() { return NULL; }
|
||||
#endif
|
||||
// Shall return a text to show in the GUI
|
||||
virtual std::string getText() { return ""; }
|
||||
@@ -152,9 +149,10 @@ class MaterialItem : public InventoryItem
|
||||
return new MaterialItem(m_content, m_count);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage() const
|
||||
video::ITexture * getImage()
|
||||
{
|
||||
return content_features(m_content).inventory_texture;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
std::string getText()
|
||||
@@ -195,6 +193,56 @@ class MaterialItem : public InventoryItem
|
||||
content_t m_content;
|
||||
};
|
||||
|
||||
//TODO: Remove
|
||||
class MapBlockObjectItem : public InventoryItem
|
||||
{
|
||||
public:
|
||||
MapBlockObjectItem(std::string inventorystring):
|
||||
InventoryItem(1)
|
||||
{
|
||||
m_inventorystring = inventorystring;
|
||||
}
|
||||
|
||||
/*
|
||||
Implementation interface
|
||||
*/
|
||||
virtual const char* getName() const
|
||||
{
|
||||
return "MBOItem";
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
std::string sane_string(m_inventorystring);
|
||||
str_replace_char(sane_string, '|', '?');
|
||||
os<<getName();
|
||||
os<<" ";
|
||||
os<<sane_string;
|
||||
os<<"|";
|
||||
}
|
||||
virtual InventoryItem* clone()
|
||||
{
|
||||
return new MapBlockObjectItem(m_inventorystring);
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage();
|
||||
#endif
|
||||
std::string getText();
|
||||
|
||||
/*
|
||||
Special methods
|
||||
*/
|
||||
std::string getInventoryString()
|
||||
{
|
||||
return m_inventorystring;
|
||||
}
|
||||
|
||||
MapBlockObject * createObject(v3f pos, f32 player_yaw, f32 player_pitch);
|
||||
|
||||
private:
|
||||
std::string m_inventorystring;
|
||||
};
|
||||
|
||||
/*
|
||||
An item that is used as a mid-product when crafting.
|
||||
Subnames:
|
||||
@@ -228,7 +276,7 @@ class CraftItem : public InventoryItem
|
||||
return new CraftItem(m_subname, m_count);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage() const;
|
||||
video::ITexture * getImage();
|
||||
#endif
|
||||
std::string getText()
|
||||
{
|
||||
@@ -305,43 +353,40 @@ class ToolItem : public InventoryItem
|
||||
return new ToolItem(m_toolname, m_wear);
|
||||
}
|
||||
#ifndef SERVER
|
||||
std::string getBasename() const {
|
||||
if(m_toolname == "WPick")
|
||||
return "tool_woodpick.png";
|
||||
else if(m_toolname == "STPick")
|
||||
return "tool_stonepick.png";
|
||||
else if(m_toolname == "SteelPick")
|
||||
return "tool_steelpick.png";
|
||||
else if(m_toolname == "MesePick")
|
||||
return "tool_mesepick.png";
|
||||
else if(m_toolname == "WShovel")
|
||||
return "tool_woodshovel.png";
|
||||
else if(m_toolname == "STShovel")
|
||||
return "tool_stoneshovel.png";
|
||||
else if(m_toolname == "SteelShovel")
|
||||
return "tool_steelshovel.png";
|
||||
else if(m_toolname == "WAxe")
|
||||
return "tool_woodaxe.png";
|
||||
else if(m_toolname == "STAxe")
|
||||
return "tool_stoneaxe.png";
|
||||
else if(m_toolname == "SteelAxe")
|
||||
return "tool_steelaxe.png";
|
||||
else if(m_toolname == "WSword")
|
||||
return "tool_woodsword.png";
|
||||
else if(m_toolname == "STSword")
|
||||
return "tool_stonesword.png";
|
||||
else if(m_toolname == "SteelSword")
|
||||
return "tool_steelsword.png";
|
||||
else
|
||||
return "cloud.png";
|
||||
}
|
||||
|
||||
video::ITexture * getImage() const
|
||||
video::ITexture * getImage()
|
||||
{
|
||||
if(g_texturesource == NULL)
|
||||
return NULL;
|
||||
|
||||
std::string basename = getBasename();
|
||||
std::string basename;
|
||||
if(m_toolname == "WPick")
|
||||
basename = "tool_woodpick.png";
|
||||
else if(m_toolname == "STPick")
|
||||
basename = "tool_stonepick.png";
|
||||
else if(m_toolname == "SteelPick")
|
||||
basename = "tool_steelpick.png";
|
||||
else if(m_toolname == "MesePick")
|
||||
basename = "tool_mesepick.png";
|
||||
else if(m_toolname == "WShovel")
|
||||
basename = "tool_woodshovel.png";
|
||||
else if(m_toolname == "STShovel")
|
||||
basename = "tool_stoneshovel.png";
|
||||
else if(m_toolname == "SteelShovel")
|
||||
basename = "tool_steelshovel.png";
|
||||
else if(m_toolname == "WAxe")
|
||||
basename = "tool_woodaxe.png";
|
||||
else if(m_toolname == "STAxe")
|
||||
basename = "tool_stoneaxe.png";
|
||||
else if(m_toolname == "SteelAxe")
|
||||
basename = "tool_steelaxe.png";
|
||||
else if(m_toolname == "WSword")
|
||||
basename = "tool_woodsword.png";
|
||||
else if(m_toolname == "STSword")
|
||||
basename = "tool_stonesword.png";
|
||||
else if(m_toolname == "SteelSword")
|
||||
basename = "tool_steelsword.png";
|
||||
else
|
||||
basename = "cloud.png";
|
||||
|
||||
/*
|
||||
Calculate a progress value with sane amount of
|
||||
@@ -356,14 +401,6 @@ class ToolItem : public InventoryItem
|
||||
|
||||
return g_texturesource->getTextureRaw(os.str());
|
||||
}
|
||||
|
||||
video::ITexture * getImageRaw() const
|
||||
{
|
||||
if(g_texturesource == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_texturesource->getTextureRaw(getBasename());
|
||||
}
|
||||
#endif
|
||||
std::string getText()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "keycode.h"
|
||||
#include "main.h" // For g_settings
|
||||
#include "exceptions.h"
|
||||
#include "settings.h"
|
||||
|
||||
class UnknownKeycode : public BaseException
|
||||
{
|
||||
@@ -335,7 +334,7 @@ KeyPress getKeySetting(const char *settingname)
|
||||
if(n)
|
||||
return n->getValue();
|
||||
g_key_setting_cache.insert(settingname,
|
||||
g_settings->get(settingname).c_str());
|
||||
g_settings.get(settingname).c_str());
|
||||
return g_key_setting_cache.find(settingname)->getValue();
|
||||
}
|
||||
|
||||
|
||||
144
src/log.cpp
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include "threads.h"
|
||||
#include "debug.h"
|
||||
#include "gettime.h"
|
||||
|
||||
std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
|
||||
std::map<threadid_t, std::string> log_threadnames;
|
||||
|
||||
void log_add_output(ILogOutput *out, enum LogMessageLevel lev)
|
||||
{
|
||||
log_outputs[lev].push_back(out);
|
||||
}
|
||||
|
||||
void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev)
|
||||
{
|
||||
for(int i=0; i<=lev; i++)
|
||||
log_outputs[i].push_back(out);
|
||||
}
|
||||
|
||||
void log_add_output_all_levs(ILogOutput *out)
|
||||
{
|
||||
for(int i=0; i<LMT_NUM_VALUES; i++)
|
||||
log_outputs[i].push_back(out);
|
||||
}
|
||||
|
||||
void log_register_thread(const std::string &name)
|
||||
{
|
||||
threadid_t id = get_current_thread_id();
|
||||
log_threadnames[id] = name;
|
||||
}
|
||||
|
||||
static std::string get_lev_string(enum LogMessageLevel lev)
|
||||
{
|
||||
switch(lev){
|
||||
case LMT_ERROR:
|
||||
return "ERROR";
|
||||
case LMT_ACTION:
|
||||
return "ACTION";
|
||||
case LMT_INFO:
|
||||
return "INFO";
|
||||
case LMT_VERBOSE:
|
||||
return "VERBOSE";
|
||||
case LMT_NUM_VALUES:
|
||||
break;
|
||||
}
|
||||
return "(unknown level)";
|
||||
}
|
||||
|
||||
void log_printline(enum LogMessageLevel lev, const std::string &text)
|
||||
{
|
||||
std::string threadname = "(unknown thread)";
|
||||
std::map<threadid_t, std::string>::const_iterator i;
|
||||
i = log_threadnames.find(get_current_thread_id());
|
||||
if(i != log_threadnames.end())
|
||||
threadname = i->second;
|
||||
std::string levelname = get_lev_string(lev);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
os<<getTimestamp()<<": "<<levelname<<"["<<threadname<<"]: "<<text;
|
||||
for(std::list<ILogOutput*>::iterator i = log_outputs[lev].begin();
|
||||
i != log_outputs[lev].end(); i++){
|
||||
ILogOutput *out = *i;
|
||||
out->printLog(os.str());
|
||||
out->printLog(lev, text);
|
||||
}
|
||||
}
|
||||
|
||||
class Logbuf : public std::streambuf
|
||||
{
|
||||
public:
|
||||
Logbuf(enum LogMessageLevel lev):
|
||||
m_lev(lev)
|
||||
{
|
||||
}
|
||||
|
||||
~Logbuf()
|
||||
{
|
||||
}
|
||||
|
||||
int overflow(int c)
|
||||
{
|
||||
bufchar(c);
|
||||
return c;
|
||||
}
|
||||
std::streamsize xsputn(const char *s, std::streamsize n)
|
||||
{
|
||||
for(int i=0; i<n; i++)
|
||||
bufchar(s[i]);
|
||||
return n;
|
||||
}
|
||||
|
||||
void printbuf()
|
||||
{
|
||||
log_printline(m_lev, m_buf);
|
||||
}
|
||||
|
||||
void bufchar(char c)
|
||||
{
|
||||
if(c == '\n' || c == '\r'){
|
||||
if(m_buf != "")
|
||||
printbuf();
|
||||
m_buf = "";
|
||||
return;
|
||||
}
|
||||
m_buf += c;
|
||||
}
|
||||
|
||||
private:
|
||||
enum LogMessageLevel m_lev;
|
||||
std::string m_buf;
|
||||
};
|
||||
|
||||
Logbuf errorbuf(LMT_ERROR);
|
||||
Logbuf actionbuf(LMT_ACTION);
|
||||
Logbuf infobuf(LMT_INFO);
|
||||
Logbuf verbosebuf(LMT_VERBOSE);
|
||||
std::ostream errorstream(&errorbuf);
|
||||
std::ostream actionstream(&actionbuf);
|
||||
std::ostream infostream(&infobuf);
|
||||
std::ostream verbosestream(&verbosebuf);
|
||||
|
||||
|
||||
69
src/log.h
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef LOG_HEADER
|
||||
#define LOG_HEADER
|
||||
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
Use this for logging everything.
|
||||
|
||||
If you need to explicitly print something, use dstream or cout or cerr.
|
||||
*/
|
||||
|
||||
enum LogMessageLevel {
|
||||
LMT_ERROR, /* Something failed ("invalid map data on disk, block (2,2,1)") */
|
||||
LMT_ACTION, /* In-game actions ("celeron55 placed block at (12,4,-5)") */
|
||||
LMT_INFO, /* More deep info ("saving map on disk (only_modified=true)") */
|
||||
LMT_VERBOSE, /* Flood-style ("loaded block (2,2,2) from disk") */
|
||||
LMT_NUM_VALUES,
|
||||
};
|
||||
|
||||
class ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
virtual void printLog(const std::string &line){};
|
||||
/* line: Only actual printed text */
|
||||
virtual void printLog(enum LogMessageLevel lev, const std::string &line){};
|
||||
};
|
||||
|
||||
void log_add_output(ILogOutput *out, enum LogMessageLevel lev);
|
||||
void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev);
|
||||
void log_add_output_all_levs(ILogOutput *out);
|
||||
|
||||
void log_register_thread(const std::string &name);
|
||||
|
||||
void log_printline(enum LogMessageLevel lev, const std::string &text);
|
||||
|
||||
#define LOGLINEF(lev, ...)\
|
||||
{\
|
||||
char buf[10000];\
|
||||
snprintf(buf, 10000, __VA_ARGS__);\
|
||||
log_printline(lev, buf);\
|
||||
}
|
||||
|
||||
extern std::ostream errorstream;
|
||||
extern std::ostream actionstream;
|
||||
extern std::ostream infostream;
|
||||
extern std::ostream verbosestream;
|
||||
|
||||
#endif
|
||||
|
||||
194
src/main.cpp
@@ -411,13 +411,10 @@ Doing currently:
|
||||
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
|
||||
#endif
|
||||
|
||||
#include "irrlicht.h" // createDevice
|
||||
|
||||
#include "main.h"
|
||||
#include "mainmenumanager.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <locale.h>
|
||||
#include "main.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
#include "test.h"
|
||||
@@ -434,11 +431,8 @@ Doing currently:
|
||||
#include "game.h"
|
||||
#include "keycode.h"
|
||||
#include "tile.h"
|
||||
#include "defaultsettings.h"
|
||||
|
||||
#include "gettext.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
|
||||
// This makes textures
|
||||
ITextureSource *g_texturesource = NULL;
|
||||
@@ -447,23 +441,25 @@ ITextureSource *g_texturesource = NULL;
|
||||
Settings.
|
||||
These are loaded from the config file.
|
||||
*/
|
||||
Settings main_settings;
|
||||
Settings *g_settings = &main_settings;
|
||||
|
||||
Settings g_settings;
|
||||
// This is located in defaultsettings.cpp
|
||||
extern void set_default_settings();
|
||||
|
||||
// Global profiler
|
||||
Profiler main_profiler;
|
||||
Profiler *g_profiler = &main_profiler;
|
||||
Profiler g_profiler;
|
||||
|
||||
/*
|
||||
Random stuff
|
||||
*/
|
||||
|
||||
/*
|
||||
mainmenumanager.h
|
||||
GUI Stuff
|
||||
*/
|
||||
|
||||
gui::IGUIEnvironment* guienv = NULL;
|
||||
gui::IGUIStaticText *guiroot = NULL;
|
||||
|
||||
MainMenuManager g_menumgr;
|
||||
|
||||
bool noMenuActive()
|
||||
@@ -472,6 +468,7 @@ bool noMenuActive()
|
||||
}
|
||||
|
||||
// Passed to menus to allow disconnecting and exiting
|
||||
|
||||
MainGameCallback *g_gamecallback = NULL;
|
||||
|
||||
/*
|
||||
@@ -480,17 +477,19 @@ MainGameCallback *g_gamecallback = NULL;
|
||||
|
||||
// Connection
|
||||
std::ostream *dout_con_ptr = &dummyout;
|
||||
std::ostream *derr_con_ptr = &verbosestream;
|
||||
//std::ostream *dout_con_ptr = &infostream;
|
||||
//std::ostream *derr_con_ptr = &errorstream;
|
||||
std::ostream *derr_con_ptr = &dstream_no_stderr;
|
||||
//std::ostream *dout_con_ptr = &dstream_no_stderr;
|
||||
//std::ostream *derr_con_ptr = &dstream_no_stderr;
|
||||
//std::ostream *dout_con_ptr = &dstream;
|
||||
//std::ostream *derr_con_ptr = &dstream;
|
||||
|
||||
// Server
|
||||
std::ostream *dout_server_ptr = &infostream;
|
||||
std::ostream *derr_server_ptr = &errorstream;
|
||||
std::ostream *dout_server_ptr = &dstream;
|
||||
std::ostream *derr_server_ptr = &dstream;
|
||||
|
||||
// Client
|
||||
std::ostream *dout_client_ptr = &infostream;
|
||||
std::ostream *derr_client_ptr = &errorstream;
|
||||
std::ostream *dout_client_ptr = &dstream;
|
||||
std::ostream *derr_client_ptr = &dstream;
|
||||
|
||||
/*
|
||||
gettime.h implementation
|
||||
@@ -582,6 +581,7 @@ class MyEventReceiver : public IEventReceiver
|
||||
}
|
||||
else
|
||||
{
|
||||
//dstream<<"MyEventReceiver: mouse input"<<std::endl;
|
||||
left_active = event.MouseInput.isLeftPressed();
|
||||
middle_active = event.MouseInput.isMiddlePressed();
|
||||
right_active = event.MouseInput.isRightPressed();
|
||||
@@ -1024,7 +1024,7 @@ void SpeedTests()
|
||||
|
||||
u32 dtime = timer.stop();
|
||||
u32 per_ms = n / dtime;
|
||||
dstream<<"Done. "<<dtime<<"ms, "
|
||||
std::cout<<"Done. "<<dtime<<"ms, "
|
||||
<<per_ms<<"/ms"<<std::endl;
|
||||
}
|
||||
}
|
||||
@@ -1076,37 +1076,12 @@ void drawMenuBackground(video::IVideoDriver* driver)
|
||||
}
|
||||
}
|
||||
|
||||
class StderrLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
std::cerr<<line<<std::endl;
|
||||
}
|
||||
} main_stderr_log_out;
|
||||
|
||||
class DstreamNoStderrLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
dstream_no_stderr<<line<<std::endl;
|
||||
}
|
||||
} main_dstream_no_stderr_log_out;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/*
|
||||
Initialization
|
||||
*/
|
||||
|
||||
log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION);
|
||||
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
||||
|
||||
log_register_thread("main");
|
||||
|
||||
// Set locale. This is for forcing '.' as the decimal point.
|
||||
std::locale::global(std::locale("C"));
|
||||
// This enables printing all characters in bitmap font
|
||||
@@ -1133,7 +1108,6 @@ int main(int argc, char *argv[])
|
||||
allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG));
|
||||
#endif
|
||||
allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG));
|
||||
allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG));
|
||||
|
||||
Settings cmd_args;
|
||||
|
||||
@@ -1175,9 +1149,6 @@ int main(int argc, char *argv[])
|
||||
if(cmd_args.getFlag("dstream-on-stderr") == false)
|
||||
disable_stderr = true;
|
||||
#endif
|
||||
|
||||
if(cmd_args.getFlag("info-on-stderr"))
|
||||
log_add_output(&main_stderr_log_out, LMT_INFO);
|
||||
|
||||
porting::signal_handler_init();
|
||||
bool &kill = *porting::signal_handler_killstatus();
|
||||
@@ -1188,13 +1159,13 @@ int main(int argc, char *argv[])
|
||||
// Create user data directory
|
||||
fs::CreateDir(porting::path_userdata);
|
||||
|
||||
init_gettext((porting::path_data+DIR_DELIM+".."+DIR_DELIM+"locale").c_str());
|
||||
init_gettext((porting::path_data+"/../locale").c_str());
|
||||
|
||||
// Initialize debug streams
|
||||
#ifdef RUN_IN_PLACE
|
||||
std::string debugfile = DEBUGFILE;
|
||||
#else
|
||||
std::string debugfile = porting::path_userdata+DIR_DELIM+DEBUGFILE;
|
||||
std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;
|
||||
#endif
|
||||
debugstreams_init(disable_stderr, debugfile.c_str());
|
||||
// Initialize debug stacks
|
||||
@@ -1209,7 +1180,7 @@ int main(int argc, char *argv[])
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
// Print startup message
|
||||
actionstream<<PROJECT_NAME<<
|
||||
dstream<<DTIME<<PROJECT_NAME
|
||||
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
|
||||
<<", "<<BUILD_INFO
|
||||
<<std::endl;
|
||||
@@ -1219,7 +1190,7 @@ int main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
// Initialize default settings
|
||||
set_default_settings(g_settings);
|
||||
set_default_settings();
|
||||
|
||||
// Initialize sockets
|
||||
sockets_init();
|
||||
@@ -1234,10 +1205,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(cmd_args.exists("config"))
|
||||
{
|
||||
bool r = g_settings->readConfigFile(cmd_args.get("config").c_str());
|
||||
bool r = g_settings.readConfigFile(cmd_args.get("config").c_str());
|
||||
if(r == false)
|
||||
{
|
||||
errorstream<<"Could not read configuration from \""
|
||||
dstream<<"Could not read configuration from \""
|
||||
<<cmd_args.get("config")<<"\""<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
@@ -1246,16 +1217,14 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
{
|
||||
core::array<std::string> filenames;
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + "minetest.conf");
|
||||
filenames.push_back(porting::path_userdata + "/minetest.conf");
|
||||
#ifdef RUN_IN_PLACE
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + ".." + DIR_DELIM + "minetest.conf");
|
||||
filenames.push_back(porting::path_userdata + "/../minetest.conf");
|
||||
#endif
|
||||
|
||||
for(u32 i=0; i<filenames.size(); i++)
|
||||
{
|
||||
bool r = g_settings->readConfigFile(filenames[i].c_str());
|
||||
bool r = g_settings.readConfigFile(filenames[i].c_str());
|
||||
if(r)
|
||||
{
|
||||
configpath = filenames[i];
|
||||
@@ -1280,9 +1249,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Initial call with g_texturesource not set.
|
||||
init_mapnode();
|
||||
// Must be called before g_texturesource is created
|
||||
// (for texture atlas making)
|
||||
init_mineral();
|
||||
|
||||
/*
|
||||
Run unit tests
|
||||
@@ -1309,17 +1275,17 @@ int main(int argc, char *argv[])
|
||||
u16 port = 30000;
|
||||
if(cmd_args.exists("port"))
|
||||
port = cmd_args.getU16("port");
|
||||
else if(g_settings->exists("port"))
|
||||
port = g_settings->getU16("port");
|
||||
else if(g_settings.exists("port"))
|
||||
port = g_settings.getU16("port");
|
||||
if(port == 0)
|
||||
port = 30000;
|
||||
|
||||
// Map directory
|
||||
std::string map_dir = porting::path_userdata+DIR_DELIM+"world";
|
||||
std::string map_dir = porting::path_userdata+"/world";
|
||||
if(cmd_args.exists("map-dir"))
|
||||
map_dir = cmd_args.get("map-dir");
|
||||
else if(g_settings->exists("map-dir"))
|
||||
map_dir = g_settings->get("map-dir");
|
||||
else if(g_settings.exists("map-dir"))
|
||||
map_dir = g_settings.get("map-dir");
|
||||
|
||||
// Run dedicated server if asked to
|
||||
if(cmd_args.getFlag("server"))
|
||||
@@ -1353,10 +1319,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
address = g_settings->get("address");
|
||||
address = g_settings.get("address");
|
||||
}
|
||||
|
||||
std::string playername = g_settings->get("name");
|
||||
std::string playername = g_settings.get("name");
|
||||
|
||||
/*
|
||||
Device initialization
|
||||
@@ -1365,14 +1331,14 @@ int main(int argc, char *argv[])
|
||||
// Resolution selection
|
||||
|
||||
bool fullscreen = false;
|
||||
u16 screenW = g_settings->getU16("screenW");
|
||||
u16 screenH = g_settings->getU16("screenH");
|
||||
u16 screenW = g_settings.getU16("screenW");
|
||||
u16 screenH = g_settings.getU16("screenH");
|
||||
|
||||
// Determine driver
|
||||
|
||||
video::E_DRIVER_TYPE driverType;
|
||||
|
||||
std::string driverstring = g_settings->get("video_driver");
|
||||
std::string driverstring = g_settings.get("video_driver");
|
||||
|
||||
if(driverstring == "null")
|
||||
driverType = video::EDT_NULL;
|
||||
@@ -1388,7 +1354,7 @@ int main(int argc, char *argv[])
|
||||
driverType = video::EDT_OPENGL;
|
||||
else
|
||||
{
|
||||
errorstream<<"WARNING: Invalid video_driver specified; defaulting "
|
||||
dstream<<"WARNING: Invalid video_driver specified; defaulting "
|
||||
"to opengl"<<std::endl;
|
||||
driverType = video::EDT_OPENGL;
|
||||
}
|
||||
@@ -1407,21 +1373,6 @@ int main(int argc, char *argv[])
|
||||
if (device == 0)
|
||||
return 1; // could not create selected driver.
|
||||
|
||||
/*
|
||||
Continue initialization
|
||||
*/
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
|
||||
// Disable mipmaps (because some of them look ugly)
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
|
||||
|
||||
/*
|
||||
This changes the minimum allowed number of vertices in a VBO.
|
||||
Default is 500.
|
||||
*/
|
||||
//driver->setMinHardwareBufferVertexCount(50);
|
||||
|
||||
// Set the window caption
|
||||
device->setWindowCaption(L"Minetest [Main Menu]");
|
||||
|
||||
@@ -1446,7 +1397,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
device->setResizable(true);
|
||||
|
||||
bool random_input = g_settings->getBool("random_input")
|
||||
bool random_input = g_settings.getBool("random_input")
|
||||
|| cmd_args.getFlag("random-input");
|
||||
InputHandler *input = NULL;
|
||||
if(random_input)
|
||||
@@ -1454,6 +1405,18 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
input = new RealInputHandler(device, &receiver);
|
||||
|
||||
/*
|
||||
Continue initialization
|
||||
*/
|
||||
|
||||
//video::IVideoDriver* driver = device->getVideoDriver();
|
||||
|
||||
/*
|
||||
This changes the minimum allowed number of vertices in a VBO.
|
||||
Default is 500.
|
||||
*/
|
||||
//driver->setMinHardwareBufferVertexCount(50);
|
||||
|
||||
scene::ISceneManager* smgr = device->getSceneManager();
|
||||
|
||||
guienv = device->getGUIEnvironment();
|
||||
@@ -1462,14 +1425,14 @@ int main(int argc, char *argv[])
|
||||
if(font)
|
||||
skin->setFont(font);
|
||||
else
|
||||
errorstream<<"WARNING: Font file was not found."
|
||||
dstream<<"WARNING: Font file was not found."
|
||||
" Using default font."<<std::endl;
|
||||
// If font was not found, this will get us one
|
||||
font = skin->getFont();
|
||||
assert(font);
|
||||
|
||||
u32 text_height = font->getDimension(L"Hello, world!").Height;
|
||||
infostream<<"text_height="<<text_height<<std::endl;
|
||||
dstream<<"text_height="<<text_height<<std::endl;
|
||||
|
||||
//skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0));
|
||||
skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255));
|
||||
@@ -1483,6 +1446,7 @@ int main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
init_mapnode(); // Second call with g_texturesource set
|
||||
init_mineral();
|
||||
|
||||
/*
|
||||
GUI stuff
|
||||
@@ -1544,12 +1508,10 @@ int main(int argc, char *argv[])
|
||||
menudata.address = narrow_to_wide(address);
|
||||
menudata.name = narrow_to_wide(playername);
|
||||
menudata.port = narrow_to_wide(itos(port));
|
||||
menudata.fancy_trees = g_settings->getBool("new_style_leaves");
|
||||
menudata.smooth_lighting = g_settings->getBool("smooth_lighting");
|
||||
menudata.clouds_3d = g_settings->getBool("enable_3d_clouds");
|
||||
menudata.opaque_water = g_settings->getBool("opaque_water");
|
||||
menudata.creative_mode = g_settings->getBool("creative_mode");
|
||||
menudata.enable_damage = g_settings->getBool("enable_damage");
|
||||
menudata.fancy_trees = g_settings.getBool("new_style_leaves");
|
||||
menudata.smooth_lighting = g_settings.getBool("smooth_lighting");
|
||||
menudata.creative_mode = g_settings.getBool("creative_mode");
|
||||
menudata.enable_damage = g_settings.getBool("enable_damage");
|
||||
|
||||
GUIMainMenu *menu =
|
||||
new GUIMainMenu(guienv, guiroot, -1,
|
||||
@@ -1558,7 +1520,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(error_message != L"")
|
||||
{
|
||||
errorstream<<"error_message = "
|
||||
dstream<<"WARNING: error_message = "
|
||||
<<wide_to_narrow(error_message)<<std::endl;
|
||||
|
||||
GUIMessageMenu *menu2 =
|
||||
@@ -1570,7 +1532,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
|
||||
infostream<<"Created main menu"<<std::endl;
|
||||
dstream<<"Created main menu"<<std::endl;
|
||||
|
||||
while(device->run() && kill == false)
|
||||
{
|
||||
@@ -1595,7 +1557,7 @@ int main(int argc, char *argv[])
|
||||
if(device->run() == false || kill == true)
|
||||
break;
|
||||
|
||||
infostream<<"Dropping main menu"<<std::endl;
|
||||
dstream<<"Dropping main menu"<<std::endl;
|
||||
|
||||
menu->drop();
|
||||
|
||||
@@ -1612,18 +1574,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
password = translatePassword(playername, menudata.password);
|
||||
|
||||
//infostream<<"Main: password hash: '"<<password<<"'"<<std::endl;
|
||||
//dstream<<"Main: password hash: '"<<password<<"'"<<std::endl;
|
||||
|
||||
address = wide_to_narrow(menudata.address);
|
||||
int newport = stoi(wide_to_narrow(menudata.port));
|
||||
if(newport != 0)
|
||||
port = newport;
|
||||
g_settings->set("new_style_leaves", itos(menudata.fancy_trees));
|
||||
g_settings->set("smooth_lighting", itos(menudata.smooth_lighting));
|
||||
g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d));
|
||||
g_settings->set("opaque_water", itos(menudata.opaque_water));
|
||||
g_settings->set("creative_mode", itos(menudata.creative_mode));
|
||||
g_settings->set("enable_damage", itos(menudata.enable_damage));
|
||||
g_settings.set("new_style_leaves", itos(menudata.fancy_trees));
|
||||
g_settings.set("smooth_lighting", itos(menudata.smooth_lighting));
|
||||
g_settings.set("creative_mode", itos(menudata.creative_mode));
|
||||
g_settings.set("enable_damage", itos(menudata.enable_damage));
|
||||
|
||||
// NOTE: These are now checked server side; no need to do it
|
||||
// here, so let's not do it here.
|
||||
@@ -1642,12 +1602,12 @@ int main(int argc, char *argv[])
|
||||
}*/
|
||||
|
||||
// Save settings
|
||||
g_settings->set("name", playername);
|
||||
g_settings->set("address", address);
|
||||
g_settings->set("port", itos(port));
|
||||
g_settings.set("name", playername);
|
||||
g_settings.set("address", address);
|
||||
g_settings.set("port", itos(port));
|
||||
// Update configuration file
|
||||
if(configpath != "")
|
||||
g_settings->updateConfigFile(configpath.c_str());
|
||||
g_settings.updateConfigFile(configpath.c_str());
|
||||
|
||||
// Continue to game
|
||||
break;
|
||||
@@ -1681,12 +1641,12 @@ int main(int argc, char *argv[])
|
||||
} //try
|
||||
catch(con::PeerNotFoundException &e)
|
||||
{
|
||||
errorstream<<"Connection error (timed out?)"<<std::endl;
|
||||
dstream<<DTIME<<"Connection error (timed out?)"<<std::endl;
|
||||
error_message = L"Connection error (timed out?)";
|
||||
}
|
||||
catch(SocketException &e)
|
||||
{
|
||||
errorstream<<"Socket error (port already in use?)"<<std::endl;
|
||||
dstream<<DTIME<<"Socket error (port already in use?)"<<std::endl;
|
||||
error_message = L"Socket error (port already in use?)";
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
@@ -1695,7 +1655,7 @@ int main(int argc, char *argv[])
|
||||
std::string narrow_message = "Some exception, what()=\"";
|
||||
narrow_message += e.what();
|
||||
narrow_message += "\"";
|
||||
errorstream<<narrow_message<<std::endl;
|
||||
dstream<<DTIME<<narrow_message<<std::endl;
|
||||
error_message = narrow_to_wide(narrow_message);
|
||||
}
|
||||
#endif
|
||||
@@ -1709,7 +1669,7 @@ int main(int argc, char *argv[])
|
||||
*/
|
||||
device->drop();
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
END_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
debugstreams_deinit();
|
||||
|
||||
|
||||
108
src/main.h
@@ -21,16 +21,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MAIN_HEADER
|
||||
|
||||
// Settings
|
||||
class Settings;
|
||||
extern Settings *g_settings;
|
||||
#include "utility.h"
|
||||
extern Settings g_settings;
|
||||
|
||||
// This makes and maps textures
|
||||
class ITextureSource;
|
||||
extern ITextureSource *g_texturesource;
|
||||
|
||||
// Global profiler
|
||||
class Profiler;
|
||||
extern Profiler *g_profiler;
|
||||
#include "profiler.h"
|
||||
extern Profiler g_profiler;
|
||||
|
||||
// Debug streams
|
||||
|
||||
@@ -50,5 +50,105 @@ extern std::ostream *derr_server_ptr;
|
||||
#define dout_server (*dout_server_ptr)
|
||||
#define derr_server (*derr_server_ptr)
|
||||
|
||||
/*
|
||||
All kinds of stuff that needs to be exposed from main.cpp
|
||||
*/
|
||||
|
||||
#include "modalMenu.h"
|
||||
#include "guiPauseMenu.h" //For IGameCallback
|
||||
|
||||
extern gui::IGUIEnvironment* guienv;
|
||||
extern gui::IGUIStaticText *guiroot;
|
||||
|
||||
// Handler for the modal menus
|
||||
|
||||
class MainMenuManager : public IMenuManager
|
||||
{
|
||||
public:
|
||||
virtual void createdMenu(GUIModalMenu *menu)
|
||||
{
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
assert(*i != menu);
|
||||
}
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(false);
|
||||
m_stack.push_back(menu);
|
||||
}
|
||||
|
||||
virtual void deletingMenu(GUIModalMenu *menu)
|
||||
{
|
||||
// Remove all entries if there are duplicates
|
||||
bool removed_entry;
|
||||
do{
|
||||
removed_entry = false;
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
if(*i == menu)
|
||||
{
|
||||
m_stack.erase(i);
|
||||
removed_entry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(removed_entry);
|
||||
|
||||
/*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast();
|
||||
assert(*i == menu);
|
||||
m_stack.erase(i);*/
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(true);
|
||||
}
|
||||
|
||||
u32 menuCount()
|
||||
{
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
core::list<GUIModalMenu*> m_stack;
|
||||
};
|
||||
|
||||
extern MainMenuManager g_menumgr;
|
||||
|
||||
extern bool noMenuActive();
|
||||
|
||||
class MainGameCallback : public IGameCallback
|
||||
{
|
||||
public:
|
||||
MainGameCallback(IrrlichtDevice *a_device):
|
||||
disconnect_requested(false),
|
||||
changepassword_requested(false),
|
||||
device(a_device)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void exitToOS()
|
||||
{
|
||||
device->closeDevice();
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
disconnect_requested = true;
|
||||
}
|
||||
|
||||
virtual void changePassword()
|
||||
{
|
||||
changepassword_requested = true;
|
||||
}
|
||||
|
||||
bool disconnect_requested;
|
||||
bool changepassword_requested;
|
||||
IrrlichtDevice *device;
|
||||
};
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,124 +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.
|
||||
*/
|
||||
|
||||
#ifndef MAINMENUMANAGER_HEADER
|
||||
#define MAINMENUMANAGER_HEADER
|
||||
|
||||
/*
|
||||
All kinds of stuff that needs to be exposed from main.cpp
|
||||
*/
|
||||
#include "debug.h" // assert
|
||||
#include "modalMenu.h"
|
||||
#include "guiPauseMenu.h" //For IGameCallback
|
||||
|
||||
extern gui::IGUIEnvironment* guienv;
|
||||
extern gui::IGUIStaticText *guiroot;
|
||||
|
||||
// Handler for the modal menus
|
||||
|
||||
class MainMenuManager : public IMenuManager
|
||||
{
|
||||
public:
|
||||
virtual void createdMenu(GUIModalMenu *menu)
|
||||
{
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
assert(*i != menu);
|
||||
}
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(false);
|
||||
m_stack.push_back(menu);
|
||||
}
|
||||
|
||||
virtual void deletingMenu(GUIModalMenu *menu)
|
||||
{
|
||||
// Remove all entries if there are duplicates
|
||||
bool removed_entry;
|
||||
do{
|
||||
removed_entry = false;
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
if(*i == menu)
|
||||
{
|
||||
m_stack.erase(i);
|
||||
removed_entry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(removed_entry);
|
||||
|
||||
/*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast();
|
||||
assert(*i == menu);
|
||||
m_stack.erase(i);*/
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(true);
|
||||
}
|
||||
|
||||
u32 menuCount()
|
||||
{
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
core::list<GUIModalMenu*> m_stack;
|
||||
};
|
||||
|
||||
extern MainMenuManager g_menumgr;
|
||||
|
||||
extern bool noMenuActive();
|
||||
|
||||
class MainGameCallback : public IGameCallback
|
||||
{
|
||||
public:
|
||||
MainGameCallback(IrrlichtDevice *a_device):
|
||||
disconnect_requested(false),
|
||||
changepassword_requested(false),
|
||||
device(a_device)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void exitToOS()
|
||||
{
|
||||
device->closeDevice();
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
disconnect_requested = true;
|
||||
}
|
||||
|
||||
virtual void changePassword()
|
||||
{
|
||||
changepassword_requested = true;
|
||||
}
|
||||
|
||||
bool disconnect_requested;
|
||||
bool changepassword_requested;
|
||||
IrrlichtDevice *device;
|
||||
};
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
||||
|
||||
#endif
|
||||
|
||||
775
src/map.cpp
16
src/map.h
@@ -157,10 +157,6 @@ class Map /*: public NodeContainer*/
|
||||
// Returns NULL if not found
|
||||
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
||||
|
||||
/* Server overrides */
|
||||
virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true)
|
||||
{ return getBlockNoCreateNoEx(p); }
|
||||
|
||||
// Returns InvalidPositionException if not found
|
||||
bool isNodeUnderground(v3s16 p);
|
||||
|
||||
@@ -209,7 +205,7 @@ class Map /*: public NodeContainer*/
|
||||
These handle lighting but not faces.
|
||||
*/
|
||||
void addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name);
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
void removeNodeAndUpdate(v3s16 p,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
|
||||
@@ -383,7 +379,6 @@ class ServerMap : public Map
|
||||
void verifyDatabase();
|
||||
// Get an integer suitable for a block
|
||||
static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
|
||||
static v3s16 getIntegerAsBlock(sqlite3_int64 i);
|
||||
|
||||
// Returns true if the database file does not exist
|
||||
bool loadFromFolders();
|
||||
@@ -395,8 +390,6 @@ class ServerMap : public Map
|
||||
void save(bool only_changed);
|
||||
//void loadAll();
|
||||
|
||||
void listAllLoadableBlocks(core::list<v3s16> &dst);
|
||||
|
||||
// Saves map seed and possibly other stuff
|
||||
void saveMapMeta();
|
||||
void loadMapMeta();
|
||||
@@ -461,7 +454,6 @@ class ServerMap : public Map
|
||||
sqlite3 *m_database;
|
||||
sqlite3_stmt *m_database_read;
|
||||
sqlite3_stmt *m_database_write;
|
||||
sqlite3_stmt *m_database_list;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -526,12 +518,11 @@ class ClientMap : public Map, public scene::ISceneNode
|
||||
ISceneNode::drop();
|
||||
}
|
||||
|
||||
void updateCamera(v3f pos, v3f dir, f32 fov)
|
||||
void updateCamera(v3f pos, v3f dir)
|
||||
{
|
||||
JMutexAutoLock lock(m_camera_mutex);
|
||||
m_camera_position = pos;
|
||||
m_camera_direction = dir;
|
||||
m_camera_fov = fov;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -561,8 +552,6 @@ class ClientMap : public Map, public scene::ISceneNode
|
||||
|
||||
void renderMap(video::IVideoDriver* driver, s32 pass);
|
||||
|
||||
void renderPostFx();
|
||||
|
||||
/*
|
||||
Methods for setting temporary modifications to nodes for
|
||||
drawing.
|
||||
@@ -612,7 +601,6 @@ class ClientMap : public Map, public scene::ISceneNode
|
||||
|
||||
v3f m_camera_position;
|
||||
v3f m_camera_direction;
|
||||
f32 m_camera_fov;
|
||||
JMutex m_camera_mutex;
|
||||
|
||||
core::map<v2s16, bool> m_last_drawn_sectors;
|
||||
|
||||
@@ -36,6 +36,7 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
||||
m_lighting_expired(true),
|
||||
m_day_night_differs(false),
|
||||
m_generated(false),
|
||||
m_objects(this),
|
||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||
m_usage_timer(0)
|
||||
{
|
||||
@@ -433,6 +434,17 @@ void MapBlock::copyFrom(VoxelManipulator &dst)
|
||||
getPosRelative(), data_size);
|
||||
}
|
||||
|
||||
void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
||||
{
|
||||
/*
|
||||
Step objects
|
||||
*/
|
||||
m_objects.step(dtime, server, daynight_ratio);
|
||||
|
||||
setChangedFlag();
|
||||
}
|
||||
|
||||
|
||||
void MapBlock::updateDayNightDiff()
|
||||
{
|
||||
if(data == NULL)
|
||||
@@ -805,9 +817,10 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
|
||||
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||
{
|
||||
// Versions up from 9 have block objects. (DEPRECATED)
|
||||
// Versions up from 9 have block objects.
|
||||
if(version >= 9)
|
||||
{
|
||||
//serializeObjects(os, version); // DEPRECATED
|
||||
// count=0
|
||||
writeU16(os, 0);
|
||||
}
|
||||
@@ -828,17 +841,11 @@ void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||
void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
|
||||
{
|
||||
/*
|
||||
Versions up from 9 have block objects. (DEPRECATED)
|
||||
Versions up from 9 have block objects.
|
||||
*/
|
||||
if(version >= 9)
|
||||
{
|
||||
u16 count = readU16(is);
|
||||
// Not supported and length not known if count is not 0
|
||||
if(count != 0){
|
||||
dstream<<"WARNING: MapBlock::deSerializeDiskExtra(): "
|
||||
<<"Ignoring stuff coming at and after MBOs"<<std::endl;
|
||||
return;
|
||||
}
|
||||
updateObjects(is, version, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "exceptions.h"
|
||||
#include "serialization.h"
|
||||
#include "constants.h"
|
||||
#include "mapblockobject.h"
|
||||
#include "voxel.h"
|
||||
#include "nodemetadata.h"
|
||||
#include "staticobject.h"
|
||||
@@ -224,10 +225,8 @@ class MapBlock /*: public NodeContainer*/
|
||||
|
||||
void setLightingExpired(bool expired)
|
||||
{
|
||||
if(expired != m_lighting_expired){
|
||||
m_lighting_expired = expired;
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
m_lighting_expired = expired;
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
bool getLightingExpired()
|
||||
{
|
||||
@@ -240,10 +239,8 @@ class MapBlock /*: public NodeContainer*/
|
||||
}
|
||||
void setGenerated(bool b)
|
||||
{
|
||||
if(b != m_generated){
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
m_generated = b;
|
||||
}
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
m_generated = b;
|
||||
}
|
||||
|
||||
bool isValid()
|
||||
@@ -422,6 +419,68 @@ class MapBlock /*: public NodeContainer*/
|
||||
// Copies data from VoxelManipulator getPosRelative()
|
||||
void copyFrom(VoxelManipulator &dst);
|
||||
|
||||
/*
|
||||
MapBlockObject stuff
|
||||
DEPRECATED
|
||||
*/
|
||||
|
||||
/*void serializeObjects(std::ostream &os, u8 version)
|
||||
{
|
||||
m_objects.serialize(os, version);
|
||||
}*/
|
||||
// If smgr!=NULL, new objects are added to the scene
|
||||
void updateObjects(std::istream &is, u8 version,
|
||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
||||
{
|
||||
m_objects.update(is, version, smgr, daynight_ratio);
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void clearObjects()
|
||||
{
|
||||
m_objects.clear();
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void addObject(MapBlockObject *object)
|
||||
throw(ContainerFullException, AlreadyExistsException)
|
||||
{
|
||||
m_objects.add(object);
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void removeObject(s16 id)
|
||||
{
|
||||
m_objects.remove(id);
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
MapBlockObject * getObject(s16 id)
|
||||
{
|
||||
return m_objects.get(id);
|
||||
}
|
||||
JMutexAutoLock * getObjectLock()
|
||||
{
|
||||
return m_objects.getLock();
|
||||
}
|
||||
|
||||
/*
|
||||
Moves objects, deletes objects and spawns new objects
|
||||
*/
|
||||
void stepObjects(float dtime, bool server, u32 daynight_ratio);
|
||||
|
||||
// origin is relative to block
|
||||
void getObjects(v3f origin, f32 max_d,
|
||||
core::array<DistanceSortedObject> &dest)
|
||||
{
|
||||
m_objects.getObjects(origin, max_d, dest);
|
||||
}
|
||||
|
||||
s32 getObjectCount()
|
||||
{
|
||||
return m_objects.getCount();
|
||||
}
|
||||
|
||||
#ifndef SERVER // Only on client
|
||||
/*
|
||||
Methods for setting temporary modifications to nodes for
|
||||
@@ -625,6 +684,9 @@ class MapBlock /*: public NodeContainer*/
|
||||
|
||||
bool m_generated;
|
||||
|
||||
// DEPRECATED
|
||||
MapBlockObjectList m_objects;
|
||||
|
||||
#ifndef SERVER // Only on client
|
||||
/*
|
||||
Set to true if the mesh has been ordered to be updated
|
||||
|
||||
@@ -23,8 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "map.h"
|
||||
#include "main.h" // For g_settings and g_texturesource
|
||||
#include "content_mapblock.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
|
||||
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
||||
{
|
||||
@@ -427,8 +425,7 @@ void getTileInfo(
|
||||
// This is hackish
|
||||
content_t content0 = getNodeContent(p, n0, temp_mods);
|
||||
content_t content1 = getNodeContent(p + face_dir, n1, temp_mods);
|
||||
bool equivalent = false;
|
||||
u8 mf = face_contents(content0, content1, &equivalent);
|
||||
u8 mf = face_contents(content0, content1);
|
||||
|
||||
if(mf == 0)
|
||||
{
|
||||
@@ -451,10 +448,6 @@ void getTileInfo(
|
||||
face_dir_corrected = -face_dir;
|
||||
}
|
||||
|
||||
// eg. water and glass
|
||||
if(equivalent)
|
||||
tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
|
||||
if(smooth_lighting == false)
|
||||
{
|
||||
lights[0] = lights[1] = lights[2] = lights[3] =
|
||||
@@ -498,10 +491,10 @@ void updateFastFaceRow(
|
||||
|
||||
u16 continuous_tiles_count = 0;
|
||||
|
||||
bool makes_face = false;
|
||||
bool makes_face;
|
||||
v3s16 p_corrected;
|
||||
v3s16 face_dir_corrected;
|
||||
u8 lights[4] = {0,0,0,0};
|
||||
u8 lights[4];
|
||||
TileSpec tile;
|
||||
getTileInfo(blockpos_nodes, p, face_dir, daynight_ratio,
|
||||
vmanip, temp_mods, smooth_lighting,
|
||||
@@ -533,7 +526,7 @@ void updateFastFaceRow(
|
||||
next_tile);
|
||||
|
||||
if(next_makes_face == makes_face
|
||||
&& next_p_corrected == p_corrected + translate_dir
|
||||
&& next_p_corrected == p_corrected
|
||||
&& next_face_dir_corrected == face_dir_corrected
|
||||
&& next_lights[0] == lights[0]
|
||||
&& next_lights[1] == lights[1]
|
||||
@@ -543,29 +536,6 @@ void updateFastFaceRow(
|
||||
{
|
||||
next_is_different = false;
|
||||
}
|
||||
else{
|
||||
/*if(makes_face){
|
||||
g_profiler->add("Meshgen: diff: next_makes_face != makes_face",
|
||||
next_makes_face != makes_face ? 1 : 0);
|
||||
g_profiler->add("Meshgen: diff: n_p_corr != p_corr + t_dir",
|
||||
(next_p_corrected != p_corrected + translate_dir) ? 1 : 0);
|
||||
g_profiler->add("Meshgen: diff: next_f_dir_corr != f_dir_corr",
|
||||
next_face_dir_corrected != face_dir_corrected ? 1 : 0);
|
||||
g_profiler->add("Meshgen: diff: next_lights[] != lights[]",
|
||||
(next_lights[0] != lights[0] ||
|
||||
next_lights[0] != lights[0] ||
|
||||
next_lights[0] != lights[0] ||
|
||||
next_lights[0] != lights[0]) ? 1 : 0);
|
||||
g_profiler->add("Meshgen: diff: !(next_tile == tile)",
|
||||
!(next_tile == tile) ? 1 : 0);
|
||||
}*/
|
||||
}
|
||||
/*g_profiler->add("Meshgen: Total faces checked", 1);
|
||||
if(makes_face)
|
||||
g_profiler->add("Meshgen: Total makes_face checked", 1);*/
|
||||
} else {
|
||||
/*if(makes_face)
|
||||
g_profiler->add("Meshgen: diff: last position", 1);*/
|
||||
}
|
||||
|
||||
continuous_tiles_count++;
|
||||
@@ -597,8 +567,6 @@ void updateFastFaceRow(
|
||||
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;
|
||||
if(continuous_tiles_count != 1)
|
||||
sp += translate_dir_f;
|
||||
v3f scale(1,1,1);
|
||||
|
||||
if(translate_dir.X != 0)
|
||||
@@ -617,11 +585,6 @@ void updateFastFaceRow(
|
||||
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
|
||||
sp, face_dir_corrected, scale,
|
||||
posRelative_f, dest);
|
||||
|
||||
g_profiler->avg("Meshgen: faces drawn by tiling", 0);
|
||||
for(int i=1; i<continuous_tiles_count; i++){
|
||||
g_profiler->avg("Meshgen: faces drawn by tiling", 1);
|
||||
}
|
||||
}
|
||||
|
||||
continuous_tiles_count = 0;
|
||||
@@ -656,9 +619,9 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
|
||||
/*
|
||||
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");
|
||||
//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.
|
||||
@@ -743,13 +706,10 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
|
||||
|
||||
video::SMaterial material;
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||
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);
|
||||
material.MaterialType
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
for(u32 i=0; i<fastfaces_new.size(); i++)
|
||||
{
|
||||
|
||||
939
src/mapblockobject.cpp
Normal file
@@ -0,0 +1,939 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file contains the DEPRECATED MapBlockObject system
|
||||
|
||||
#include "mapblockobject.h"
|
||||
#include "mapblock.h"
|
||||
// For object wrapping
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
#include "utility.h"
|
||||
#include "mapblock.h"
|
||||
|
||||
/*
|
||||
MapBlockObject
|
||||
*/
|
||||
|
||||
// This is here because it uses the MapBlock
|
||||
v3f MapBlockObject::getAbsolutePos()
|
||||
{
|
||||
if(m_block == NULL)
|
||||
return m_pos;
|
||||
|
||||
// getPosRelative gets nodepos relative to map origin
|
||||
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
||||
return blockpos + m_pos;
|
||||
}
|
||||
|
||||
void MapBlockObject::setBlockChanged()
|
||||
{
|
||||
if(m_block)
|
||||
m_block->setChangedFlag();
|
||||
}
|
||||
|
||||
/*
|
||||
MovingObject
|
||||
*/
|
||||
|
||||
v3f MovingObject::getAbsoluteShowPos()
|
||||
{
|
||||
if(m_block == NULL)
|
||||
return m_pos;
|
||||
|
||||
// getPosRelative gets nodepos relative to map origin
|
||||
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
||||
return blockpos + m_showpos;
|
||||
}
|
||||
|
||||
void MovingObject::move(float dtime, v3f acceleration)
|
||||
{
|
||||
DSTACKF("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
|
||||
", dtime=%f, acc=(%f,%f,%f)",
|
||||
__FUNCTION_NAME,
|
||||
getTypeId(),
|
||||
m_pos.X, m_pos.Y, m_pos.Z,
|
||||
m_speed.X, m_speed.Y, m_speed.Z,
|
||||
dtime,
|
||||
acceleration.X, acceleration.Y, acceleration.Z
|
||||
);
|
||||
|
||||
v3s16 oldpos_i = floatToInt(m_pos, BS);
|
||||
|
||||
if(m_block->isValidPosition(oldpos_i) == false)
|
||||
{
|
||||
// Should have wrapped, cancelling further movement.
|
||||
return;
|
||||
}
|
||||
|
||||
// No collisions if there is no collision box
|
||||
if(m_collision_box == NULL)
|
||||
{
|
||||
m_speed += dtime * acceleration;
|
||||
m_pos += m_speed * dtime;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set insane speed to zero
|
||||
// Otherwise there will be divides by zero and other silly stuff
|
||||
if(m_speed.getLength() > 1000.0*BS)
|
||||
m_speed = v3f(0,0,0);
|
||||
|
||||
// Limit speed to a reasonable value
|
||||
float speed_limit = 20.0*BS;
|
||||
if(m_speed.getLength() > speed_limit)
|
||||
m_speed = m_speed * (speed_limit / m_speed.getLength());
|
||||
|
||||
v3f position = m_pos;
|
||||
v3f oldpos = position;
|
||||
|
||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// Allow 0.1 blocks per increment
|
||||
// time = distance / speed
|
||||
// NOTE: In the loop below collisions are detected at 0.15*BS radius
|
||||
float speedlength = m_speed.getLength();
|
||||
f32 dtime_max_increment;
|
||||
if(fabs(speedlength) > 0.001)
|
||||
dtime_max_increment = 0.05*BS / speedlength;
|
||||
else
|
||||
dtime_max_increment = 0.5;
|
||||
|
||||
m_touching_ground = false;
|
||||
|
||||
u32 loopcount = 0;
|
||||
do
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
f32 dtime_part;
|
||||
if(dtime > dtime_max_increment)
|
||||
dtime_part = dtime_max_increment;
|
||||
else
|
||||
dtime_part = dtime;
|
||||
dtime -= dtime_part;
|
||||
|
||||
// Begin of dtime limited code
|
||||
|
||||
m_speed += acceleration * dtime_part;
|
||||
position += m_speed * dtime_part;
|
||||
|
||||
/*
|
||||
Collision detection
|
||||
*/
|
||||
|
||||
v3s16 pos_i = floatToInt(position, BS);
|
||||
|
||||
// The loop length is limited to the object moving a distance
|
||||
f32 d = (float)BS * 0.15;
|
||||
|
||||
core::aabbox3d<f32> objectbox(
|
||||
m_collision_box->MinEdge + position,
|
||||
m_collision_box->MaxEdge + position
|
||||
);
|
||||
|
||||
core::aabbox3d<f32> objectbox_old(
|
||||
m_collision_box->MinEdge + oldpos,
|
||||
m_collision_box->MaxEdge + oldpos
|
||||
);
|
||||
|
||||
//TODO: Get these ranges from somewhere
|
||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
try{
|
||||
MapNode n = m_block->getNodeParent(v3s16(x,y,z));
|
||||
if(content_features(n).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Doing nothing here will block the object from
|
||||
// walking over map borders
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
// See if the object is touching ground
|
||||
if(
|
||||
fabs(nodebox.MaxEdge.Y-objectbox.MinEdge.Y) < d
|
||||
&& nodebox.MaxEdge.X-d > objectbox.MinEdge.X
|
||||
&& nodebox.MinEdge.X+d < objectbox.MaxEdge.X
|
||||
&& nodebox.MaxEdge.Z-d > objectbox.MinEdge.Z
|
||||
&& nodebox.MinEdge.Z+d < objectbox.MaxEdge.Z
|
||||
){
|
||||
m_touching_ground = true;
|
||||
}
|
||||
|
||||
if(objectbox.intersectsWithBox(nodebox))
|
||||
{
|
||||
|
||||
v3f dirs[3] = {
|
||||
v3f(0,0,1), // back
|
||||
v3f(0,1,0), // top
|
||||
v3f(1,0,0), // right
|
||||
};
|
||||
for(u16 i=0; i<3; i++)
|
||||
{
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax = objectbox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin = objectbox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax_old = objectbox_old.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin_old = objectbox_old.MinEdge.dotProduct(dirs[i]);
|
||||
|
||||
bool main_edge_collides =
|
||||
((nodemax > playermin && nodemax <= playermin_old + d
|
||||
&& m_speed.dotProduct(dirs[i]) < 0)
|
||||
||
|
||||
(nodemin < playermax && nodemin >= playermax_old - d
|
||||
&& m_speed.dotProduct(dirs[i]) > 0));
|
||||
|
||||
bool other_edges_collide = true;
|
||||
for(u16 j=0; j<3; j++)
|
||||
{
|
||||
if(j == i)
|
||||
continue;
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
||||
f32 playermax = objectbox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 playermin = objectbox.MinEdge.dotProduct(dirs[j]);
|
||||
if(!(nodemax - d > playermin && nodemin + d < playermax))
|
||||
{
|
||||
other_edges_collide = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(main_edge_collides && other_edges_collide)
|
||||
{
|
||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // if(objectbox.intersectsWithBox(nodebox))
|
||||
} // for y
|
||||
|
||||
} // End of dtime limited loop
|
||||
while(dtime > 0.001);
|
||||
|
||||
m_pos = position;
|
||||
}
|
||||
|
||||
void MovingObject::simpleMove(float dtime)
|
||||
{
|
||||
m_pos_animation_time_counter += dtime;
|
||||
m_pos_animation_counter += dtime;
|
||||
v3f movevector = m_pos - m_oldpos;
|
||||
f32 moveratio;
|
||||
if(m_pos_animation_time < 0.001)
|
||||
moveratio = 1.0;
|
||||
else
|
||||
moveratio = m_pos_animation_counter / m_pos_animation_time;
|
||||
if(moveratio > 1.5)
|
||||
moveratio = 1.5;
|
||||
m_showpos = m_oldpos + movevector * moveratio;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
/*
|
||||
RatObject
|
||||
*/
|
||||
void RatObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture
|
||||
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
updateNodePos();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
ItemObject
|
||||
*/
|
||||
#ifndef SERVER
|
||||
void ItemObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
// Get image of item for showing
|
||||
video::ITexture *texture = getItemImage();
|
||||
|
||||
/*
|
||||
Create a mesh
|
||||
*/
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, texture);
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
// Set it to use the materials of the meshbuffers directly.
|
||||
// This is needed for changing the texture in the future
|
||||
((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
|
||||
mesh->drop();
|
||||
|
||||
updateSceneNode();
|
||||
}
|
||||
|
||||
video::ITexture * ItemObject::getItemImage()
|
||||
{
|
||||
/*
|
||||
Create an inventory item to see what is its image
|
||||
*/
|
||||
video::ITexture *texture = NULL;
|
||||
InventoryItem *item = createInventoryItem();
|
||||
if(item)
|
||||
texture = item->getImage();
|
||||
if(item)
|
||||
delete item;
|
||||
return texture;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
InventoryItem * ItemObject::createInventoryItem()
|
||||
{
|
||||
try{
|
||||
std::istringstream is(m_itemstring, std::ios_base::binary);
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
dstream<<__FUNCTION_NAME<<": m_itemstring=\""
|
||||
<<m_itemstring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
return item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": serialization error: "
|
||||
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PlayerObject
|
||||
*/
|
||||
#ifndef SERVER
|
||||
void PlayerObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
// Attach a simple mesh to the player for showing an image
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
{ // Front
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
{ // Back
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
updateNodePos();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
MapBlockObjectList
|
||||
*/
|
||||
|
||||
MapBlockObjectList::MapBlockObjectList(MapBlock *block):
|
||||
m_block(block)
|
||||
{
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
MapBlockObjectList::~MapBlockObjectList()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
/*
|
||||
The serialization format:
|
||||
[0] u16 number of entries
|
||||
[2] entries (id, typeId, parameters)
|
||||
*/
|
||||
|
||||
void MapBlockObjectList::serialize(std::ostream &os, u8 version)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
u8 buf[2];
|
||||
writeU16(buf, m_objects.size());
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
i.getNode()->getValue()->serialize(os, version);
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlockObjectList::update(std::istream &is, u8 version,
|
||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
/*
|
||||
Collect all existing ids to a set.
|
||||
|
||||
As things are updated, they are removed from this.
|
||||
|
||||
All remaining ones are deleted.
|
||||
*/
|
||||
core::map<s16, bool> ids_to_delete;
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
ids_to_delete.insert(i.getNode()->getKey(), true);
|
||||
}
|
||||
|
||||
u8 buf[6];
|
||||
|
||||
is.read((char*)buf, 2);
|
||||
u16 count = readU16(buf);
|
||||
|
||||
for(u16 i=0; i<count; i++)
|
||||
{
|
||||
// Read id
|
||||
is.read((char*)buf, 2);
|
||||
s16 id = readS16(buf);
|
||||
|
||||
// Read position
|
||||
// stored as x1000/BS v3s16
|
||||
is.read((char*)buf, 6);
|
||||
v3s16 pos_i = readV3S16(buf);
|
||||
v3f pos((f32)pos_i.X/1000*BS,
|
||||
(f32)pos_i.Y/1000*BS,
|
||||
(f32)pos_i.Z/1000*BS);
|
||||
|
||||
// Read typeId
|
||||
is.read((char*)buf, 2);
|
||||
u16 type_id = readU16(buf);
|
||||
|
||||
bool create_new = false;
|
||||
|
||||
// Find an object with the id
|
||||
core::map<s16, MapBlockObject*>::Node *n;
|
||||
n = m_objects.find(id);
|
||||
// If no entry is found for id
|
||||
if(n == NULL)
|
||||
{
|
||||
// Insert dummy pointer node
|
||||
m_objects.insert(id, NULL);
|
||||
// Get node
|
||||
n = m_objects.find(id);
|
||||
// A new object will be created at this node
|
||||
create_new = true;
|
||||
}
|
||||
// If type_id differs
|
||||
else if(n->getValue()->getTypeId() != type_id)
|
||||
{
|
||||
// Delete old object
|
||||
delete n->getValue();
|
||||
// A new object will be created at this node
|
||||
create_new = true;
|
||||
}
|
||||
|
||||
MapBlockObject *obj = NULL;
|
||||
|
||||
if(create_new)
|
||||
{
|
||||
/*dstream<<"MapBlockObjectList adding new object"
|
||||
" id="<<id
|
||||
<<std::endl;*/
|
||||
|
||||
if(type_id == MAPBLOCKOBJECT_TYPE_SIGN)
|
||||
{
|
||||
obj = new SignObject(m_block, id, pos);
|
||||
}
|
||||
else if(type_id == MAPBLOCKOBJECT_TYPE_RAT)
|
||||
{
|
||||
obj = new RatObject(m_block, id, pos);
|
||||
}
|
||||
else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
|
||||
{
|
||||
obj = new ItemObject(m_block, id, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is fatal because we cannot know the length
|
||||
// of the object's data
|
||||
throw SerializationError
|
||||
("MapBlockObjectList::update(): Unknown MapBlockObject type");
|
||||
}
|
||||
|
||||
if(smgr != NULL)
|
||||
//obj->addToScene(smgr, daynight_ratio);
|
||||
obj->addToScene(smgr);
|
||||
|
||||
n->setValue(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = n->getValue();
|
||||
obj->updatePos(pos);
|
||||
/*if(daynight_ratio != m_last_update_daynight_ratio)
|
||||
{
|
||||
obj->removeFromScene();
|
||||
obj->addToScene(smgr, daynight_ratio);
|
||||
}*/
|
||||
}
|
||||
|
||||
// Now there is an object in obj.
|
||||
// Update it.
|
||||
|
||||
obj->update(is, version);
|
||||
|
||||
/*
|
||||
Update light on client
|
||||
*/
|
||||
if(smgr != NULL)
|
||||
{
|
||||
u8 light = LIGHT_MAX;
|
||||
try{
|
||||
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
||||
MapNode n = m_block->getNodeParent(relpos_i);
|
||||
light = n.getLightBlend(daynight_ratio);
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
obj->updateLight(light);
|
||||
}
|
||||
|
||||
// Remove from deletion list
|
||||
if(ids_to_delete.find(id) != NULL)
|
||||
ids_to_delete.remove(id);
|
||||
}
|
||||
|
||||
// Delete all objects whose ids_to_delete remain in ids_to_delete
|
||||
for(core::map<s16, bool>::Iterator
|
||||
i = ids_to_delete.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
s16 id = i.getNode()->getKey();
|
||||
|
||||
/*dstream<<"MapBlockObjectList deleting object"
|
||||
" id="<<id
|
||||
<<std::endl;*/
|
||||
|
||||
MapBlockObject *obj = m_objects[id];
|
||||
obj->removeFromScene();
|
||||
delete obj;
|
||||
m_objects.remove(id);
|
||||
}
|
||||
|
||||
m_last_update_daynight_ratio = daynight_ratio;
|
||||
}
|
||||
|
||||
s16 MapBlockObjectList::getFreeId() throw(ContainerFullException)
|
||||
{
|
||||
s16 id = 0;
|
||||
for(;;)
|
||||
{
|
||||
if(m_objects.find(id) == NULL)
|
||||
return id;
|
||||
if(id == 32767)
|
||||
throw ContainerFullException
|
||||
("MapBlockObjectList doesn't fit more objects");
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlockObjectList::add(MapBlockObject *object)
|
||||
throw(ContainerFullException, AlreadyExistsException)
|
||||
{
|
||||
if(object == NULL)
|
||||
{
|
||||
dstream<<"MapBlockObjectList::add(): NULL object"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Create unique id if id==-1
|
||||
if(object->m_id == -1)
|
||||
{
|
||||
object->m_id = getFreeId();
|
||||
}
|
||||
|
||||
if(m_objects.find(object->m_id) != NULL)
|
||||
{
|
||||
dstream<<"MapBlockObjectList::add(): "
|
||||
"object with same id already exists"<<std::endl;
|
||||
throw AlreadyExistsException
|
||||
("MapBlockObjectList already has given id");
|
||||
}
|
||||
|
||||
object->m_block = m_block;
|
||||
|
||||
/*v3f p = object->m_pos;
|
||||
dstream<<"MapBlockObjectList::add(): "
|
||||
<<"m_block->getPos()=("
|
||||
<<m_block->getPos().X<<","
|
||||
<<m_block->getPos().Y<<","
|
||||
<<m_block->getPos().Z<<")"
|
||||
<<" inserting object with id="<<object->m_id
|
||||
<<" pos="
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
m_objects.insert(object->m_id, object);
|
||||
}
|
||||
|
||||
void MapBlockObjectList::clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
//FIXME: This really shouldn't be NULL at any time,
|
||||
// but this condition was added because it was.
|
||||
if(obj != NULL)
|
||||
{
|
||||
obj->removeFromScene();
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
m_objects.clear();
|
||||
}
|
||||
|
||||
void MapBlockObjectList::remove(s16 id)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<s16, MapBlockObject*>::Node *n;
|
||||
n = m_objects.find(id);
|
||||
if(n == NULL)
|
||||
return;
|
||||
|
||||
n->getValue()->removeFromScene();
|
||||
delete n->getValue();
|
||||
m_objects.remove(id);
|
||||
}
|
||||
|
||||
MapBlockObject * MapBlockObjectList::get(s16 id)
|
||||
{
|
||||
core::map<s16, MapBlockObject*>::Node *n;
|
||||
n = m_objects.find(id);
|
||||
if(n == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<s16, bool> ids_to_delete;
|
||||
|
||||
{
|
||||
DSTACKF("%s: stepping objects", __FUNCTION_NAME);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
|
||||
DSTACKF("%s: stepping object type %i", __FUNCTION_NAME,
|
||||
obj->getTypeId());
|
||||
|
||||
if(server)
|
||||
{
|
||||
// Update light
|
||||
u8 light = LIGHT_MAX;
|
||||
try{
|
||||
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
||||
MapNode n = m_block->getNodeParent(relpos_i);
|
||||
light = n.getLightBlend(daynight_ratio);
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
obj->updateLight(light);
|
||||
|
||||
bool to_delete = obj->serverStep(dtime, daynight_ratio);
|
||||
|
||||
if(to_delete)
|
||||
ids_to_delete.insert(obj->m_id, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->clientStep(dtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
DSTACKF("%s: deleting objects", __FUNCTION_NAME);
|
||||
|
||||
// Delete objects in delete queue
|
||||
for(core::map<s16, bool>::Iterator
|
||||
i = ids_to_delete.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
s16 id = i.getNode()->getKey();
|
||||
|
||||
MapBlockObject *obj = m_objects[id];
|
||||
obj->removeFromScene();
|
||||
delete obj;
|
||||
m_objects.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Wrap objects on server
|
||||
*/
|
||||
|
||||
if(server == false)
|
||||
return;
|
||||
|
||||
{
|
||||
DSTACKF("%s: object wrap loop", __FUNCTION_NAME);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
|
||||
v3s16 pos_i = floatToInt(obj->m_pos, BS);
|
||||
|
||||
if(m_block->isValidPosition(pos_i))
|
||||
{
|
||||
// No wrap
|
||||
continue;
|
||||
}
|
||||
|
||||
bool impossible = wrapObject(obj);
|
||||
|
||||
if(impossible)
|
||||
{
|
||||
// No wrap
|
||||
continue;
|
||||
}
|
||||
|
||||
// Restart find
|
||||
i = m_objects.getIterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
// No lock here; this is called so that the lock is already locked.
|
||||
//JMutexAutoLock lock(m_mutex);
|
||||
|
||||
assert(object->m_block == m_block);
|
||||
assert(m_objects.find(object->m_id) != NULL);
|
||||
assert(m_objects[object->m_id] == object);
|
||||
|
||||
Map *map = m_block->getParent();
|
||||
|
||||
// Calculate blockpos on map
|
||||
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
||||
v3f pos_f_on_oldblock = object->m_pos;
|
||||
v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock, BS);
|
||||
v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
|
||||
v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
|
||||
|
||||
// Get new block
|
||||
MapBlock *newblock;
|
||||
try{
|
||||
newblock = map->getBlockNoCreate(pos_blocks_on_map);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Couldn't find block -> not wrapping
|
||||
/*dstream<<"WARNING: Wrapping object not possible: "
|
||||
<<"could not find new block"
|
||||
<<"("<<pos_blocks_on_map.X
|
||||
<<","<<pos_blocks_on_map.Y
|
||||
<<","<<pos_blocks_on_map.Z
|
||||
<<")"<<std::endl;*/
|
||||
/*dstream<<"pos_f_on_oldblock=("
|
||||
<<pos_f_on_oldblock.X<<","
|
||||
<<pos_f_on_oldblock.Y<<","
|
||||
<<pos_f_on_oldblock.Z<<")"
|
||||
<<std::endl;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if(newblock == m_block)
|
||||
{
|
||||
dstream<<"WARNING: Wrapping object not possible: "
|
||||
"newblock == oldblock"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate position on new block
|
||||
v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map, BS);
|
||||
v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
|
||||
v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map, BS);
|
||||
v3f pos_f_on_newblock = pos_f_on_oldblock
|
||||
- newblock_pos_f_on_map + oldblock_pos_f_on_map;
|
||||
|
||||
// Remove object from this block
|
||||
m_objects.remove(object->m_id);
|
||||
|
||||
// Add object to new block
|
||||
object->m_pos = pos_f_on_newblock;
|
||||
object->m_id = -1;
|
||||
object->m_block = NULL;
|
||||
newblock->addObject(object);
|
||||
|
||||
//dstream<<"NOTE: Wrapped object"<<std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MapBlockObjectList::getObjects(v3f origin, f32 max_d,
|
||||
core::array<DistanceSortedObject> &dest)
|
||||
{
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
|
||||
f32 d = (obj->getRelativeShowPos() - origin).getLength();
|
||||
|
||||
if(d > max_d)
|
||||
continue;
|
||||
|
||||
DistanceSortedObject dso(obj, d);
|
||||
|
||||
dest.push_back(dso);
|
||||
}
|
||||
}
|
||||
|
||||
//END
|
||||
1116
src/mapblockobject.h
Normal file
@@ -80,7 +80,7 @@ static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d)
|
||||
}
|
||||
#endif
|
||||
|
||||
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree)
|
||||
static void make_tree(VoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree)
|
||||
{
|
||||
MapNode treenode(CONTENT_TREE);
|
||||
MapNode leavesnode(CONTENT_LEAVES);
|
||||
@@ -1405,7 +1405,6 @@ bool get_have_sand(u64 seed, v2s16 p2d)
|
||||
*/
|
||||
void add_random_objects(MapBlock *block)
|
||||
{
|
||||
#if 0
|
||||
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||
{
|
||||
@@ -1466,7 +1465,6 @@ void add_random_objects(MapBlock *block)
|
||||
}
|
||||
}
|
||||
block->setChangedFlag();
|
||||
#endif
|
||||
}
|
||||
|
||||
void make_block(BlockMakeData *data)
|
||||
|
||||
@@ -40,9 +40,6 @@ namespace mapgen
|
||||
|
||||
// Add objects according to block content
|
||||
void add_random_objects(MapBlock *block);
|
||||
|
||||
// Add a tree
|
||||
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree);
|
||||
|
||||
/*
|
||||
These are used by FarMesh
|
||||
|
||||
@@ -19,9 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "mapnode.h"
|
||||
#ifndef SERVER
|
||||
#include "tile.h"
|
||||
#endif
|
||||
#include "porting.h"
|
||||
#include <string>
|
||||
#include "mineral.h"
|
||||
@@ -33,17 +31,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
ContentFeatures::~ContentFeatures()
|
||||
{
|
||||
delete initial_metadata;
|
||||
#ifndef SERVER
|
||||
delete special_material;
|
||||
delete special_atlas;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
|
||||
{
|
||||
used_texturenames[name] = true;
|
||||
|
||||
if(g_texturesource)
|
||||
{
|
||||
tiles[i].texture = g_texturesource->getTexture(name);
|
||||
@@ -88,7 +81,6 @@ void ContentFeatures::setInventoryTextureCube(std::string top,
|
||||
imgname_full += right;
|
||||
inventory_texture = g_texturesource->getTextureRaw(imgname_full);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ContentFeatures g_content_features[MAX_CONTENT+1];
|
||||
|
||||
@@ -126,8 +118,7 @@ void init_mapnode()
|
||||
/*
|
||||
Initialize content feature table
|
||||
*/
|
||||
|
||||
#ifndef SERVER
|
||||
|
||||
/*
|
||||
Set initial material type to same in all tiles, so that the
|
||||
same material can be used in more stuff.
|
||||
@@ -149,7 +140,6 @@ void init_mapnode()
|
||||
for(u16 j=0; j<6; j++)
|
||||
f->tiles[j].material_type = initial_material_type;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Initially set every block to be shown as an unknown block.
|
||||
@@ -164,9 +154,6 @@ void init_mapnode()
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
}
|
||||
|
||||
// Make CONTENT_IGNORE to not block the view when occlusion culling
|
||||
content_features(CONTENT_IGNORE).solidness = 0;
|
||||
|
||||
/*
|
||||
Initialize mapnode content
|
||||
*/
|
||||
@@ -174,57 +161,6 @@ void init_mapnode()
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Nodes make a face if contents differ and solidness differs.
|
||||
Return value:
|
||||
0: No face
|
||||
1: Face uses m1's content
|
||||
2: Face uses m2's content
|
||||
equivalent: Whether the blocks share the same face (eg. water and glass)
|
||||
*/
|
||||
u8 face_contents(content_t m1, content_t m2, bool *equivalent)
|
||||
{
|
||||
*equivalent = false;
|
||||
|
||||
if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
|
||||
return 0;
|
||||
|
||||
bool contents_differ = (m1 != m2);
|
||||
|
||||
// Contents don't differ for different forms of same liquid
|
||||
if(content_liquid(m1) && content_liquid(m2)
|
||||
&& make_liquid_flowing(m1) == make_liquid_flowing(m2))
|
||||
contents_differ = false;
|
||||
|
||||
u8 c1 = content_solidness(m1);
|
||||
u8 c2 = content_solidness(m2);
|
||||
|
||||
bool solidness_differs = (c1 != c2);
|
||||
bool makes_face = contents_differ && solidness_differs;
|
||||
|
||||
if(makes_face == false)
|
||||
return 0;
|
||||
|
||||
if(c1 == 0)
|
||||
c1 = content_features(m1).visual_solidness;
|
||||
if(c2 == 0)
|
||||
c2 = content_features(m2).visual_solidness;
|
||||
|
||||
if(c1 == c2){
|
||||
*equivalent = true;
|
||||
// If same solidness, liquid takes precense
|
||||
if(content_features(m1).liquid_type != LIQUID_NONE)
|
||||
return 1;
|
||||
if(content_features(m2).liquid_type != LIQUID_NONE)
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(c1 > c2)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
v3s16 facedir_rotate(u8 facedir, v3s16 dir)
|
||||
{
|
||||
/*
|
||||
@@ -248,7 +184,6 @@ v3s16 facedir_rotate(u8 facedir, v3s16 dir)
|
||||
return newdir;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
TileSpec MapNode::getTile(v3s16 dir)
|
||||
{
|
||||
if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
|
||||
@@ -300,7 +235,6 @@ TileSpec MapNode::getTile(v3s16 dir)
|
||||
|
||||
return spec;
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 MapNode::getMineral()
|
||||
{
|
||||
|
||||
@@ -23,12 +23,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <iostream>
|
||||
#include "common_irrlicht.h"
|
||||
#include "light.h"
|
||||
#include "utility.h"
|
||||
#include "exceptions.h"
|
||||
#include "serialization.h"
|
||||
#include "materials.h"
|
||||
#ifndef SERVER
|
||||
#include "tile.h"
|
||||
#endif
|
||||
#include "materials.h"
|
||||
|
||||
/*
|
||||
Naming scheme:
|
||||
@@ -102,7 +101,9 @@ class NodeMetadata;
|
||||
|
||||
struct ContentFeatures
|
||||
{
|
||||
#ifndef SERVER
|
||||
// Type of MapNode::param1
|
||||
ContentParamType param_type;
|
||||
|
||||
/*
|
||||
0: up
|
||||
1: down
|
||||
@@ -114,23 +115,7 @@ struct ContentFeatures
|
||||
TileSpec tiles[6];
|
||||
|
||||
video::ITexture *inventory_texture;
|
||||
|
||||
// Used currently for flowing liquids
|
||||
u8 vertex_alpha;
|
||||
// Post effect color, drawn when the camera is inside the node.
|
||||
video::SColor post_effect_color;
|
||||
// Special irrlicht material, used sometimes
|
||||
video::SMaterial *special_material;
|
||||
video::SMaterial *special_material2;
|
||||
AtlasPointer *special_atlas;
|
||||
#endif
|
||||
|
||||
// List of all block textures that have been used (value is dummy)
|
||||
// Exists on server too for cleaner code in content_mapnode.cpp
|
||||
core::map<std::string, bool> used_texturenames;
|
||||
|
||||
// Type of MapNode::param1
|
||||
ContentParamType param_type;
|
||||
// True for all ground-like things like stone and mud, false for eg. trees
|
||||
bool is_ground_content;
|
||||
bool light_propagates;
|
||||
@@ -156,19 +141,11 @@ struct ContentFeatures
|
||||
// If true, node is equivalent to air. Torches are, air is. Water is not.
|
||||
// Is used for example to check whether a mud block can have grass on.
|
||||
bool air_equivalent;
|
||||
// Whether this content type often contains mineral.
|
||||
// Used for texture atlas creation.
|
||||
// Currently only enabled for CONTENT_STONE.
|
||||
bool often_contains_mineral;
|
||||
|
||||
// Inventory item string as which the node appears in inventory when dug.
|
||||
// Mineral overrides this.
|
||||
std::string dug_item;
|
||||
|
||||
// Extra dug item and its rarity
|
||||
std::string extra_dug_item;
|
||||
s32 extra_dug_item_rarity;
|
||||
|
||||
|
||||
// Initial metadata is cloned from this
|
||||
NodeMetadata *initial_metadata;
|
||||
|
||||
@@ -181,6 +158,11 @@ struct ContentFeatures
|
||||
// 1 giving almost instantaneous propagation and 7 being
|
||||
// the slowest possible
|
||||
u8 liquid_viscosity;
|
||||
// Used currently for flowing liquids
|
||||
u8 vertex_alpha;
|
||||
// Special irrlicht material, used sometimes
|
||||
video::SMaterial *special_material;
|
||||
AtlasPointer *special_atlas;
|
||||
|
||||
// Amount of light the node emits
|
||||
u8 light_source;
|
||||
@@ -194,16 +176,8 @@ struct ContentFeatures
|
||||
|
||||
void reset()
|
||||
{
|
||||
#ifndef SERVER
|
||||
inventory_texture = NULL;
|
||||
|
||||
vertex_alpha = 255;
|
||||
post_effect_color = video::SColor(0, 0, 0, 0);
|
||||
special_material = NULL;
|
||||
special_material2 = NULL;
|
||||
special_atlas = NULL;
|
||||
#endif
|
||||
param_type = CPT_NONE;
|
||||
inventory_texture = NULL;
|
||||
is_ground_content = false;
|
||||
light_propagates = false;
|
||||
sunlight_propagates = false;
|
||||
@@ -217,12 +191,14 @@ struct ContentFeatures
|
||||
liquid_type = LIQUID_NONE;
|
||||
wall_mounted = false;
|
||||
air_equivalent = false;
|
||||
often_contains_mineral = false;
|
||||
dug_item = "";
|
||||
initial_metadata = NULL;
|
||||
liquid_alternative_flowing = CONTENT_IGNORE;
|
||||
liquid_alternative_source = CONTENT_IGNORE;
|
||||
liquid_viscosity = 0;
|
||||
vertex_alpha = 255;
|
||||
special_material = NULL;
|
||||
special_atlas = NULL;
|
||||
light_source = 0;
|
||||
digging_properties.clear();
|
||||
damage_per_second = 0;
|
||||
@@ -239,12 +215,6 @@ struct ContentFeatures
|
||||
Quickhands for simple materials
|
||||
*/
|
||||
|
||||
#ifdef SERVER
|
||||
void setTexture(u16 i, std::string name, u8 alpha=255)
|
||||
{}
|
||||
void setAllTextures(std::string name, u8 alpha=255)
|
||||
{}
|
||||
#else
|
||||
void setTexture(u16 i, std::string name, u8 alpha=255);
|
||||
|
||||
void setAllTextures(std::string name, u8 alpha=255)
|
||||
@@ -256,9 +226,7 @@ struct ContentFeatures
|
||||
// Force inventory texture too
|
||||
setInventoryTexture(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERVER
|
||||
void setTile(u16 i, const TileSpec &tile)
|
||||
{
|
||||
tiles[i] = tile;
|
||||
@@ -270,20 +238,11 @@ struct ContentFeatures
|
||||
setTile(i, tile);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SERVER
|
||||
void setInventoryTexture(std::string imgname)
|
||||
{}
|
||||
void setInventoryTextureCube(std::string top,
|
||||
std::string left, std::string right)
|
||||
{}
|
||||
#else
|
||||
void setInventoryTexture(std::string imgname);
|
||||
|
||||
void setInventoryTextureCube(std::string top,
|
||||
std::string left, std::string right);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -379,9 +338,30 @@ inline bool content_buildable_to(content_t m)
|
||||
0: No face
|
||||
1: Face uses m1's content
|
||||
2: Face uses m2's content
|
||||
equivalent: Whether the blocks share the same face (eg. water and glass)
|
||||
*/
|
||||
u8 face_contents(content_t m1, content_t m2, bool *equivalent);
|
||||
inline u8 face_contents(content_t m1, content_t m2)
|
||||
{
|
||||
if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
|
||||
return 0;
|
||||
|
||||
bool contents_differ = (m1 != m2);
|
||||
|
||||
// Contents don't differ for different forms of same liquid
|
||||
if(content_liquid(m1) && content_liquid(m2)
|
||||
&& make_liquid_flowing(m1) == make_liquid_flowing(m2))
|
||||
contents_differ = false;
|
||||
|
||||
bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
|
||||
bool makes_face = contents_differ && solidness_differs;
|
||||
|
||||
if(makes_face == false)
|
||||
return 0;
|
||||
|
||||
if(content_solidness(m1) > content_solidness(m2))
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
Packs directions like (1,0,0), (1,-1,0)
|
||||
@@ -645,7 +625,6 @@ struct MapNode
|
||||
}
|
||||
|
||||
// In mapnode.cpp
|
||||
#ifndef SERVER
|
||||
/*
|
||||
Get tile of a face of the node.
|
||||
dir: direction of face
|
||||
@@ -653,7 +632,6 @@ struct MapNode
|
||||
which must be obeyed so that the texture atlas can be used.
|
||||
*/
|
||||
TileSpec getTile(v3s16 dir);
|
||||
#endif
|
||||
|
||||
/*
|
||||
Gets mineral content of node, if there is any.
|
||||
|
||||
@@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "inventory.h"
|
||||
#include <sstream>
|
||||
#include "content_mapnode.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
NodeMetadata
|
||||
@@ -56,7 +55,7 @@ NodeMetadata* NodeMetadata::deSerialize(std::istream &is)
|
||||
if(n == NULL)
|
||||
{
|
||||
// If factory is not found, just return.
|
||||
infostream<<"WARNING: NodeMetadata: No factory for typeId="
|
||||
dstream<<"WARNING: NodeMetadata: No factory for typeId="
|
||||
<<id<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
@@ -72,7 +71,7 @@ NodeMetadata* NodeMetadata::deSerialize(std::istream &is)
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
|
||||
dstream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -139,7 +138,7 @@ void NodeMetadataList::deSerialize(std::istream &is)
|
||||
|
||||
if(version > 1)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
|
||||
dstream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
|
||||
<<std::endl;
|
||||
throw SerializationError("NodeMetadataList::deSerialize");
|
||||
}
|
||||
@@ -166,7 +165,7 @@ void NodeMetadataList::deSerialize(std::istream &is)
|
||||
|
||||
if(m_data.find(p))
|
||||
{
|
||||
infostream<<"WARNING: NodeMetadataList::deSerialize(): "
|
||||
dstream<<"WARNING: NodeMetadataList::deSerialize(): "
|
||||
<<"already set data at position"
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
|
||||
<<std::endl;
|
||||
|
||||
@@ -65,9 +65,6 @@ class NodeMetadata
|
||||
// Used to make custom inventory menus.
|
||||
// See format in guiInventoryMenu.cpp.
|
||||
virtual std::string getInventoryDrawSpecString(){return "";}
|
||||
// primarily used for locking chests, but others can play too
|
||||
virtual std::string getOwner(){ return std::string(""); }
|
||||
virtual void setOwner(std::string t){ }
|
||||
|
||||
protected:
|
||||
static void registerType(u16 id, Factory f);
|
||||
|
||||
@@ -22,16 +22,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "connection.h"
|
||||
#include "constants.h"
|
||||
#include "utility.h"
|
||||
#ifndef SERVER
|
||||
#include <ITextSceneNode.h>
|
||||
#endif
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
Player::Player():
|
||||
touching_ground(false),
|
||||
in_water(false),
|
||||
in_water_stable(false),
|
||||
is_climbing(false),
|
||||
swimming_up(false),
|
||||
inventory_backup(NULL),
|
||||
craftresult_is_preview(true),
|
||||
@@ -334,10 +330,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
/*
|
||||
Calculate new position
|
||||
*/
|
||||
position += m_speed * dtime;
|
||||
if(is_frozen) {
|
||||
// Still move very slowly so as not to feel all completely stuck
|
||||
position += m_speed * dtime * 0.001;
|
||||
}
|
||||
else {
|
||||
position += m_speed * dtime;
|
||||
}
|
||||
|
||||
/*
|
||||
If the player enters an unloaded chunk this is set to true.
|
||||
*/
|
||||
is_frozen = false;
|
||||
|
||||
// Skip collision detection if a special movement mode is used
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
bool free_move = g_settings.getBool("free_move");
|
||||
if(free_move)
|
||||
{
|
||||
setPosition(position);
|
||||
@@ -493,8 +500,6 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
|
||||
<<"):"<<std::endl;*/
|
||||
|
||||
bool standing_on_unloaded = false;
|
||||
|
||||
/*
|
||||
Go through every node around the player
|
||||
*/
|
||||
@@ -502,7 +507,6 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
bool is_unloaded = false;
|
||||
try{
|
||||
// Player collides into walkable nodes
|
||||
if(content_walkable(map.getNode(v3s16(x,y,z)).getContent()) == false)
|
||||
@@ -510,9 +514,11 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
is_unloaded = true;
|
||||
// Doing nothing here will block the player from
|
||||
// walking over map borders
|
||||
if(!is_frozen) {
|
||||
// freeze when entering unloaded areas
|
||||
is_frozen = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
@@ -535,8 +541,6 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
&& nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z
|
||||
){
|
||||
touching_ground = true;
|
||||
if(is_unloaded)
|
||||
standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
// If player doesn't intersect with node, ignore node.
|
||||
@@ -718,7 +722,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1 && !standing_on_unloaded)
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
@@ -750,9 +754,9 @@ void LocalPlayer::applyControl(float dtime)
|
||||
|
||||
v3f speed = v3f(0,0,0);
|
||||
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
bool fast_move = g_settings->getBool("fast_move");
|
||||
bool continuous_forward = g_settings->getBool("continuous_forward");
|
||||
bool free_move = g_settings.getBool("free_move");
|
||||
bool fast_move = g_settings.getBool("fast_move");
|
||||
bool continuous_forward = g_settings.getBool("continuous_forward");
|
||||
|
||||
if(free_move || is_climbing)
|
||||
{
|
||||
|
||||
40
src/player.h
@@ -67,17 +67,12 @@ class Player
|
||||
return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
|
||||
}
|
||||
|
||||
v3f getEyeOffset()
|
||||
{
|
||||
// This is at the height of the eyes of the current figure
|
||||
// return v3f(0, BS+BS/2, 0);
|
||||
// This is more like in minecraft
|
||||
return v3f(0,BS+(5*BS)/8,0);
|
||||
}
|
||||
|
||||
v3f getEyePosition()
|
||||
{
|
||||
return m_position + getEyeOffset();
|
||||
// This is at the height of the eyes of the current figure
|
||||
// return m_position + v3f(0, BS+BS/2, 0);
|
||||
// This is more like in minecraft
|
||||
return m_position + v3f(0,BS+(5*BS)/8,0);
|
||||
}
|
||||
|
||||
virtual void setPosition(const v3f &position)
|
||||
@@ -126,10 +121,7 @@ class Player
|
||||
|
||||
virtual bool isLocal() const = 0;
|
||||
|
||||
virtual void updateLight(u8 light_at_pos)
|
||||
{
|
||||
light = light_at_pos;
|
||||
}
|
||||
virtual void updateLight(u8 light_at_pos) {};
|
||||
|
||||
// NOTE: Use peer_id == 0 for disconnected
|
||||
/*virtual bool isClientConnected() { return false; }
|
||||
@@ -150,9 +142,8 @@ class Player
|
||||
bool in_water_stable;
|
||||
bool is_climbing;
|
||||
bool swimming_up;
|
||||
bool is_frozen;
|
||||
|
||||
u8 light;
|
||||
|
||||
Inventory inventory;
|
||||
// Actual inventory is backed up here when creative mode is used
|
||||
Inventory *inventory_backup;
|
||||
@@ -270,14 +261,25 @@ class RemotePlayer : public Player, public scene::ISceneNode
|
||||
|
||||
virtual void updateLight(u8 light_at_pos)
|
||||
{
|
||||
Player::updateLight(light_at_pos);
|
||||
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||
@@ -354,7 +356,7 @@ class LocalPlayer : public Player
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
core::list<CollisionInfo> *collision_info);
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||
|
||||
@@ -75,45 +75,10 @@ void signal_handler_init(void)
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
#include <signal.h>
|
||||
#include <windows.h>
|
||||
|
||||
BOOL WINAPI event_handler(DWORD sig)
|
||||
{
|
||||
switch(sig)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
|
||||
if(g_killed == false)
|
||||
{
|
||||
dstream<<DTIME<<"INFO: event_handler(): "
|
||||
<<"Ctrl+C, Close Event, Logoff Event or Shutdown Event, shutting down."<<std::endl;
|
||||
dstream<<DTIME<<"INFO: event_handler(): "
|
||||
<<"Printing debug stacks"<<std::endl;
|
||||
debug_stacks_print();
|
||||
|
||||
g_killed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)signal(SIGINT, SIG_DFL);
|
||||
}
|
||||
|
||||
break;
|
||||
case CTRL_BREAK_EVENT:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void signal_handler_init(void)
|
||||
{
|
||||
dstream<<"signal_handler_init()"<<std::endl;
|
||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)event_handler,TRUE);
|
||||
// No-op
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -122,8 +87,8 @@ void signal_handler_init(void)
|
||||
Path mangler
|
||||
*/
|
||||
|
||||
std::string path_data = ".." DIR_DELIM "data";
|
||||
std::string path_userdata = "..";
|
||||
std::string path_data = "../data";
|
||||
std::string path_userdata = "../";
|
||||
|
||||
void pathRemoveFile(char *path, char delim)
|
||||
{
|
||||
@@ -162,10 +127,10 @@ void initializePaths()
|
||||
pathRemoveFile(buf, '\\');
|
||||
|
||||
// Use "./bin/../data"
|
||||
path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data";
|
||||
path_data = std::string(buf) + "/../data";
|
||||
|
||||
// Use "./bin/.."
|
||||
path_userdata = std::string(buf) + DIR_DELIM "..";
|
||||
// Use "./bin/../"
|
||||
path_userdata = std::string(buf) + "/../";
|
||||
|
||||
/*
|
||||
Linux
|
||||
@@ -184,7 +149,7 @@ void initializePaths()
|
||||
path_data = std::string(buf) + "/../data";
|
||||
|
||||
// Use "./bin/../"
|
||||
path_userdata = std::string(buf) + "/..";
|
||||
path_userdata = std::string(buf) + "/../";
|
||||
|
||||
/*
|
||||
OS X
|
||||
@@ -195,7 +160,7 @@ void initializePaths()
|
||||
dstream<<"WARNING: Relative path not properly supported on OS X and FreeBSD"
|
||||
<<std::endl;
|
||||
path_data = std::string("../data");
|
||||
path_userdata = std::string("..");
|
||||
path_userdata = std::string("../");
|
||||
|
||||
#endif
|
||||
|
||||
@@ -223,13 +188,13 @@ void initializePaths()
|
||||
pathRemoveFile(buf, '\\');
|
||||
|
||||
// Use "./bin/../data"
|
||||
path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data";
|
||||
path_data = std::string(buf) + "/../data";
|
||||
//path_data = std::string(buf) + "/../share/" + PROJECT_NAME;
|
||||
|
||||
// Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
|
||||
len = GetEnvironmentVariable("APPDATA", buf, buflen);
|
||||
assert(len < buflen);
|
||||
path_userdata = std::string(buf) + DIR_DELIM + PROJECT_NAME;
|
||||
path_userdata = std::string(buf) + "/" + PROJECT_NAME;
|
||||
|
||||
/*
|
||||
Linux
|
||||
|
||||
@@ -38,83 +38,42 @@ class Profiler
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
void add(const std::string &name, float value)
|
||||
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)
|
||||
{
|
||||
/* No average shall have been used; mark add used as -2 */
|
||||
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||
if(n == NULL)
|
||||
m_avgcounts[name] = -2;
|
||||
else{
|
||||
if(n->getValue() == -1)
|
||||
n->setValue(-2);
|
||||
assert(n->getValue() == -2);
|
||||
}
|
||||
m_data[name] = duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||
if(n == NULL)
|
||||
m_data[name] = value;
|
||||
else
|
||||
n->setValue(n->getValue() + value);
|
||||
}
|
||||
}
|
||||
|
||||
void avg(const std::string &name, float value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
{
|
||||
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||
if(n == NULL)
|
||||
m_avgcounts[name] = 1;
|
||||
else{
|
||||
/* No add shall have been used */
|
||||
assert(n->getValue() != -2);
|
||||
if(n->getValue() <= 0)
|
||||
n->setValue(1);
|
||||
else
|
||||
n->setValue(n->getValue() + 1);
|
||||
}
|
||||
}
|
||||
{
|
||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||
if(n == NULL)
|
||||
m_data[name] = value;
|
||||
else
|
||||
n->setValue(n->getValue() + value);
|
||||
n->setValue(n->getValue()+duration);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
for(core::map<std::string, float>::Iterator
|
||||
for(core::map<std::string, u32>::Iterator
|
||||
i = m_data.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
i.getNode()->setValue(0);
|
||||
}
|
||||
m_avgcounts.clear();
|
||||
}
|
||||
|
||||
void print(std::ostream &o)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
for(core::map<std::string, float>::Iterator
|
||||
for(core::map<std::string, u32>::Iterator
|
||||
i = m_data.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
int avgcount = 1;
|
||||
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||
if(n){
|
||||
if(n->getValue() >= 1)
|
||||
avgcount = n->getValue();
|
||||
}
|
||||
o<<" "<<name<<": ";
|
||||
o<<name<<": ";
|
||||
s32 clampsize = 40;
|
||||
s32 space = clampsize - name.size();
|
||||
s32 space = clampsize-name.size();
|
||||
for(s32 j=0; j<space; j++)
|
||||
{
|
||||
if(j%2 == 0 && j < space - 1)
|
||||
@@ -122,42 +81,32 @@ class Profiler
|
||||
else
|
||||
o<<" ";
|
||||
}
|
||||
o<<(i.getNode()->getValue() / avgcount);
|
||||
o<<i.getNode()->getValue();
|
||||
o<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
core::map<std::string, float> m_data;
|
||||
core::map<std::string, int> m_avgcounts;
|
||||
};
|
||||
|
||||
enum ScopeProfilerType{
|
||||
SPT_ADD,
|
||||
SPT_AVG
|
||||
core::map<std::string, u32> m_data;
|
||||
};
|
||||
|
||||
class ScopeProfiler
|
||||
{
|
||||
public:
|
||||
ScopeProfiler(Profiler *profiler, const std::string &name,
|
||||
enum ScopeProfilerType type = SPT_ADD):
|
||||
ScopeProfiler(Profiler *profiler, const std::string &name):
|
||||
m_profiler(profiler),
|
||||
m_name(name),
|
||||
m_timer(NULL),
|
||||
m_type(type)
|
||||
m_timer(NULL)
|
||||
{
|
||||
if(m_profiler)
|
||||
m_timer = new TimeTaker(m_name.c_str());
|
||||
}
|
||||
// name is copied
|
||||
ScopeProfiler(Profiler *profiler, const char *name,
|
||||
enum ScopeProfilerType type = SPT_ADD):
|
||||
ScopeProfiler(Profiler *profiler, const char *name):
|
||||
m_profiler(profiler),
|
||||
m_name(name),
|
||||
m_timer(NULL),
|
||||
m_type(type)
|
||||
m_timer(NULL)
|
||||
{
|
||||
if(m_profiler)
|
||||
m_timer = new TimeTaker(m_name.c_str());
|
||||
@@ -166,18 +115,9 @@ class ScopeProfiler
|
||||
{
|
||||
if(m_timer)
|
||||
{
|
||||
float duration_ms = m_timer->stop(true);
|
||||
float duration = duration_ms / 1000.0;
|
||||
if(m_profiler){
|
||||
switch(m_type){
|
||||
case SPT_ADD:
|
||||
m_profiler->add(m_name, duration);
|
||||
break;
|
||||
case SPT_AVG:
|
||||
m_profiler->avg(m_name, duration);
|
||||
break;
|
||||
}
|
||||
}
|
||||
u32 duration = m_timer->stop(true);
|
||||
if(m_profiler)
|
||||
m_profiler->add(m_name, duration);
|
||||
delete m_timer;
|
||||
}
|
||||
}
|
||||
@@ -185,7 +125,6 @@ class ScopeProfiler
|
||||
Profiler *m_profiler;
|
||||
std::string m_name;
|
||||
TimeTaker *m_timer;
|
||||
enum ScopeProfilerType m_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
1240
src/server.cpp
20
src/server.h
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "environment.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
#include "utility.h"
|
||||
#include "porting.h"
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
@@ -449,7 +450,11 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
}
|
||||
|
||||
// Saves g_settings to configpath given at initialization
|
||||
void saveConfig();
|
||||
void saveConfig()
|
||||
{
|
||||
if(m_configpath != "")
|
||||
g_settings.updateConfigFile(m_configpath.c_str());
|
||||
}
|
||||
|
||||
void setIpBanned(const std::string &ip, const std::string &name)
|
||||
{
|
||||
@@ -468,14 +473,10 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
return m_banmanager.getBanDescription(ip_or_name);
|
||||
}
|
||||
|
||||
Address getPeerAddress(u16 peer_id)
|
||||
con::Peer* getPeerNoEx(u16 peer_id)
|
||||
{
|
||||
return m_con.GetPeerAddress(peer_id);
|
||||
return m_con.GetPeerNoEx(peer_id);
|
||||
}
|
||||
|
||||
// Envlock and conlock should be locked when calling this
|
||||
void notifyPlayer(const char *name, const std::wstring msg);
|
||||
void notifyPlayers(const std::wstring msg);
|
||||
|
||||
private:
|
||||
|
||||
@@ -492,8 +493,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
|
||||
static void SendAccessDenied(con::Connection &con, u16 peer_id,
|
||||
const std::wstring &reason);
|
||||
static void SendDeathscreen(con::Connection &con, u16 peer_id,
|
||||
bool set_camera_point_target, v3f camera_point_target);
|
||||
|
||||
/*
|
||||
Non-static send methods
|
||||
@@ -532,9 +531,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
Something random
|
||||
*/
|
||||
|
||||
void HandlePlayerHP(Player *player, s16 damage);
|
||||
void RespawnPlayer(Player *player);
|
||||
|
||||
void UpdateCrafting(u16 peer_id);
|
||||
|
||||
// When called, connection mutex should be locked
|
||||
|
||||
@@ -18,9 +18,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "servercommand.h"
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
void cmd_status(std::wostringstream &os,
|
||||
ServerCommandContext *ctx)
|
||||
@@ -96,31 +93,10 @@ void cmd_grantrevoke(std::wostringstream &os,
|
||||
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")
|
||||
privs |= newprivs;
|
||||
actionstream<<ctx->player->getName()<<" grants "
|
||||
<<wide_to_narrow(ctx->parms[2])<<" to "
|
||||
<<playername<<std::endl;
|
||||
|
||||
std::wstring msg;
|
||||
msg += narrow_to_wide(ctx->player->getName());
|
||||
msg += L" granted you the privilege \"";
|
||||
msg += ctx->parms[2];
|
||||
msg += L"\"";
|
||||
ctx->server->notifyPlayer(playername.c_str(), msg);
|
||||
} else {
|
||||
else
|
||||
privs &= ~newprivs;
|
||||
actionstream<<ctx->player->getName()<<" revokes "
|
||||
<<wide_to_narrow(ctx->parms[2])<<" from "
|
||||
<<playername<<std::endl;
|
||||
|
||||
std::wstring msg;
|
||||
msg += narrow_to_wide(ctx->player->getName());
|
||||
msg += L" revoked from you the privilege \"";
|
||||
msg += ctx->parms[2];
|
||||
msg += L"\"";
|
||||
ctx->server->notifyPlayer(playername.c_str(), msg);
|
||||
}
|
||||
|
||||
ctx->server->setPlayerAuthPrivs(playername, privs);
|
||||
|
||||
@@ -146,9 +122,6 @@ void cmd_time(std::wostringstream &os,
|
||||
u32 time = stoi(wide_to_narrow(ctx->parms[1]));
|
||||
ctx->server->setTimeOfDay(time);
|
||||
os<<L"-!- time_of_day changed.";
|
||||
|
||||
actionstream<<ctx->player->getName()<<" sets time "
|
||||
<<time<<std::endl;
|
||||
}
|
||||
|
||||
void cmd_shutdown(std::wostringstream &os,
|
||||
@@ -160,9 +133,8 @@ void cmd_shutdown(std::wostringstream &os,
|
||||
return;
|
||||
}
|
||||
|
||||
actionstream<<ctx->player->getName()
|
||||
<<" shuts down server"<<std::endl;
|
||||
|
||||
dstream<<DTIME<<" Server: Operator requested shutdown."
|
||||
<<std::endl;
|
||||
ctx->server->requestShutdown();
|
||||
|
||||
os<<L"*** Server shutting down (operator request)";
|
||||
@@ -183,10 +155,7 @@ void cmd_setting(std::wostringstream &os,
|
||||
|
||||
std::string confline = wide_to_narrow(ctx->paramstring);
|
||||
|
||||
actionstream<<ctx->player->getName()
|
||||
<<" sets: "<<confline<<std::endl;
|
||||
|
||||
g_settings->parseConfigLine(confline);
|
||||
g_settings.parseConfigLine(confline);
|
||||
|
||||
ctx->server->saveConfig();
|
||||
|
||||
@@ -216,11 +185,6 @@ void cmd_teleport(std::wostringstream &os,
|
||||
}
|
||||
|
||||
v3f dest(stoi(coords[0])*10, stoi(coords[1])*10, stoi(coords[2])*10);
|
||||
|
||||
actionstream<<ctx->player->getName()<<" teleports from "
|
||||
<<PP(ctx->player->getPosition()/BS)<<" to "
|
||||
<<PP(dest/BS)<<std::endl;
|
||||
|
||||
ctx->player->setPosition(dest);
|
||||
ctx->server->SendMovePlayer(ctx->player);
|
||||
|
||||
@@ -250,19 +214,17 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
||||
os<<L"-!- No such player";
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
Address address = ctx->server->getPeerAddress(player->peer_id);
|
||||
std::string ip_string = address.serializeString();
|
||||
ctx->server->setIpBanned(ip_string, player->getName());
|
||||
os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
|
||||
<<narrow_to_wide(player->getName());
|
||||
|
||||
actionstream<<ctx->player->getName()<<" bans "
|
||||
<<player->getName()<<" / "<<ip_string<<std::endl;
|
||||
} catch(con::PeerNotFoundException){
|
||||
con::Peer *peer = ctx->server->getPeerNoEx(player->peer_id);
|
||||
if(peer == NULL)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": peer was not found"<<std::endl;
|
||||
return;
|
||||
}
|
||||
std::string ip_string = peer->address.serializeString();
|
||||
ctx->server->setIpBanned(ip_string, player->getName());
|
||||
os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
|
||||
<<narrow_to_wide(player->getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -270,41 +232,9 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
||||
std::string desc = ctx->server->getBanDescription(ip_or_name);
|
||||
ctx->server->unsetIpBanned(ip_or_name);
|
||||
os<<L"-!- Unbanned "<<narrow_to_wide(desc);
|
||||
|
||||
actionstream<<ctx->player->getName()<<" unbans "
|
||||
<<ip_or_name<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_clearobjects(std::wostringstream &os,
|
||||
ServerCommandContext *ctx)
|
||||
{
|
||||
if((ctx->privs & PRIV_SERVER) ==0)
|
||||
{
|
||||
os<<L"-!- You don't have permission to do that";
|
||||
return;
|
||||
}
|
||||
|
||||
actionstream<<ctx->player->getName()
|
||||
<<" clears all objects"<<std::endl;
|
||||
|
||||
{
|
||||
std::wstring msg;
|
||||
msg += L"Clearing all objects. This may take long.";
|
||||
msg += L" You may experience a timeout. (by ";
|
||||
msg += narrow_to_wide(ctx->player->getName());
|
||||
msg += L")";
|
||||
ctx->server->notifyPlayers(msg);
|
||||
}
|
||||
|
||||
ctx->env->clearAllObjects();
|
||||
|
||||
actionstream<<"object clearing done"<<std::endl;
|
||||
|
||||
os<<L"*** cleared all objects";
|
||||
ctx->flags |= SEND_TO_OTHERS;
|
||||
}
|
||||
|
||||
|
||||
std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||
{
|
||||
@@ -330,28 +260,45 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||
os<<L" ban unban";
|
||||
}
|
||||
else if(ctx->parms[0] == L"status")
|
||||
{
|
||||
cmd_status(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"privs")
|
||||
{
|
||||
cmd_privs(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
|
||||
{
|
||||
cmd_grantrevoke(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"time")
|
||||
{
|
||||
cmd_time(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"shutdown")
|
||||
{
|
||||
cmd_shutdown(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"setting")
|
||||
{
|
||||
cmd_setting(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"teleport")
|
||||
{
|
||||
cmd_teleport(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
|
||||
{
|
||||
cmd_banunban(os, ctx);
|
||||
}
|
||||
else if(ctx->parms[0] == L"me")
|
||||
{
|
||||
cmd_me(os, ctx);
|
||||
else if(ctx->parms[0] == L"clearobjects")
|
||||
cmd_clearobjects(os, ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
os<<L"-!- Invalid command: " + ctx->parms[0];
|
||||
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,21 +70,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "config.h"
|
||||
#include "mineral.h"
|
||||
#include "filesys.h"
|
||||
#include "defaultsettings.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
Settings.
|
||||
These are loaded from the config file.
|
||||
*/
|
||||
Settings main_settings;
|
||||
Settings *g_settings = &main_settings;
|
||||
|
||||
Settings g_settings;
|
||||
|
||||
extern void set_default_settings();
|
||||
|
||||
// Global profiler
|
||||
Profiler main_profiler;
|
||||
Profiler *g_profiler = &main_profiler;
|
||||
Profiler g_profiler;
|
||||
|
||||
// A dummy thing
|
||||
ITextureSource *g_texturesource = NULL;
|
||||
@@ -95,15 +92,15 @@ ITextureSource *g_texturesource = NULL;
|
||||
|
||||
// Connection
|
||||
std::ostream *dout_con_ptr = &dummyout;
|
||||
std::ostream *derr_con_ptr = &verbosestream;
|
||||
std::ostream *derr_con_ptr = &dstream_no_stderr;
|
||||
|
||||
// Server
|
||||
std::ostream *dout_server_ptr = &infostream;
|
||||
std::ostream *derr_server_ptr = &errorstream;
|
||||
std::ostream *dout_server_ptr = &dstream;
|
||||
std::ostream *derr_server_ptr = &dstream;
|
||||
|
||||
// Client
|
||||
std::ostream *dout_client_ptr = &infostream;
|
||||
std::ostream *derr_client_ptr = &errorstream;
|
||||
std::ostream *dout_client_ptr = &dstream;
|
||||
std::ostream *derr_client_ptr = &dstream;
|
||||
|
||||
/*
|
||||
gettime.h implementation
|
||||
@@ -117,37 +114,12 @@ u32 getTimeMs()
|
||||
return porting::getTimeMs();
|
||||
}
|
||||
|
||||
class StderrLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
std::cerr<<line<<std::endl;
|
||||
}
|
||||
} main_stderr_log_out;
|
||||
|
||||
class DstreamNoStderrLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
dstream_no_stderr<<line<<std::endl;
|
||||
}
|
||||
} main_dstream_no_stderr_log_out;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/*
|
||||
Initialization
|
||||
*/
|
||||
|
||||
log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION);
|
||||
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
||||
|
||||
log_register_thread("main");
|
||||
|
||||
// Set locale. This is for forcing '.' as the decimal point.
|
||||
std::locale::global(std::locale("C"));
|
||||
// This enables printing all characters in bitmap font
|
||||
@@ -175,7 +147,7 @@ int main(int argc, char *argv[])
|
||||
#ifdef RUN_IN_PLACE
|
||||
std::string debugfile = DEBUGFILE;
|
||||
#else
|
||||
std::string debugfile = porting::path_userdata+DIR_DELIM+DEBUGFILE;
|
||||
std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;
|
||||
#endif
|
||||
debugstreams_init(disable_stderr, debugfile.c_str());
|
||||
// Initialize debug stacks
|
||||
@@ -190,7 +162,7 @@ int main(int argc, char *argv[])
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
// Print startup message
|
||||
actionstream<<PROJECT_NAME<<
|
||||
dstream<<DTIME<<PROJECT_NAME <<
|
||||
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
|
||||
<<", "<<BUILD_INFO
|
||||
<<std::endl;
|
||||
@@ -211,7 +183,6 @@ int main(int argc, char *argv[])
|
||||
allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG));
|
||||
allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG));
|
||||
allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING));
|
||||
allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG));
|
||||
|
||||
Settings cmd_args;
|
||||
|
||||
@@ -244,15 +215,13 @@ int main(int argc, char *argv[])
|
||||
return cmd_args.getFlag("help") ? 0 : 1;
|
||||
}
|
||||
|
||||
if(cmd_args.getFlag("info-on-stderr"))
|
||||
log_add_output(&main_stderr_log_out, LMT_INFO);
|
||||
|
||||
/*
|
||||
Basic initialization
|
||||
*/
|
||||
|
||||
// Initialize default settings
|
||||
set_default_settings(g_settings);
|
||||
set_default_settings();
|
||||
|
||||
// Initialize sockets
|
||||
sockets_init();
|
||||
@@ -267,10 +236,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(cmd_args.exists("config"))
|
||||
{
|
||||
bool r = g_settings->readConfigFile(cmd_args.get("config").c_str());
|
||||
bool r = g_settings.readConfigFile(cmd_args.get("config").c_str());
|
||||
if(r == false)
|
||||
{
|
||||
errorstream<<"Could not read configuration from \""
|
||||
dstream<<"Could not read configuration from \""
|
||||
<<cmd_args.get("config")<<"\""<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
@@ -279,16 +248,14 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
{
|
||||
core::array<std::string> filenames;
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + "minetest.conf");
|
||||
filenames.push_back(porting::path_userdata + "/minetest.conf");
|
||||
#ifdef RUN_IN_PLACE
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + ".." + DIR_DELIM + "minetest.conf");
|
||||
filenames.push_back(porting::path_userdata + "/../minetest.conf");
|
||||
#endif
|
||||
|
||||
for(u32 i=0; i<filenames.size(); i++)
|
||||
{
|
||||
bool r = g_settings->readConfigFile(filenames[i].c_str());
|
||||
bool r = g_settings.readConfigFile(filenames[i].c_str());
|
||||
if(r)
|
||||
{
|
||||
configpath = filenames[i];
|
||||
@@ -338,9 +305,9 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
port = cmd_args.getU16("port");
|
||||
}
|
||||
else if(g_settings->exists("port") && g_settings->getU16("port") != 0)
|
||||
else if(g_settings.exists("port") && g_settings.getU16("port") != 0)
|
||||
{
|
||||
port = g_settings->getU16("port");
|
||||
port = g_settings.getU16("port");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -349,11 +316,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Figure out path to map
|
||||
std::string map_dir = porting::path_userdata+DIR_DELIM+"world";
|
||||
std::string map_dir = porting::path_userdata+"/world";
|
||||
if(cmd_args.exists("map-dir"))
|
||||
map_dir = cmd_args.get("map-dir");
|
||||
else if(g_settings->exists("map-dir"))
|
||||
map_dir = g_settings->get("map-dir");
|
||||
else if(g_settings.exists("map-dir"))
|
||||
map_dir = g_settings.get("map-dir");
|
||||
|
||||
// Create server
|
||||
Server server(map_dir.c_str(), configpath);
|
||||
@@ -365,10 +332,10 @@ int main(int argc, char *argv[])
|
||||
} //try
|
||||
catch(con::PeerNotFoundException &e)
|
||||
{
|
||||
errorstream<<"Connection timed out."<<std::endl;
|
||||
dstream<<DTIME<<"Connection timed out."<<std::endl;
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
END_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
debugstreams_deinit();
|
||||
|
||||
|
||||
@@ -104,15 +104,12 @@ class ServerActiveObject : public ActiveObject
|
||||
If the object doesn't return an item, this will be called.
|
||||
Return value is tool wear.
|
||||
*/
|
||||
virtual u16 punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername)
|
||||
virtual u16 punch(const std::string &toolname, v3f dir)
|
||||
{return 0;}
|
||||
|
||||
/*
|
||||
*/
|
||||
virtual void rightClick(Player *player){}
|
||||
|
||||
virtual bool isPeaceful(){return true;}
|
||||
|
||||
/*
|
||||
Number of players which know about this object. Object won't be
|
||||
|
||||
658
src/settings.h
@@ -1,658 +0,0 @@
|
||||
/*
|
||||
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 SETTINGS_HEADER
|
||||
#define SETTINGS_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include "strfnd.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "debug.h"
|
||||
#include "utility.h"
|
||||
#include "log.h"
|
||||
|
||||
enum ValueType
|
||||
{
|
||||
VALUETYPE_STRING,
|
||||
VALUETYPE_FLAG // Doesn't take any arguments
|
||||
};
|
||||
|
||||
struct ValueSpec
|
||||
{
|
||||
ValueSpec(ValueType a_type, const char *a_help=NULL)
|
||||
{
|
||||
type = a_type;
|
||||
help = a_help;
|
||||
}
|
||||
ValueType type;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings()
|
||||
{
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
void writeLines(std::ostream &os)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseConfigLine(const std::string &line)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
return true;
|
||||
|
||||
//infostream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
return true;
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
/*infostream<<"Config name=\""<<name<<"\" value=\""
|
||||
<<value<<"\""<<std::endl;*/
|
||||
|
||||
m_settings[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void parseConfigLines(std::istream &is, const std::string &endstring)
|
||||
{
|
||||
for(;;){
|
||||
if(is.eof())
|
||||
break;
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
std::string trimmedline = trim(line);
|
||||
if(endstring != ""){
|
||||
if(trimmedline == endstring)
|
||||
break;
|
||||
}
|
||||
parseConfigLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns false on EOF
|
||||
bool parseConfigObject(std::istream &is)
|
||||
{
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
/*
|
||||
NOTE: This function might be expanded to allow multi-line
|
||||
settings.
|
||||
*/
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
//infostream<<"got line: \""<<line<<"\""<<std::endl;
|
||||
|
||||
return parseConfigLine(line);
|
||||
}
|
||||
|
||||
/*
|
||||
Read configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool readConfigFile(const char *filename)
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
errorstream<<"Error opening configuration file \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
infostream<<"Parsing configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
while(parseConfigObject(is));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Reads a configuration object from stream (usually a single line)
|
||||
and adds it to dst.
|
||||
|
||||
Preserves comments and empty lines.
|
||||
|
||||
Settings that were added to dst are also added to updated.
|
||||
key of updated is setting name, value of updated is dummy.
|
||||
|
||||
Returns false on EOF
|
||||
*/
|
||||
bool getUpdatedConfigObject(std::istream &is,
|
||||
core::list<std::string> &dst,
|
||||
core::map<std::string, bool> &updated)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
// NOTE: This function will be expanded to allow multi-line settings
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
std::string line_end = "";
|
||||
if(is.eof() == false)
|
||||
line_end = "\n";
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
if(m_settings.find(name))
|
||||
{
|
||||
std::string newvalue = m_settings[name];
|
||||
|
||||
if(newvalue != value)
|
||||
{
|
||||
infostream<<"Changing value of \""<<name<<"\" = \""
|
||||
<<value<<"\" -> \""<<newvalue<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
dst.push_back(name + " = " + newvalue + line_end);
|
||||
|
||||
updated[name] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Updates configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool updateConfigFile(const char *filename)
|
||||
{
|
||||
infostream<<"Updating configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
core::list<std::string> objects;
|
||||
core::map<std::string, bool> updated;
|
||||
|
||||
// Read and modify stuff
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
infostream<<"updateConfigFile():"
|
||||
" Error opening configuration file"
|
||||
" for reading: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(getUpdatedConfigObject(is, objects, updated));
|
||||
}
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Write stuff back
|
||||
{
|
||||
std::ofstream os(filename);
|
||||
if(os.good() == false)
|
||||
{
|
||||
errorstream<<"Error opening configuration file"
|
||||
" for writing: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Write updated stuff
|
||||
*/
|
||||
for(core::list<std::string>::Iterator
|
||||
i = objects.begin();
|
||||
i != objects.end(); i++)
|
||||
{
|
||||
os<<(*i);
|
||||
}
|
||||
|
||||
/*
|
||||
Write stuff that was not already in the file
|
||||
*/
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
if(updated.find(i.getNode()->getKey()))
|
||||
continue;
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: Types of allowed_options are ignored
|
||||
|
||||
returns true on success
|
||||
*/
|
||||
bool parseCommandLine(int argc, char *argv[],
|
||||
core::map<std::string, ValueSpec> &allowed_options)
|
||||
{
|
||||
int i=1;
|
||||
for(;;)
|
||||
{
|
||||
if(i >= argc)
|
||||
break;
|
||||
std::string argname = argv[i];
|
||||
if(argname.substr(0, 2) != "--")
|
||||
{
|
||||
errorstream<<"Invalid command-line parameter \""
|
||||
<<argname<<"\": --<option> expected."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
|
||||
std::string name = argname.substr(2);
|
||||
|
||||
core::map<std::string, ValueSpec>::Node *n;
|
||||
n = allowed_options.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
errorstream<<"Unknown command-line parameter \""
|
||||
<<argname<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueType type = n->getValue().type;
|
||||
|
||||
std::string value = "";
|
||||
|
||||
if(type == VALUETYPE_FLAG)
|
||||
{
|
||||
value = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i >= argc)
|
||||
{
|
||||
errorstream<<"Invalid command-line parameter \""
|
||||
<<name<<"\": missing value"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
value = argv[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
infostream<<"Valid command-line parameter: \""
|
||||
<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
set(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
void set(std::string name, const char *value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
void setDefault(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_defaults[name] = value;
|
||||
}
|
||||
|
||||
bool exists(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
return (m_settings.find(name) || m_defaults.find(name));
|
||||
}
|
||||
|
||||
std::string get(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, std::string>::Node *n;
|
||||
n = m_settings.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
n = m_defaults.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
infostream<<"Settings: Setting not found: \""
|
||||
<<name<<"\""<<std::endl;
|
||||
throw SettingNotFoundException("Setting not found");
|
||||
}
|
||||
}
|
||||
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
bool getBool(std::string name)
|
||||
{
|
||||
return is_yes(get(name));
|
||||
}
|
||||
|
||||
bool getFlag(std::string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getBool(name);
|
||||
}
|
||||
catch(SettingNotFoundException &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Asks if empty
|
||||
bool getBoolAsk(std::string name, std::string question, bool def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getBool(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" [y/N]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return is_yes(s);
|
||||
}
|
||||
|
||||
float getFloat(std::string name)
|
||||
{
|
||||
return stof(get(name));
|
||||
}
|
||||
|
||||
u16 getU16(std::string name)
|
||||
{
|
||||
return stoi(get(name), 0, 65535);
|
||||
}
|
||||
|
||||
u16 getU16Ask(std::string name, std::string question, u16 def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getU16(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" ["<<def<<"]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return stoi(s, 0, 65535);
|
||||
}
|
||||
|
||||
s16 getS16(std::string name)
|
||||
{
|
||||
return stoi(get(name), -32768, 32767);
|
||||
}
|
||||
|
||||
s32 getS32(std::string name)
|
||||
{
|
||||
return stoi(get(name));
|
||||
}
|
||||
|
||||
v3f getV3F(std::string name)
|
||||
{
|
||||
v3f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(","));
|
||||
value.Z = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
v2f getV2F(std::string name)
|
||||
{
|
||||
v2f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
u64 getU64(std::string name)
|
||||
{
|
||||
u64 value = 0;
|
||||
std::string s = get(name);
|
||||
std::istringstream ss(s);
|
||||
ss>>value;
|
||||
return value;
|
||||
}
|
||||
|
||||
void setBool(std::string name, bool value)
|
||||
{
|
||||
if(value)
|
||||
set(name, "true");
|
||||
else
|
||||
set(name, "false");
|
||||
}
|
||||
|
||||
void setS32(std::string name, s32 value)
|
||||
{
|
||||
set(name, itos(value));
|
||||
}
|
||||
|
||||
void setFloat(std::string name, float value)
|
||||
{
|
||||
set(name, ftos(value));
|
||||
}
|
||||
|
||||
void setV3F(std::string name, v3f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setV2F(std::string name, v2f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setU64(std::string name, u64 value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<value;
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings.clear();
|
||||
m_defaults.clear();
|
||||
}
|
||||
|
||||
void updateValue(Settings &other, const std::string &name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return;
|
||||
|
||||
try{
|
||||
std::string val = other.get(name);
|
||||
m_settings[name] = val;
|
||||
} catch(SettingNotFoundException &e){
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void update(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return;
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_settings[i.getNode()->getKey()] = i.getNode()->getValue();
|
||||
}
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_defaults.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_defaults[i.getNode()->getKey()] = i.getNode()->getValue();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Settings & operator+=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_settings.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_defaults.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_defaults.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
Settings & operator=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
(*this) += other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
core::map<std::string, std::string> m_settings;
|
||||
core::map<std::string, std::string> m_defaults;
|
||||
// All methods that access m_settings/m_defaults directly should lock this.
|
||||
JMutex m_mutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -97,7 +97,7 @@ void Address::Resolve(const char *name)
|
||||
freeaddrinfo(resolved);
|
||||
}
|
||||
|
||||
std::string Address::serializeString() const
|
||||
std::string Address::serializeString()
|
||||
{
|
||||
unsigned int a, b, c, d;
|
||||
a = (m_address & 0xFF000000)>>24;
|
||||
|
||||
@@ -97,7 +97,7 @@ class Address
|
||||
void setPort(unsigned short port);
|
||||
void print(std::ostream *s) const;
|
||||
void print() const;
|
||||
std::string serializeString() const;
|
||||
std::string serializeString();
|
||||
private:
|
||||
unsigned int m_address;
|
||||
unsigned short m_port;
|
||||
|
||||
285
src/test.cpp
@@ -32,8 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "porting.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "mapsector.h"
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
Asserts that the exception occurs
|
||||
@@ -50,9 +48,9 @@ struct TestUtilities
|
||||
{
|
||||
void Run()
|
||||
{
|
||||
/*infostream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
|
||||
infostream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
|
||||
infostream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
|
||||
/*dstream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
|
||||
dstream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
|
||||
dstream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
|
||||
assert(fabs(wrapDegrees(100.0) - 100.0) < 0.001);
|
||||
assert(fabs(wrapDegrees(720.5) - 0.5) < 0.001);
|
||||
assert(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
|
||||
@@ -113,13 +111,13 @@ struct TestCompress
|
||||
|
||||
std::string str_out = os.str();
|
||||
|
||||
infostream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
infostream<<"TestCompress: 1,5,5,1 -> ";
|
||||
dstream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
dstream<<"TestCompress: 1,5,5,1 -> ";
|
||||
for(u32 i=0; i<str_out.size(); i++)
|
||||
{
|
||||
infostream<<(u32)str_out[i]<<",";
|
||||
dstream<<(u32)str_out[i]<<",";
|
||||
}
|
||||
infostream<<std::endl;
|
||||
dstream<<std::endl;
|
||||
|
||||
assert(str_out.size() == 10);
|
||||
|
||||
@@ -140,12 +138,12 @@ struct TestCompress
|
||||
decompress(is, os2, 0);
|
||||
std::string str_out2 = os2.str();
|
||||
|
||||
infostream<<"decompress: ";
|
||||
dstream<<"decompress: ";
|
||||
for(u32 i=0; i<str_out2.size(); i++)
|
||||
{
|
||||
infostream<<(u32)str_out2[i]<<",";
|
||||
dstream<<(u32)str_out2[i]<<",";
|
||||
}
|
||||
infostream<<std::endl;
|
||||
dstream<<std::endl;
|
||||
|
||||
assert(str_out2.size() == fromdata.getSize());
|
||||
|
||||
@@ -169,13 +167,13 @@ struct TestCompress
|
||||
|
||||
std::string str_out = os.str();
|
||||
|
||||
infostream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
infostream<<"TestCompress: 1,5,5,1 -> ";
|
||||
dstream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
dstream<<"TestCompress: 1,5,5,1 -> ";
|
||||
for(u32 i=0; i<str_out.size(); i++)
|
||||
{
|
||||
infostream<<(u32)str_out[i]<<",";
|
||||
dstream<<(u32)str_out[i]<<",";
|
||||
}
|
||||
infostream<<std::endl;
|
||||
dstream<<std::endl;
|
||||
|
||||
/*assert(str_out.size() == 10);
|
||||
|
||||
@@ -196,12 +194,12 @@ struct TestCompress
|
||||
decompress(is, os2, SER_FMT_VER_HIGHEST);
|
||||
std::string str_out2 = os2.str();
|
||||
|
||||
infostream<<"decompress: ";
|
||||
dstream<<"decompress: ";
|
||||
for(u32 i=0; i<str_out2.size(); i++)
|
||||
{
|
||||
infostream<<(u32)str_out2[i]<<",";
|
||||
dstream<<(u32)str_out2[i]<<",";
|
||||
}
|
||||
infostream<<std::endl;
|
||||
dstream<<std::endl;
|
||||
|
||||
assert(str_out2.size() == fromdata.getSize());
|
||||
|
||||
@@ -259,12 +257,12 @@ struct TestVoxelManipulator
|
||||
|
||||
assert(aa.size() == results.size());
|
||||
|
||||
infostream<<"Result of diff:"<<std::endl;
|
||||
dstream<<"Result of diff:"<<std::endl;
|
||||
for(core::list<VoxelArea>::Iterator
|
||||
i = aa.begin(); i != aa.end(); i++)
|
||||
{
|
||||
i->print(infostream);
|
||||
infostream<<std::endl;
|
||||
i->print(dstream);
|
||||
dstream<<std::endl;
|
||||
|
||||
s32 j = results.linear_search(*i);
|
||||
assert(j != -1);
|
||||
@@ -278,27 +276,27 @@ struct TestVoxelManipulator
|
||||
|
||||
VoxelManipulator v;
|
||||
|
||||
v.print(infostream);
|
||||
v.print(dstream);
|
||||
|
||||
infostream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
|
||||
dstream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
|
||||
|
||||
v.setNodeNoRef(v3s16(-1,0,-1), MapNode(2));
|
||||
|
||||
v.print(infostream);
|
||||
v.print(dstream);
|
||||
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
|
||||
|
||||
infostream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
|
||||
dstream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
|
||||
|
||||
EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,0,-1)));
|
||||
|
||||
v.print(infostream);
|
||||
v.print(dstream);
|
||||
|
||||
infostream<<"*** Adding area ***"<<std::endl;
|
||||
dstream<<"*** Adding area ***"<<std::endl;
|
||||
|
||||
v.addArea(a);
|
||||
|
||||
v.print(infostream);
|
||||
v.print(dstream);
|
||||
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
|
||||
EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1)));
|
||||
@@ -344,12 +342,12 @@ struct TestVoxelManipulator
|
||||
p++;
|
||||
}
|
||||
|
||||
v.print(infostream, VOXELPRINT_WATERPRESSURE);
|
||||
v.print(dstream, VOXELPRINT_WATERPRESSURE);
|
||||
|
||||
core::map<v3s16, u8> active_nodes;
|
||||
v.updateAreaWaterPressure(area, active_nodes);
|
||||
|
||||
v.print(infostream, VOXELPRINT_WATERPRESSURE);
|
||||
v.print(dstream, VOXELPRINT_WATERPRESSURE);
|
||||
|
||||
//s16 highest_y = -32768;
|
||||
/*
|
||||
@@ -366,8 +364,8 @@ struct TestVoxelManipulator
|
||||
//v.flowWater(active_nodes, 0, true, 1000);
|
||||
v.flowWater(active_nodes, 0, false, 1000);
|
||||
|
||||
infostream<<"Final result of flowWater:"<<std::endl;
|
||||
v.print(infostream, VOXELPRINT_WATERPRESSURE);
|
||||
dstream<<"Final result of flowWater:"<<std::endl;
|
||||
v.print(dstream, VOXELPRINT_WATERPRESSURE);
|
||||
#endif
|
||||
|
||||
//assert(0);
|
||||
@@ -766,15 +764,15 @@ struct TestConnection
|
||||
assert(readU8(&p1.data[6]) == channel);
|
||||
assert(readU8(&p1.data[7]) == data1[0]);
|
||||
|
||||
//infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
|
||||
//dstream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
|
||||
|
||||
SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
|
||||
|
||||
/*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
|
||||
/*dstream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
|
||||
<<data1.getSize()<<std::endl;
|
||||
infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
|
||||
dstream<<"readU8(&p2[3])="<<readU8(&p2[3])
|
||||
<<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
|
||||
infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
|
||||
dstream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
|
||||
|
||||
assert(p2.getSize() == 3 + data1.getSize());
|
||||
assert(readU8(&p2[0]) == TYPE_RELIABLE);
|
||||
@@ -792,14 +790,14 @@ struct TestConnection
|
||||
}
|
||||
void peerAdded(con::Peer *peer)
|
||||
{
|
||||
infostream<<"Handler("<<name<<")::peerAdded(): "
|
||||
dstream<<"Handler("<<name<<")::peerAdded(): "
|
||||
"id="<<peer->id<<std::endl;
|
||||
last_id = peer->id;
|
||||
count++;
|
||||
}
|
||||
void deletingPeer(con::Peer *peer, bool timeout)
|
||||
{
|
||||
infostream<<"Handler("<<name<<")::deletingPeer(): "
|
||||
dstream<<"Handler("<<name<<")::deletingPeer(): "
|
||||
"id="<<peer->id
|
||||
<<", timeout="<<timeout<<std::endl;
|
||||
last_id = peer->id;
|
||||
@@ -819,20 +817,17 @@ struct TestConnection
|
||||
|
||||
/*
|
||||
Test some real connections
|
||||
|
||||
NOTE: This mostly tests the legacy interface.
|
||||
*/
|
||||
|
||||
u32 proto_id = 0xad26846a;
|
||||
|
||||
Handler hand_server("server");
|
||||
Handler hand_client("client");
|
||||
|
||||
infostream<<"** Creating server Connection"<<std::endl;
|
||||
dstream<<"** Creating server Connection"<<std::endl;
|
||||
con::Connection server(proto_id, 512, 5.0, &hand_server);
|
||||
server.Serve(30001);
|
||||
|
||||
infostream<<"** Creating client Connection"<<std::endl;
|
||||
dstream<<"** Creating client Connection"<<std::endl;
|
||||
con::Connection client(proto_id, 512, 5.0, &hand_client);
|
||||
|
||||
assert(hand_server.count == 0);
|
||||
@@ -841,43 +836,24 @@ struct TestConnection
|
||||
sleep_ms(50);
|
||||
|
||||
Address server_address(127,0,0,1, 30001);
|
||||
infostream<<"** running client.Connect()"<<std::endl;
|
||||
dstream<<"** running client.Connect()"<<std::endl;
|
||||
client.Connect(server_address);
|
||||
|
||||
sleep_ms(50);
|
||||
|
||||
// Client should not have added client yet
|
||||
assert(hand_client.count == 0);
|
||||
|
||||
try
|
||||
{
|
||||
u16 peer_id;
|
||||
SharedBuffer<u8> data;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
u32 size = client.Receive(peer_id, data);
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
catch(con::NoIncomingDataException &e)
|
||||
{
|
||||
}
|
||||
|
||||
// Client should have added server now
|
||||
assert(hand_client.count == 1);
|
||||
assert(hand_client.last_id == 1);
|
||||
// Server should not have added client yet
|
||||
// But server should not have added client
|
||||
assert(hand_server.count == 0);
|
||||
|
||||
sleep_ms(50);
|
||||
|
||||
try
|
||||
{
|
||||
u16 peer_id;
|
||||
SharedBuffer<u8> data;
|
||||
infostream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, data);
|
||||
infostream<<"** Server received: peer_id="<<peer_id
|
||||
u8 data[100];
|
||||
dstream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, data, 100);
|
||||
dstream<<"** Server received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
@@ -901,10 +877,10 @@ struct TestConnection
|
||||
try
|
||||
{
|
||||
u16 peer_id;
|
||||
SharedBuffer<u8> data;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
u32 size = client.Receive(peer_id, data);
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
u8 data[100];
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
u32 size = client.Receive(peer_id, data, 100);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
@@ -919,61 +895,57 @@ struct TestConnection
|
||||
try
|
||||
{
|
||||
u16 peer_id;
|
||||
SharedBuffer<u8> data;
|
||||
infostream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, data);
|
||||
infostream<<"** Server received: peer_id="<<peer_id
|
||||
u8 data[100];
|
||||
dstream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, data, 100);
|
||||
dstream<<"** Server received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
catch(con::NoIncomingDataException &e)
|
||||
{
|
||||
}
|
||||
#if 1
|
||||
/*
|
||||
Simple send-receive test
|
||||
*/
|
||||
|
||||
{
|
||||
/*u8 data[] = "Hello World!";
|
||||
u32 datasize = sizeof(data);*/
|
||||
SharedBuffer<u8> data = SharedBufferFromString("Hello World!");
|
||||
|
||||
infostream<<"** running client.Send()"<<std::endl;
|
||||
dstream<<"** running client.Send()"<<std::endl;
|
||||
client.Send(PEER_ID_SERVER, 0, data, true);
|
||||
|
||||
sleep_ms(50);
|
||||
|
||||
u16 peer_id;
|
||||
SharedBuffer<u8> recvdata;
|
||||
infostream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, recvdata);
|
||||
infostream<<"** Server received: peer_id="<<peer_id
|
||||
u8 recvdata[100];
|
||||
dstream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, recvdata, 100);
|
||||
dstream<<"** Server received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<*data
|
||||
<<std::endl;
|
||||
assert(memcmp(*data, *recvdata, data.getSize()) == 0);
|
||||
assert(memcmp(*data, recvdata, data.getSize()) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
u16 peer_id_client = 2;
|
||||
#if 0
|
||||
/*
|
||||
Send consequent packets in different order
|
||||
Not compatible with new Connection, thus commented out.
|
||||
*/
|
||||
|
||||
{
|
||||
/*
|
||||
Send consequent packets in different order
|
||||
*/
|
||||
//u8 data1[] = "hello1";
|
||||
//u8 data2[] = "hello2";
|
||||
SharedBuffer<u8> data1 = SharedBufferFromString("hello1");
|
||||
SharedBuffer<u8> data2 = SharedBufferFromString("Hello2");
|
||||
|
||||
Address client_address =
|
||||
server.GetPeerAddress(peer_id_client);
|
||||
server.GetPeer(peer_id_client)->address;
|
||||
|
||||
infostream<<"*** Sending packets in wrong order (2,1,2)"
|
||||
dstream<<"*** Sending packets in wrong order (2,1,2)"
|
||||
<<std::endl;
|
||||
|
||||
u8 chn = 0;
|
||||
con::Channel *ch = &server.getPeer(peer_id_client)->channels[chn];
|
||||
con::Channel *ch = &server.GetPeer(peer_id_client)->channels[chn];
|
||||
u16 sn = ch->next_outgoing_seqnum;
|
||||
ch->next_outgoing_seqnum = sn+1;
|
||||
server.Send(peer_id_client, chn, data2, true);
|
||||
@@ -984,94 +956,52 @@ struct TestConnection
|
||||
|
||||
sleep_ms(50);
|
||||
|
||||
infostream<<"*** Receiving the packets"<<std::endl;
|
||||
dstream<<"*** Receiving the packets"<<std::endl;
|
||||
|
||||
u16 peer_id;
|
||||
SharedBuffer<u8> recvdata;
|
||||
u8 recvdata[20];
|
||||
u32 size;
|
||||
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
peer_id = 132;
|
||||
size = client.Receive(peer_id, recvdata);
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
size = client.Receive(peer_id, recvdata, 20);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<*recvdata
|
||||
<<", data="<<recvdata
|
||||
<<std::endl;
|
||||
assert(size == data1.getSize());
|
||||
assert(memcmp(*data1, *recvdata, data1.getSize()) == 0);
|
||||
assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
|
||||
assert(peer_id == PEER_ID_SERVER);
|
||||
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
peer_id = 132;
|
||||
size = client.Receive(peer_id, recvdata);
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
size = client.Receive(peer_id, recvdata, 20);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<*recvdata
|
||||
<<", data="<<recvdata
|
||||
<<std::endl;
|
||||
assert(size == data2.getSize());
|
||||
assert(memcmp(*data2, *recvdata, data2.getSize()) == 0);
|
||||
assert(memcmp(*data2, recvdata, data2.getSize()) == 0);
|
||||
assert(peer_id == PEER_ID_SERVER);
|
||||
|
||||
bool got_exception = false;
|
||||
try
|
||||
{
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
peer_id = 132;
|
||||
size = client.Receive(peer_id, recvdata);
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
size = client.Receive(peer_id, recvdata, 20);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<*recvdata
|
||||
<<", data="<<recvdata
|
||||
<<std::endl;
|
||||
}
|
||||
catch(con::NoIncomingDataException &e)
|
||||
{
|
||||
infostream<<"** No incoming data for client"<<std::endl;
|
||||
dstream<<"** No incoming data for client"<<std::endl;
|
||||
got_exception = true;
|
||||
}
|
||||
assert(got_exception);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
/*
|
||||
Send large amounts of packets (infinite test)
|
||||
Commented out because of infinity.
|
||||
*/
|
||||
{
|
||||
infostream<<"Sending large amounts of packets (infinite test)"<<std::endl;
|
||||
int sendcount = 0;
|
||||
for(;;){
|
||||
int datasize = myrand_range(0,5)==0?myrand_range(100,10000):myrand_range(0,100);
|
||||
infostream<<"datasize="<<datasize<<std::endl;
|
||||
SharedBuffer<u8> data1(datasize);
|
||||
for(u16 i=0; i<datasize; i++)
|
||||
data1[i] = i/4;
|
||||
|
||||
int sendtimes = myrand_range(1,10);
|
||||
for(int i=0; i<sendtimes; i++){
|
||||
server.Send(peer_id_client, 0, data1, true);
|
||||
sendcount++;
|
||||
}
|
||||
infostream<<"sendcount="<<sendcount<<std::endl;
|
||||
|
||||
//int receivetimes = myrand_range(1,20);
|
||||
int receivetimes = 20;
|
||||
for(int i=0; i<receivetimes; i++){
|
||||
SharedBuffer<u8> recvdata;
|
||||
u16 peer_id = 132;
|
||||
u16 size = 0;
|
||||
bool received = false;
|
||||
try{
|
||||
size = client.Receive(peer_id, recvdata);
|
||||
received = true;
|
||||
}catch(con::NoIncomingDataException &e){
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
Send a large packet
|
||||
*/
|
||||
{
|
||||
const int datasize = 30000;
|
||||
SharedBuffer<u8> data1(datasize);
|
||||
@@ -1079,50 +1009,37 @@ struct TestConnection
|
||||
data1[i] = i/4;
|
||||
}
|
||||
|
||||
infostream<<"Sending data (size="<<datasize<<"):";
|
||||
dstream<<"Sending data (size="<<datasize<<"):";
|
||||
for(int i=0; i<datasize && i<20; i++){
|
||||
if(i%2==0) DEBUGPRINT(" ");
|
||||
DEBUGPRINT("%.2X", ((int)((const char*)*data1)[i])&0xff);
|
||||
}
|
||||
if(datasize>20)
|
||||
infostream<<"...";
|
||||
infostream<<std::endl;
|
||||
dstream<<"...";
|
||||
dstream<<std::endl;
|
||||
|
||||
server.Send(peer_id_client, 0, data1, true);
|
||||
|
||||
sleep_ms(3000);
|
||||
sleep_ms(50);
|
||||
|
||||
SharedBuffer<u8> recvdata;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
u8 recvdata[datasize + 1000];
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
u16 peer_id = 132;
|
||||
u16 size = 0;
|
||||
bool received = false;
|
||||
u32 timems0 = porting::getTimeMs();
|
||||
for(;;){
|
||||
if(porting::getTimeMs() - timems0 > 5000)
|
||||
break;
|
||||
try{
|
||||
size = client.Receive(peer_id, recvdata);
|
||||
received = true;
|
||||
}catch(con::NoIncomingDataException &e){
|
||||
}
|
||||
sleep_ms(10);
|
||||
}
|
||||
assert(received);
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
u16 size = client.Receive(peer_id, recvdata, datasize + 1000);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
|
||||
infostream<<"Received data (size="<<size<<"):";
|
||||
dstream<<"Received data (size="<<size<<"):";
|
||||
for(int i=0; i<size && i<20; i++){
|
||||
if(i%2==0) DEBUGPRINT(" ");
|
||||
DEBUGPRINT("%.2X", ((int)(recvdata[i]))&0xff);
|
||||
DEBUGPRINT("%.2X", ((int)((const char*)recvdata)[i])&0xff);
|
||||
}
|
||||
if(size>20)
|
||||
infostream<<"...";
|
||||
infostream<<std::endl;
|
||||
dstream<<"...";
|
||||
dstream<<std::endl;
|
||||
|
||||
assert(memcmp(*data1, *recvdata, data1.getSize()) == 0);
|
||||
assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
|
||||
assert(peer_id == PEER_ID_SERVER);
|
||||
}
|
||||
|
||||
@@ -1139,14 +1056,14 @@ struct TestConnection
|
||||
#define TEST(X)\
|
||||
{\
|
||||
X x;\
|
||||
infostream<<"Running " #X <<std::endl;\
|
||||
dstream<<"Running " #X <<std::endl;\
|
||||
x.Run();\
|
||||
}
|
||||
|
||||
void run_tests()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
infostream<<"run_tests() started"<<std::endl;
|
||||
dstream<<"run_tests() started"<<std::endl;
|
||||
TEST(TestUtilities);
|
||||
TEST(TestSettings);
|
||||
TEST(TestCompress);
|
||||
@@ -1160,6 +1077,6 @@ void run_tests()
|
||||
TEST(TestConnection);
|
||||
dout_con<<"=== END RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
|
||||
}
|
||||
infostream<<"run_tests() passed"<<std::endl;
|
||||
dstream<<"run_tests() passed"<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
337
src/tile.cpp
@@ -22,11 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "main.h" // for g_settings
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include "log.h"
|
||||
#include "mapnode.h" // For texture atlas making
|
||||
#include "mineral.h" // For texture atlas making
|
||||
|
||||
/*
|
||||
A cache from texture name to texture path
|
||||
@@ -117,10 +112,10 @@ std::string getTexturePath(const std::string &filename)
|
||||
/*
|
||||
Check from texture_path
|
||||
*/
|
||||
std::string texture_path = g_settings->get("texture_path");
|
||||
std::string texture_path = g_settings.get("texture_path");
|
||||
if(texture_path != "")
|
||||
{
|
||||
std::string testpath = texture_path + DIR_DELIM + filename;
|
||||
std::string testpath = texture_path + '/' + filename;
|
||||
// Check all filename extensions. Returns "" if not found.
|
||||
fullpath = getImagePath(testpath);
|
||||
}
|
||||
@@ -162,10 +157,10 @@ TextureSource::TextureSource(IrrlichtDevice *device):
|
||||
m_name_to_id[""] = 0;
|
||||
|
||||
// Build main texture atlas
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
if(g_settings.getBool("enable_texture_atlas"))
|
||||
buildMainAtlas();
|
||||
else
|
||||
infostream<<"Not building texture atlas."<<std::endl;
|
||||
dstream<<"INFO: Not building texture atlas."<<std::endl;
|
||||
}
|
||||
|
||||
TextureSource::~TextureSource()
|
||||
@@ -182,7 +177,7 @@ void TextureSource::processQueue()
|
||||
GetRequest<std::string, u32, u8, u8>
|
||||
request = m_get_texture_queue.pop();
|
||||
|
||||
infostream<<"TextureSource::processQueue(): "
|
||||
dstream<<"INFO: TextureSource::processQueue(): "
|
||||
<<"got texture request with "
|
||||
<<"name=\""<<request.key<<"\""
|
||||
<<std::endl;
|
||||
@@ -199,7 +194,7 @@ void TextureSource::processQueue()
|
||||
|
||||
u32 TextureSource::getTextureId(const std::string &name)
|
||||
{
|
||||
//infostream<<"getTextureId(): \""<<name<<"\""<<std::endl;
|
||||
//dstream<<"INFO: getTextureId(): \""<<name<<"\""<<std::endl;
|
||||
|
||||
{
|
||||
/*
|
||||
@@ -223,7 +218,7 @@ u32 TextureSource::getTextureId(const std::string &name)
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
|
||||
dstream<<"INFO: getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
|
||||
|
||||
// We're gonna ask the result to be put into here
|
||||
ResultQueue<std::string, u32, u8, u8> result_queue;
|
||||
@@ -231,7 +226,7 @@ u32 TextureSource::getTextureId(const std::string &name)
|
||||
// Throw a request in
|
||||
m_get_texture_queue.add(name, 0, 0, &result_queue);
|
||||
|
||||
infostream<<"Waiting for texture from main thread, name=\""
|
||||
dstream<<"INFO: Waiting for texture from main thread, name=\""
|
||||
<<name<<"\""<<std::endl;
|
||||
|
||||
try
|
||||
@@ -247,12 +242,12 @@ u32 TextureSource::getTextureId(const std::string &name)
|
||||
}
|
||||
catch(ItemNotFoundException &e)
|
||||
{
|
||||
infostream<<"Waiting for texture timed out."<<std::endl;
|
||||
dstream<<"WARNING: Waiting for texture timed out."<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
infostream<<"getTextureId(): Failed"<<std::endl;
|
||||
dstream<<"WARNING: getTextureId(): Failed"<<std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -281,12 +276,12 @@ video::IImage* generate_image_from_scratch(std::string name,
|
||||
*/
|
||||
u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
{
|
||||
//infostream<<"getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
|
||||
//dstream<<"INFO: getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
|
||||
|
||||
// Empty name means texture 0
|
||||
if(name == "")
|
||||
{
|
||||
infostream<<"getTextureIdDirect(): name is empty"<<std::endl;
|
||||
dstream<<"INFO: getTextureIdDirect(): name is empty"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -295,7 +290,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
*/
|
||||
if(get_current_thread_id() != m_main_thread)
|
||||
{
|
||||
errorstream<<"TextureSource::getTextureIdDirect() "
|
||||
dstream<<"ERROR: TextureSource::getTextureIdDirect() "
|
||||
"called not from main thread"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -310,13 +305,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
n = m_name_to_id.find(name);
|
||||
if(n != NULL)
|
||||
{
|
||||
infostream<<"getTextureIdDirect(): \""<<name
|
||||
dstream<<"INFO: getTextureIdDirect(): \""<<name
|
||||
<<"\" found in cache"<<std::endl;
|
||||
return n->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
infostream<<"getTextureIdDirect(): \""<<name
|
||||
dstream<<"INFO: getTextureIdDirect(): \""<<name
|
||||
<<"\" NOT found in cache. Creating it."<<std::endl;
|
||||
|
||||
/*
|
||||
@@ -351,13 +346,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
{
|
||||
// Construct base name
|
||||
base_image_name = name.substr(0, last_separator_position);
|
||||
/*infostream<<"getTextureIdDirect(): Calling itself recursively"
|
||||
/*dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
|
||||
" to get base image of \""<<name<<"\" = \""
|
||||
<<base_image_name<<"\""<<std::endl;*/
|
||||
base_image_id = getTextureIdDirect(base_image_name);
|
||||
}
|
||||
|
||||
//infostream<<"base_image_id="<<base_image_id<<std::endl;
|
||||
//dstream<<"base_image_id="<<base_image_id<<std::endl;
|
||||
|
||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||
assert(driver);
|
||||
@@ -380,7 +375,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"getTextureIdDirect(): NULL image in "
|
||||
dstream<<"WARNING: getTextureIdDirect(): NULL image in "
|
||||
<<"cache: \""<<base_image_name<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
@@ -399,7 +394,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
core::rect<s32>(pos_from, dim) // from
|
||||
);
|
||||
|
||||
/*infostream<<"getTextureIdDirect(): Loaded \""
|
||||
/*dstream<<"INFO: getTextureIdDirect(): Loaded \""
|
||||
<<base_image_name<<"\" from image cache"
|
||||
<<std::endl;*/
|
||||
}
|
||||
@@ -411,12 +406,12 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
*/
|
||||
|
||||
std::string last_part_of_name = name.substr(last_separator_position+1);
|
||||
//infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
//dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
|
||||
// Generate image according to part of name
|
||||
if(generate_image(last_part_of_name, baseimg, m_device) == false)
|
||||
{
|
||||
infostream<<"getTextureIdDirect(): "
|
||||
dstream<<"INFO: getTextureIdDirect(): "
|
||||
"failed to generate \""<<last_part_of_name<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
@@ -424,7 +419,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
// If no resulting image, print a warning
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
infostream<<"getTextureIdDirect(): baseimg is NULL (attempted to"
|
||||
dstream<<"WARNING: getTextureIdDirect(): baseimg is NULL (attempted to"
|
||||
" create texture \""<<name<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
@@ -453,7 +448,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
m_atlaspointer_cache.push_back(nap);
|
||||
m_name_to_id.insert(name, id);
|
||||
|
||||
/*infostream<<"getTextureIdDirect(): "
|
||||
/*dstream<<"INFO: getTextureIdDirect(): "
|
||||
<<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/
|
||||
|
||||
return id;
|
||||
@@ -465,7 +460,7 @@ std::string TextureSource::getTextureName(u32 id)
|
||||
|
||||
if(id >= m_atlaspointer_cache.size())
|
||||
{
|
||||
infostream<<"TextureSource::getTextureName(): id="<<id
|
||||
dstream<<"WARNING: TextureSource::getTextureName(): id="<<id
|
||||
<<" >= m_atlaspointer_cache.size()="
|
||||
<<m_atlaspointer_cache.size()<<std::endl;
|
||||
return "";
|
||||
@@ -487,7 +482,7 @@ AtlasPointer TextureSource::getTexture(u32 id)
|
||||
|
||||
void TextureSource::buildMainAtlas()
|
||||
{
|
||||
infostream<<"TextureSource::buildMainAtlas()"<<std::endl;
|
||||
dstream<<"TextureSource::buildMainAtlas()"<<std::endl;
|
||||
|
||||
//return; // Disable (for testing)
|
||||
|
||||
@@ -503,68 +498,58 @@ void TextureSource::buildMainAtlas()
|
||||
//assert(atlas_img);
|
||||
if(atlas_img == NULL)
|
||||
{
|
||||
errorstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
|
||||
dstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
|
||||
"image; not building texture atlas."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Grab list of stuff to include in the texture atlas from the
|
||||
main content features
|
||||
A list of stuff to include in the texture atlas.
|
||||
|
||||
It is a single-dimensional texture atlas due to the need to tile
|
||||
textures.
|
||||
|
||||
It should contain as much of the stuff shown in game as possible,
|
||||
to minimize texture changes.
|
||||
|
||||
It fills up quickly, so do not add anything that isn't contained
|
||||
in most MapBlocks. E.g. mese isn't suitable but stone is.
|
||||
*/
|
||||
|
||||
core::map<std::string, bool> sourcelist;
|
||||
core::array<std::string> sourcelist;
|
||||
|
||||
for(u16 j=0; j<MAX_CONTENT+1; j++)
|
||||
{
|
||||
if(j == CONTENT_IGNORE || j == CONTENT_AIR)
|
||||
continue;
|
||||
ContentFeatures *f = &content_features(j);
|
||||
for(core::map<std::string, bool>::Iterator
|
||||
i = f->used_texturenames.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
sourcelist[name] = true;
|
||||
|
||||
if(f->often_contains_mineral){
|
||||
for(int k=1; k<MINERAL_COUNT; k++){
|
||||
std::string mineraltexture = mineral_block_texture(k);
|
||||
std::string fulltexture = name + "^" + mineraltexture;
|
||||
sourcelist[fulltexture] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sourcelist.push_back("stone.png");
|
||||
sourcelist.push_back("mud.png");
|
||||
sourcelist.push_back("sand.png");
|
||||
sourcelist.push_back("grass.png");
|
||||
sourcelist.push_back("grass_footsteps.png");
|
||||
sourcelist.push_back("tree.png");
|
||||
sourcelist.push_back("tree_top.png");
|
||||
sourcelist.push_back("water.png");
|
||||
sourcelist.push_back("leaves.png");
|
||||
sourcelist.push_back("glass.png");
|
||||
sourcelist.push_back("mud.png^grass_side.png");
|
||||
sourcelist.push_back("cobble.png");
|
||||
sourcelist.push_back("mossycobble.png");
|
||||
sourcelist.push_back("gravel.png");
|
||||
sourcelist.push_back("jungletree.png");
|
||||
|
||||
sourcelist.push_back("stone.png^mineral_coal.png");
|
||||
sourcelist.push_back("stone.png^mineral_iron.png");
|
||||
|
||||
infostream<<"Creating texture atlas out of textures: ";
|
||||
for(core::map<std::string, bool>::Iterator
|
||||
i = sourcelist.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
infostream<<"\""<<name<<"\" ";
|
||||
}
|
||||
infostream<<std::endl;
|
||||
|
||||
// Padding to disallow texture bleeding
|
||||
s32 padding = 16;
|
||||
|
||||
s32 column_width = 256;
|
||||
s32 column_padding = 16;
|
||||
|
||||
/*
|
||||
First pass: generate almost everything
|
||||
*/
|
||||
core::position2d<s32> pos_in_atlas(0,0);
|
||||
|
||||
pos_in_atlas.Y = padding;
|
||||
pos_in_atlas.Y += padding;
|
||||
|
||||
for(core::map<std::string, bool>::Iterator
|
||||
i = sourcelist.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(u32 i=0; i<sourcelist.size(); i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string name = sourcelist[i];
|
||||
|
||||
/*video::IImage *img = driver->createImageFromFile(
|
||||
getTexturePath(name.c_str()).c_str());
|
||||
@@ -582,7 +567,7 @@ void TextureSource::buildMainAtlas()
|
||||
video::IImage *img2 = generate_image_from_scratch(name, m_device);
|
||||
if(img2 == NULL)
|
||||
{
|
||||
infostream<<"TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
|
||||
dstream<<"WARNING: TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -593,31 +578,25 @@ void TextureSource::buildMainAtlas()
|
||||
if(dim.Width > max_size_in_atlas.Width
|
||||
|| dim.Height > max_size_in_atlas.Height)
|
||||
{
|
||||
infostream<<"TextureSource::buildMainAtlas(): Not adding "
|
||||
dstream<<"INFO: TextureSource::buildMainAtlas(): Not adding "
|
||||
<<"\""<<name<<"\" because image is large"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wrap columns and stop making atlas if atlas is full
|
||||
// Stop making atlas if atlas is full
|
||||
if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
|
||||
{
|
||||
if(pos_in_atlas.X > (s32)atlas_dim.Width - 256 - padding){
|
||||
errorstream<<"TextureSource::buildMainAtlas(): "
|
||||
<<"Atlas is full, not adding more textures."
|
||||
<<std::endl;
|
||||
break;
|
||||
}
|
||||
pos_in_atlas.Y = padding;
|
||||
pos_in_atlas.X += column_width + column_padding;
|
||||
dstream<<"WARNING: TextureSource::buildMainAtlas(): "
|
||||
<<"Atlas is full, not adding more textures."
|
||||
<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
|
||||
dstream<<"INFO: TextureSource::buildMainAtlas(): Adding \""<<name
|
||||
<<"\" to texture atlas"<<std::endl;
|
||||
|
||||
// Tile it a few times in the X direction
|
||||
u16 xwise_tiling = column_width / dim.Width;
|
||||
if(xwise_tiling > 16) // Limit to 16 (more gives no benefit)
|
||||
xwise_tiling = 16;
|
||||
u16 xwise_tiling = 16;
|
||||
for(u32 j=0; j<xwise_tiling; j++)
|
||||
{
|
||||
// Copy the copy to the atlas
|
||||
@@ -645,7 +624,7 @@ void TextureSource::buildMainAtlas()
|
||||
dst_y = -y0 + pos_in_atlas.Y-1;
|
||||
src_y = pos_in_atlas.Y;
|
||||
}
|
||||
s32 x = x0 + pos_in_atlas.X;
|
||||
s32 x = x0 + pos_in_atlas.X * dim.Width;
|
||||
video::SColor c = atlas_img->getPixel(x, src_y);
|
||||
atlas_img->setPixel(x,dst_y,c);
|
||||
}
|
||||
@@ -686,33 +665,27 @@ void TextureSource::buildMainAtlas()
|
||||
/*
|
||||
Second pass: set texture pointer in generated AtlasPointers
|
||||
*/
|
||||
for(core::map<std::string, bool>::Iterator
|
||||
i = sourcelist.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(u32 i=0; i<sourcelist.size(); i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string name = sourcelist[i];
|
||||
if(m_name_to_id.find(name) == NULL)
|
||||
continue;
|
||||
u32 id = m_name_to_id[name];
|
||||
//infostream<<"id of name "<<name<<" is "<<id<<std::endl;
|
||||
//dstream<<"id of name "<<name<<" is "<<id<<std::endl;
|
||||
m_atlaspointer_cache[id].a.atlas = t;
|
||||
}
|
||||
|
||||
/*
|
||||
Write image to file so that it can be inspected
|
||||
*/
|
||||
/*std::string atlaspath = porting::path_userdata
|
||||
+ DIR_DELIM + "generated_texture_atlas.png";
|
||||
infostream<<"Removing and writing texture atlas for inspection to "
|
||||
<<atlaspath<<std::endl;
|
||||
fs::RecursiveDelete(atlaspath);
|
||||
driver->writeImageToFile(atlas_img, atlaspath.c_str());*/
|
||||
/*driver->writeImageToFile(atlas_img,
|
||||
getTexturePath("main_atlas.png").c_str());*/
|
||||
}
|
||||
|
||||
video::IImage* generate_image_from_scratch(std::string name,
|
||||
IrrlichtDevice *device)
|
||||
{
|
||||
/*infostream<<"generate_image_from_scratch(): "
|
||||
/*dstream<<"INFO: generate_image_from_scratch(): "
|
||||
"\""<<name<<"\""<<std::endl;*/
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
@@ -737,7 +710,7 @@ video::IImage* generate_image_from_scratch(std::string name,
|
||||
}
|
||||
}
|
||||
|
||||
/*infostream<<"generate_image_from_scratch(): "
|
||||
/*dstream<<"INFO: generate_image_from_scratch(): "
|
||||
<<"last_separator_position="<<last_separator_position
|
||||
<<std::endl;*/
|
||||
|
||||
@@ -750,7 +723,7 @@ video::IImage* generate_image_from_scratch(std::string name,
|
||||
{
|
||||
// Construct base name
|
||||
base_image_name = name.substr(0, last_separator_position);
|
||||
/*infostream<<"generate_image_from_scratch(): Calling itself recursively"
|
||||
/*dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
|
||||
" to get base image of \""<<name<<"\" = \""
|
||||
<<base_image_name<<"\""<<std::endl;*/
|
||||
baseimg = generate_image_from_scratch(base_image_name, device);
|
||||
@@ -762,12 +735,12 @@ video::IImage* generate_image_from_scratch(std::string name,
|
||||
*/
|
||||
|
||||
std::string last_part_of_name = name.substr(last_separator_position+1);
|
||||
//infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
//dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
|
||||
// Generate image according to part of name
|
||||
if(generate_image(last_part_of_name, baseimg, device) == false)
|
||||
{
|
||||
infostream<<"generate_image_from_scratch(): "
|
||||
dstream<<"INFO: generate_image_from_scratch(): "
|
||||
"failed to generate \""<<last_part_of_name<<"\""
|
||||
<<std::endl;
|
||||
return NULL;
|
||||
@@ -787,20 +760,20 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
{
|
||||
// A normal texture; load it from a file
|
||||
std::string path = getTexturePath(part_of_name.c_str());
|
||||
/*infostream<<"generate_image(): Loading path \""<<path
|
||||
/*dstream<<"INFO: generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;*/
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): Could not load image \""
|
||||
dstream<<"WARNING: generate_image(): Could not load image \""
|
||||
<<part_of_name<<"\" from path \""<<path<<"\""
|
||||
<<" while building texture"<<std::endl;
|
||||
|
||||
//return false;
|
||||
|
||||
infostream<<"generate_image(): Creating a dummy"
|
||||
dstream<<"WARNING: generate_image(): Creating a dummy"
|
||||
<<" image for \""<<part_of_name<<"\""<<std::endl;
|
||||
|
||||
// Just create a dummy image
|
||||
@@ -825,7 +798,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
// If base image is NULL, load as base.
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
//infostream<<"Setting "<<part_of_name<<" as base"<<std::endl;
|
||||
//dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
|
||||
/*
|
||||
Copy it this way to get an alpha channel.
|
||||
Otherwise images with alpha cannot be blitted on
|
||||
@@ -839,7 +812,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
// Else blit on base.
|
||||
else
|
||||
{
|
||||
//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||
//dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||
// Size of the copied area
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
//core::dimension2d<u32> dim(16,16);
|
||||
@@ -860,7 +833,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
{
|
||||
// A special texture modification
|
||||
|
||||
infostream<<"generate_image(): generating special "
|
||||
dstream<<"INFO: generate_image(): generating special "
|
||||
<<"modification \""<<part_of_name<<"\""
|
||||
<<std::endl;
|
||||
|
||||
@@ -883,7 +856,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
{
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg==NULL "
|
||||
dstream<<"WARNING: generate_image(): baseimg==NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
@@ -977,7 +950,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
sf.next(":");
|
||||
u32 w0 = stoi(sf.next("x"));
|
||||
u32 h0 = stoi(sf.next(":"));
|
||||
infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
|
||||
dstream<<"INFO: combined w="<<w0<<" h="<<h0<<std::endl;
|
||||
core::dimension2d<u32> dim(w0,h0);
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
while(sf.atend() == false)
|
||||
@@ -985,7 +958,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
u32 x = stoi(sf.next(","));
|
||||
u32 y = stoi(sf.next("="));
|
||||
std::string filename = sf.next(":");
|
||||
infostream<<"Adding \""<<filename
|
||||
dstream<<"INFO: Adding \""<<filename
|
||||
<<"\" to combined ("<<x<<","<<y<<")"
|
||||
<<std::endl;
|
||||
video::IImage *img = driver->createImageFromFile(
|
||||
@@ -993,7 +966,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
if(img)
|
||||
{
|
||||
core::dimension2d<u32> dim = img->getDimension();
|
||||
infostream<<"Size "<<dim.Width
|
||||
dstream<<"INFO: Size "<<dim.Width
|
||||
<<"x"<<dim.Height<<std::endl;
|
||||
core::position2d<s32> pos_base(x, y);
|
||||
video::IImage *img2 =
|
||||
@@ -1008,7 +981,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"img==NULL"<<std::endl;
|
||||
dstream<<"WARNING: img==NULL"<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1020,7 +993,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
{
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg==NULL "
|
||||
dstream<<"WARNING: generate_image(): baseimg==NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
@@ -1040,7 +1013,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
dstream<<"WARNING: generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
@@ -1050,14 +1023,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
|
||||
std::string path = getTexturePath(filename.c_str());
|
||||
|
||||
infostream<<"generate_image(): Loading path \""<<path
|
||||
dstream<<"INFO: generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): Loading path \""
|
||||
dstream<<"WARNING: generate_image(): Loading path \""
|
||||
<<path<<"\" failed"<<std::endl;
|
||||
}
|
||||
else
|
||||
@@ -1079,122 +1052,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
image->drop();
|
||||
}
|
||||
}
|
||||
/*
|
||||
"[makealpha:R,G,B:filename.png"
|
||||
Use an image with converting one color to transparent.
|
||||
*/
|
||||
else if(part_of_name.substr(0,11) == "[makealpha:")
|
||||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Strfnd sf(part_of_name.substr(11));
|
||||
u32 r1 = stoi(sf.next(","));
|
||||
u32 g1 = stoi(sf.next(","));
|
||||
u32 b1 = stoi(sf.next(":"));
|
||||
std::string filename = sf.next("");
|
||||
|
||||
std::string path = getTexturePath(filename.c_str());
|
||||
|
||||
infostream<<"generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): Loading path \""
|
||||
<<path<<"\" failed"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
|
||||
// Blit
|
||||
image->copyTo(baseimg);
|
||||
|
||||
image->drop();
|
||||
|
||||
for(u32 y=0; y<dim.Height; y++)
|
||||
for(u32 x=0; x<dim.Width; x++)
|
||||
{
|
||||
video::SColor c = baseimg->getPixel(x,y);
|
||||
u32 r = c.getRed();
|
||||
u32 g = c.getGreen();
|
||||
u32 b = c.getBlue();
|
||||
if(!(r == r1 && g == g1 && b == b1))
|
||||
continue;
|
||||
c.setAlpha(0);
|
||||
baseimg->setPixel(x,y,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
"[makealpha2:R,G,B;R2,G2,B2:filename.png"
|
||||
Use an image with converting two colors to transparent.
|
||||
*/
|
||||
else if(part_of_name.substr(0,12) == "[makealpha2:")
|
||||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Strfnd sf(part_of_name.substr(12));
|
||||
u32 r1 = stoi(sf.next(","));
|
||||
u32 g1 = stoi(sf.next(","));
|
||||
u32 b1 = stoi(sf.next(";"));
|
||||
u32 r2 = stoi(sf.next(","));
|
||||
u32 g2 = stoi(sf.next(","));
|
||||
u32 b2 = stoi(sf.next(":"));
|
||||
std::string filename = sf.next("");
|
||||
|
||||
std::string path = getTexturePath(filename.c_str());
|
||||
|
||||
infostream<<"generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): Loading path \""
|
||||
<<path<<"\" failed"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
|
||||
// Blit
|
||||
image->copyTo(baseimg);
|
||||
|
||||
image->drop();
|
||||
|
||||
for(u32 y=0; y<dim.Height; y++)
|
||||
for(u32 x=0; x<dim.Width; x++)
|
||||
{
|
||||
video::SColor c = baseimg->getPixel(x,y);
|
||||
u32 r = c.getRed();
|
||||
u32 g = c.getGreen();
|
||||
u32 b = c.getBlue();
|
||||
if(!(r == r1 && g == g1 && b == b1) &&
|
||||
!(r == r2 && g == g2 && b == b2))
|
||||
continue;
|
||||
c.setAlpha(0);
|
||||
baseimg->setPixel(x,y,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
[inventorycube{topimage{leftimage{rightimage
|
||||
In every subimage, replace ^ with &.
|
||||
@@ -1207,7 +1064,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
dstream<<"WARNING: generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
@@ -1225,7 +1082,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
|
||||
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
|
||||
{
|
||||
infostream<<"generate_image(): EVDF_RENDER_TO_TARGET"
|
||||
dstream<<"WARNING: generate_image(): EVDF_RENDER_TO_TARGET"
|
||||
" not supported. Creating fallback image"<<std::endl;
|
||||
baseimg = generate_image_from_scratch(
|
||||
imagename_top, device);
|
||||
@@ -1234,7 +1091,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
|
||||
u32 w0 = 64;
|
||||
u32 h0 = 64;
|
||||
//infostream<<"inventorycube w="<<w0<<" h="<<h0<<std::endl;
|
||||
//dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl;
|
||||
core::dimension2d<u32> dim(w0,h0);
|
||||
|
||||
// Generate images for the faces of the cube
|
||||
@@ -1336,7 +1193,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"generate_image(): Invalid "
|
||||
dstream<<"WARNING: generate_image(): Invalid "
|
||||
" modification: \""<<part_of_name<<"\""<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,9 +283,9 @@ struct TileSpec
|
||||
TileSpec():
|
||||
texture(0),
|
||||
alpha(255),
|
||||
//material_type(MATERIAL_ALPHA_NONE),
|
||||
material_type(MATERIAL_ALPHA_NONE),
|
||||
// Use this so that leaves don't need a separate material
|
||||
material_type(MATERIAL_ALPHA_SIMPLE),
|
||||
//material_type(MATERIAL_ALPHA_SIMPLE),
|
||||
material_flags(
|
||||
//0 // <- DEBUG, Use the one below
|
||||
MATERIAL_FLAG_BACKFACE_CULLING
|
||||
@@ -304,7 +304,7 @@ struct TileSpec
|
||||
}
|
||||
|
||||
// Sets everything else except the texture in the material
|
||||
void applyMaterialOptions(video::SMaterial &material) const
|
||||
void applyMaterialOptions(video::SMaterial &material)
|
||||
{
|
||||
if(alpha != 255 && material_type != MATERIAL_ALPHA_VERTEX)
|
||||
dstream<<"WARNING: TileSpec: alpha != 255 "
|
||||
|
||||
@@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gettime.h"
|
||||
#include "sha1.h"
|
||||
#include "base64.h"
|
||||
#include "log.h"
|
||||
|
||||
TimeTaker::TimeTaker(const char *name, u32 *result)
|
||||
{
|
||||
@@ -48,7 +47,7 @@ u32 TimeTaker::stop(bool quiet)
|
||||
else
|
||||
{
|
||||
if(quiet == false)
|
||||
infostream<<m_name<<" took "<<dtime<<"ms"<<std::endl;
|
||||
std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
|
||||
}
|
||||
m_running = false;
|
||||
return dtime;
|
||||
@@ -157,50 +156,14 @@ void mysrand(unsigned seed)
|
||||
next = seed;
|
||||
}
|
||||
|
||||
int myrand_range(int min, int max)
|
||||
{
|
||||
if(max-min > MYRAND_MAX)
|
||||
{
|
||||
errorstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
|
||||
assert(0);
|
||||
}
|
||||
if(min > max)
|
||||
{
|
||||
assert(0);
|
||||
return max;
|
||||
}
|
||||
return (myrand()%(max-min+1))+min;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
// Sets the color of all vertices in the mesh
|
||||
void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color)
|
||||
{
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
blockpos: position of block in block coordinates
|
||||
camera_pos: position of camera in nodes
|
||||
camera_dir: an unit vector pointing to camera direction
|
||||
range: viewing range
|
||||
*/
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
f32 camera_fov, f32 range, f32 *distance_ptr)
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
|
||||
f32 *distance_ptr)
|
||||
{
|
||||
v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
|
||||
|
||||
@@ -236,21 +199,22 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
|
||||
// If block is (nearly) touching the camera, don't
|
||||
// bother validating further (that is, render it anyway)
|
||||
if(d < block_max_radius)
|
||||
return true;
|
||||
|
||||
// Cosine of the angle between the camera direction
|
||||
// and the block direction (camera_dir is an unit vector)
|
||||
f32 cosangle = dforward / d;
|
||||
|
||||
// Compensate for the size of the block
|
||||
// (as the block has to be shown even if it's a bit off FOV)
|
||||
// This is an estimate, plus an arbitary factor
|
||||
cosangle += block_max_radius / d * 0.5;
|
||||
if(d > block_max_radius * 1.5)
|
||||
{
|
||||
// Cosine of the angle between the camera direction
|
||||
// and the block direction (camera_dir is an unit vector)
|
||||
f32 cosangle = dforward / d;
|
||||
|
||||
// Compensate for the size of the block
|
||||
// (as the block has to be shown even if it's a bit off FOV)
|
||||
// This is an estimate.
|
||||
cosangle += block_max_radius / dforward;
|
||||
|
||||
// If block is not in the field of view, skip it
|
||||
if(cosangle < cos(camera_fov / 2))
|
||||
return false;
|
||||
// If block is not in the field of view, skip it
|
||||
//if(cosangle < cos(FOV_ANGLE/2))
|
||||
if(cosangle < cos(FOV_ANGLE/2. * 4./3.))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
663
src/utility.h
@@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
@@ -222,13 +221,13 @@ inline u16 readU16(std::istream &is)
|
||||
return readU16((u8*)buf);
|
||||
}
|
||||
|
||||
inline void writeU32(std::ostream &os, u32 p)
|
||||
inline void writeU32(std::ostream &os, u16 p)
|
||||
{
|
||||
char buf[4];
|
||||
writeU16((u8*)buf, p);
|
||||
os.write(buf, 4);
|
||||
}
|
||||
inline u32 readU32(std::istream &is)
|
||||
inline u16 readU32(std::istream &is)
|
||||
{
|
||||
char buf[4];
|
||||
is.read(buf, 4);
|
||||
@@ -343,59 +342,26 @@ template <typename T>
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer()
|
||||
{
|
||||
m_size = 0;
|
||||
data = NULL;
|
||||
}
|
||||
Buffer(unsigned int size)
|
||||
{
|
||||
m_size = size;
|
||||
if(size != 0)
|
||||
data = new T[size];
|
||||
else
|
||||
data = NULL;
|
||||
data = new T[size];
|
||||
}
|
||||
Buffer(const Buffer &buffer)
|
||||
{
|
||||
m_size = buffer.m_size;
|
||||
if(m_size != 0)
|
||||
{
|
||||
data = new T[buffer.m_size];
|
||||
memcpy(data, buffer.data, buffer.m_size);
|
||||
}
|
||||
else
|
||||
data = NULL;
|
||||
data = new T[buffer.m_size];
|
||||
memcpy(data, buffer.data, buffer.m_size);
|
||||
}
|
||||
Buffer(T *t, unsigned int size)
|
||||
{
|
||||
m_size = size;
|
||||
if(size != 0)
|
||||
{
|
||||
data = new T[size];
|
||||
memcpy(data, t, size);
|
||||
}
|
||||
else
|
||||
data = NULL;
|
||||
data = new T[size];
|
||||
memcpy(data, t, size);
|
||||
}
|
||||
~Buffer()
|
||||
{
|
||||
drop();
|
||||
}
|
||||
Buffer& operator=(const Buffer &buffer)
|
||||
{
|
||||
if(this == &buffer)
|
||||
return *this;
|
||||
drop();
|
||||
m_size = buffer.m_size;
|
||||
if(m_size != 0)
|
||||
{
|
||||
data = new T[buffer.m_size];
|
||||
memcpy(data, buffer.data, buffer.m_size);
|
||||
}
|
||||
else
|
||||
data = NULL;
|
||||
return *this;
|
||||
delete[] data;
|
||||
}
|
||||
T & operator[](unsigned int i) const
|
||||
{
|
||||
@@ -410,11 +376,6 @@ class Buffer
|
||||
return m_size;
|
||||
}
|
||||
private:
|
||||
void drop()
|
||||
{
|
||||
if(data)
|
||||
delete[] data;
|
||||
}
|
||||
T *data;
|
||||
unsigned int m_size;
|
||||
};
|
||||
@@ -509,10 +470,6 @@ class SharedBuffer
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
operator Buffer<T>() const
|
||||
{
|
||||
return Buffer<T>(data, m_size);
|
||||
}
|
||||
private:
|
||||
void drop()
|
||||
{
|
||||
@@ -596,11 +553,6 @@ class TimeTaker
|
||||
u32 *m_result;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
// Sets the color of all vertices in the mesh
|
||||
void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
|
||||
#endif
|
||||
|
||||
// Calculates the borders of a "d-radius" cube
|
||||
inline void getFacePositions(core::list<v3s16> &list, u16 d)
|
||||
{
|
||||
@@ -852,35 +804,6 @@ inline float wrapDegrees(float f)
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Wrap to 0...360 */
|
||||
inline float wrapDegrees_0_360(float f)
|
||||
{
|
||||
// Take examples of f=10, f=720.5, f=-0.5, f=-360.5
|
||||
// This results in
|
||||
// 10, 720, -1, -361
|
||||
int i = floor(f);
|
||||
// 0, 2, 0, -1
|
||||
int l = i / 360;
|
||||
// Wrap to 0...360
|
||||
// 0, 2, -1, -2
|
||||
if(i < 0)
|
||||
l -= 1;
|
||||
// 0, 720, 0, -360
|
||||
int k = l * 360;
|
||||
// 10, 0.5, -0.5, -0.5
|
||||
f -= float(k);
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Wrap to -180...180 */
|
||||
inline float wrapDegrees_180(float f)
|
||||
{
|
||||
f += 180;
|
||||
f = wrapDegrees_0_360(f);
|
||||
f -= 180;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline std::string lowercase(const std::string &s)
|
||||
{
|
||||
std::string s2;
|
||||
@@ -1012,6 +935,557 @@ class SimpleThread : public JThread
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Config stuff
|
||||
*/
|
||||
|
||||
enum ValueType
|
||||
{
|
||||
VALUETYPE_STRING,
|
||||
VALUETYPE_FLAG // Doesn't take any arguments
|
||||
};
|
||||
|
||||
struct ValueSpec
|
||||
{
|
||||
ValueSpec(ValueType a_type, const char *a_help=NULL)
|
||||
{
|
||||
type = a_type;
|
||||
help = a_help;
|
||||
}
|
||||
ValueType type;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings()
|
||||
{
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
void writeLines(std::ostream &os)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseConfigLine(const std::string &line)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
return true;
|
||||
|
||||
//dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
return true;
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
/*dstream<<"Config name=\""<<name<<"\" value=\""
|
||||
<<value<<"\""<<std::endl;*/
|
||||
|
||||
m_settings[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns false on EOF
|
||||
bool parseConfigObject(std::istream &is)
|
||||
{
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
/*
|
||||
NOTE: This function might be expanded to allow multi-line
|
||||
settings.
|
||||
*/
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
//dstream<<"got line: \""<<line<<"\""<<std::endl;
|
||||
|
||||
return parseConfigLine(line);
|
||||
}
|
||||
|
||||
/*
|
||||
Read configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool readConfigFile(const char *filename)
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"Error opening configuration file \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
dstream<<"Parsing configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
while(parseConfigObject(is));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Reads a configuration object from stream (usually a single line)
|
||||
and adds it to dst.
|
||||
|
||||
Preserves comments and empty lines.
|
||||
|
||||
Settings that were added to dst are also added to updated.
|
||||
key of updated is setting name, value of updated is dummy.
|
||||
|
||||
Returns false on EOF
|
||||
*/
|
||||
bool getUpdatedConfigObject(std::istream &is,
|
||||
core::list<std::string> &dst,
|
||||
core::map<std::string, bool> &updated)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
// NOTE: This function will be expanded to allow multi-line settings
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
std::string line_end = "";
|
||||
if(is.eof() == false)
|
||||
line_end = "\n";
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
if(m_settings.find(name))
|
||||
{
|
||||
std::string newvalue = m_settings[name];
|
||||
|
||||
if(newvalue != value)
|
||||
{
|
||||
dstream<<"Changing value of \""<<name<<"\" = \""
|
||||
<<value<<"\" -> \""<<newvalue<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
dst.push_back(name + " = " + newvalue + line_end);
|
||||
|
||||
updated[name] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Updates configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool updateConfigFile(const char *filename)
|
||||
{
|
||||
dstream<<"Updating configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
core::list<std::string> objects;
|
||||
core::map<std::string, bool> updated;
|
||||
|
||||
// Read and modify stuff
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"INFO: updateConfigFile():"
|
||||
" Error opening configuration file"
|
||||
" for reading: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(getUpdatedConfigObject(is, objects, updated));
|
||||
}
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Write stuff back
|
||||
{
|
||||
std::ofstream os(filename);
|
||||
if(os.good() == false)
|
||||
{
|
||||
dstream<<"Error opening configuration file"
|
||||
" for writing: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Write updated stuff
|
||||
*/
|
||||
for(core::list<std::string>::Iterator
|
||||
i = objects.begin();
|
||||
i != objects.end(); i++)
|
||||
{
|
||||
os<<(*i);
|
||||
}
|
||||
|
||||
/*
|
||||
Write stuff that was not already in the file
|
||||
*/
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
if(updated.find(i.getNode()->getKey()))
|
||||
continue;
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: Types of allowed_options are ignored
|
||||
|
||||
returns true on success
|
||||
*/
|
||||
bool parseCommandLine(int argc, char *argv[],
|
||||
core::map<std::string, ValueSpec> &allowed_options)
|
||||
{
|
||||
int i=1;
|
||||
for(;;)
|
||||
{
|
||||
if(i >= argc)
|
||||
break;
|
||||
std::string argname = argv[i];
|
||||
if(argname.substr(0, 2) != "--")
|
||||
{
|
||||
dstream<<"Invalid command-line parameter \""
|
||||
<<argname<<"\": --<option> expected."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
|
||||
std::string name = argname.substr(2);
|
||||
|
||||
core::map<std::string, ValueSpec>::Node *n;
|
||||
n = allowed_options.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
dstream<<"Unknown command-line parameter \""
|
||||
<<argname<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueType type = n->getValue().type;
|
||||
|
||||
std::string value = "";
|
||||
|
||||
if(type == VALUETYPE_FLAG)
|
||||
{
|
||||
value = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i >= argc)
|
||||
{
|
||||
dstream<<"Invalid command-line parameter \""
|
||||
<<name<<"\": missing value"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
value = argv[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
dstream<<"Valid command-line parameter: \""
|
||||
<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
set(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
void set(std::string name, const char *value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
void setDefault(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_defaults[name] = value;
|
||||
}
|
||||
|
||||
bool exists(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
return (m_settings.find(name) || m_defaults.find(name));
|
||||
}
|
||||
|
||||
std::string get(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, std::string>::Node *n;
|
||||
n = m_settings.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
n = m_defaults.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
dstream<<"INFO: Settings: Setting not found: \""
|
||||
<<name<<"\""<<std::endl;
|
||||
throw SettingNotFoundException("Setting not found");
|
||||
}
|
||||
}
|
||||
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
bool getBool(std::string name)
|
||||
{
|
||||
return is_yes(get(name));
|
||||
}
|
||||
|
||||
bool getFlag(std::string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getBool(name);
|
||||
}
|
||||
catch(SettingNotFoundException &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Asks if empty
|
||||
bool getBoolAsk(std::string name, std::string question, bool def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getBool(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" [y/N]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return is_yes(s);
|
||||
}
|
||||
|
||||
float getFloat(std::string name)
|
||||
{
|
||||
return stof(get(name));
|
||||
}
|
||||
|
||||
u16 getU16(std::string name)
|
||||
{
|
||||
return stoi(get(name), 0, 65535);
|
||||
}
|
||||
|
||||
u16 getU16Ask(std::string name, std::string question, u16 def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getU16(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" ["<<def<<"]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return stoi(s, 0, 65535);
|
||||
}
|
||||
|
||||
s16 getS16(std::string name)
|
||||
{
|
||||
return stoi(get(name), -32768, 32767);
|
||||
}
|
||||
|
||||
s32 getS32(std::string name)
|
||||
{
|
||||
return stoi(get(name));
|
||||
}
|
||||
|
||||
v3f getV3F(std::string name)
|
||||
{
|
||||
v3f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(","));
|
||||
value.Z = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
u64 getU64(std::string name)
|
||||
{
|
||||
u64 value = 0;
|
||||
std::string s = get(name);
|
||||
std::istringstream ss(s);
|
||||
ss>>value;
|
||||
return value;
|
||||
}
|
||||
|
||||
void setBool(std::string name, bool value)
|
||||
{
|
||||
if(value)
|
||||
set(name, "true");
|
||||
else
|
||||
set(name, "false");
|
||||
}
|
||||
|
||||
void setS32(std::string name, s32 value)
|
||||
{
|
||||
set(name, itos(value));
|
||||
}
|
||||
|
||||
void setFloat(std::string name, float value)
|
||||
{
|
||||
set(name, ftos(value));
|
||||
}
|
||||
|
||||
void setV3F(std::string name, v3f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setU64(std::string name, u64 value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<value;
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings.clear();
|
||||
m_defaults.clear();
|
||||
}
|
||||
|
||||
Settings & operator+=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_settings.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_defaults.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_defaults.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
Settings & operator=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
(*this) += other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
core::map<std::string, std::string> m_settings;
|
||||
core::map<std::string, std::string> m_defaults;
|
||||
// All methods that access m_settings/m_defaults directly should lock this.
|
||||
JMutex m_mutex;
|
||||
};
|
||||
|
||||
/*
|
||||
FIFO queue (well, actually a FILO also)
|
||||
*/
|
||||
@@ -1272,14 +1746,27 @@ int myrand(void);
|
||||
void mysrand(unsigned seed);
|
||||
#define MYRAND_MAX 32767
|
||||
|
||||
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)
|
||||
{
|
||||
assert(0);
|
||||
return max;
|
||||
}
|
||||
return (myrand()%(max-min+1))+min;
|
||||
}
|
||||
|
||||
/*
|
||||
Miscellaneous functions
|
||||
*/
|
||||
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
|
||||
f32 *distance_ptr=NULL);
|
||||
|
||||
/*
|
||||
Queue with unique values with fast checking of value existence
|
||||
|
||||