mirror of
https://github.com/minetest/minetest.git
synced 2024-12-27 16:37:30 +01:00
Merge remote branch 'origin/master'
This commit is contained in:
commit
a0566270d9
9
.gitignore
vendored
9
.gitignore
vendored
@ -4,13 +4,16 @@
|
||||
*bak*
|
||||
tags
|
||||
*.vim
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
## Non-static Minetest directories
|
||||
/bin/
|
||||
/games/*
|
||||
!/games/minimal/
|
||||
/cache/
|
||||
/textures/
|
||||
/textures/*
|
||||
!/textures/base/
|
||||
/sounds/
|
||||
/mods/*
|
||||
!/mods/minetest/
|
||||
@ -41,7 +44,9 @@ src/cguittfont/libcguittfont.a
|
||||
src/cguittfont/cmake_install.cmake
|
||||
src/cguittfont/Makefile
|
||||
src/json/CMakeFiles/
|
||||
src/json/libjson.a
|
||||
src/json/libjsoncpp.a
|
||||
src/sqlite/CMakeFiles/*
|
||||
src/sqlite/libsqlite3.a
|
||||
CMakeCache.txt
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
|
@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 4)
|
||||
set(VERSION_PATCH 4-d1)
|
||||
set(VERSION_PATCH 5)
|
||||
if(VERSION_EXTRA)
|
||||
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
|
||||
endif()
|
||||
@ -133,6 +133,11 @@ endif()
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client" DESTINATION "${SHAREDIR}")
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games")
|
||||
set(COMMON_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/common")
|
||||
if(EXISTS ${COMMON_SOURCE} AND IS_DIRECTORY ${COMMON_SOURCE})
|
||||
install(FILES ${COMMON_SOURCE}/README.txt DESTINATION "${SHAREDIR}/games/common/")
|
||||
install(DIRECTORY ${COMMON_SOURCE}/mods DESTINATION "${SHAREDIR}/games/common")
|
||||
endif()
|
||||
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
|
||||
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
|
||||
install(FILES ${MINETEST_GAME_SOURCE}/game.conf DESTINATION "${SHAREDIR}/games/minetest_game/")
|
||||
|
21
README.txt
21
README.txt
@ -9,9 +9,10 @@ and contributors (see source file comments and the version control log)
|
||||
In case you downloaded the source code:
|
||||
---------------------------------------
|
||||
If you downloaded the Minetest Engine source code in which this file is
|
||||
contained, you probably want to download the minetest_game project too:
|
||||
contained, you probably want to download these projects too:
|
||||
https://github.com/minetest/common/
|
||||
https://github.com/minetest/minetest_game/
|
||||
See the README.txt in it.
|
||||
See the README.txt in them.
|
||||
|
||||
Further documentation
|
||||
----------------------
|
||||
@ -80,17 +81,24 @@ 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 libogg-dev libvorbis-dev libopenal-dev
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-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/minetest/minetest/tarball/master -O master.tar.gz
|
||||
$ tar xf master.tar.gz
|
||||
$ cd minetest-minetest-286edd4 (or similar)
|
||||
|
||||
Download common (needed for minetest_game and some others)
|
||||
$ cd games/
|
||||
$ wget https://github.com/minetest/common/tarball/master -O common.tar.gz
|
||||
$ tar xf common.tar.gz
|
||||
$ mv minetest-common-* common
|
||||
$ cd ..
|
||||
|
||||
Download minetest_game (otherwise only the "Minimal development test" game is available)
|
||||
$ cd games/
|
||||
$ wget https://github.com/minetest/minetest_game/tarball/master -O master.tar.gz
|
||||
$ tar xf master.tar.gz
|
||||
$ wget https://github.com/minetest/minetest_game/tarball/master -O minetest_game.tar.gz
|
||||
$ tar xf minetest_game.tar.gz
|
||||
$ mv minetest-minetest_game-* minetest_game
|
||||
$ cd ..
|
||||
|
||||
@ -107,11 +115,12 @@ $ ./minetest
|
||||
- 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
|
||||
- If you build a bare server, you don't need to have Irrlicht installed. In that case use -DIRRLICHT_SOURCE_DIR=/the/irrlicht/source
|
||||
|
||||
Compiling on Windows:
|
||||
---------------------
|
||||
- This section is outdated. In addition to what is described here:
|
||||
- In addition to minetest, you need to download minetest_game.
|
||||
- In addition to minetest, you need to download common and minetest_game.
|
||||
- If you wish to have sound support, you need libogg, libvorbis and libopenal
|
||||
|
||||
- You need:
|
||||
|
@ -57,6 +57,10 @@ minetest.register_entity("__builtin:falling_node", {
|
||||
-- Note: walkable is in the node definition, not in item groups
|
||||
if minetest.registered_nodes[bcn.name] and
|
||||
minetest.registered_nodes[bcn.name].walkable then
|
||||
if minetest.registered_nodes[bcn.name].buildable_to then
|
||||
minetest.env:remove_node(bcp)
|
||||
return
|
||||
end
|
||||
local np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
|
||||
-- Check what's here
|
||||
local n2 = minetest.env:get_node(np)
|
||||
@ -80,6 +84,7 @@ minetest.register_entity("__builtin:falling_node", {
|
||||
-- Create node and remove entity
|
||||
minetest.env:add_node(np, {name=self.nodename})
|
||||
self.object:remove()
|
||||
nodeupdate(np)
|
||||
else
|
||||
-- Do nothing
|
||||
end
|
||||
@ -144,7 +149,8 @@ function nodeupdate_single(p)
|
||||
n_bottom = minetest.env:get_node(p_bottom)
|
||||
-- Note: walkable is in the node definition, not in item groups
|
||||
if minetest.registered_nodes[n_bottom.name] and
|
||||
not minetest.registered_nodes[n_bottom.name].walkable then
|
||||
(not minetest.registered_nodes[n_bottom.name].walkable or
|
||||
minetest.registered_nodes[n_bottom.name].buildable_to) then
|
||||
minetest.env:remove_node(p)
|
||||
spawn_falling_node(p, n.name)
|
||||
nodeupdate(p)
|
||||
|
@ -129,11 +129,18 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
end
|
||||
|
||||
local under = pointed_thing.under
|
||||
local oldnode_under = minetest.env:get_node(under)
|
||||
local oldnode_under = minetest.env:get_node_or_nil(under)
|
||||
local above = pointed_thing.above
|
||||
local oldnode_above = minetest.env:get_node_or_nil(above)
|
||||
|
||||
if not oldnode_under or not oldnode_above then
|
||||
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||
.. " node in unloaded position " .. minetest.pos_to_string(above))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local olddef_under = ItemStack({name=oldnode_under.name}):get_definition()
|
||||
olddef_under = olddef_under or minetest.nodedef_default
|
||||
local above = pointed_thing.above
|
||||
local oldnode_above = minetest.env:get_node(above)
|
||||
local olddef_above = ItemStack({name=oldnode_above.name}):get_definition()
|
||||
olddef_above = olddef_above or minetest.nodedef_default
|
||||
|
||||
|
@ -111,6 +111,7 @@ minetest.register_entity("__builtin:item", {
|
||||
if self.itemstring ~= '' then
|
||||
local left = hitter:get_inventory():add_item("main", self.itemstring)
|
||||
if not left:is_empty() then
|
||||
self.itemstring = left:to_string()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -14,14 +14,14 @@ minetest.register_globalstep(function(dtime)
|
||||
for index, timer in ipairs(minetest.timers) do
|
||||
timer.time = timer.time - dtime
|
||||
if timer.time <= 0 then
|
||||
timer.func(timer.param)
|
||||
timer.func(unpack(timer.args or {}))
|
||||
table.remove(minetest.timers,index)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function minetest.after(time, func, param)
|
||||
table.insert(minetest.timers_to_add, {time=time, func=func, param=param})
|
||||
function minetest.after(time, func, ...)
|
||||
table.insert(minetest.timers_to_add, {time=time, func=func, args={...}})
|
||||
end
|
||||
|
||||
function minetest.check_player_privs(name, privs)
|
||||
@ -99,3 +99,10 @@ function minetest.setting_get_pos(name)
|
||||
return minetest.string_to_pos(value)
|
||||
end
|
||||
|
||||
function minetest.formspec_escape(str)
|
||||
str = string.gsub(str, "\\", "\\\\")
|
||||
str = string.gsub(str, "%[", "\\[")
|
||||
str = string.gsub(str, "%]", "\\]")
|
||||
return str
|
||||
end
|
||||
|
||||
|
@ -8,9 +8,7 @@ varying vec3 vPosition;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 pos = gl_Vertex;
|
||||
pos.y -= 2.0;
|
||||
gl_Position = mWorldViewProj * pos;
|
||||
gl_Position = mWorldViewProj * gl_Vertex;
|
||||
|
||||
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||
|
||||
|
@ -2,17 +2,17 @@
|
||||
|
||||
#FIND_PATH(JSON_INCLUDE_DIR json.h)
|
||||
|
||||
#FIND_LIBRARY(JSON_LIBRARY NAMES json)
|
||||
#FIND_LIBRARY(JSON_LIBRARY NAMES jsoncpp)
|
||||
|
||||
#IF(JSON_LIBRARY AND JSON_INCLUDE_DIR)
|
||||
# SET( JSON_FOUND TRUE )
|
||||
#ENDIF(JSON_LIBRARY AND JSON_INCLUDE_DIR)
|
||||
|
||||
#IF(JSON_FOUND)
|
||||
# MESSAGE(STATUS "Found system json header file in ${JSON_INCLUDE_DIR}")
|
||||
# MESSAGE(STATUS "Found system json library ${JSON_LIBRARY}")
|
||||
# MESSAGE(STATUS "Found system jsoncpp header file in ${JSON_INCLUDE_DIR}")
|
||||
# MESSAGE(STATUS "Found system jsoncpp library ${JSON_LIBRARY}")
|
||||
#ELSE(JSON_FOUND)
|
||||
SET(JSON_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/json)
|
||||
SET(JSON_LIBRARY json)
|
||||
MESSAGE(STATUS "Using project json library")
|
||||
SET(JSON_LIBRARY jsoncpp)
|
||||
MESSAGE(STATUS "Using project jsoncpp library")
|
||||
#ENDIF(JSON_FOUND)
|
||||
|
130
cmake/Modules/FindOpenGLES2.cmake
Normal file
130
cmake/Modules/FindOpenGLES2.cmake
Normal file
@ -0,0 +1,130 @@
|
||||
#-------------------------------------------------------------------
|
||||
# This file is stolen from part of the CMake build system for OGRE (Object-oriented Graphics Rendering Engine) http://www.ogre3d.org/
|
||||
#
|
||||
# The contents of this file are placed in the public domain. Feel
|
||||
# free to make use of it in any way you like.
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# - Try to find OpenGLES and EGL
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENGLES2_FOUND - system has OpenGLES
|
||||
# OPENGLES2_INCLUDE_DIR - the GL include directory
|
||||
# OPENGLES2_LIBRARIES - Link these to use OpenGLES
|
||||
#
|
||||
# EGL_FOUND - system has EGL
|
||||
# EGL_INCLUDE_DIR - the EGL include directory
|
||||
# EGL_LIBRARIES - Link these to use EGL
|
||||
|
||||
# win32, apple, android NOT TESED
|
||||
# linux tested and works
|
||||
|
||||
IF (WIN32)
|
||||
IF (CYGWIN)
|
||||
|
||||
FIND_PATH(OPENGLES2_INCLUDE_DIR GLES2/gl2.h )
|
||||
|
||||
FIND_LIBRARY(OPENGLES2_gl_LIBRARY libGLESv2 )
|
||||
|
||||
ELSE (CYGWIN)
|
||||
|
||||
IF(BORLAND)
|
||||
SET (OPENGLES2_gl_LIBRARY import32 CACHE STRING "OpenGL ES 2.x library for win32")
|
||||
ELSE(BORLAND)
|
||||
# todo
|
||||
# SET (OPENGLES_gl_LIBRARY ${SOURCE_DIR}/Dependencies/lib/release/libGLESv2.lib CACHE STRING "OpenGL ES 2.x library for win32"
|
||||
ENDIF(BORLAND)
|
||||
|
||||
ENDIF (CYGWIN)
|
||||
|
||||
ELSE (WIN32)
|
||||
|
||||
IF (APPLE)
|
||||
|
||||
create_search_paths(/Developer/Platforms)
|
||||
findpkg_framework(OpenGLES2)
|
||||
set(OPENGLES2_gl_LIBRARY "-framework OpenGLES")
|
||||
|
||||
ELSE(APPLE)
|
||||
|
||||
FIND_PATH(OPENGLES2_INCLUDE_DIR GLES2/gl2.h
|
||||
/usr/openwin/share/include
|
||||
/opt/graphics/OpenGL/include /usr/X11R6/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(OPENGLES2_gl_LIBRARY
|
||||
NAMES GLESv2
|
||||
PATHS /opt/graphics/OpenGL/lib
|
||||
/usr/openwin/lib
|
||||
/usr/shlib /usr/X11R6/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
IF (NOT BUILD_ANDROID)
|
||||
FIND_PATH(EGL_INCLUDE_DIR EGL/egl.h
|
||||
/usr/openwin/share/include
|
||||
/opt/graphics/OpenGL/include /usr/X11R6/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(EGL_egl_LIBRARY
|
||||
NAMES EGL
|
||||
PATHS /opt/graphics/OpenGL/lib
|
||||
/usr/openwin/lib
|
||||
/usr/shlib /usr/X11R6/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
# On Unix OpenGL most certainly always requires X11.
|
||||
# Feel free to tighten up these conditions if you don't
|
||||
# think this is always true.
|
||||
# It's not true on OSX.
|
||||
|
||||
IF (OPENGLES2_gl_LIBRARY)
|
||||
IF(NOT X11_FOUND)
|
||||
INCLUDE(FindX11)
|
||||
ENDIF(NOT X11_FOUND)
|
||||
IF (X11_FOUND)
|
||||
IF (NOT APPLE)
|
||||
SET (OPENGLES2_LIBRARIES ${X11_LIBRARIES})
|
||||
ENDIF (NOT APPLE)
|
||||
ENDIF (X11_FOUND)
|
||||
ENDIF (OPENGLES2_gl_LIBRARY)
|
||||
ENDIF ()
|
||||
|
||||
ENDIF(APPLE)
|
||||
ENDIF (WIN32)
|
||||
|
||||
#SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||
|
||||
IF (BUILD_ANDROID)
|
||||
IF(OPENGLES2_gl_LIBRARY)
|
||||
SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||
SET( EGL_LIBRARIES)
|
||||
SET( OPENGLES2_FOUND "YES" )
|
||||
ENDIF(OPENGLES2_gl_LIBRARY)
|
||||
ELSE ()
|
||||
|
||||
SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||
|
||||
IF(OPENGLES2_gl_LIBRARY AND EGL_egl_LIBRARY)
|
||||
SET( OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY} ${OPENGLES2_LIBRARIES})
|
||||
SET( EGL_LIBRARIES ${EGL_egl_LIBRARY} ${EGL_LIBRARIES})
|
||||
SET( OPENGLES2_FOUND "YES" )
|
||||
ENDIF(OPENGLES2_gl_LIBRARY AND EGL_egl_LIBRARY)
|
||||
|
||||
ENDIF ()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
OPENGLES2_INCLUDE_DIR
|
||||
OPENGLES2_gl_LIBRARY
|
||||
EGL_INCLUDE_DIR
|
||||
EGL_egl_LIBRARY
|
||||
)
|
||||
|
||||
IF(OPENGLES2_FOUND)
|
||||
MESSAGE(STATUS "Found system opengles2 library ${OPENGLES2_LIBRARIES}")
|
||||
ELSE ()
|
||||
SET(OPENGLES2_LIBRARIES "")
|
||||
ENDIF ()
|
297
doc/lua_api.txt
297
doc/lua_api.txt
@ -1,4 +1,4 @@
|
||||
Minetest Lua Modding API Reference 0.4.4
|
||||
Minetest Lua Modding API Reference 0.4.5
|
||||
==========================================
|
||||
More information at http://c55.me/minetest/
|
||||
|
||||
@ -27,6 +27,39 @@ Startup
|
||||
Mods are loaded during server startup from the mod load paths by running
|
||||
the init.lua scripts in a shared environment.
|
||||
|
||||
Paths
|
||||
-----
|
||||
RUN_IN_PLACE=1: (Windows release, local build)
|
||||
$path_user: Linux: <build directory>
|
||||
Windows: <build directory>
|
||||
$path_share: Linux: <build directory>
|
||||
Windows: <build directory>
|
||||
|
||||
RUN_IN_PLACE=0: (Linux release)
|
||||
$path_share: Linux: /usr/share/minetest
|
||||
Windows: <install directory>/minetest-0.4.x
|
||||
$path_user: Linux: ~/.minetest
|
||||
Windows: C:/users/<user>/AppData/minetest (maybe)
|
||||
|
||||
Games
|
||||
-----
|
||||
Games are looked up from:
|
||||
$path_share/games/gameid/
|
||||
$path_user/games/gameid/
|
||||
where gameid is unique to each game.
|
||||
|
||||
The game directory contains the file game.conf, which contains these fields:
|
||||
name = <Human-readable full name of the game>
|
||||
common_mods = <Comma-separated list of common mods>
|
||||
eg.
|
||||
name = Minetest
|
||||
common_mods = bucket, default, doors, fire, stairs
|
||||
|
||||
Common mods are loaded from the pseudo-game "common".
|
||||
|
||||
The game directory can contain the file minetest.conf, which will be used
|
||||
to set default settings when running the particular game.
|
||||
|
||||
Mod load path
|
||||
-------------
|
||||
Generic:
|
||||
@ -170,18 +203,18 @@ from the available ones of the following files:
|
||||
Examples of sound parameter tables:
|
||||
-- Play locationless on all clients
|
||||
{
|
||||
gain = 1.0, -- default
|
||||
gain = 1.0, -- default
|
||||
}
|
||||
-- Play locationless to a player
|
||||
{
|
||||
to_player = name,
|
||||
gain = 1.0, -- default
|
||||
to_player = name,
|
||||
gain = 1.0, -- default
|
||||
}
|
||||
-- Play in a location
|
||||
{
|
||||
pos = {x=1,y=2,z=3},
|
||||
gain = 1.0, -- default
|
||||
max_hear_distance = 32, -- default
|
||||
pos = {x=1,y=2,z=3},
|
||||
gain = 1.0, -- default
|
||||
max_hear_distance = 32, -- default
|
||||
}
|
||||
-- Play connected to an object, looped
|
||||
{
|
||||
@ -233,11 +266,11 @@ local drawtype = get_nodedef_field(nodename, "drawtype")
|
||||
Example: minetest.get_item_group(name, group) has been implemented as:
|
||||
|
||||
function minetest.get_item_group(name, group)
|
||||
if not minetest.registered_items[name] or not
|
||||
minetest.registered_items[name].groups[group] then
|
||||
return 0
|
||||
end
|
||||
return minetest.registered_items[name].groups[group]
|
||||
if not minetest.registered_items[name] or not
|
||||
minetest.registered_items[name].groups[group] then
|
||||
return 0
|
||||
end
|
||||
return minetest.registered_items[name].groups[group]
|
||||
end
|
||||
|
||||
Nodes
|
||||
@ -277,6 +310,10 @@ param2 is reserved for the engine when any of these are used:
|
||||
paramtype2 == "facedir"
|
||||
^ The rotation of the node is stored in param2. Furnaces and chests are
|
||||
rotated this way. Can be made by using minetest.dir_to_facedir().
|
||||
Values range 0 - 23
|
||||
facedir modulo 4 = axisdir
|
||||
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
|
||||
facedir's two less significant bits are rotation around the axis
|
||||
|
||||
Nodes can also contain extra data. See "Node Metadata".
|
||||
|
||||
@ -335,6 +372,28 @@ A box is defined as:
|
||||
A box of a regular node would look like:
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
|
||||
Ore types
|
||||
---------------
|
||||
These tell in what manner the ore is generated.
|
||||
All default ores are of the uniformly-distributed scatter type.
|
||||
|
||||
- scatter
|
||||
Randomly chooses a location and generates a cluster of ore.
|
||||
If noise_params is specified, the ore will be placed if the 3d perlin noise at
|
||||
that point is greater than the noise_threshhold, giving the ability to create a non-equal
|
||||
distribution of ore.
|
||||
- sheet
|
||||
Creates a sheet of ore in a blob shape according to the 2d perlin noise described by noise_params.
|
||||
The relative height of the sheet can be controlled by the same perlin noise as well, by specifying
|
||||
a non-zero 'scale' parameter in noise_params. IMPORTANT: The noise is not transformed by offset or
|
||||
scale when comparing against the noise threshhold, but scale is used to determine relative height.
|
||||
The height of the blob is randomly scattered, with a maximum height of clust_size.
|
||||
clust_scarcity and clust_num_ores are ignored.
|
||||
This is essentially an improved version of the so-called "stratus" ore seen in some unofficial mods.
|
||||
- claylike - NOT YET IMPLEMENTED
|
||||
Places ore if there are no more than clust_scarcity number of specified nodes within a Von Neumann
|
||||
neighborhood of clust_size radius.
|
||||
|
||||
Representations of simple things
|
||||
--------------------------------
|
||||
Position/vector:
|
||||
@ -412,9 +471,11 @@ a node is destroyable and how long it takes to destroy by a tool.
|
||||
Groups of entities
|
||||
-------------------
|
||||
For entities, groups are, as of now, used only for calculating damage.
|
||||
The rating is the percentage of damage caused by tools with this damage group.
|
||||
See "Entity damage mechanism".
|
||||
|
||||
object.get_armor_groups() -> a group-rating table (eg. {fleshy=3})
|
||||
object.set_armor_groups({level=2, fleshy=2, cracky=2})
|
||||
object.get_armor_groups() -> a group-rating table (eg. {fleshy=100})
|
||||
object.set_armor_groups({fleshy=30, cracky=80})
|
||||
|
||||
Groups of tools
|
||||
----------------
|
||||
@ -435,7 +496,7 @@ An example: Make meat soup from any meat, any water and any bowl
|
||||
}
|
||||
An another example: Make red wool from white wool and red dye
|
||||
{
|
||||
type = 'shapeless',
|
||||
type = 'shapeless',
|
||||
output = 'wool:red',
|
||||
recipe = {'wool:white', 'group:dye,basecolor_red'},
|
||||
}
|
||||
@ -446,7 +507,7 @@ Special groups
|
||||
- level: Can be used to give an additional sense of progression in the game.
|
||||
- A larger level will cause eg. a weapon of a lower level make much less
|
||||
damage, and get weared out much faster, or not be able to get drops
|
||||
from destroyed nodes.
|
||||
from destroyed nodes.
|
||||
- 0 is something that is directly accessible at the start of gameplay
|
||||
- There is no upper limit
|
||||
- dig_immediate: (player can always pick up node without tool wear)
|
||||
@ -463,7 +524,6 @@ Special groups
|
||||
|
||||
Known damage and digging time defining groups
|
||||
----------------------------------------------
|
||||
Valid ratings for these are 0, 1, 2 and 3, unless otherwise stated.
|
||||
- crumbly: dirt, sand
|
||||
- cracky: tough but crackable stuff like stone.
|
||||
- snappy: something that can be cut using fine tools; eg. leaves, small
|
||||
@ -516,6 +576,7 @@ groups to enable interaction with tools.
|
||||
* Uses (until the tool breaks)
|
||||
* Maximum level (usually 0, 1, 2 or 3)
|
||||
* Digging times
|
||||
* Damage groups
|
||||
|
||||
**Full punch interval**:
|
||||
When used as a weapon, the tool will do full damage if this time is spent
|
||||
@ -547,17 +608,19 @@ maximum level.
|
||||
result in the tool to be able to dig nodes that have a rating of 2 or 3
|
||||
for this group, and unable to dig the rating 1, which is the toughest.
|
||||
Unless there is a matching group that enables digging otherwise.
|
||||
* For entities, damage equals the amount of nodes dug in the time spent
|
||||
between hits, with a maximum time of ''full_punch_interval''.
|
||||
|
||||
**Damage groups**
|
||||
List of damage for groups of entities. See "Entity damage mechanism".
|
||||
|
||||
Example definition of the capabilities of a tool
|
||||
-------------------------------------------------
|
||||
tool_capabilities = {
|
||||
full_punch_interval=1.5,
|
||||
max_drop_level=1,
|
||||
groupcaps={
|
||||
crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
|
||||
}
|
||||
full_punch_interval=1.5,
|
||||
max_drop_level=1,
|
||||
groupcaps={
|
||||
crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
|
||||
}
|
||||
damage_groups = {fleshy=2},
|
||||
}
|
||||
|
||||
This makes the tool be able to dig nodes that fullfill both of these:
|
||||
@ -588,10 +651,12 @@ Notes:
|
||||
Entity damage mechanism
|
||||
------------------------
|
||||
Damage calculation:
|
||||
- Take the time spent after the last hit
|
||||
- Limit time to full_punch_interval
|
||||
- Take the damage groups and imagine a bunch of nodes that have them
|
||||
- Damage in HP is the amount of nodes destroyed in this time.
|
||||
damage = 0
|
||||
foreach group in cap.damage_groups:
|
||||
damage += cap.damage_groups[group] * limit(actual_interval / cap.full_punch_interval, 0.0, 1.0)
|
||||
* (object.armor_groups[group] / 100.0)
|
||||
-- Where object.armor_groups[group] is 0 for inexisting values
|
||||
return damage
|
||||
|
||||
Client predicts damage based on damage groups. Because of this, it is able to
|
||||
give an immediate response when an entity is damaged or dies; the response is
|
||||
@ -717,7 +782,7 @@ field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
|
||||
^ default is the default value of the field
|
||||
^ default may contain variable references such as '${text}' which
|
||||
will fill the value from the metadata value 'text'
|
||||
^ Note: no extra text or more than a single variable is supported ATM.
|
||||
^ Note: no extra text or more than a single variable is supported ATM.
|
||||
|
||||
field[<name>;<label>;<default>]
|
||||
^ as above but without position/size units
|
||||
@ -778,6 +843,9 @@ string:trim()
|
||||
minetest.pos_to_string({x=X,y=Y,z=Z}) -> "(X,Y,Z)"
|
||||
^ Convert position to a printable string
|
||||
minetest.string_to_pos(string) -> position
|
||||
^ Same but in reverse
|
||||
minetest.formspec_escape(string) -> string
|
||||
^ escapes characters like [, ], and \ that can not be used in formspecs
|
||||
|
||||
minetest namespace reference
|
||||
-----------------------------
|
||||
@ -804,6 +872,7 @@ minetest.register_tool(name, item definition)
|
||||
minetest.register_craftitem(name, item definition)
|
||||
minetest.register_alias(name, convert_to)
|
||||
minetest.register_craft(recipe)
|
||||
minetest.register_ore(ore definition)
|
||||
|
||||
Global callback registration functions: (Call these only at load time)
|
||||
minetest.register_globalstep(func(dtime))
|
||||
@ -919,12 +988,17 @@ minetest.get_craft_result(input) -> output, decremented_input
|
||||
^ output.time = number, if unsuccessful: 0
|
||||
^ decremented_input = like input
|
||||
minetest.get_craft_recipe(output) -> input
|
||||
^ returns last registered recipe for output item (node)
|
||||
^ output is a node or item type such as 'default:torch'
|
||||
^ input.method = 'normal' or 'cooking' or 'fuel'
|
||||
^ input.width = for example 3
|
||||
^ input.items = for example { stack 1, stack 2, stack 3, stack 4,
|
||||
stack 5, stack 6, stack 7, stack 8, stack 9 }
|
||||
^ input.items = nil if no recipe found
|
||||
minetest.get_all_craft_recipes(output) -> table or nil
|
||||
^ returns table with all registered recipes for output item (node)
|
||||
^ returns nil if no recipe was found
|
||||
^ table entries have same format as minetest.get_craft_recipe
|
||||
minetest.handle_node_drops(pos, drops, digger)
|
||||
^ drops: list of itemstrings
|
||||
^ Handles drops from nodes after digging: Default action is to put them into
|
||||
@ -969,9 +1043,9 @@ minetest.sound_play(spec, parameters) -> handle
|
||||
minetest.sound_stop(handle)
|
||||
|
||||
Timing:
|
||||
minetest.after(time, func, param)
|
||||
minetest.after(time, func, ...)
|
||||
^ Call function after time seconds
|
||||
^ param is optional; to pass multiple parameters, pass a table.
|
||||
^ Optional: Variable number of arguments that are passed to func
|
||||
|
||||
Server:
|
||||
minetest.request_shutdown() -> request for server shutdown
|
||||
@ -983,6 +1057,37 @@ minetest.get_ban_description(ip_or_name) -> ban description (string)
|
||||
minetest.ban_player(name) -> ban a player
|
||||
minetest.unban_player_or_ip(name) -> unban player or IP address
|
||||
|
||||
Particles:
|
||||
minetest.add_particle(pos, velocity, acceleration, expirationtime,
|
||||
size, collisiondetection, texture, playername)
|
||||
^ Spawn particle at pos with velocity and acceleration
|
||||
^ Disappears after expirationtime seconds
|
||||
^ collisiondetection: if true collides with physical objects
|
||||
^ Uses texture (string)
|
||||
^ Playername is optional, if specified spawns particle only on the player's client
|
||||
|
||||
minetest.add_particlespawner(amount, time,
|
||||
minpos, maxpos,
|
||||
minvel, maxvel,
|
||||
minacc, maxacc,
|
||||
minexptime, maxexptime,
|
||||
minsize, maxsize,
|
||||
collisiondetection, texture, playername)
|
||||
^ Add a particlespawner, an object that spawns an amount of particles over time seconds
|
||||
^ The particle's properties are random values in between the boundings:
|
||||
^ minpos/maxpos, minvel/maxvel (velocity), minacc/maxacc (acceleration),
|
||||
^ minsize/maxsize, minexptime/maxexptime (expirationtime)
|
||||
^ collisiondetection: if true uses collisiondetection
|
||||
^ Uses texture (string)
|
||||
^ Playername is optional, if specified spawns particle only on the player's client
|
||||
^ If time is 0 has infinite lifespan and spawns the amount on a per-second base
|
||||
^ Returns and id
|
||||
|
||||
minetest.delete_particlespawner(id, player)
|
||||
^ Delete ParticleSpawner with id (return value from add_particlespawner)
|
||||
^ If playername is specified, only deletes on the player's client,
|
||||
^ otherwise on all clients
|
||||
|
||||
Random:
|
||||
minetest.get_connected_players() -> list of ObjectRefs
|
||||
minetest.hash_node_position({x=,y=,z=}) -> 48-bit integer
|
||||
@ -1196,9 +1301,15 @@ methods:
|
||||
- set_wielded_item(item): replaces the wielded item, returns true if successful
|
||||
- set_armor_groups({group1=rating, group2=rating, ...})
|
||||
- set_animation({x=1,y=1}, frame_speed=15, frame_blend=0)
|
||||
- set_attach(parent, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
- set_attach(parent, bone, position, rotation)
|
||||
^ bone = string
|
||||
^ position = {x=num, y=num, z=num} (relative)
|
||||
^ rotation = {x=num, y=num, z=num}
|
||||
- set_detach()
|
||||
- set_bone_position("", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
- set_bone_position(bone, position, rotation)
|
||||
^ bone = string
|
||||
^ position = {x=num, y=num, z=num} (relative)
|
||||
^ rotation = {x=num, y=num, z=num}
|
||||
- set_properties(object property table)
|
||||
LuaEntitySAO-only: (no-op for other objects)
|
||||
- setvelocity({x=num, y=num, z=num})
|
||||
@ -1220,15 +1331,17 @@ Player-only: (no-op for other objects)
|
||||
- get_look_dir(): get camera direction as a unit vector
|
||||
- get_look_pitch(): pitch in radians
|
||||
- get_look_yaw(): yaw in radians (wraps around pretty randomly as of now)
|
||||
- set_look_pitch(radians): sets look pitch
|
||||
- set_look_yaw(radians): sets look yaw
|
||||
- set_inventory_formspec(formspec)
|
||||
^ Redefine player's inventory form
|
||||
^ Should usually be called in on_joinplayer
|
||||
- get_inventory_formspec() -> formspec string
|
||||
- get_player_control(): returns table with player pressed keys
|
||||
{jump=bool,right=bool,left=bool,LMB=bool,RMB=bool,sneak=bool,aux1=bool,down=bool,up=bool}
|
||||
{jump=bool,right=bool,left=bool,LMB=bool,RMB=bool,sneak=bool,aux1=bool,down=bool,up=bool}
|
||||
- get_player_control_bits(): returns integer with bit packed player pressed keys
|
||||
bit nr/meaning: 0/up ,1/down ,2/left ,3/right ,4/jump ,5/aux1 ,6/sneak ,7/LMB ,8/RMB
|
||||
|
||||
bit nr/meaning: 0/up ,1/down ,2/left ,3/right ,4/jump ,5/aux1 ,6/sneak ,7/LMB ,8/RMB
|
||||
|
||||
InvRef: Reference to an inventory
|
||||
methods:
|
||||
- is_empty(listname): return true if list is empty
|
||||
@ -1313,8 +1426,8 @@ Registered entities
|
||||
^ puncher: ObjectRef (can be nil)
|
||||
^ time_from_last_punch: Meant for disallowing spamming of clicks (can be nil)
|
||||
^ tool_capabilities: capability table of used tool (can be nil)
|
||||
^ dir: unit vector of direction of punch. Always defined. Points from
|
||||
the puncher to the punched.
|
||||
^ dir: unit vector of direction of punch. Always defined. Points from
|
||||
the puncher to the punched.
|
||||
- on_rightclick(self, clicker)
|
||||
- get_staticdata(self)
|
||||
^ Should return a string that will be passed to on_activate when
|
||||
@ -1389,10 +1502,10 @@ Item definition (register_node, register_craftitem, register_tool)
|
||||
max_drop_level=0,
|
||||
groupcaps={
|
||||
-- For example:
|
||||
fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
|
||||
snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
|
||||
choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
|
||||
}
|
||||
},
|
||||
damage_groups = {groupname=damage},
|
||||
}
|
||||
node_placement_prediction = nil,
|
||||
^ If nil and item is node, prediction is made automatically
|
||||
@ -1401,6 +1514,9 @@ Item definition (register_node, register_craftitem, register_tool)
|
||||
^ Otherwise should be name of node which the client immediately places
|
||||
on ground when the player places the item. Server will always update
|
||||
actual result to client in a short moment.
|
||||
sound = {
|
||||
place = <SimpleSoundSpec>,
|
||||
}
|
||||
|
||||
on_place = func(itemstack, placer, pointed_thing),
|
||||
^ Shall place item and return the leftover itemstack
|
||||
@ -1435,10 +1551,10 @@ Node definition (register_node)
|
||||
drawtype = "normal", -- See "Node drawtypes"
|
||||
visual_scale = 1.0,
|
||||
tiles = {tile definition 1, def2, def3, def4, def5, def6},
|
||||
^ Textures of node; +Y, -Y, +X, -X, +Z, -Z (old field name: tile_images)
|
||||
^ Textures of node; +Y, -Y, +X, -X, +Z, -Z (old field name: tile_images)
|
||||
^ List can be shortened to needed length
|
||||
special_tiles = {tile definition 1, Tile definition 2},
|
||||
^ Special textures of node; used rarely (old field name: special_materials)
|
||||
^ Special textures of node; used rarely (old field name: special_materials)
|
||||
^ List can be shortened to needed length
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0}, -- If player is inside node
|
||||
@ -1468,6 +1584,7 @@ Node definition (register_node)
|
||||
footstep = <SimpleSoundSpec>,
|
||||
dig = <SimpleSoundSpec>, -- "__group" = group-based sound (default)
|
||||
dug = <SimpleSoundSpec>,
|
||||
place = <SimpleSoundSpec>,
|
||||
},
|
||||
|
||||
on_construct = func(pos),
|
||||
@ -1494,7 +1611,7 @@ Node definition (register_node)
|
||||
can_dig = function(pos,player)
|
||||
^ returns true if node can be dug, or false if not
|
||||
^ default: nil
|
||||
|
||||
|
||||
on_punch = func(pos, node, puncher),
|
||||
^ default: minetest.node_punch
|
||||
^ By default: does nothing
|
||||
@ -1517,32 +1634,32 @@ Node definition (register_node)
|
||||
^ Called when an UI form (eg. sign text input) returns data
|
||||
^ default: nil
|
||||
|
||||
allow_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
^ Called when a player wants to move items inside the inventory
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
allow_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to put something into the inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
allow_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to take something out of the inventory
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
on_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
on_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
allow_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
^ Called when a player wants to move items inside the inventory
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
on_blast = func(pos, intensity),
|
||||
^ intensity: 1.0 = mid range of regular TNT
|
||||
^ If defined, called when an explosion touches the node, instead of
|
||||
removing the node
|
||||
allow_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to put something into the inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
allow_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called when a player wants to take something out of the inventory
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_metadata_inventory_move = func(pos, from_list, from_index,
|
||||
to_list, to_index, count, player),
|
||||
on_metadata_inventory_put = func(pos, listname, index, stack, player),
|
||||
on_metadata_inventory_take = func(pos, listname, index, stack, player),
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
|
||||
on_blast = func(pos, intensity),
|
||||
^ intensity: 1.0 = mid range of regular TNT
|
||||
^ If defined, called when an explosion touches the node, instead of
|
||||
removing the node
|
||||
}
|
||||
|
||||
Recipe for register_craft: (shaped)
|
||||
@ -1591,6 +1708,28 @@ Recipe for register_craft (furnace fuel)
|
||||
burntime = 1,
|
||||
}
|
||||
|
||||
Ore definition (register_ore)
|
||||
{
|
||||
ore_type = "scatter" -- See "Ore types"
|
||||
ore = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 8*8*8,
|
||||
^ Ore has a 1 out of clust_scarcity chance of spawning in a node
|
||||
^ This value should be *MUCH* higher than your intuition might tell you!
|
||||
clust_num_ores = 8,
|
||||
^ Number of ores in a cluster
|
||||
clust_size = 3,
|
||||
^ Size of the bounding box of the cluster
|
||||
^ In this example, there is a 3x3x3 cluster where 8 out of the 27 nodes are coal ore
|
||||
height_min = -31000,
|
||||
height_max = 64,
|
||||
noise_threshhold = 0.5,
|
||||
^ If noise is above this threshhold, ore is placed. Not needed for a uniform distribution
|
||||
noise_params = {offset=0, scale=1, spread={x=100, y=100, z=100}, seed=23, octaves=3, persist=0.70}
|
||||
^ NoiseParams structure describing the perlin noise used for ore distribution.
|
||||
^ Needed for sheet ore_type. Omit from scatter ore_type for a uniform ore distribution
|
||||
}
|
||||
|
||||
Chatcommand definition (register_chatcommand)
|
||||
{
|
||||
params = "<name> <privilege>", -- short parameter description
|
||||
@ -1601,24 +1740,24 @@ Chatcommand definition (register_chatcommand)
|
||||
|
||||
Detached inventory callbacks
|
||||
{
|
||||
allow_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
allow_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
^ Called when a player wants to move items inside the inventory
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
^ Return value: number of items allowed to move
|
||||
|
||||
allow_put = func(inv, listname, index, stack, player),
|
||||
^ Called when a player wants to put something into the inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
^ Return value: number of items allowed to put
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
allow_take = func(inv, listname, index, stack, player),
|
||||
^ Called when a player wants to take something out of the inventory
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
^ Return value: number of items allowed to take
|
||||
^ Return value: -1: Allow and don't modify item count in inventory
|
||||
|
||||
on_move = func(inv, from_list, from_index, to_list, to_index, count, player),
|
||||
on_put = func(inv, listname, index, stack, player),
|
||||
on_take = func(inv, listname, index, stack, player),
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
^ Called after the actual action has happened, according to what was allowed.
|
||||
^ No return value
|
||||
}
|
||||
|
||||
|
@ -70,3 +70,39 @@ function check_if_minetestserver_up($host, $port)
|
||||
return false;
|
||||
}
|
||||
|
||||
- Here's a Python script for checking if a minetest server is up, confirmed working
|
||||
#!/usr/bin/env python
|
||||
import sys, time, socket
|
||||
address = ""
|
||||
port = 30000
|
||||
if len(sys.argv) <= 1:
|
||||
print("Usage: %s <address>" % sys.argv[0])
|
||||
exit()
|
||||
if ':' in sys.argv[1]:
|
||||
address = sys.argv[1].split(':')[0]
|
||||
try:
|
||||
port = int(sys.argv[1].split(':')[1])
|
||||
except ValueError:
|
||||
print("Please specify a valid port")
|
||||
exit()
|
||||
else:
|
||||
address = sys.argv[1]
|
||||
|
||||
try:
|
||||
start = time.time()
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.settimeout(2.0)
|
||||
buf = "\x4f\x45\x74\x03\x00\x00\x00\x01"
|
||||
sock.sendto(buf, (address, port))
|
||||
data, addr = sock.recvfrom(1000)
|
||||
if data:
|
||||
peer_id = data[12:14]
|
||||
buf = "\x4f\x45\x74\x03" + peer_id + "\x00\x00\x03"
|
||||
sock.sendto(buf, (address, port))
|
||||
sock.close()
|
||||
end = time.time()
|
||||
print("%s is up (%0.5fms)" % (sys.argv[1],end-start))
|
||||
else:
|
||||
print("%s seems to be down " % sys.argv[1])
|
||||
except:
|
||||
print("%s seems to be down " % sys.argv[1])
|
||||
|
@ -659,6 +659,8 @@ function default.node_sound_dirt_defaults(table)
|
||||
{name="", gain=0.5}
|
||||
--table.dug = table.dug or
|
||||
-- {name="default_dirt_break", gain=0.5}
|
||||
table.place = table.place or
|
||||
{name="default_grass_footstep", gain=0.5}
|
||||
default.node_sound_defaults(table)
|
||||
return table
|
||||
end
|
||||
|
@ -27,52 +27,74 @@ minetest.register_alias("mapgen_mese", "default:mese")
|
||||
-- Ore generation
|
||||
--
|
||||
|
||||
local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max, param2)
|
||||
if maxp.y < height_min or minp.y > height_max then
|
||||
return
|
||||
end
|
||||
local y_min = math.max(minp.y, height_min)
|
||||
local y_max = math.min(maxp.y, height_max)
|
||||
local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1)
|
||||
local pr = PseudoRandom(seed)
|
||||
local num_chunks = math.floor(chunks_per_volume * volume)
|
||||
local chunk_size = 3
|
||||
if ore_per_chunk <= 4 then
|
||||
chunk_size = 2
|
||||
end
|
||||
local inverse_chance = math.floor(chunk_size*chunk_size*chunk_size / ore_per_chunk)
|
||||
--print("generate_ore num_chunks: "..dump(num_chunks))
|
||||
for i=1,num_chunks do
|
||||
local y0 = pr:next(y_min, y_max-chunk_size+1)
|
||||
if y0 >= height_min and y0 <= height_max then
|
||||
local x0 = pr:next(minp.x, maxp.x-chunk_size+1)
|
||||
local z0 = pr:next(minp.z, maxp.z-chunk_size+1)
|
||||
local p0 = {x=x0, y=y0, z=z0}
|
||||
for x1=0,chunk_size-1 do
|
||||
for y1=0,chunk_size-1 do
|
||||
for z1=0,chunk_size-1 do
|
||||
if pr:next(1,inverse_chance) == 1 then
|
||||
local x2 = x0+x1
|
||||
local y2 = y0+y1
|
||||
local z2 = z0+z1
|
||||
local p2 = {x=x2, y=y2, z=z2}
|
||||
if minetest.env:get_node(p2).name == wherein then
|
||||
minetest.env:set_node(p2, {name=name, param2=param2})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--print("generate_ore done")
|
||||
end
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 8*8*8,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -31000,
|
||||
height_max = 64,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 16*16*16,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -5,
|
||||
height_max = 7,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 12*12*12,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -16,
|
||||
height_max = -5,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 9*9*9,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = -31000,
|
||||
height_max = -17,
|
||||
})
|
||||
|
||||
-- for float islands and far scaled
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 8*8*8,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = 200,
|
||||
height_max = 31000,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 9*9*9,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
height_min = 200,
|
||||
height_max = 31000,
|
||||
})
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
generate_ore("default:stone_with_coal", "default:stone", minp, maxp, seed, 1/8/8/8, 5, -31000, 64)
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+1, 1/16/16/16, 5, -5, 7)
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+2, 1/12/12/12, 5, -16, -5)
|
||||
generate_ore("default:stone_with_iron", "default:stone", minp, maxp, seed+3, 1/9/9/9, 5, -31000, -17)
|
||||
-- Generate clay
|
||||
if maxp.y >= 2 and minp.y <= 0 then
|
||||
-- Assume X and Z lengths are equal
|
||||
@ -110,11 +132,5 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
end
|
||||
end
|
||||
end
|
||||
if minetest.setting_get("liquid_finite") then
|
||||
generate_ore("default:water_source", "default:stone", minp, maxp, seed+42, 1/24/24/24, 4, -100, -10, 128)
|
||||
generate_ore("default:water_source", "default:stone", minp, maxp, seed+42, 1/28/28/28, 3, -10000, -101, 128)
|
||||
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+43, 1/38/38/38, 2, -500, -100, 128)
|
||||
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+43, 1/30/30/30, 4, -31000, -501, 128)
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -80,6 +80,7 @@
|
||||
# when set to higher number than 0
|
||||
#fsaa = 0
|
||||
#vsync = false
|
||||
#fov = 72
|
||||
# Address to connect to (#blank = start local server)
|
||||
#address =
|
||||
# Enable random user input, for testing
|
||||
@ -95,9 +96,11 @@
|
||||
# Update liquids every .. recommend for finite: 0.2
|
||||
#liquid_update = 1.0
|
||||
# When finite liquid: relax flowing blocks to source if level near max and N nearby source blocks, more realistic, but not true constant. values: 0,1,2,3,4 : 0 - disable, 1 - most aggresive
|
||||
#liquid_relax = 1
|
||||
# optimization: faster cave flood (and not true constant)
|
||||
#liquid_relax = 2
|
||||
# Optimization: faster cave flood (and not true constant)
|
||||
#liquid_fast_flood = 1
|
||||
# Underground water and lava springs, its infnity sources if liquid_finite enabled
|
||||
#underground_springs = 1
|
||||
# Enable nice leaves; disable for speed
|
||||
#new_style_leaves = true
|
||||
# Enable smooth lighting with simple ambient occlusion;
|
||||
@ -125,6 +128,10 @@
|
||||
#farmesh_distance = 40
|
||||
# Enable/disable clouds
|
||||
#enable_clouds = true
|
||||
#cloud_height = 120
|
||||
#enable_3d_clouds = true
|
||||
# Use a cloud animation for the main menu background
|
||||
#menu_clouds = true
|
||||
# Path for screenshots
|
||||
#screenshot_path = .
|
||||
# Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double)
|
||||
@ -304,29 +311,45 @@
|
||||
# Mapgen stuff
|
||||
#
|
||||
|
||||
# Name of map generator to be used. Currently only v6 is supported.
|
||||
# Name of map generator to be used. Currently v6, indev and singlenode are supported.
|
||||
#mg_name = v6
|
||||
# Water level of map.
|
||||
#water_level = 1
|
||||
# Size of chunks to be generated.
|
||||
#chunksize = 5
|
||||
# Map generation attributes. Currently supported: trees, caves, flat, v6_biome_blend
|
||||
# Map generation attributes. Currently supported: trees, caves, flat, v6_biome_blend, v6_jungles, dungeons
|
||||
#mg_flags = trees, caves, v6_biome_blend
|
||||
# How large deserts and beaches are
|
||||
#mgv6_freq_desert = 0.45
|
||||
#mgv6_freq_beach = 0.15
|
||||
# Perlin noise attributes for different map generation parameters
|
||||
# Offset, scale, spread factor, seed offset, number of octaves, persistence
|
||||
#mgv6_np_terrain_base = -4, 20, (250.0, 250, 250), 82341, 5, 0.6
|
||||
#mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6
|
||||
#mgv6_np_terrain_higher = 20, 16, (500, 500, 500), 85039, 5, 0.6
|
||||
#mgv6_np_steepness = 0.85, 0.5, (125, 125, 125), -932, 5, 0.7
|
||||
#mgv6_np_height_select = 0.5, 1, (250, 250, 250), 4213, 5, 0.69
|
||||
#mgv6_np_trees = 0, 1, (125, 125, 125), 2, 4, 0.66
|
||||
#mgv6_np_mud = 4, 2, (200, 200, 200), 91013, 3, 0.55
|
||||
#mgv6_np_beach = 0, 1, (250, 250, 250), 59420, 3, 0.50
|
||||
#mgv6_np_biome = 0, 1, (250, 250, 250), 9130, 3, 0.50
|
||||
#mgv6_np_cave = 6, 6, (250, 250, 250), 34329, 3, 0.50
|
||||
#mgv6_np_humidity = 0.5, 0.5, (500, 500, 500), 72384, 4, 0.66
|
||||
#mgv6_np_trees = 0, 1, (125, 125, 125), 2, 4, 0.66
|
||||
#mgv6_np_apple_trees = 0, 1, (100, 100, 100), 342902, 3, 0.45
|
||||
|
||||
#mgv7_np_terrain = 10, 12, (350, 350, 350), 82341, 5, 0.6
|
||||
#mgv7_np_bgroup = 0.5, 0.3125, (350, 350, 350), 5923, 2, 0.6
|
||||
#mgv7_np_heat = 25, 50, (500, 500, 500), 35293, 1, 0
|
||||
#mgv7_np_humidity = 50, 31.25, (750, 750, 750), 12094, 2, 0.6
|
||||
|
||||
# Offset, scale, spread factor, seed offset, number of octaves, persistence, farscale, farspread
|
||||
#mgindev_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 10, 10
|
||||
#mgindev_np_terrain_higher = 20, 16, (500, 500, 500), 85039, 5, 0.6, 10, 10
|
||||
#mgindev_np_steepness = 0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2, 10
|
||||
#mgindev_np_mud = 4, 2, (200, 200, 200), 91013, 3, 0.55, 1, 1
|
||||
#mgindev_np_float_islands1 = 0, 1, (64, 64, 64 ), 3683, 5, 0.5, 1, 1.5
|
||||
#mgindev_np_float_islands2 = 0, 1, (8, 8, 8 ), 9292, 2, 0.5, 1, 1.5
|
||||
#mgindev_np_float_islands3 = 0, 1, (256, 256, 256), 6412, 2, 0.5, 1, 0.5
|
||||
#mgindev_np_biome = 0, 1, (250, 250, 250), 9130, 3, 0.50, 1, 10
|
||||
|
||||
# Float islands starts from height, 0 to disable
|
||||
#mgindev_float_islands = 500
|
||||
|
@ -161,7 +161,7 @@ else()
|
||||
endif(APPLE)
|
||||
endif(BUILD_CLIENT)
|
||||
find_package(ZLIB REQUIRED)
|
||||
set(PLATFORM_LIBS -lpthread ${CMAKE_DL_LIBS})
|
||||
set(PLATFORM_LIBS -lpthread -lrt ${CMAKE_DL_LIBS})
|
||||
#set(CLIENT_PLATFORM_LIBS -lXxf86vm)
|
||||
# This way Xxf86vm is found on OpenBSD too
|
||||
find_library(XXF86VM_LIBRARY Xxf86vm)
|
||||
@ -172,6 +172,7 @@ endif()
|
||||
find_package(Jthread REQUIRED)
|
||||
find_package(Sqlite3 REQUIRED)
|
||||
find_package(Json REQUIRED)
|
||||
find_package(OpenGLES2)
|
||||
|
||||
if(USE_FREETYPE)
|
||||
find_package(Freetype REQUIRED)
|
||||
@ -205,6 +206,20 @@ set(common_SRCS
|
||||
itemdef.cpp
|
||||
nodedef.cpp
|
||||
object_properties.cpp
|
||||
scriptapi_types.cpp
|
||||
scriptapi_common.cpp
|
||||
scriptapi_content.cpp
|
||||
scriptapi_craft.cpp
|
||||
scriptapi_node.cpp
|
||||
scriptapi_item.cpp
|
||||
scriptapi_env.cpp
|
||||
scriptapi_nodetimer.cpp
|
||||
scriptapi_noise.cpp
|
||||
scriptapi_entity.cpp
|
||||
scriptapi_object.cpp
|
||||
scriptapi_nodemeta.cpp
|
||||
scriptapi_inventory.cpp
|
||||
scriptapi_particles.cpp
|
||||
scriptapi.cpp
|
||||
script.cpp
|
||||
log.cpp
|
||||
@ -212,7 +227,10 @@ set(common_SRCS
|
||||
emerge.cpp
|
||||
mapgen.cpp
|
||||
mapgen_v6.cpp
|
||||
mapgen_indev.cpp
|
||||
mapgen_singlenode.cpp
|
||||
treegen.cpp
|
||||
dungeongen.cpp
|
||||
content_nodemeta.cpp
|
||||
content_mapnode.cpp
|
||||
collision.cpp
|
||||
@ -371,6 +389,7 @@ if(BUILD_CLIENT)
|
||||
${SQLITE3_LIBRARY}
|
||||
${LUA_LIBRARY}
|
||||
${JSON_LIBRARY}
|
||||
${OPENGLES2_LIBRARIES}
|
||||
${PLATFORM_LIBS}
|
||||
${CLIENT_PLATFORM_LIBS}
|
||||
)
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
}
|
||||
|
||||
virtual u8 getType() const = 0;
|
||||
|
||||
virtual bool getCollisionBox(aabb3f *toset) = 0;
|
||||
protected:
|
||||
u16 m_id; // 0 is invalid, "no id"
|
||||
};
|
||||
|
20
src/chat.cpp
20
src/chat.cpp
@ -117,8 +117,8 @@ void ChatBuffer::deleteOldest(u32 count)
|
||||
--count;
|
||||
}
|
||||
|
||||
m_unformatted.erase(0, del_unformatted);
|
||||
m_formatted.erase(0, del_formatted);
|
||||
m_unformatted.erase(m_unformatted.begin(), m_unformatted.begin() + del_unformatted);
|
||||
m_formatted.erase(m_formatted.begin(), m_formatted.begin() + del_formatted);
|
||||
}
|
||||
|
||||
void ChatBuffer::deleteByAge(f32 maxAge)
|
||||
@ -232,10 +232,10 @@ void ChatBuffer::scrollTop()
|
||||
}
|
||||
|
||||
u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
|
||||
core::array<ChatFormattedLine>& destination) const
|
||||
std::vector<ChatFormattedLine>& destination) const
|
||||
{
|
||||
u32 num_added = 0;
|
||||
core::array<ChatFormattedFragment> next_frags;
|
||||
std::vector<ChatFormattedFragment> next_frags;
|
||||
ChatFormattedLine next_line;
|
||||
ChatFormattedFragment temp_frag;
|
||||
u32 out_column = 0;
|
||||
@ -292,7 +292,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
|
||||
frag.column = out_column;
|
||||
next_line.fragments.push_back(frag);
|
||||
out_column += frag.text.size();
|
||||
next_frags.erase(0, 1);
|
||||
next_frags.erase(next_frags.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -414,7 +414,7 @@ std::wstring ChatPrompt::submit()
|
||||
if (!line.empty())
|
||||
m_history.push_back(line);
|
||||
if (m_history.size() > m_history_limit)
|
||||
m_history.erase(0);
|
||||
m_history.erase(m_history.begin());
|
||||
m_history_index = m_history.size();
|
||||
m_view = 0;
|
||||
m_cursor = 0;
|
||||
@ -464,7 +464,7 @@ void ChatPrompt::historyNext()
|
||||
}
|
||||
}
|
||||
|
||||
void ChatPrompt::nickCompletion(const core::list<std::wstring>& names, bool backwards)
|
||||
void ChatPrompt::nickCompletion(const std::list<std::wstring>& names, bool backwards)
|
||||
{
|
||||
// Two cases:
|
||||
// (a) m_nick_completion_start == m_nick_completion_end == 0
|
||||
@ -492,10 +492,10 @@ void ChatPrompt::nickCompletion(const core::list<std::wstring>& names, bool back
|
||||
std::wstring prefix = m_line.substr(prefix_start, prefix_end - prefix_start);
|
||||
|
||||
// find all names that start with the selected prefix
|
||||
core::array<std::wstring> completions;
|
||||
for (core::list<std::wstring>::ConstIterator
|
||||
std::vector<std::wstring> completions;
|
||||
for (std::list<std::wstring>::const_iterator
|
||||
i = names.begin();
|
||||
i != names.end(); i++)
|
||||
i != names.end(); ++i)
|
||||
{
|
||||
if (str_starts_with(*i, prefix, true))
|
||||
{
|
||||
|
14
src/chat.h
14
src/chat.h
@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
// Chat console related classes, only used by the client
|
||||
|
||||
@ -55,7 +57,7 @@ struct ChatFormattedFragment
|
||||
struct ChatFormattedLine
|
||||
{
|
||||
// Array of text fragments
|
||||
core::array<ChatFormattedFragment> fragments;
|
||||
std::vector<ChatFormattedFragment> fragments;
|
||||
// true if first line of one formatted ChatLine
|
||||
bool first;
|
||||
};
|
||||
@ -110,7 +112,7 @@ public:
|
||||
// Appends the formatted lines to the destination array and
|
||||
// returns the number of formatted lines.
|
||||
u32 formatChatLine(const ChatLine& line, u32 cols,
|
||||
core::array<ChatFormattedLine>& destination) const;
|
||||
std::vector<ChatFormattedLine>& destination) const;
|
||||
|
||||
protected:
|
||||
s32 getTopScrollPos() const;
|
||||
@ -120,7 +122,7 @@ private:
|
||||
// Scrollback size
|
||||
u32 m_scrollback;
|
||||
// Array of unformatted chat lines
|
||||
core::array<ChatLine> m_unformatted;
|
||||
std::vector<ChatLine> m_unformatted;
|
||||
|
||||
// Number of character columns in console
|
||||
u32 m_cols;
|
||||
@ -129,7 +131,7 @@ private:
|
||||
// Scroll position (console's top line index into m_formatted)
|
||||
s32 m_scroll;
|
||||
// Array of formatted lines
|
||||
core::array<ChatFormattedLine> m_formatted;
|
||||
std::vector<ChatFormattedLine> m_formatted;
|
||||
// Empty formatted line, for error returns
|
||||
ChatFormattedLine m_empty_formatted_line;
|
||||
};
|
||||
@ -158,7 +160,7 @@ public:
|
||||
void historyNext();
|
||||
|
||||
// Nick completion
|
||||
void nickCompletion(const core::list<std::wstring>& names, bool backwards);
|
||||
void nickCompletion(const std::list<std::wstring>& names, bool backwards);
|
||||
|
||||
// Update console size and reformat the visible portion of the prompt
|
||||
void reformat(u32 cols);
|
||||
@ -209,7 +211,7 @@ private:
|
||||
// Currently edited line
|
||||
std::wstring m_line;
|
||||
// History buffer
|
||||
core::array<std::wstring> m_history;
|
||||
std::vector<std::wstring> m_history;
|
||||
// History index (0 <= m_history_index <= m_history.size())
|
||||
u32 m_history_index;
|
||||
// Maximum number of history entries
|
||||
|
185
src/client.cpp
185
src/client.cpp
@ -232,8 +232,8 @@ void * MediaFetchThread::Thread()
|
||||
#if USE_CURL
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
for (core::list<MediaRequest>::Iterator i = m_file_requests.begin();
|
||||
i != m_file_requests.end(); i++) {
|
||||
for (std::list<MediaRequest>::iterator i = m_file_requests.begin();
|
||||
i != m_file_requests.end(); ++i) {
|
||||
curl = curl_easy_init();
|
||||
assert(curl);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
@ -360,8 +360,8 @@ Client::~Client()
|
||||
}
|
||||
}
|
||||
|
||||
for (core::list<MediaFetchThread*>::Iterator i = m_media_fetch_threads.begin();
|
||||
i != m_media_fetch_threads.end(); i++)
|
||||
for (std::list<MediaFetchThread*>::iterator i = m_media_fetch_threads.begin();
|
||||
i != m_media_fetch_threads.end(); ++i)
|
||||
delete *i;
|
||||
}
|
||||
|
||||
@ -585,7 +585,7 @@ void Client::step(float dtime)
|
||||
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "Client: map timer and unload");
|
||||
core::list<v3s16> deleted_blocks;
|
||||
std::list<v3s16> deleted_blocks;
|
||||
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||
g_settings->getFloat("client_unload_unused_data_timeout"),
|
||||
&deleted_blocks);
|
||||
@ -599,8 +599,8 @@ void Client::step(float dtime)
|
||||
NOTE: This loop is intentionally iterated the way it is.
|
||||
*/
|
||||
|
||||
core::list<v3s16>::Iterator i = deleted_blocks.begin();
|
||||
core::list<v3s16> sendlist;
|
||||
std::list<v3s16>::iterator i = deleted_blocks.begin();
|
||||
std::list<v3s16> sendlist;
|
||||
for(;;)
|
||||
{
|
||||
if(sendlist.size() == 255 || i == deleted_blocks.end())
|
||||
@ -619,9 +619,9 @@ void Client::step(float dtime)
|
||||
writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
|
||||
reply[2] = sendlist.size();
|
||||
u32 k = 0;
|
||||
for(core::list<v3s16>::Iterator
|
||||
for(std::list<v3s16>::iterator
|
||||
j = sendlist.begin();
|
||||
j != sendlist.end(); j++)
|
||||
j != sendlist.end(); ++j)
|
||||
{
|
||||
writeV3S16(&reply[2+1+6*k], *j);
|
||||
k++;
|
||||
@ -635,7 +635,7 @@ void Client::step(float dtime)
|
||||
}
|
||||
|
||||
sendlist.push_back(*i);
|
||||
i++;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -727,7 +727,7 @@ void Client::step(float dtime)
|
||||
<<std::endl;*/
|
||||
|
||||
int num_processed_meshes = 0;
|
||||
while(m_mesh_update_thread.m_queue_out.size() > 0)
|
||||
while(!m_mesh_update_thread.m_queue_out.empty())
|
||||
{
|
||||
num_processed_meshes++;
|
||||
MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_front();
|
||||
@ -779,10 +779,10 @@ void Client::step(float dtime)
|
||||
*/
|
||||
if (m_media_receive_started) {
|
||||
bool all_stopped = true;
|
||||
for (core::list<MediaFetchThread*>::Iterator thread = m_media_fetch_threads.begin();
|
||||
thread != m_media_fetch_threads.end(); thread++) {
|
||||
for (std::list<MediaFetchThread*>::iterator thread = m_media_fetch_threads.begin();
|
||||
thread != m_media_fetch_threads.end(); ++thread) {
|
||||
all_stopped &= !(*thread)->IsRunning();
|
||||
while ((*thread)->m_file_data.size() > 0) {
|
||||
while (!(*thread)->m_file_data.empty()) {
|
||||
std::pair <std::string, std::string> out = (*thread)->m_file_data.pop_front();
|
||||
++m_media_received_count;
|
||||
|
||||
@ -803,9 +803,9 @@ void Client::step(float dtime)
|
||||
}
|
||||
|
||||
{
|
||||
core::map<std::string, std::string>::Node *n;
|
||||
std::map<std::string, std::string>::iterator n;
|
||||
n = m_media_name_sha1_map.find(out.first);
|
||||
if(n == NULL)
|
||||
if(n == m_media_name_sha1_map.end())
|
||||
errorstream<<"The server sent a file that has not "
|
||||
<<"been announced."<<std::endl;
|
||||
else
|
||||
@ -814,11 +814,11 @@ void Client::step(float dtime)
|
||||
}
|
||||
}
|
||||
if (all_stopped) {
|
||||
core::list<MediaRequest> fetch_failed;
|
||||
for (core::list<MediaFetchThread*>::Iterator thread = m_media_fetch_threads.begin();
|
||||
thread != m_media_fetch_threads.end(); thread++) {
|
||||
for (core::list<MediaRequest>::Iterator request = (*thread)->m_failed.begin();
|
||||
request != (*thread)->m_failed.end(); request++)
|
||||
std::list<MediaRequest> fetch_failed;
|
||||
for (std::list<MediaFetchThread*>::iterator thread = m_media_fetch_threads.begin();
|
||||
thread != m_media_fetch_threads.end(); ++thread) {
|
||||
for (std::list<MediaRequest>::iterator request = (*thread)->m_failed.begin();
|
||||
request != (*thread)->m_failed.end(); ++request)
|
||||
fetch_failed.push_back(*request);
|
||||
(*thread)->m_failed.clear();
|
||||
}
|
||||
@ -1015,14 +1015,14 @@ void Client::deletingPeer(con::Peer *peer, bool timeout)
|
||||
string name
|
||||
}
|
||||
*/
|
||||
void Client::request_media(const core::list<MediaRequest> &file_requests)
|
||||
void Client::request_media(const std::list<MediaRequest> &file_requests)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
writeU16(os, TOSERVER_REQUEST_MEDIA);
|
||||
writeU16(os, file_requests.size());
|
||||
|
||||
for(core::list<MediaRequest>::ConstIterator i = file_requests.begin();
|
||||
i != file_requests.end(); i++) {
|
||||
for(std::list<MediaRequest>::const_iterator i = file_requests.begin();
|
||||
i != file_requests.end(); ++i) {
|
||||
os<<serializeString(i->name);
|
||||
}
|
||||
|
||||
@ -1622,7 +1622,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
infostream<<"Client: Received media announcement: packet size: "
|
||||
<<datasize<<std::endl;
|
||||
|
||||
core::list<MediaRequest> file_requests;
|
||||
std::list<MediaRequest> file_requests;
|
||||
|
||||
for(int i=0; i<num_files; i++)
|
||||
{
|
||||
@ -1641,7 +1641,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
std::string sha1_hex = hex_encode(sha1_raw);
|
||||
std::ostringstream tmp_os(std::ios_base::binary);
|
||||
bool found_in_cache = m_media_cache.load_sha1(sha1_raw, tmp_os);
|
||||
m_media_name_sha1_map.set(name, sha1_raw);
|
||||
m_media_name_sha1_map[name] = sha1_raw;
|
||||
|
||||
// If found in cache, try to load it from there
|
||||
if(found_in_cache)
|
||||
@ -1677,16 +1677,16 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
request_media(file_requests);
|
||||
} else {
|
||||
#if USE_CURL
|
||||
core::list<MediaFetchThread*>::Iterator cur = m_media_fetch_threads.begin();
|
||||
for(core::list<MediaRequest>::Iterator i = file_requests.begin();
|
||||
i != file_requests.end(); i++) {
|
||||
std::list<MediaFetchThread*>::iterator cur = m_media_fetch_threads.begin();
|
||||
for(std::list<MediaRequest>::iterator i = file_requests.begin();
|
||||
i != file_requests.end(); ++i) {
|
||||
(*cur)->m_file_requests.push_back(*i);
|
||||
cur++;
|
||||
if (cur == m_media_fetch_threads.end())
|
||||
cur = m_media_fetch_threads.begin();
|
||||
}
|
||||
for (core::list<MediaFetchThread*>::Iterator i = m_media_fetch_threads.begin();
|
||||
i != m_media_fetch_threads.end(); i++) {
|
||||
for (std::list<MediaFetchThread*>::iterator i = m_media_fetch_threads.begin();
|
||||
i != m_media_fetch_threads.end(); ++i) {
|
||||
(*i)->m_remote_url = remote_media;
|
||||
(*i)->Start();
|
||||
}
|
||||
@ -1762,9 +1762,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
|
||||
{
|
||||
core::map<std::string, std::string>::Node *n;
|
||||
std::map<std::string, std::string>::iterator n;
|
||||
n = m_media_name_sha1_map.find(name);
|
||||
if(n == NULL)
|
||||
if(n == m_media_name_sha1_map.end())
|
||||
errorstream<<"The server sent a file that has not "
|
||||
<<"been announced."<<std::endl;
|
||||
else
|
||||
@ -1936,6 +1936,89 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
event.show_formspec.formname = new std::string(formname);
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_SPAWN_PARTICLE)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
v3f pos = readV3F1000(is);
|
||||
v3f vel = readV3F1000(is);
|
||||
v3f acc = readV3F1000(is);
|
||||
float expirationtime = readF1000(is);
|
||||
float size = readF1000(is);
|
||||
bool collisiondetection = readU8(is);
|
||||
std::string texture = deSerializeLongString(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_SPAWN_PARTICLE;
|
||||
event.spawn_particle.pos = new v3f (pos);
|
||||
event.spawn_particle.vel = new v3f (vel);
|
||||
event.spawn_particle.acc = new v3f (acc);
|
||||
|
||||
event.spawn_particle.expirationtime = expirationtime;
|
||||
event.spawn_particle.size = size;
|
||||
event.add_particlespawner.collisiondetection =
|
||||
collisiondetection;
|
||||
event.spawn_particle.texture = new std::string(texture);
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_ADD_PARTICLESPAWNER)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u16 amount = readU16(is);
|
||||
float spawntime = readF1000(is);
|
||||
v3f minpos = readV3F1000(is);
|
||||
v3f maxpos = readV3F1000(is);
|
||||
v3f minvel = readV3F1000(is);
|
||||
v3f maxvel = readV3F1000(is);
|
||||
v3f minacc = readV3F1000(is);
|
||||
v3f maxacc = readV3F1000(is);
|
||||
float minexptime = readF1000(is);
|
||||
float maxexptime = readF1000(is);
|
||||
float minsize = readF1000(is);
|
||||
float maxsize = readF1000(is);
|
||||
bool collisiondetection = readU8(is);
|
||||
std::string texture = deSerializeLongString(is);
|
||||
u32 id = readU32(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_ADD_PARTICLESPAWNER;
|
||||
event.add_particlespawner.amount = amount;
|
||||
event.add_particlespawner.spawntime = spawntime;
|
||||
|
||||
event.add_particlespawner.minpos = new v3f (minpos);
|
||||
event.add_particlespawner.maxpos = new v3f (maxpos);
|
||||
event.add_particlespawner.minvel = new v3f (minvel);
|
||||
event.add_particlespawner.maxvel = new v3f (maxvel);
|
||||
event.add_particlespawner.minacc = new v3f (minacc);
|
||||
event.add_particlespawner.maxacc = new v3f (maxacc);
|
||||
|
||||
event.add_particlespawner.minexptime = minexptime;
|
||||
event.add_particlespawner.maxexptime = maxexptime;
|
||||
event.add_particlespawner.minsize = minsize;
|
||||
event.add_particlespawner.maxsize = maxsize;
|
||||
event.add_particlespawner.collisiondetection = collisiondetection;
|
||||
event.add_particlespawner.texture = new std::string(texture);
|
||||
event.add_particlespawner.id = id;
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_DELETE_PARTICLESPAWNER)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u32 id = readU16(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_DELETE_PARTICLESPAWNER;
|
||||
event.delete_particlespawner.id = id;
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
@ -2231,7 +2314,7 @@ void Client::sendPlayerItem(u16 item)
|
||||
|
||||
void Client::removeNode(v3s16 p)
|
||||
{
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
std::map<v3s16, MapBlock*> modified_blocks;
|
||||
|
||||
try
|
||||
{
|
||||
@ -2245,12 +2328,11 @@ void Client::removeNode(v3s16 p)
|
||||
// add urgent task to update the modified node
|
||||
addUpdateMeshTaskForNode(p, false, true);
|
||||
|
||||
for(core::map<v3s16, MapBlock * >::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<v3s16, MapBlock * >::iterator
|
||||
i = modified_blocks.begin();
|
||||
i != modified_blocks.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
addUpdateMeshTaskWithEdge(p);
|
||||
addUpdateMeshTaskWithEdge(i->first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2258,7 +2340,7 @@ void Client::addNode(v3s16 p, MapNode n)
|
||||
{
|
||||
TimeTaker timer1("Client::addNode()");
|
||||
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
std::map<v3s16, MapBlock*> modified_blocks;
|
||||
|
||||
try
|
||||
{
|
||||
@ -2268,12 +2350,11 @@ void Client::addNode(v3s16 p, MapNode n)
|
||||
catch(InvalidPositionException &e)
|
||||
{}
|
||||
|
||||
for(core::map<v3s16, MapBlock * >::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<v3s16, MapBlock * >::iterator
|
||||
i = modified_blocks.begin();
|
||||
i != modified_blocks.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
addUpdateMeshTaskWithEdge(p);
|
||||
addUpdateMeshTaskWithEdge(i->first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2373,7 +2454,7 @@ ClientActiveObject * Client::getSelectedActiveObject(
|
||||
core::line3d<f32> shootline_on_map
|
||||
)
|
||||
{
|
||||
core::array<DistanceSortedActiveObject> objects;
|
||||
std::vector<DistanceSortedActiveObject> objects;
|
||||
|
||||
m_env.getActiveObjects(from_pos_f_on_map, max_d, objects);
|
||||
|
||||
@ -2381,7 +2462,7 @@ ClientActiveObject * Client::getSelectedActiveObject(
|
||||
|
||||
// Sort them.
|
||||
// After this, the closest object is the first in the array.
|
||||
objects.sort();
|
||||
std::sort(objects.begin(), objects.end());
|
||||
|
||||
for(u32 i=0; i<objects.size(); i++)
|
||||
{
|
||||
@ -2420,13 +2501,13 @@ void Client::printDebugInfo(std::ostream &os)
|
||||
<<std::endl;*/
|
||||
}
|
||||
|
||||
core::list<std::wstring> Client::getConnectedPlayerNames()
|
||||
std::list<std::wstring> Client::getConnectedPlayerNames()
|
||||
{
|
||||
core::list<Player*> players = m_env.getPlayers(true);
|
||||
core::list<std::wstring> playerNames;
|
||||
for(core::list<Player*>::Iterator
|
||||
std::list<Player*> players = m_env.getPlayers(true);
|
||||
std::list<std::wstring> playerNames;
|
||||
for(std::list<Player*>::iterator
|
||||
i = players.begin();
|
||||
i != players.end(); i++)
|
||||
i != players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
playerNames.push_back(narrow_to_wide(player->getName()));
|
||||
|
49
src/client.h
49
src/client.h
@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "server.h"
|
||||
#include "particles.h"
|
||||
#include "util/pointedthing.h"
|
||||
#include <algorithm>
|
||||
|
||||
struct MeshMakeData;
|
||||
class MapBlockMesh;
|
||||
@ -142,9 +143,9 @@ public:
|
||||
|
||||
void * Thread();
|
||||
|
||||
core::list<MediaRequest> m_file_requests;
|
||||
std::list<MediaRequest> m_file_requests;
|
||||
MutexedQueue<std::pair<std::string, std::string> > m_file_data;
|
||||
core::list<MediaRequest> m_failed;
|
||||
std::list<MediaRequest> m_failed;
|
||||
std::string m_remote_url;
|
||||
IGameDef *m_gamedef;
|
||||
};
|
||||
@ -156,7 +157,10 @@ enum ClientEventType
|
||||
CE_PLAYER_FORCE_MOVE,
|
||||
CE_DEATHSCREEN,
|
||||
CE_TEXTURES_UPDATED,
|
||||
CE_SHOW_FORMSPEC
|
||||
CE_SHOW_FORMSPEC,
|
||||
CE_SPAWN_PARTICLE,
|
||||
CE_ADD_PARTICLESPAWNER,
|
||||
CE_DELETE_PARTICLESPAWNER
|
||||
};
|
||||
|
||||
struct ClientEvent
|
||||
@ -184,6 +188,35 @@ struct ClientEvent
|
||||
} show_formspec;
|
||||
struct{
|
||||
} textures_updated;
|
||||
struct{
|
||||
v3f *pos;
|
||||
v3f *vel;
|
||||
v3f *acc;
|
||||
f32 expirationtime;
|
||||
f32 size;
|
||||
bool collisiondetection;
|
||||
std::string *texture;
|
||||
} spawn_particle;
|
||||
struct{
|
||||
u16 amount;
|
||||
f32 spawntime;
|
||||
v3f *minpos;
|
||||
v3f *maxpos;
|
||||
v3f *minvel;
|
||||
v3f *maxvel;
|
||||
v3f *minacc;
|
||||
v3f *maxacc;
|
||||
f32 minexptime;
|
||||
f32 maxexptime;
|
||||
f32 minsize;
|
||||
f32 maxsize;
|
||||
bool collisiondetection;
|
||||
std::string *texture;
|
||||
u32 id;
|
||||
} add_particlespawner;
|
||||
struct{
|
||||
u32 id;
|
||||
} delete_particlespawner;
|
||||
};
|
||||
};
|
||||
|
||||
@ -282,7 +315,7 @@ public:
|
||||
// Prints a line or two of info
|
||||
void printDebugInfo(std::ostream &os);
|
||||
|
||||
core::list<std::wstring> getConnectedPlayerNames();
|
||||
std::list<std::wstring> getConnectedPlayerNames();
|
||||
|
||||
float getAnimationTime();
|
||||
|
||||
@ -347,7 +380,7 @@ private:
|
||||
// Insert a media file appropriately into the appropriate manager
|
||||
bool loadMedia(const std::string &data, const std::string &filename);
|
||||
|
||||
void request_media(const core::list<MediaRequest> &file_requests);
|
||||
void request_media(const std::list<MediaRequest> &file_requests);
|
||||
|
||||
// Virtual methods from con::PeerHandler
|
||||
void peerAdded(con::Peer *peer);
|
||||
@ -377,7 +410,7 @@ private:
|
||||
MtEventManager *m_event;
|
||||
|
||||
MeshUpdateThread m_mesh_update_thread;
|
||||
core::list<MediaFetchThread*> m_media_fetch_threads;
|
||||
std::list<MediaFetchThread*> m_media_fetch_threads;
|
||||
ClientEnvironment m_env;
|
||||
con::Connection m_con;
|
||||
IrrlichtDevice *m_device;
|
||||
@ -387,7 +420,7 @@ private:
|
||||
bool m_inventory_updated;
|
||||
Inventory *m_inventory_from_server;
|
||||
float m_inventory_from_server_age;
|
||||
core::map<v3s16, bool> m_active_blocks;
|
||||
std::set<v3s16> m_active_blocks;
|
||||
PacketCounter m_packetcounter;
|
||||
// Block mesh animation parameters
|
||||
float m_animation_time;
|
||||
@ -405,7 +438,7 @@ private:
|
||||
Queue<ClientEvent> m_client_event_queue;
|
||||
FileCache m_media_cache;
|
||||
// Mapping from media file name to SHA1 checksum
|
||||
core::map<std::string, std::string> m_media_name_sha1_map;
|
||||
std::map<std::string, std::string> m_media_name_sha1_map;
|
||||
bool m_media_receive_started;
|
||||
u32 m_media_count;
|
||||
u32 m_media_received_count;
|
||||
|
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "profiler.h"
|
||||
#include "settings.h"
|
||||
#include "util/mathconstants.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@ -83,7 +84,7 @@ MapSector * ClientMap::emergeSector(v2s16 p2d)
|
||||
|
||||
{
|
||||
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||
m_sectors.insert(p2d, sector);
|
||||
m_sectors[p2d] = sector;
|
||||
}
|
||||
|
||||
return sector;
|
||||
@ -164,11 +165,11 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = m_drawlist.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<v3s16, MapBlock*>::iterator
|
||||
i = m_drawlist.begin();
|
||||
i != m_drawlist.end(); ++i)
|
||||
{
|
||||
MapBlock *block = i.getNode()->getValue();
|
||||
MapBlock *block = i->second;
|
||||
block->refDrop();
|
||||
}
|
||||
m_drawlist.clear();
|
||||
@ -215,11 +216,11 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||
// Blocks from which stuff was actually drawn
|
||||
//u32 blocks_without_stuff = 0;
|
||||
|
||||
for(core::map<v2s16, MapSector*>::Iterator
|
||||
si = m_sectors.getIterator();
|
||||
si.atEnd() == false; si++)
|
||||
for(std::map<v2s16, MapSector*>::iterator
|
||||
si = m_sectors.begin();
|
||||
si != m_sectors.end(); ++si)
|
||||
{
|
||||
MapSector *sector = si.getNode()->getValue();
|
||||
MapSector *sector = si->second;
|
||||
v2s16 sp = sector->getPos();
|
||||
|
||||
if(m_control.range_all == false)
|
||||
@ -231,7 +232,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||
continue;
|
||||
}
|
||||
|
||||
core::list< MapBlock * > sectorblocks;
|
||||
std::list< MapBlock * > sectorblocks;
|
||||
sector->getBlocks(sectorblocks);
|
||||
|
||||
/*
|
||||
@ -240,7 +241,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||
|
||||
u32 sector_blocks_drawn = 0;
|
||||
|
||||
core::list< MapBlock * >::Iterator i;
|
||||
std::list< MapBlock * >::iterator i;
|
||||
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
|
||||
{
|
||||
MapBlock *block = *i;
|
||||
@ -350,7 +351,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||
} // foreach sectorblocks
|
||||
|
||||
if(sector_blocks_drawn != 0)
|
||||
m_last_drawn_sectors[sp] = true;
|
||||
m_last_drawn_sectors.insert(sp);
|
||||
}
|
||||
|
||||
m_control.blocks_would_have_drawn = blocks_would_have_drawn;
|
||||
@ -368,12 +369,12 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||
struct MeshBufList
|
||||
{
|
||||
video::SMaterial m;
|
||||
core::list<scene::IMeshBuffer*> bufs;
|
||||
std::list<scene::IMeshBuffer*> bufs;
|
||||
};
|
||||
|
||||
struct MeshBufListList
|
||||
{
|
||||
core::list<MeshBufList> lists;
|
||||
std::list<MeshBufList> lists;
|
||||
|
||||
void clear()
|
||||
{
|
||||
@ -382,8 +383,8 @@ struct MeshBufListList
|
||||
|
||||
void add(scene::IMeshBuffer *buf)
|
||||
{
|
||||
for(core::list<MeshBufList>::Iterator i = lists.begin();
|
||||
i != lists.end(); i++){
|
||||
for(std::list<MeshBufList>::iterator i = lists.begin();
|
||||
i != lists.end(); ++i){
|
||||
MeshBufList &l = *i;
|
||||
if(l.m == buf->getMaterial()){
|
||||
l.bufs.push_back(buf);
|
||||
@ -487,11 +488,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
|
||||
MeshBufListList drawbufs;
|
||||
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = m_drawlist.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<v3s16, MapBlock*>::iterator
|
||||
i = m_drawlist.begin();
|
||||
i != m_drawlist.end(); ++i)
|
||||
{
|
||||
MapBlock *block = i.getNode()->getValue();
|
||||
MapBlock *block = i->second;
|
||||
|
||||
// If the mesh of the block happened to get deleted, ignore it
|
||||
if(block->mesh == NULL)
|
||||
@ -569,11 +570,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
}
|
||||
}
|
||||
|
||||
core::list<MeshBufList> &lists = drawbufs.lists;
|
||||
std::list<MeshBufList> &lists = drawbufs.lists;
|
||||
|
||||
int timecheck_counter = 0;
|
||||
for(core::list<MeshBufList>::Iterator i = lists.begin();
|
||||
i != lists.end(); i++)
|
||||
for(std::list<MeshBufList>::iterator i = lists.begin();
|
||||
i != lists.end(); ++i)
|
||||
{
|
||||
{
|
||||
timecheck_counter++;
|
||||
@ -595,8 +596,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
|
||||
driver->setMaterial(list.m);
|
||||
|
||||
for(core::list<scene::IMeshBuffer*>::Iterator j = list.bufs.begin();
|
||||
j != list.bufs.end(); j++)
|
||||
for(std::list<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
|
||||
j != list.bufs.end(); ++j)
|
||||
{
|
||||
scene::IMeshBuffer *buf = *j;
|
||||
driver->drawMeshBuffer(buf);
|
||||
@ -769,7 +770,7 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
|
||||
float sunlight_min_d = max_d*0.8;
|
||||
if(sunlight_min_d > 35*BS)
|
||||
sunlight_min_d = 35*BS;
|
||||
core::array<int> values;
|
||||
std::vector<int> values;
|
||||
for(u32 i=0; i<sizeof(z_directions)/sizeof(*z_directions); i++){
|
||||
v3f z_dir = z_directions[i];
|
||||
z_dir.normalize();
|
||||
@ -798,7 +799,7 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
|
||||
}
|
||||
int brightness_sum = 0;
|
||||
int brightness_count = 0;
|
||||
values.sort();
|
||||
std::sort(values.begin(), values.end());
|
||||
u32 num_values_to_use = values.size();
|
||||
if(num_values_to_use >= 10)
|
||||
num_values_to_use -= num_values_to_use/2;
|
||||
|
@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "map.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
struct MapDrawControl
|
||||
{
|
||||
@ -128,7 +130,7 @@ public:
|
||||
// Check if sector was drawn on last render()
|
||||
bool sectorWasDrawn(v2s16 p)
|
||||
{
|
||||
return (m_last_drawn_sectors.find(p) != NULL);
|
||||
return (m_last_drawn_sectors.find(p) != m_last_drawn_sectors.end());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -143,9 +145,9 @@ private:
|
||||
f32 m_camera_fov;
|
||||
JMutex m_camera_mutex;
|
||||
|
||||
core::map<v3s16, MapBlock*> m_drawlist;
|
||||
std::map<v3s16, MapBlock*> m_drawlist;
|
||||
|
||||
core::map<v2s16, bool> m_last_drawn_sectors;
|
||||
std::set<v2s16> m_last_drawn_sectors;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -43,9 +43,9 @@ ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
|
||||
ClientEnvironment *env)
|
||||
{
|
||||
// Find factory function
|
||||
core::map<u16, Factory>::Node *n;
|
||||
std::map<u16, Factory>::iterator n;
|
||||
n = m_types.find(type);
|
||||
if(n == NULL)
|
||||
if(n == m_types.end())
|
||||
{
|
||||
// If factory is not found, just return.
|
||||
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
||||
@ -53,18 +53,18 @@ ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Factory f = n->getValue();
|
||||
Factory f = n->second;
|
||||
ClientActiveObject *object = (*f)(gamedef, env);
|
||||
return object;
|
||||
}
|
||||
|
||||
void ClientActiveObject::registerType(u16 type, Factory f)
|
||||
{
|
||||
core::map<u16, Factory>::Node *n;
|
||||
std::map<u16, Factory>::iterator n;
|
||||
n = m_types.find(type);
|
||||
if(n)
|
||||
if(n != m_types.end())
|
||||
return;
|
||||
m_types.insert(type, f);
|
||||
m_types[type] = f;
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "activeobject.h"
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
|
||||
@ -96,7 +97,7 @@ protected:
|
||||
ClientEnvironment *m_env;
|
||||
private:
|
||||
// Used for creating objects based on type
|
||||
static core::map<u16, Factory> m_types;
|
||||
static std::map<u16, Factory> m_types;
|
||||
};
|
||||
|
||||
struct DistanceSortedActiveObject
|
||||
@ -110,7 +111,7 @@ struct DistanceSortedActiveObject
|
||||
d = a_d;
|
||||
}
|
||||
|
||||
bool operator < (DistanceSortedActiveObject &other)
|
||||
bool operator < (const DistanceSortedActiveObject &other) const
|
||||
{
|
||||
return d < other.d;
|
||||
}
|
||||
|
@ -79,9 +79,18 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
|
||||
Serialization format changes
|
||||
PROTOCOL_VERSION 16:
|
||||
TOCLIENT_SHOW_FORMSPEC
|
||||
PROTOCOL_VERSION 17:
|
||||
Serialization format change: include backface_culling flag in TileDef
|
||||
Added rightclickable field in nodedef
|
||||
TOCLIENT_SPAWN_PARTICLE
|
||||
TOCLIENT_ADD_PARTICLESPAWNER
|
||||
TOCLIENT_DELETE_PARTICLESPAWNER
|
||||
PROTOCOL_VERSION 18:
|
||||
damageGroups added to ToolCapabilities
|
||||
sound_place added to ItemDefinition
|
||||
*/
|
||||
|
||||
#define LATEST_PROTOCOL_VERSION 16
|
||||
#define LATEST_PROTOCOL_VERSION 18
|
||||
|
||||
// Server's supported network protocol range
|
||||
#define SERVER_PROTOCOL_VERSION_MIN 13
|
||||
@ -356,6 +365,7 @@ enum ToClientCommand
|
||||
u8[len] name
|
||||
[2] serialized inventory
|
||||
*/
|
||||
|
||||
TOCLIENT_SHOW_FORMSPEC = 0x44,
|
||||
/*
|
||||
[0] u16 command
|
||||
@ -381,6 +391,46 @@ enum ToClientCommand
|
||||
f1000 movement_liquid_sink
|
||||
f1000 movement_gravity
|
||||
*/
|
||||
|
||||
TOCLIENT_SPAWN_PARTICLE = 0x46,
|
||||
/*
|
||||
u16 command
|
||||
v3f1000 pos
|
||||
v3f1000 velocity
|
||||
v3f1000 acceleration
|
||||
f1000 expirationtime
|
||||
f1000 size
|
||||
u8 bool collisiondetection
|
||||
u32 len
|
||||
u8[len] texture
|
||||
*/
|
||||
|
||||
TOCLIENT_ADD_PARTICLESPAWNER = 0x47,
|
||||
/*
|
||||
u16 command
|
||||
u16 amount
|
||||
f1000 spawntime
|
||||
v3f1000 minpos
|
||||
v3f1000 maxpos
|
||||
v3f1000 minvel
|
||||
v3f1000 maxvel
|
||||
v3f1000 minacc
|
||||
v3f1000 maxacc
|
||||
f1000 minexptime
|
||||
f1000 maxexptime
|
||||
f1000 minsize
|
||||
f1000 maxsize
|
||||
u8 bool collisiondetection
|
||||
u32 len
|
||||
u8[len] texture
|
||||
u32 id
|
||||
*/
|
||||
|
||||
TOCLIENT_DELETE_PARTICLESPAWNER = 0x48,
|
||||
/*
|
||||
u16 command
|
||||
u32 id
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
@ -29,7 +29,8 @@ Clouds::Clouds(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id,
|
||||
u32 seed
|
||||
u32 seed,
|
||||
s16 cloudheight
|
||||
):
|
||||
scene::ISceneNode(parent, mgr, id),
|
||||
m_seed(seed),
|
||||
@ -45,7 +46,8 @@ Clouds::Clouds(
|
||||
//m_material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
|
||||
m_cloud_y = BS * g_settings->getS16("cloud_height");
|
||||
m_cloud_y = BS * (cloudheight ? cloudheight :
|
||||
g_settings->getS16("cloud_height"));
|
||||
|
||||
m_box = core::aabbox3d<f32>(-BS*1000000,m_cloud_y-BS,-BS*1000000,
|
||||
BS*1000000,m_cloud_y+BS,BS*1000000);
|
||||
|
@ -30,7 +30,8 @@ public:
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id,
|
||||
u32 seed
|
||||
u32 seed,
|
||||
s16 cloudheight=0
|
||||
);
|
||||
|
||||
~Clouds();
|
||||
|
@ -23,7 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "log.h"
|
||||
#include "environment.h"
|
||||
#include "serverobject.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "util/timetaker.h"
|
||||
#include "main.h" // g_profiler
|
||||
#include "profiler.h"
|
||||
@ -186,11 +189,12 @@ bool wouldCollideWithCeiling(
|
||||
}
|
||||
|
||||
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f)
|
||||
{
|
||||
Map *map = &env->getMap();
|
||||
//TimeTaker tt("collisionMoveSimple");
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
|
||||
|
||||
@ -215,6 +219,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
std::vector<aabb3f> cboxes;
|
||||
std::vector<bool> is_unloaded;
|
||||
std::vector<bool> is_step_up;
|
||||
std::vector<bool> is_object;
|
||||
std::vector<int> bouncy_values;
|
||||
std::vector<v3s16> node_positions;
|
||||
{
|
||||
@ -256,6 +261,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
is_step_up.push_back(false);
|
||||
bouncy_values.push_back(n_bouncy_value);
|
||||
node_positions.push_back(p);
|
||||
is_object.push_back(false);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
@ -267,14 +273,72 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
is_step_up.push_back(false);
|
||||
bouncy_values.push_back(0);
|
||||
node_positions.push_back(p);
|
||||
is_object.push_back(false);
|
||||
}
|
||||
}
|
||||
} // tt2
|
||||
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
|
||||
//TimeTaker tt3("collisionMoveSimple collect object boxes");
|
||||
|
||||
/* add object boxes to cboxes */
|
||||
|
||||
|
||||
std::list<ActiveObject*> objects;
|
||||
#ifndef SERVER
|
||||
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
|
||||
if (c_env != 0)
|
||||
{
|
||||
f32 distance = speed_f.getLength();
|
||||
std::vector<DistanceSortedActiveObject> clientobjects;
|
||||
c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects);
|
||||
for (int i=0; i < clientobjects.size(); i++)
|
||||
{
|
||||
objects.push_back((ActiveObject*)clientobjects[i].obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
||||
if (s_env != 0)
|
||||
{
|
||||
f32 distance = speed_f.getLength();
|
||||
std::set<u16> s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5);
|
||||
for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++)
|
||||
{
|
||||
ServerActiveObject *current = s_env->getActiveObject(*iter);
|
||||
objects.push_back((ActiveObject*)current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::list<ActiveObject*>::const_iterator iter = objects.begin();iter != objects.end(); ++iter)
|
||||
{
|
||||
ActiveObject *object = *iter;
|
||||
|
||||
if (object != NULL)
|
||||
{
|
||||
aabb3f object_collisionbox;
|
||||
if (object->getCollisionBox(&object_collisionbox))
|
||||
{
|
||||
cboxes.push_back(object_collisionbox);
|
||||
is_unloaded.push_back(false);
|
||||
is_step_up.push_back(false);
|
||||
bouncy_values.push_back(0);
|
||||
node_positions.push_back(v3s16(0,0,0));
|
||||
is_object.push_back(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} //tt3
|
||||
|
||||
assert(cboxes.size() == is_unloaded.size());
|
||||
assert(cboxes.size() == is_step_up.size());
|
||||
assert(cboxes.size() == bouncy_values.size());
|
||||
assert(cboxes.size() == node_positions.size());
|
||||
assert(cboxes.size() == is_object.size());
|
||||
|
||||
/*
|
||||
Collision detection
|
||||
@ -386,7 +450,11 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
is_collision = false;
|
||||
|
||||
CollisionInfo info;
|
||||
info.type = COLLISION_NODE;
|
||||
if (is_object[nearest_boxindex]) {
|
||||
info.type = COLLISION_OBJECT;
|
||||
}
|
||||
else
|
||||
info.type = COLLISION_NODE;
|
||||
info.node_p = node_positions[nearest_boxindex];
|
||||
info.bouncy = bouncy;
|
||||
info.old_speed = speed_f;
|
||||
|
@ -25,10 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
class Environment;
|
||||
|
||||
enum CollisionType
|
||||
{
|
||||
COLLISION_NODE
|
||||
COLLISION_NODE,
|
||||
COLLISION_OBJECT,
|
||||
};
|
||||
|
||||
struct CollisionInfo
|
||||
@ -65,7 +67,7 @@ struct collisionMoveResult
|
||||
};
|
||||
|
||||
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
|
||||
f32 pos_max_d, const aabb3f &box_0,
|
||||
f32 stepheight, f32 dtime,
|
||||
v3f &pos_f, v3f &speed_f, v3f &accel_f);
|
||||
|
@ -76,19 +76,20 @@ SharedBuffer<u8> makeOriginalPacket(
|
||||
return b;
|
||||
}
|
||||
|
||||
core::list<SharedBuffer<u8> > makeSplitPacket(
|
||||
std::list<SharedBuffer<u8> > makeSplitPacket(
|
||||
SharedBuffer<u8> data,
|
||||
u32 chunksize_max,
|
||||
u16 seqnum)
|
||||
{
|
||||
// Chunk packets, containing the TYPE_SPLIT header
|
||||
core::list<SharedBuffer<u8> > chunks;
|
||||
std::list<SharedBuffer<u8> > chunks;
|
||||
|
||||
u32 chunk_header_size = 7;
|
||||
u32 maximum_data_size = chunksize_max - chunk_header_size;
|
||||
u32 start = 0;
|
||||
u32 end = 0;
|
||||
u32 chunk_num = 0;
|
||||
u16 chunk_count = 0;
|
||||
do{
|
||||
end = start + maximum_data_size - 1;
|
||||
if(end > data.getSize() - 1)
|
||||
@ -106,16 +107,15 @@ core::list<SharedBuffer<u8> > makeSplitPacket(
|
||||
memcpy(&chunk[chunk_header_size], &data[start], payload_size);
|
||||
|
||||
chunks.push_back(chunk);
|
||||
chunk_count++;
|
||||
|
||||
start = end + 1;
|
||||
chunk_num++;
|
||||
}
|
||||
while(end != data.getSize() - 1);
|
||||
|
||||
u16 chunk_count = chunks.getSize();
|
||||
|
||||
core::list<SharedBuffer<u8> >::Iterator i = chunks.begin();
|
||||
for(; i != chunks.end(); i++)
|
||||
for(std::list<SharedBuffer<u8> >::iterator i = chunks.begin();
|
||||
i != chunks.end(); ++i)
|
||||
{
|
||||
// Write chunk_count
|
||||
writeU16(&((*i)[3]), chunk_count);
|
||||
@ -124,13 +124,13 @@ core::list<SharedBuffer<u8> > makeSplitPacket(
|
||||
return chunks;
|
||||
}
|
||||
|
||||
core::list<SharedBuffer<u8> > makeAutoSplitPacket(
|
||||
std::list<SharedBuffer<u8> > makeAutoSplitPacket(
|
||||
SharedBuffer<u8> data,
|
||||
u32 chunksize_max,
|
||||
u16 &split_seqnum)
|
||||
{
|
||||
u32 original_header_size = 1;
|
||||
core::list<SharedBuffer<u8> > list;
|
||||
std::list<SharedBuffer<u8> > list;
|
||||
if(data.getSize() + original_header_size > chunksize_max)
|
||||
{
|
||||
list = makeSplitPacket(data, chunksize_max, split_seqnum);
|
||||
@ -170,11 +170,13 @@ SharedBuffer<u8> makeReliablePacket(
|
||||
ReliablePacketBuffer
|
||||
*/
|
||||
|
||||
ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0) {}
|
||||
|
||||
void ReliablePacketBuffer::print()
|
||||
{
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
for(; i != m_list.end(); i++)
|
||||
for(std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
i != m_list.end();
|
||||
++i)
|
||||
{
|
||||
u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1]));
|
||||
dout_con<<s<<" ";
|
||||
@ -186,13 +188,12 @@ bool ReliablePacketBuffer::empty()
|
||||
}
|
||||
u32 ReliablePacketBuffer::size()
|
||||
{
|
||||
return m_list.getSize();
|
||||
return m_list_size;
|
||||
}
|
||||
RPBSearchResult ReliablePacketBuffer::findPacket(u16 seqnum)
|
||||
{
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
for(; i != m_list.end(); i++)
|
||||
std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
for(; i != m_list.end(); ++i)
|
||||
{
|
||||
u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1]));
|
||||
/*dout_con<<"findPacket(): finding seqnum="<<seqnum
|
||||
@ -218,8 +219,8 @@ BufferedPacket ReliablePacketBuffer::popFirst()
|
||||
if(empty())
|
||||
throw NotFoundException("Buffer is empty");
|
||||
BufferedPacket p = *m_list.begin();
|
||||
core::list<BufferedPacket>::Iterator i = m_list.begin();
|
||||
m_list.erase(i);
|
||||
m_list.erase(m_list.begin());
|
||||
--m_list_size;
|
||||
return p;
|
||||
}
|
||||
BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum)
|
||||
@ -231,6 +232,7 @@ BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum)
|
||||
}
|
||||
BufferedPacket p = *r;
|
||||
m_list.erase(r);
|
||||
--m_list_size;
|
||||
return p;
|
||||
}
|
||||
void ReliablePacketBuffer::insert(BufferedPacket &p)
|
||||
@ -240,6 +242,7 @@ void ReliablePacketBuffer::insert(BufferedPacket &p)
|
||||
assert(type == TYPE_RELIABLE);
|
||||
u16 seqnum = readU16(&p.data[BASE_HEADER_SIZE+1]);
|
||||
|
||||
++m_list_size;
|
||||
// Find the right place for the packet and insert it there
|
||||
|
||||
// If list is empty, just add it
|
||||
@ -250,12 +253,12 @@ void ReliablePacketBuffer::insert(BufferedPacket &p)
|
||||
return;
|
||||
}
|
||||
// Otherwise find the right place
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
// Find the first packet in the list which has a higher seqnum
|
||||
for(; i != m_list.end(); i++){
|
||||
for(; i != m_list.end(); ++i){
|
||||
u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1]));
|
||||
if(s == seqnum){
|
||||
--m_list_size;
|
||||
throw AlreadyExistsException("Same seqnum in list");
|
||||
}
|
||||
if(seqnum_higher(s, seqnum)){
|
||||
@ -271,14 +274,14 @@ void ReliablePacketBuffer::insert(BufferedPacket &p)
|
||||
return;
|
||||
}
|
||||
// Insert before i
|
||||
m_list.insert_before(i, p);
|
||||
m_list.insert(i, p);
|
||||
}
|
||||
|
||||
void ReliablePacketBuffer::incrementTimeouts(float dtime)
|
||||
{
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
for(; i != m_list.end(); i++){
|
||||
for(std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
i != m_list.end(); ++i)
|
||||
{
|
||||
i->time += dtime;
|
||||
i->totaltime += dtime;
|
||||
}
|
||||
@ -286,9 +289,9 @@ void ReliablePacketBuffer::incrementTimeouts(float dtime)
|
||||
|
||||
void ReliablePacketBuffer::resetTimedOuts(float timeout)
|
||||
{
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
for(; i != m_list.end(); i++){
|
||||
for(std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
i != m_list.end(); ++i)
|
||||
{
|
||||
if(i->time >= timeout)
|
||||
i->time = 0.0;
|
||||
}
|
||||
@ -296,21 +299,20 @@ void ReliablePacketBuffer::resetTimedOuts(float timeout)
|
||||
|
||||
bool ReliablePacketBuffer::anyTotaltimeReached(float timeout)
|
||||
{
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
for(; i != m_list.end(); i++){
|
||||
for(std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
i != m_list.end(); ++i)
|
||||
{
|
||||
if(i->totaltime >= timeout)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
core::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout)
|
||||
std::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout)
|
||||
{
|
||||
core::list<BufferedPacket> timed_outs;
|
||||
core::list<BufferedPacket>::Iterator i;
|
||||
i = m_list.begin();
|
||||
for(; i != m_list.end(); i++)
|
||||
std::list<BufferedPacket> timed_outs;
|
||||
for(std::list<BufferedPacket>::iterator i = m_list.begin();
|
||||
i != m_list.end(); ++i)
|
||||
{
|
||||
if(i->time >= timeout)
|
||||
timed_outs.push_back(*i);
|
||||
@ -324,11 +326,10 @@ core::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout)
|
||||
|
||||
IncomingSplitBuffer::~IncomingSplitBuffer()
|
||||
{
|
||||
core::map<u16, IncomingSplitPacket*>::Iterator i;
|
||||
i = m_buf.getIterator();
|
||||
for(; i.atEnd() == false; i++)
|
||||
for(std::map<u16, IncomingSplitPacket*>::iterator i = m_buf.begin();
|
||||
i != m_buf.end(); ++i)
|
||||
{
|
||||
delete i.getNode()->getValue();
|
||||
delete i->second;
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -346,7 +347,7 @@ SharedBuffer<u8> IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable)
|
||||
u16 chunk_num = readU16(&p.data[BASE_HEADER_SIZE+5]);
|
||||
|
||||
// Add if doesn't exist
|
||||
if(m_buf.find(seqnum) == NULL)
|
||||
if(m_buf.find(seqnum) == m_buf.end())
|
||||
{
|
||||
IncomingSplitPacket *sp = new IncomingSplitPacket();
|
||||
sp->chunk_count = chunk_count;
|
||||
@ -369,7 +370,7 @@ SharedBuffer<u8> IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable)
|
||||
// If chunk already exists, ignore it.
|
||||
// Sometimes two identical packets may arrive when there is network
|
||||
// lag and the server re-sends stuff.
|
||||
if(sp->chunks.find(chunk_num) != NULL)
|
||||
if(sp->chunks.find(chunk_num) != sp->chunks.end())
|
||||
return SharedBuffer<u8>();
|
||||
|
||||
// Cut chunk data out of packet
|
||||
@ -386,11 +387,10 @@ SharedBuffer<u8> IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable)
|
||||
|
||||
// Calculate total size
|
||||
u32 totalsize = 0;
|
||||
core::map<u16, SharedBuffer<u8> >::Iterator i;
|
||||
i = sp->chunks.getIterator();
|
||||
for(; i.atEnd() == false; i++)
|
||||
for(std::map<u16, SharedBuffer<u8> >::iterator i = sp->chunks.begin();
|
||||
i != sp->chunks.end(); ++i)
|
||||
{
|
||||
totalsize += i.getNode()->getValue().getSize();
|
||||
totalsize += i->second.getSize();
|
||||
}
|
||||
|
||||
SharedBuffer<u8> fulldata(totalsize);
|
||||
@ -407,34 +407,32 @@ SharedBuffer<u8> IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable)
|
||||
}
|
||||
|
||||
// Remove sp from buffer
|
||||
m_buf.remove(seqnum);
|
||||
m_buf.erase(seqnum);
|
||||
delete sp;
|
||||
|
||||
return fulldata;
|
||||
}
|
||||
void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout)
|
||||
{
|
||||
core::list<u16> remove_queue;
|
||||
core::map<u16, IncomingSplitPacket*>::Iterator i;
|
||||
i = m_buf.getIterator();
|
||||
for(; i.atEnd() == false; i++)
|
||||
std::list<u16> remove_queue;
|
||||
for(std::map<u16, IncomingSplitPacket*>::iterator i = m_buf.begin();
|
||||
i != m_buf.end(); ++i)
|
||||
{
|
||||
IncomingSplitPacket *p = i.getNode()->getValue();
|
||||
IncomingSplitPacket *p = i->second;
|
||||
// Reliable ones are not removed by timeout
|
||||
if(p->reliable == true)
|
||||
continue;
|
||||
p->time += dtime;
|
||||
if(p->time >= timeout)
|
||||
remove_queue.push_back(i.getNode()->getKey());
|
||||
remove_queue.push_back(i->first);
|
||||
}
|
||||
core::list<u16>::Iterator j;
|
||||
j = remove_queue.begin();
|
||||
for(; j != remove_queue.end(); j++)
|
||||
for(std::list<u16>::iterator j = remove_queue.begin();
|
||||
j != remove_queue.end(); ++j)
|
||||
{
|
||||
dout_con<<"NOTE: Removing timed out unreliable split packet"
|
||||
<<std::endl;
|
||||
delete m_buf[*j];
|
||||
m_buf.remove(*j);
|
||||
m_buf.erase(*j);
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,12 +554,11 @@ Connection::~Connection()
|
||||
{
|
||||
stop();
|
||||
// Delete peers
|
||||
for(core::map<u16, Peer*>::Iterator
|
||||
j = m_peers.getIterator();
|
||||
j.atEnd() == false; j++)
|
||||
for(std::map<u16, Peer*>::iterator
|
||||
j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
delete peer;
|
||||
delete j->second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,7 +588,7 @@ void * Connection::Thread()
|
||||
|
||||
runTimeouts(dtime);
|
||||
|
||||
while(m_command_queue.size() != 0){
|
||||
while(!m_command_queue.empty()){
|
||||
ConnectionCommand c = m_command_queue.pop_front();
|
||||
processCommand(c);
|
||||
}
|
||||
@ -648,18 +645,18 @@ void Connection::processCommand(ConnectionCommand &c)
|
||||
|
||||
void Connection::send(float dtime)
|
||||
{
|
||||
for(core::map<u16, Peer*>::Iterator
|
||||
j = m_peers.getIterator();
|
||||
j.atEnd() == false; j++)
|
||||
for(std::map<u16, Peer*>::iterator
|
||||
j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
peer->m_sendtime_accu += dtime;
|
||||
peer->m_num_sent = 0;
|
||||
peer->m_max_num_sent = peer->m_sendtime_accu *
|
||||
peer->m_max_packets_per_second;
|
||||
}
|
||||
Queue<OutgoingPacket> postponed_packets;
|
||||
while(m_outgoing_queue.size() != 0){
|
||||
while(!m_outgoing_queue.empty()){
|
||||
OutgoingPacket packet = m_outgoing_queue.pop_front();
|
||||
Peer *peer = getPeerNoEx(packet.peer_id);
|
||||
if(!peer)
|
||||
@ -674,14 +671,14 @@ void Connection::send(float dtime)
|
||||
postponed_packets.push_back(packet);
|
||||
}
|
||||
}
|
||||
while(postponed_packets.size() != 0){
|
||||
while(!postponed_packets.empty()){
|
||||
m_outgoing_queue.push_back(postponed_packets.pop_front());
|
||||
}
|
||||
for(core::map<u16, Peer*>::Iterator
|
||||
j = m_peers.getIterator();
|
||||
j.atEnd() == false; j++)
|
||||
for(std::map<u16, Peer*>::iterator
|
||||
j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
peer->m_sendtime_accu -= (float)peer->m_num_sent /
|
||||
peer->m_max_packets_per_second;
|
||||
if(peer->m_sendtime_accu > 10. / peer->m_max_packets_per_second)
|
||||
@ -751,11 +748,11 @@ void Connection::receive()
|
||||
Allow only entries that have has_sent_with_id==false.
|
||||
*/
|
||||
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
std::map<u16, Peer*>::iterator j;
|
||||
j = m_peers.begin();
|
||||
for(; j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
if(peer->has_sent_with_id)
|
||||
continue;
|
||||
if(peer->address == sender)
|
||||
@ -766,14 +763,14 @@ void Connection::receive()
|
||||
If no peer was found with the same address and port,
|
||||
we shall assume it is a new peer and create an entry.
|
||||
*/
|
||||
if(j.atEnd())
|
||||
if(j == m_peers.end())
|
||||
{
|
||||
// Pass on to adding the peer
|
||||
}
|
||||
// Else: A peer was found.
|
||||
else
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
peer_id = peer->id;
|
||||
PrintInfo(derr_con);
|
||||
derr_con<<"WARNING: Assuming unknown peer to be "
|
||||
@ -797,7 +794,7 @@ void Connection::receive()
|
||||
for(;;)
|
||||
{
|
||||
// Check if exists
|
||||
if(m_peers.find(peer_id_new) == NULL)
|
||||
if(m_peers.find(peer_id_new) == m_peers.end())
|
||||
break;
|
||||
// Check for overflow
|
||||
if(peer_id_new == 65535){
|
||||
@ -817,7 +814,7 @@ void Connection::receive()
|
||||
|
||||
// Create a peer
|
||||
Peer *peer = new Peer(peer_id_new, sender);
|
||||
m_peers.insert(peer->id, peer);
|
||||
m_peers[peer->id] = peer;
|
||||
|
||||
// Create peer addition event
|
||||
ConnectionEvent e;
|
||||
@ -837,9 +834,9 @@ void Connection::receive()
|
||||
// Go on and process whatever it sent
|
||||
}
|
||||
|
||||
core::map<u16, Peer*>::Node *node = m_peers.find(peer_id);
|
||||
std::map<u16, Peer*>::iterator node = m_peers.find(peer_id);
|
||||
|
||||
if(node == NULL)
|
||||
if(node == m_peers.end())
|
||||
{
|
||||
// Peer not found
|
||||
// This means that the peer id of the sender is not PEER_ID_INEXISTENT
|
||||
@ -849,7 +846,7 @@ void Connection::receive()
|
||||
throw InvalidIncomingDataException("Peer not found (possible timeout)");
|
||||
}
|
||||
|
||||
Peer *peer = node->getValue();
|
||||
Peer *peer = node->second;
|
||||
|
||||
// Validate peer address
|
||||
if(peer->address != sender)
|
||||
@ -902,12 +899,11 @@ void Connection::runTimeouts(float dtime)
|
||||
float congestion_control_min_rate
|
||||
= g_settings->getFloat("congestion_control_min_rate");
|
||||
|
||||
core::list<u16> timeouted_peers;
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
std::list<u16> timeouted_peers;
|
||||
for(std::map<u16, Peer*>::iterator j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
|
||||
// Update congestion control values
|
||||
peer->congestion_control_aim_rtt = congestion_control_aim_rtt;
|
||||
@ -934,8 +930,7 @@ void Connection::runTimeouts(float dtime)
|
||||
float resend_timeout = peer->resend_timeout;
|
||||
for(u16 i=0; i<CHANNEL_COUNT; i++)
|
||||
{
|
||||
core::list<BufferedPacket> timed_outs;
|
||||
core::list<BufferedPacket>::Iterator j;
|
||||
std::list<BufferedPacket> timed_outs;
|
||||
|
||||
Channel *channel = &peer->channels[i];
|
||||
|
||||
@ -966,8 +961,8 @@ void Connection::runTimeouts(float dtime)
|
||||
|
||||
channel->outgoing_reliables.resetTimedOuts(resend_timeout);
|
||||
|
||||
j = timed_outs.begin();
|
||||
for(; j != timed_outs.end(); j++)
|
||||
for(std::list<BufferedPacket>::iterator j = timed_outs.begin();
|
||||
j != timed_outs.end(); ++j)
|
||||
{
|
||||
u16 peer_id = readPeerId(*(j->data));
|
||||
u8 channel = readChannel(*(j->data));
|
||||
@ -1012,8 +1007,8 @@ nextpeer:
|
||||
}
|
||||
|
||||
// Remove timed out peers
|
||||
core::list<u16>::Iterator i = timeouted_peers.begin();
|
||||
for(; i != timeouted_peers.end(); i++)
|
||||
for(std::list<u16>::iterator i = timeouted_peers.begin();
|
||||
i != timeouted_peers.end(); ++i)
|
||||
{
|
||||
PrintInfo(derr_con);
|
||||
derr_con<<"RunTimeouts(): Removing peer "<<(*i)<<std::endl;
|
||||
@ -1041,13 +1036,13 @@ void Connection::connect(Address address)
|
||||
dout_con<<getDesc()<<" connecting to "<<address.serializeString()
|
||||
<<":"<<address.getPort()<<std::endl;
|
||||
|
||||
core::map<u16, Peer*>::Node *node = m_peers.find(PEER_ID_SERVER);
|
||||
if(node != NULL){
|
||||
std::map<u16, Peer*>::iterator node = m_peers.find(PEER_ID_SERVER);
|
||||
if(node != m_peers.end()){
|
||||
throw ConnectionException("Already connected to a server");
|
||||
}
|
||||
|
||||
Peer *peer = new Peer(PEER_ID_SERVER, address);
|
||||
m_peers.insert(peer->id, peer);
|
||||
m_peers[peer->id] = peer;
|
||||
|
||||
// Create event
|
||||
ConnectionEvent e;
|
||||
@ -1072,22 +1067,20 @@ void Connection::disconnect()
|
||||
writeU8(&data[1], CONTROLTYPE_DISCO);
|
||||
|
||||
// Send to all
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
for(std::map<u16, Peer*>::iterator j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
rawSendAsPacket(peer->id, 0, data, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::sendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable)
|
||||
{
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
for(std::map<u16, Peer*>::iterator j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
send(peer->id, channelnum, data, reliable);
|
||||
}
|
||||
}
|
||||
@ -1108,13 +1101,12 @@ void Connection::send(u16 peer_id, u8 channelnum,
|
||||
if(reliable)
|
||||
chunksize_max -= RELIABLE_HEADER_SIZE;
|
||||
|
||||
core::list<SharedBuffer<u8> > originals;
|
||||
std::list<SharedBuffer<u8> > originals;
|
||||
originals = makeAutoSplitPacket(data, chunksize_max,
|
||||
channel->next_outgoing_split_seqnum);
|
||||
|
||||
core::list<SharedBuffer<u8> >::Iterator i;
|
||||
i = originals.begin();
|
||||
for(; i != originals.end(); i++)
|
||||
for(std::list<SharedBuffer<u8> >::iterator i = originals.begin();
|
||||
i != originals.end(); ++i)
|
||||
{
|
||||
SharedBuffer<u8> original = *i;
|
||||
|
||||
@ -1187,40 +1179,39 @@ void Connection::rawSend(const BufferedPacket &packet)
|
||||
|
||||
Peer* Connection::getPeer(u16 peer_id)
|
||||
{
|
||||
core::map<u16, Peer*>::Node *node = m_peers.find(peer_id);
|
||||
std::map<u16, Peer*>::iterator node = m_peers.find(peer_id);
|
||||
|
||||
if(node == NULL){
|
||||
if(node == m_peers.end()){
|
||||
throw PeerNotFoundException("GetPeer: Peer not found (possible timeout)");
|
||||
}
|
||||
|
||||
// Error checking
|
||||
assert(node->getValue()->id == peer_id);
|
||||
assert(node->second->id == peer_id);
|
||||
|
||||
return node->getValue();
|
||||
return node->second;
|
||||
}
|
||||
|
||||
Peer* Connection::getPeerNoEx(u16 peer_id)
|
||||
{
|
||||
core::map<u16, Peer*>::Node *node = m_peers.find(peer_id);
|
||||
std::map<u16, Peer*>::iterator node = m_peers.find(peer_id);
|
||||
|
||||
if(node == NULL){
|
||||
if(node == m_peers.end()){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Error checking
|
||||
assert(node->getValue()->id == peer_id);
|
||||
assert(node->second->id == peer_id);
|
||||
|
||||
return node->getValue();
|
||||
return node->second;
|
||||
}
|
||||
|
||||
core::list<Peer*> Connection::getPeers()
|
||||
std::list<Peer*> Connection::getPeers()
|
||||
{
|
||||
core::list<Peer*> list;
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
std::list<Peer*> list;
|
||||
for(std::map<u16, Peer*>::iterator j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
list.push_back(peer);
|
||||
}
|
||||
return list;
|
||||
@ -1228,11 +1219,10 @@ core::list<Peer*> Connection::getPeers()
|
||||
|
||||
bool Connection::getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst)
|
||||
{
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
for(std::map<u16, Peer*>::iterator j = m_peers.begin();
|
||||
j != m_peers.end(); ++j)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
Peer *peer = j->second;
|
||||
for(u16 i=0; i<CHANNEL_COUNT; i++)
|
||||
{
|
||||
Channel *channel = &peer->channels[i];
|
||||
@ -1538,7 +1528,7 @@ SharedBuffer<u8> Connection::processPacket(Channel *channel,
|
||||
|
||||
bool Connection::deletePeer(u16 peer_id, bool timeout)
|
||||
{
|
||||
if(m_peers.find(peer_id) == NULL)
|
||||
if(m_peers.find(peer_id) == m_peers.end())
|
||||
return false;
|
||||
|
||||
Peer *peer = m_peers[peer_id];
|
||||
@ -1549,7 +1539,7 @@ bool Connection::deletePeer(u16 peer_id, bool timeout)
|
||||
putEvent(e);
|
||||
|
||||
delete m_peers[peer_id];
|
||||
m_peers.remove(peer_id);
|
||||
m_peers.erase(peer_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1557,7 +1547,7 @@ bool Connection::deletePeer(u16 peer_id, bool timeout)
|
||||
|
||||
ConnectionEvent Connection::getEvent()
|
||||
{
|
||||
if(m_event_queue.size() == 0){
|
||||
if(m_event_queue.empty()){
|
||||
ConnectionEvent e;
|
||||
e.type = CONNEVENT_NONE;
|
||||
return e;
|
||||
@ -1602,8 +1592,8 @@ bool Connection::Connected()
|
||||
if(m_peers.size() != 1)
|
||||
return false;
|
||||
|
||||
core::map<u16, Peer*>::Node *node = m_peers.find(PEER_ID_SERVER);
|
||||
if(node == NULL)
|
||||
std::map<u16, Peer*>::iterator node = m_peers.find(PEER_ID_SERVER);
|
||||
if(node == m_peers.end())
|
||||
return false;
|
||||
|
||||
if(m_peer_id == PEER_ID_INEXISTENT)
|
||||
|
@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "util/thread.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
namespace con
|
||||
{
|
||||
@ -142,14 +144,14 @@ SharedBuffer<u8> makeOriginalPacket(
|
||||
SharedBuffer<u8> data);
|
||||
|
||||
// Split data in chunks and add TYPE_SPLIT headers to them
|
||||
core::list<SharedBuffer<u8> > makeSplitPacket(
|
||||
std::list<SharedBuffer<u8> > makeSplitPacket(
|
||||
SharedBuffer<u8> data,
|
||||
u32 chunksize_max,
|
||||
u16 seqnum);
|
||||
|
||||
// Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
|
||||
// Increments split_seqnum if a split packet is made
|
||||
core::list<SharedBuffer<u8> > makeAutoSplitPacket(
|
||||
std::list<SharedBuffer<u8> > makeAutoSplitPacket(
|
||||
SharedBuffer<u8> data,
|
||||
u32 chunksize_max,
|
||||
u16 &split_seqnum);
|
||||
@ -167,7 +169,7 @@ struct IncomingSplitPacket
|
||||
reliable = false;
|
||||
}
|
||||
// Key is chunk number, value is data without headers
|
||||
core::map<u16, SharedBuffer<u8> > chunks;
|
||||
std::map<u16, SharedBuffer<u8> > chunks;
|
||||
u32 chunk_count;
|
||||
float time; // Seconds from adding
|
||||
bool reliable; // If true, isn't deleted on timeout
|
||||
@ -268,12 +270,12 @@ with a buffer in the receiving and transmitting end.
|
||||
for fast access to the smallest one.
|
||||
*/
|
||||
|
||||
typedef core::list<BufferedPacket>::Iterator RPBSearchResult;
|
||||
typedef std::list<BufferedPacket>::iterator RPBSearchResult;
|
||||
|
||||
class ReliablePacketBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
ReliablePacketBuffer();
|
||||
void print();
|
||||
bool empty();
|
||||
u32 size();
|
||||
@ -286,10 +288,11 @@ public:
|
||||
void incrementTimeouts(float dtime);
|
||||
void resetTimedOuts(float timeout);
|
||||
bool anyTotaltimeReached(float timeout);
|
||||
core::list<BufferedPacket> getTimedOuts(float timeout);
|
||||
std::list<BufferedPacket> getTimedOuts(float timeout);
|
||||
|
||||
private:
|
||||
core::list<BufferedPacket> m_list;
|
||||
std::list<BufferedPacket> m_list;
|
||||
u16 m_list_size;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -310,7 +313,7 @@ public:
|
||||
|
||||
private:
|
||||
// Key is seqnum
|
||||
core::map<u16, IncomingSplitPacket*> m_buf;
|
||||
std::map<u16, IncomingSplitPacket*> m_buf;
|
||||
};
|
||||
|
||||
class Connection;
|
||||
@ -589,7 +592,7 @@ private:
|
||||
void rawSend(const BufferedPacket &packet);
|
||||
Peer* getPeer(u16 peer_id);
|
||||
Peer* getPeerNoEx(u16 peer_id);
|
||||
core::list<Peer*> getPeers();
|
||||
std::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.
|
||||
@ -619,7 +622,7 @@ private:
|
||||
UDPSocket m_socket;
|
||||
u16 m_peer_id;
|
||||
|
||||
core::map<u16, Peer*> m_peers;
|
||||
std::map<u16, Peer*> m_peers;
|
||||
JMutex m_peers_mutex;
|
||||
|
||||
// Backwards compatibility
|
||||
|
@ -94,11 +94,22 @@ public:
|
||||
class MakeTreesFromSaplingsABM : public ActiveBlockModifier
|
||||
{
|
||||
private:
|
||||
content_t c_junglesapling;
|
||||
content_t c_dirt;
|
||||
content_t c_dirt_with_grass;
|
||||
|
||||
public:
|
||||
MakeTreesFromSaplingsABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
|
||||
c_junglesapling = nodemgr->getId("junglesapling");
|
||||
c_dirt = nodemgr->getId("mapgen_dirt");
|
||||
c_dirt_with_grass = nodemgr->getId("mapgen_dirt_with_grass");
|
||||
}
|
||||
|
||||
virtual std::set<std::string> getTriggerContents()
|
||||
{
|
||||
std::set<std::string> s;
|
||||
s.insert("sapling");
|
||||
s.insert("junglesapling");
|
||||
return s;
|
||||
}
|
||||
virtual float getTriggerInterval()
|
||||
@ -111,37 +122,46 @@ public:
|
||||
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||
ServerMap *map = &env->getServerMap();
|
||||
|
||||
actionstream<<"A sapling grows into a tree at "
|
||||
<<PP(p)<<std::endl;
|
||||
MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0));
|
||||
if (n_below.getContent() != c_dirt &&
|
||||
n_below.getContent() != c_dirt_with_grass)
|
||||
return;
|
||||
|
||||
bool is_jungle_tree = n.getContent() == c_junglesapling;
|
||||
|
||||
actionstream <<"A " << (is_jungle_tree ? "jungle " : "")
|
||||
<< "sapling grows into a tree at "
|
||||
<< PP(p) << std::endl;
|
||||
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
std::map<v3s16, MapBlock*> modified_blocks;
|
||||
v3s16 tree_p = p;
|
||||
ManualMapVoxelManipulator vmanip(map);
|
||||
v3s16 tree_blockp = getNodeBlockPos(tree_p);
|
||||
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
|
||||
bool is_apple_tree = myrand()%4 == 0;
|
||||
treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef, myrand());
|
||||
|
||||
if (is_jungle_tree) {
|
||||
treegen::make_jungletree(vmanip, tree_p, ndef, myrand());
|
||||
} else {
|
||||
bool is_apple_tree = myrand() % 4 == 0;
|
||||
treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef, myrand());
|
||||
}
|
||||
|
||||
vmanip.blitBackAll(&modified_blocks);
|
||||
|
||||
// update lighting
|
||||
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
||||
}
|
||||
std::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||
lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
|
||||
map->updateLighting(lighting_modified_blocks, 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++)
|
||||
// event.modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
|
||||
for(std::map<v3s16, MapBlock*>::iterator
|
||||
i = modified_blocks.begin();
|
||||
i != modified_blocks.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
event.modified_blocks.insert(p, true);
|
||||
event.modified_blocks.insert(i->first);
|
||||
}
|
||||
map->dispatchEvent(&event);
|
||||
}
|
||||
@ -182,7 +202,7 @@ void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
|
||||
{
|
||||
env->addActiveBlockModifier(new GrowGrassABM());
|
||||
env->addActiveBlockModifier(new RemoveGrassABM());
|
||||
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
|
||||
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef));
|
||||
if (g_settings->getBool("liquid_finite"))
|
||||
env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ struct ToolCapabilities;
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||
std::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||
|
||||
/*
|
||||
SmoothTranslator
|
||||
@ -174,6 +174,7 @@ public:
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) { return false; }
|
||||
private:
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
@ -329,6 +330,7 @@ public:
|
||||
std::string infoText()
|
||||
{return m_infotext;}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) { return false; }
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
@ -643,6 +645,22 @@ public:
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
if (m_prop.physical) {
|
||||
aabb3f retval;
|
||||
//update collision box
|
||||
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
|
||||
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
|
||||
|
||||
toset->MinEdge += m_position;
|
||||
toset->MaxEdge += m_position;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void initialize(const std::string &data)
|
||||
{
|
||||
infostream<<"GenericCAO: Got init data"<<std::endl;
|
||||
@ -1127,8 +1145,7 @@ public:
|
||||
v3f p_pos = m_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&env->getMap(), gamedef,
|
||||
moveresult = collisionMoveSimple(env,env->getGameDef(),
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
|
@ -42,14 +42,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// (compatible with ContentFeatures). If you specified 0,0,1,1
|
||||
// for each face, that would be the same as passing NULL.
|
||||
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||
const TileSpec *tiles, int tilecount,
|
||||
TileSpec *tiles, int tilecount,
|
||||
video::SColor &c, const f32* txc)
|
||||
{
|
||||
assert(tilecount >= 1 && tilecount <= 6);
|
||||
|
||||
v3f min = box.MinEdge;
|
||||
v3f max = box.MaxEdge;
|
||||
|
||||
|
||||
|
||||
|
||||
if(txc == NULL)
|
||||
{
|
||||
static const f32 txc_default[24] = {
|
||||
@ -97,15 +99,70 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
|
||||
};
|
||||
|
||||
for(s32 j=0; j<24; j++)
|
||||
v2f t;
|
||||
for(int i = 0; i < tilecount; i++)
|
||||
{
|
||||
switch (tiles[i].rotation)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1: //R90
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
|
||||
break;
|
||||
case 2: //R180
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(180,irr::core::vector2df(0, 0));
|
||||
break;
|
||||
case 3: //R270
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
|
||||
break;
|
||||
case 4: //FXR90
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
|
||||
|
||||
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
|
||||
tiles[i].texture.size.Y *= -1;
|
||||
break;
|
||||
case 5: //FXR270
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
|
||||
t=vertices[i*4].TCoords;
|
||||
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
|
||||
tiles[i].texture.size.Y *= -1;
|
||||
break;
|
||||
case 6: //FYR90
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
|
||||
tiles[i].texture.pos.X += tiles[i].texture.size.X;
|
||||
tiles[i].texture.size.X *= -1;
|
||||
break;
|
||||
case 7: //FYR270
|
||||
for (int x = 0; x < 4; x++)
|
||||
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
|
||||
tiles[i].texture.pos.X += tiles[i].texture.size.X;
|
||||
tiles[i].texture.size.X *= -1;
|
||||
break;
|
||||
case 8: //FX
|
||||
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
|
||||
tiles[i].texture.size.Y *= -1;
|
||||
break;
|
||||
case 9: //FY
|
||||
tiles[i].texture.pos.X += tiles[i].texture.size.X;
|
||||
tiles[i].texture.size.X *= -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(s32 j=0; j<24; j++)
|
||||
{
|
||||
int tileindex = MYMIN(j/4, tilecount-1);
|
||||
vertices[j].TCoords *= tiles[tileindex].texture.size;
|
||||
vertices[j].TCoords += tiles[tileindex].texture.pos;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
|
||||
// Add to mesh collector
|
||||
for(s32 j=0; j<24; j+=4)
|
||||
{
|
||||
@ -160,18 +217,145 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
Add water sources to mesh if using new style
|
||||
*/
|
||||
TileSpec tile_liquid = f.special_tiles[0];
|
||||
TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data);
|
||||
AtlasPointer &pa_liquid = tile_liquid.texture;
|
||||
|
||||
bool top_is_air = false;
|
||||
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
|
||||
if(n.getContent() == CONTENT_AIR)
|
||||
top_is_air = true;
|
||||
|
||||
if(top_is_air == false)
|
||||
continue;
|
||||
bool top_is_same_liquid = false;
|
||||
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
|
||||
content_t c_flowing = nodedef->getId(f.liquid_alternative_flowing);
|
||||
content_t c_source = nodedef->getId(f.liquid_alternative_source);
|
||||
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
|
||||
top_is_same_liquid = true;
|
||||
|
||||
u16 l = getInteriorLight(n, 0, data);
|
||||
video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
|
||||
|
||||
/*
|
||||
Generate sides
|
||||
*/
|
||||
v3s16 side_dirs[4] = {
|
||||
v3s16(1,0,0),
|
||||
v3s16(-1,0,0),
|
||||
v3s16(0,0,1),
|
||||
v3s16(0,0,-1),
|
||||
};
|
||||
for(u32 i=0; i<4; i++)
|
||||
{
|
||||
v3s16 dir = side_dirs[i];
|
||||
|
||||
MapNode neighbor = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dir);
|
||||
content_t neighbor_content = neighbor.getContent();
|
||||
const ContentFeatures &n_feat = nodedef->get(neighbor_content);
|
||||
MapNode n_top = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dir+ v3s16(0,1,0));
|
||||
content_t n_top_c = n_top.getContent();
|
||||
|
||||
if(neighbor_content == CONTENT_IGNORE)
|
||||
continue;
|
||||
|
||||
/*
|
||||
If our topside is liquid and neighbor's topside
|
||||
is liquid, don't draw side face
|
||||
*/
|
||||
if(top_is_same_liquid && (n_top_c == c_flowing ||
|
||||
n_top_c == c_source || n_top_c == CONTENT_IGNORE))
|
||||
continue;
|
||||
|
||||
// Don't draw face if neighbor is blocking the view
|
||||
if(n_feat.solidness == 2)
|
||||
continue;
|
||||
|
||||
bool neighbor_is_same_liquid = (neighbor_content == c_source
|
||||
|| neighbor_content == c_flowing);
|
||||
|
||||
// Don't draw any faces if neighbor same is liquid and top is
|
||||
// same liquid
|
||||
if(neighbor_is_same_liquid && !top_is_same_liquid)
|
||||
continue;
|
||||
|
||||
// Use backface culled material if neighbor doesn't have a
|
||||
// solidness of 0
|
||||
const TileSpec *current_tile = &tile_liquid;
|
||||
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
|
||||
current_tile = &tile_liquid_bfculled;
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,0,BS/2,0,0,0, c,
|
||||
pa_liquid.x0(), pa_liquid.y1()),
|
||||
video::S3DVertex(BS/2,0,BS/2,0,0,0, c,
|
||||
pa_liquid.x1(), pa_liquid.y1()),
|
||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||
pa_liquid.x1(), pa_liquid.y0()),
|
||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||
pa_liquid.x0(), pa_liquid.y0()),
|
||||
};
|
||||
|
||||
/*
|
||||
If our topside is liquid, set upper border of face
|
||||
at upper border of node
|
||||
*/
|
||||
if(top_is_same_liquid)
|
||||
{
|
||||
vertices[2].Pos.Y = 0.5*BS;
|
||||
vertices[3].Pos.Y = 0.5*BS;
|
||||
}
|
||||
/*
|
||||
Otherwise upper position of face is liquid level
|
||||
*/
|
||||
else
|
||||
{
|
||||
vertices[2].Pos.Y = (node_liquid_level-0.5)*BS;
|
||||
vertices[3].Pos.Y = (node_liquid_level-0.5)*BS;
|
||||
}
|
||||
/*
|
||||
If neighbor is liquid, lower border of face is liquid level
|
||||
*/
|
||||
if(neighbor_is_same_liquid)
|
||||
{
|
||||
vertices[0].Pos.Y = (node_liquid_level-0.5)*BS;
|
||||
vertices[1].Pos.Y = (node_liquid_level-0.5)*BS;
|
||||
}
|
||||
/*
|
||||
If neighbor is not liquid, lower border of face is
|
||||
lower border of node
|
||||
*/
|
||||
else
|
||||
{
|
||||
vertices[0].Pos.Y = -0.5*BS;
|
||||
vertices[1].Pos.Y = -0.5*BS;
|
||||
}
|
||||
|
||||
for(s32 j=0; j<4; j++)
|
||||
{
|
||||
if(dir == v3s16(0,0,1))
|
||||
vertices[j].Pos.rotateXZBy(0);
|
||||
if(dir == v3s16(0,0,-1))
|
||||
vertices[j].Pos.rotateXZBy(180);
|
||||
if(dir == v3s16(-1,0,0))
|
||||
vertices[j].Pos.rotateXZBy(90);
|
||||
if(dir == v3s16(1,0,-0))
|
||||
vertices[j].Pos.rotateXZBy(-90);
|
||||
|
||||
// Do this to not cause glitches when two liquids are
|
||||
// side-by-side
|
||||
/*if(neighbor_is_same_liquid == false){
|
||||
vertices[j].Pos.X *= 0.98;
|
||||
vertices[j].Pos.Z *= 0.98;
|
||||
}*/
|
||||
|
||||
vertices[j].Pos += intToFloat(p, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(*current_tile, vertices, 4, indices, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
Generate top
|
||||
*/
|
||||
if(top_is_same_liquid)
|
||||
continue;
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
@ -185,7 +369,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
pa_liquid.x0(), pa_liquid.y0()),
|
||||
};
|
||||
|
||||
v3f offset(p.X, p.Y + (-0.5+node_liquid_level)*BS, p.Z);
|
||||
v3f offset(p.X*BS, p.Y*BS + (-0.5+node_liquid_level)*BS, p.Z*BS);
|
||||
for(s32 i=0; i<4; i++)
|
||||
{
|
||||
vertices[i].Pos += offset;
|
||||
@ -230,9 +414,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
|
||||
// Neighbor liquid levels (key = relative position)
|
||||
// Includes current node
|
||||
core::map<v3s16, f32> neighbor_levels;
|
||||
core::map<v3s16, content_t> neighbor_contents;
|
||||
core::map<v3s16, u8> neighbor_flags;
|
||||
std::map<v3s16, f32> neighbor_levels;
|
||||
std::map<v3s16, content_t> neighbor_contents;
|
||||
std::map<v3s16, u8> neighbor_flags;
|
||||
const u8 neighborflag_top_is_same_liquid = 0x01;
|
||||
v3s16 neighbor_dirs[9] = {
|
||||
v3s16(0,0,0),
|
||||
@ -273,9 +457,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
flags |= neighborflag_top_is_same_liquid;
|
||||
}
|
||||
|
||||
neighbor_levels.insert(neighbor_dirs[i], level);
|
||||
neighbor_contents.insert(neighbor_dirs[i], content);
|
||||
neighbor_flags.insert(neighbor_dirs[i], flags);
|
||||
neighbor_levels[neighbor_dirs[i]] = level;
|
||||
neighbor_contents[neighbor_dirs[i]] = content;
|
||||
neighbor_flags[neighbor_dirs[i]] = flags;
|
||||
}
|
||||
|
||||
// Corner heights (average between four liquids)
|
||||
@ -324,7 +508,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
}
|
||||
}
|
||||
if(air_count >= 2)
|
||||
cornerlevel = -0.5*BS+0.1;
|
||||
cornerlevel = -0.5*BS+0.2;
|
||||
else if(valid_count > 0)
|
||||
cornerlevel /= valid_count;
|
||||
corner_levels[i] = cornerlevel;
|
||||
@ -1027,14 +1211,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
v3s16(0, 0, 1),
|
||||
v3s16(0, 0, -1)
|
||||
};
|
||||
|
||||
TileSpec tiles[6];
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
// Handles facedir rotation for textures
|
||||
tiles[i] = getNodeTile(n, p, tile_dirs[i], data);
|
||||
}
|
||||
|
||||
|
||||
u16 l = getInteriorLight(n, 0, data);
|
||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||
|
||||
@ -1045,17 +1223,43 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
for(int j = 0; j < 6; j++)
|
||||
{
|
||||
// Handles facedir rotation for textures
|
||||
tiles[j] = getNodeTile(n, p, tile_dirs[j], data);
|
||||
}
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += pos;
|
||||
box.MaxEdge += pos;
|
||||
|
||||
f32 temp;
|
||||
if (box.MinEdge.X > box.MaxEdge.X)
|
||||
{
|
||||
temp=box.MinEdge.X;
|
||||
box.MinEdge.X=box.MaxEdge.X;
|
||||
box.MaxEdge.X=temp;
|
||||
}
|
||||
if (box.MinEdge.Y > box.MaxEdge.Y)
|
||||
{
|
||||
temp=box.MinEdge.Y;
|
||||
box.MinEdge.Y=box.MaxEdge.Y;
|
||||
box.MaxEdge.Y=temp;
|
||||
}
|
||||
if (box.MinEdge.Z > box.MaxEdge.Z)
|
||||
{
|
||||
temp=box.MinEdge.Z;
|
||||
box.MinEdge.Z=box.MaxEdge.Z;
|
||||
box.MaxEdge.Z=temp;
|
||||
}
|
||||
|
||||
//
|
||||
// Compute texture coords
|
||||
f32 tx1 = (i->MinEdge.X/BS)+0.5;
|
||||
f32 ty1 = (i->MinEdge.Y/BS)+0.5;
|
||||
f32 tz1 = (i->MinEdge.Z/BS)+0.5;
|
||||
f32 tx2 = (i->MaxEdge.X/BS)+0.5;
|
||||
f32 ty2 = (i->MaxEdge.Y/BS)+0.5;
|
||||
f32 tz2 = (i->MaxEdge.Z/BS)+0.5;
|
||||
f32 tx1 = (box.MinEdge.X/BS)+0.5;
|
||||
f32 ty1 = (box.MinEdge.Y/BS)+0.5;
|
||||
f32 tz1 = (box.MinEdge.Z/BS)+0.5;
|
||||
f32 tx2 = (box.MaxEdge.X/BS)+0.5;
|
||||
f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
|
||||
f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
|
||||
f32 txc[24] = {
|
||||
// up
|
||||
tx1, 1-tz2, tx2, 1-tz1,
|
||||
@ -1070,7 +1274,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
// front
|
||||
tx1, 1-ty2, tx2, 1-ty1,
|
||||
};
|
||||
|
||||
makeCuboid(&collector, box, tiles, 6, c, txc);
|
||||
}
|
||||
break;}
|
||||
|
@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "genericobject.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
std::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
/*
|
||||
DummyLoadSAO
|
||||
@ -64,6 +64,10 @@ public:
|
||||
infostream<<"DummyLoadSAO step"<<std::endl;
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@ -132,6 +136,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
float m_timer1;
|
||||
float m_age;
|
||||
@ -208,8 +216,7 @@ public:
|
||||
v3f pos_f_old = pos_f;
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
|
||||
@ -314,6 +321,10 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::string m_itemstring;
|
||||
@ -370,8 +381,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||
}
|
||||
|
||||
// Initialize something to armor groups
|
||||
m_armor_groups["fleshy"] = 3;
|
||||
m_armor_groups["snappy"] = 2;
|
||||
m_armor_groups["fleshy"] = 100;
|
||||
}
|
||||
|
||||
LuaEntitySAO::~LuaEntitySAO()
|
||||
@ -490,8 +500,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
v3f p_pos = m_base_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
@ -880,6 +889,22 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
|
||||
if (m_prop.physical)
|
||||
{
|
||||
//update collision box
|
||||
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
|
||||
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
|
||||
|
||||
toset->MinEdge += m_base_position;
|
||||
toset->MaxEdge += m_base_position;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
PlayerSAO
|
||||
*/
|
||||
@ -916,8 +941,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
||||
assert(m_peer_id != 0);
|
||||
setBasePosition(m_player->getPosition());
|
||||
m_inventory = &m_player->inventory;
|
||||
m_armor_groups["choppy"] = 2;
|
||||
m_armor_groups["fleshy"] = 3;
|
||||
m_armor_groups["fleshy"] = 100;
|
||||
|
||||
m_prop.hp_max = PLAYER_MAX_HP;
|
||||
m_prop.physical = false;
|
||||
@ -1230,6 +1254,20 @@ void PlayerSAO::moveTo(v3f pos, bool continuous)
|
||||
m_moved = true;
|
||||
}
|
||||
|
||||
void PlayerSAO::setYaw(float yaw)
|
||||
{
|
||||
m_player->setYaw(yaw);
|
||||
// Force change on client
|
||||
m_moved = true;
|
||||
}
|
||||
|
||||
void PlayerSAO::setPitch(float pitch)
|
||||
{
|
||||
m_player->setPitch(pitch);
|
||||
// Force change on client
|
||||
m_moved = true;
|
||||
}
|
||||
|
||||
int PlayerSAO::punch(v3f dir,
|
||||
const ToolCapabilities *toolcap,
|
||||
ServerActiveObject *puncher,
|
||||
@ -1420,3 +1458,7 @@ std::string PlayerSAO::getPropertyPacket()
|
||||
return gob_cmd_set_properties(m_prop);
|
||||
}
|
||||
|
||||
bool PlayerSAO::getCollisionBox(aabb3f *toset) {
|
||||
//player collision handling is already done clientside no need to do it twice
|
||||
return false;
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
void setSprite(v2s16 p, int num_frames, float framelength,
|
||||
bool select_horiz_by_yawpitch);
|
||||
std::string getName();
|
||||
bool getCollisionBox(aabb3f *toset);
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||
@ -147,6 +148,8 @@ public:
|
||||
void setBasePosition(const v3f &position);
|
||||
void setPos(v3f pos);
|
||||
void moveTo(v3f pos, bool continuous);
|
||||
void setYaw(float);
|
||||
void setPitch(float);
|
||||
|
||||
/*
|
||||
Interaction interface
|
||||
@ -233,6 +236,8 @@ public:
|
||||
m_is_singleplayer = is_singleplayer;
|
||||
}
|
||||
|
||||
bool getCollisionBox(aabb3f *toset);
|
||||
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
|
||||
|
@ -987,6 +987,43 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
|
||||
IGameDef *gamedef) const
|
||||
{
|
||||
std::vector<CraftDefinition*> recipes_list;
|
||||
CraftInput input;
|
||||
CraftOutput tmpout;
|
||||
tmpout.item = "";
|
||||
tmpout.time = 0;
|
||||
|
||||
for(std::vector<CraftDefinition*>::const_reverse_iterator
|
||||
i = m_craft_definitions.rbegin();
|
||||
i != m_craft_definitions.rend(); i++)
|
||||
{
|
||||
CraftDefinition *def = *i;
|
||||
|
||||
/*infostream<<"Checking "<<input.dump()<<std::endl
|
||||
<<" against "<<def->dump()<<std::endl;*/
|
||||
|
||||
try {
|
||||
tmpout = def->getOutput(input, gamedef);
|
||||
if(tmpout.item.substr(0,output.item.length()) == output.item)
|
||||
{
|
||||
// Get output, then decrement input (if requested)
|
||||
input = def->getInput(output, gamedef);
|
||||
recipes_list.push_back(*i);
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
errorstream<<"getCraftResult: ERROR: "
|
||||
<<"Serialization error in recipe "
|
||||
<<def->dump()<<std::endl;
|
||||
// then go on with the next craft definition
|
||||
}
|
||||
}
|
||||
return recipes_list;
|
||||
}
|
||||
virtual std::string dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
|
@ -358,6 +358,8 @@ public:
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
@ -376,6 +378,8 @@ public:
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
|
@ -130,7 +130,7 @@ void DebugStack::print(std::ostream &os, bool everything)
|
||||
os<<"Probably overflown."<<std::endl;
|
||||
}
|
||||
|
||||
core::map<threadid_t, DebugStack*> g_debug_stacks;
|
||||
std::map<threadid_t, DebugStack*> g_debug_stacks;
|
||||
JMutex g_debug_stacks_mutex;
|
||||
|
||||
void debug_stacks_init()
|
||||
@ -144,12 +144,11 @@ void debug_stacks_print_to(std::ostream &os)
|
||||
|
||||
os<<"Debug stacks:"<<std::endl;
|
||||
|
||||
for(core::map<threadid_t, DebugStack*>::Iterator
|
||||
i = g_debug_stacks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<threadid_t, DebugStack*>::iterator
|
||||
i = g_debug_stacks.begin();
|
||||
i != g_debug_stacks.end(); ++i)
|
||||
{
|
||||
DebugStack *stack = i.getNode()->getValue();
|
||||
stack->print(os, false);
|
||||
i->second->print(os, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,11 +158,11 @@ void debug_stacks_print()
|
||||
|
||||
DEBUGPRINT("Debug stacks:\n");
|
||||
|
||||
for(core::map<threadid_t, DebugStack*>::Iterator
|
||||
i = g_debug_stacks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<threadid_t, DebugStack*>::iterator
|
||||
i = g_debug_stacks.begin();
|
||||
i != g_debug_stacks.end(); ++i)
|
||||
{
|
||||
DebugStack *stack = i.getNode()->getValue();
|
||||
DebugStack *stack = i->second;
|
||||
|
||||
for(int i=0; i<DEBUGSTREAM_COUNT; i++)
|
||||
{
|
||||
@ -179,18 +178,18 @@ DebugStacker::DebugStacker(const char *text)
|
||||
|
||||
JMutexAutoLock lock(g_debug_stacks_mutex);
|
||||
|
||||
core::map<threadid_t, DebugStack*>::Node *n;
|
||||
std::map<threadid_t, DebugStack*>::iterator n;
|
||||
n = g_debug_stacks.find(threadid);
|
||||
if(n != NULL)
|
||||
if(n != g_debug_stacks.end())
|
||||
{
|
||||
m_stack = n->getValue();
|
||||
m_stack = n->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*DEBUGPRINT("Creating new debug stack for thread %x\n",
|
||||
(unsigned int)threadid);*/
|
||||
m_stack = new DebugStack(threadid);
|
||||
g_debug_stacks.insert(threadid, m_stack);
|
||||
g_debug_stacks[threadid] = m_stack;
|
||||
}
|
||||
|
||||
if(m_stack->stack_i >= DEBUG_STACK_SIZE)
|
||||
@ -224,7 +223,7 @@ DebugStacker::~DebugStacker()
|
||||
/*DEBUGPRINT("Deleting debug stack for thread %x\n",
|
||||
(unsigned int)threadid);*/
|
||||
delete m_stack;
|
||||
g_debug_stacks.remove(threadid);
|
||||
g_debug_stacks.erase(threadid);
|
||||
}
|
||||
}
|
||||
|
||||
|
29
src/debug.h
29
src/debug.h
@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "threads.h"
|
||||
#include "gettime.h"
|
||||
#include "exceptions.h"
|
||||
#include <map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@ -165,7 +166,7 @@ struct DebugStack
|
||||
int stack_max_i; // Highest i that was seen
|
||||
};
|
||||
|
||||
extern core::map<threadid_t, DebugStack*> g_debug_stacks;
|
||||
extern std::map<threadid_t, DebugStack*> g_debug_stacks;
|
||||
extern JMutex g_debug_stacks_mutex;
|
||||
|
||||
extern void debug_stacks_init();
|
||||
@ -205,42 +206,42 @@ public:
|
||||
|
||||
void add(u16 command)
|
||||
{
|
||||
core::map<u16, u16>::Node *n = m_packets.find(command);
|
||||
if(n == NULL)
|
||||
std::map<u16, u16>::iterator n = m_packets.find(command);
|
||||
if(n == m_packets.end())
|
||||
{
|
||||
m_packets[command] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->setValue(n->getValue()+1);
|
||||
n->second++;
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for(core::map<u16, u16>::Iterator
|
||||
i = m_packets.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<u16, u16>::iterator
|
||||
i = m_packets.begin();
|
||||
i != m_packets.end(); ++i)
|
||||
{
|
||||
i.getNode()->setValue(0);
|
||||
i->second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void print(std::ostream &o)
|
||||
{
|
||||
for(core::map<u16, u16>::Iterator
|
||||
i = m_packets.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<u16, u16>::iterator
|
||||
i = m_packets.begin();
|
||||
i != m_packets.end(); ++i)
|
||||
{
|
||||
o<<"cmd "<<i.getNode()->getKey()
|
||||
<<" count "<<i.getNode()->getValue()
|
||||
o<<"cmd "<<i->first
|
||||
<<" count "<<i->second
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// command, count
|
||||
core::map<u16, u16> m_packets;
|
||||
std::map<u16, u16> m_packets;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -109,6 +109,7 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("view_bobbing_amount", "1.0");
|
||||
settings->setDefault("enable_3d_clouds", "true");
|
||||
settings->setDefault("cloud_height", "120");
|
||||
settings->setDefault("menu_clouds", "true");
|
||||
settings->setDefault("opaque_water", "false");
|
||||
settings->setDefault("console_color", "(0,0,0)");
|
||||
settings->setDefault("console_alpha", "200");
|
||||
@ -202,34 +203,57 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("movement_liquid_fluidity_smooth", "0.5");
|
||||
settings->setDefault("movement_liquid_sink", "10");
|
||||
settings->setDefault("movement_gravity", "9.81");
|
||||
|
||||
|
||||
//liquid stuff
|
||||
settings->setDefault("liquid_finite", "false");
|
||||
settings->setDefault("liquid_update", "1.0");
|
||||
settings->setDefault("liquid_relax", "1");
|
||||
settings->setDefault("liquid_relax", "2");
|
||||
settings->setDefault("liquid_fast_flood", "1");
|
||||
settings->setDefault("underground_springs", "1");
|
||||
|
||||
//mapgen stuff
|
||||
settings->setDefault("mg_name", "v6");
|
||||
settings->setDefault("water_level", "1");
|
||||
settings->setDefault("water_level", "1");
|
||||
settings->setDefault("chunksize", "5");
|
||||
settings->setDefault("mg_flags", "trees, caves, v6_biome_blend");
|
||||
settings->setDefault("mgv6_freq_desert", "0.45");
|
||||
settings->setDefault("mgv6_freq_beach", "0.15");
|
||||
|
||||
settings->setDefault("mgv6_np_terrain_base", "-4, 20, (250.0, 250, 250), 82341, 5, 0.6");
|
||||
settings->setDefault("mgv6_np_terrain_base", "-4, 20, (250, 250, 250), 82341, 5, 0.6");
|
||||
settings->setDefault("mgv6_np_terrain_higher", "20, 16, (500, 500, 500), 85039, 5, 0.6");
|
||||
settings->setDefault("mgv6_np_steepness", "0.85, 0.5, (125, 125, 125), -932, 5, 0.7");
|
||||
settings->setDefault("mgv6_np_height_select", "0.5, 1, (250, 250, 250), 4213, 5, 0.69");
|
||||
settings->setDefault("mgv6_np_trees", "0, 1, (125, 125, 125), 2, 4, 0.66");
|
||||
settings->setDefault("mgv6_np_mud", "4, 2, (200, 200, 200), 91013, 3, 0.55");
|
||||
settings->setDefault("mgv6_np_beach", "0, 1, (250, 250, 250), 59420, 3, 0.50");
|
||||
settings->setDefault("mgv6_np_biome", "0, 1, (250, 250, 250), 9130, 3, 0.50");
|
||||
settings->setDefault("mgv6_np_cave", "6, 6, (250, 250, 250), 34329, 3, 0.50");
|
||||
settings->setDefault("mgv6_np_humidity", "0.5, 0.5, (500, 500, 500), 72384, 4, 0.66");
|
||||
settings->setDefault("mgv6_np_trees", "0, 1, (125, 125, 125), 2, 4, 0.66");
|
||||
settings->setDefault("mgv6_np_apple_trees", "0, 1, (100, 100, 100), 342902, 3, 0.45");
|
||||
|
||||
settings->setDefault("mgv7_np_terrain", "10, 12, (350, 350, 350), 82341, 5, 0.6");
|
||||
settings->setDefault("mgv7_np_bgroup", "0.5, 0.3125, (350, 350, 350), 5923, 2, 0.6");
|
||||
settings->setDefault("mgv7_np_heat", "25, 50, (500, 500, 500), 35293, 1, 0");
|
||||
settings->setDefault("mgv7_np_humidity", "50, 31.25, (750, 750, 750), 12094, 2, 0.6");
|
||||
|
||||
settings->setDefault("mgindev_np_terrain_base", "-4, 20, (250, 250, 250), 82341, 5, 0.6, 10, 10");
|
||||
settings->setDefault("mgindev_np_terrain_higher", "20, 16, (500, 500, 500), 85039, 5, 0.6, 10, 10");
|
||||
settings->setDefault("mgindev_np_steepness", "0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2, 10");
|
||||
settings->setDefault("mgindev_np_mud", "4, 2, (200, 200, 200), 91013, 3, 0.55, 1, 1");
|
||||
settings->setDefault("mgindev_np_float_islands1", "0, 1, (64, 64, 64 ), 3683, 5, 0.5, 1, 1.5");
|
||||
settings->setDefault("mgindev_np_float_islands2", "0, 1, (8, 8, 8 ), 9292, 2, 0.5, 1, 1.5");
|
||||
settings->setDefault("mgindev_np_float_islands3", "0, 1, (256, 256, 256), 6412, 2, 0.5, 1, 0.5");
|
||||
settings->setDefault("mgindev_np_biome", "0, 1, (250, 250, 250), 9130, 3, 0.50, 1, 10");
|
||||
settings->setDefault("mgindev_float_islands", "500");
|
||||
|
||||
}
|
||||
|
||||
void override_default_settings(Settings *settings, Settings *from)
|
||||
{
|
||||
std::vector<std::string> names = from->getNames();
|
||||
for(size_t i=0; i<names.size(); i++){
|
||||
const std::string &name = names[i];
|
||||
settings->setDefault(name, from->get(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
class Settings;
|
||||
|
||||
void set_default_settings(Settings *settings);
|
||||
void override_default_settings(Settings *settings, Settings *from);
|
||||
|
||||
#endif
|
||||
|
||||
|
634
src/dungeongen.cpp
Normal file
634
src/dungeongen.cpp
Normal file
@ -0,0 +1,634 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "dungeongen.h"
|
||||
#include "mapgen.h"
|
||||
#include "voxel.h"
|
||||
#include "noise.h"
|
||||
#include "mapblock.h"
|
||||
#include "mapnode.h"
|
||||
#include "map.h"
|
||||
#include "nodedef.h"
|
||||
#include "profiler.h"
|
||||
#include "settings.h" // For g_settings
|
||||
#include "main.h" // For g_profiler
|
||||
|
||||
NoiseParams nparams_dungeon_rarity =
|
||||
{0.0, 1.0, v3f(500.0, 500.0, 500.0), 0, 2, 0.8};
|
||||
NoiseParams nparams_dungeon_wetness =
|
||||
{0.0, 1.0, v3f(40.0, 40.0, 40.0), 32474, 4, 1.1};
|
||||
NoiseParams nparams_dungeon_density =
|
||||
{0.0, 1.0, v3f(2.5, 2.5, 2.5), 0, 2, 1.4};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel) {
|
||||
this->ndef = ndef;
|
||||
this->mapseed = seed;
|
||||
this->water_level = waterlevel;
|
||||
|
||||
np_rarity = &nparams_dungeon_rarity;
|
||||
np_wetness = &nparams_dungeon_wetness;
|
||||
np_density = &nparams_dungeon_density;
|
||||
/*
|
||||
cid_water_source = ndef->getId("mapgen_water_source");
|
||||
cid_cobble = ndef->getId("mapgen_cobble");
|
||||
cid_mossycobble = ndef->getId("mapgen_mossycobble");
|
||||
cid_torch = ndef->getId("default:torch");
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
|
||||
v3s16 nmin, v3s16 nmax) {
|
||||
//TimeTaker t("gen dungeons");
|
||||
int approx_groundlevel = 10 + water_level;
|
||||
|
||||
if ((nmin.Y + nmax.Y) / 2 >= approx_groundlevel ||
|
||||
NoisePerlin3D(np_rarity, nmin.X, nmin.Y, nmin.Z, mapseed) < 0.2)
|
||||
return;
|
||||
|
||||
this->vmanip = vm;
|
||||
this->blockseed = bseed;
|
||||
random.seed(bseed + 2);
|
||||
|
||||
cid_water_source = ndef->getId("mapgen_water_source");
|
||||
cid_cobble = ndef->getId("mapgen_cobble");
|
||||
cid_mossycobble = ndef->getId("mapgen_mossycobble");
|
||||
//cid_torch = ndef->getId("default:torch");
|
||||
cid_cobblestair = ndef->getId("stairs:stair_cobble");
|
||||
|
||||
// Dungeon generator doesn't modify places which have this set
|
||||
vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
|
||||
|
||||
// Set all air and water to be untouchable to make dungeons open
|
||||
// to caves and open air
|
||||
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
|
||||
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
|
||||
u32 i = vmanip->m_area.index(nmin.X, y, z);
|
||||
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
||||
content_t c = vmanip->m_data[i].getContent();
|
||||
if (c == CONTENT_AIR || c == cid_water_source)
|
||||
vmanip->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add it
|
||||
makeDungeon(v3s16(1,1,1) * MAP_BLOCKSIZE);
|
||||
|
||||
// Convert some cobble to mossy cobble
|
||||
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
|
||||
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
|
||||
u32 i = vmanip->m_area.index(nmin.X, y, z);
|
||||
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
||||
if (vmanip->m_data[i].getContent() == cid_cobble) {
|
||||
float wetness = NoisePerlin3D(np_wetness, x, y, z, mapseed);
|
||||
float density = NoisePerlin3D(np_density, x, y, z, blockseed);
|
||||
if (density < wetness / 3.0)
|
||||
vmanip->m_data[i].setContent(cid_mossycobble);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("== gen dungeons: %dms\n", t.stop());
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::makeDungeon(v3s16 start_padding)
|
||||
{
|
||||
v3s16 areasize = vmanip->m_area.getExtent();
|
||||
v3s16 roomsize;
|
||||
v3s16 roomplace;
|
||||
|
||||
/*
|
||||
Find place for first room
|
||||
*/
|
||||
bool fits = false;
|
||||
for (u32 i = 0; i < 100; i++)
|
||||
{
|
||||
bool is_large_room = ((random.next() & 3) == 1);
|
||||
roomsize = is_large_room ?
|
||||
v3s16(random.range(8, 16),random.range(8, 16),random.range(8, 16)) :
|
||||
v3s16(random.range(4, 8),random.range(4, 6),random.range(4, 8));
|
||||
|
||||
// start_padding is used to disallow starting the generation of
|
||||
// a dungeon in a neighboring generation chunk
|
||||
roomplace = vmanip->m_area.MinEdge + start_padding + v3s16(
|
||||
random.range(0,areasize.X-roomsize.X-1-start_padding.X),
|
||||
random.range(0,areasize.Y-roomsize.Y-1-start_padding.Y),
|
||||
random.range(0,areasize.Z-roomsize.Z-1-start_padding.Z));
|
||||
|
||||
/*
|
||||
Check that we're not putting the room to an unknown place,
|
||||
otherwise it might end up floating in the air
|
||||
*/
|
||||
fits = true;
|
||||
for (s16 z = 1; z < roomsize.Z - 1; z++)
|
||||
for (s16 y = 1; y < roomsize.Y - 1; y++)
|
||||
for (s16 x = 1; x < roomsize.X - 1; x++)
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x, y, z);
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE)
|
||||
{
|
||||
fits = false;
|
||||
break;
|
||||
}
|
||||
if (vmanip->m_data[vi].getContent() == CONTENT_IGNORE)
|
||||
{
|
||||
fits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fits)
|
||||
break;
|
||||
}
|
||||
// No place found
|
||||
if (fits == false)
|
||||
return;
|
||||
|
||||
/*
|
||||
Stores the center position of the last room made, so that
|
||||
a new corridor can be started from the last room instead of
|
||||
the new room, if chosen so.
|
||||
*/
|
||||
v3s16 last_room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2);
|
||||
|
||||
u32 room_count = random.range(2, 16);
|
||||
for (u32 i = 0; i < room_count; i++)
|
||||
{
|
||||
// Make a room to the determined place
|
||||
makeRoom(roomsize, roomplace);
|
||||
|
||||
v3s16 room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2);
|
||||
|
||||
// Place torch at room center (for testing)
|
||||
//vmanip->m_data[vmanip->m_area.index(room_center)] = MapNode(cid_torch);
|
||||
|
||||
// Quit if last room
|
||||
if (i == room_count - 1)
|
||||
break;
|
||||
|
||||
// Determine walker start position
|
||||
|
||||
bool start_in_last_room = (random.range(0, 2) != 0);
|
||||
|
||||
v3s16 walker_start_place;
|
||||
|
||||
if(start_in_last_room)
|
||||
{
|
||||
walker_start_place = last_room_center;
|
||||
}
|
||||
else
|
||||
{
|
||||
walker_start_place = room_center;
|
||||
// Store center of current room as the last one
|
||||
last_room_center = room_center;
|
||||
}
|
||||
|
||||
// Create walker and find a place for a door
|
||||
v3s16 doorplace;
|
||||
v3s16 doordir;
|
||||
|
||||
m_pos = walker_start_place;
|
||||
bool r = findPlaceForDoor(doorplace, doordir);
|
||||
if (r == false)
|
||||
return;
|
||||
|
||||
if (random.range(0,1) == 0)
|
||||
// Make the door
|
||||
makeDoor(doorplace, doordir);
|
||||
else
|
||||
// Don't actually make a door
|
||||
doorplace -= doordir;
|
||||
|
||||
// Make a random corridor starting from the door
|
||||
v3s16 corridor_end;
|
||||
v3s16 corridor_end_dir;
|
||||
makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir);
|
||||
|
||||
// Find a place for a random sized room
|
||||
roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
|
||||
m_pos = corridor_end;
|
||||
m_dir = corridor_end_dir;
|
||||
r = findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace);
|
||||
if (r == false)
|
||||
return;
|
||||
|
||||
if (random.range(0,1) == 0)
|
||||
// Make the door
|
||||
makeDoor(doorplace, doordir);
|
||||
else
|
||||
// Don't actually make a door
|
||||
roomplace -= doordir;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
|
||||
{
|
||||
MapNode n_cobble(cid_cobble);
|
||||
MapNode n_air(CONTENT_AIR);
|
||||
|
||||
// Make +-X walls
|
||||
for (s16 z = 0; z < roomsize.Z; z++)
|
||||
for (s16 y = 0; y < roomsize.Y; y++)
|
||||
{
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(0, y, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
|
||||
continue;
|
||||
vmanip->m_data[vi] = n_cobble;
|
||||
}
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
|
||||
continue;
|
||||
vmanip->m_data[vi] = n_cobble;
|
||||
}
|
||||
}
|
||||
|
||||
// Make +-Z walls
|
||||
for (s16 x = 0; x < roomsize.X; x++)
|
||||
for (s16 y = 0; y < roomsize.Y; y++)
|
||||
{
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x, y, 0);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
|
||||
continue;
|
||||
vmanip->m_data[vi] = n_cobble;
|
||||
}
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
|
||||
continue;
|
||||
vmanip->m_data[vi] = n_cobble;
|
||||
}
|
||||
}
|
||||
|
||||
// Make +-Y walls (floor and ceiling)
|
||||
for (s16 z = 0; z < roomsize.Z; z++)
|
||||
for (s16 x = 0; x < roomsize.X; x++)
|
||||
{
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x, 0, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
|
||||
continue;
|
||||
vmanip->m_data[vi] = n_cobble;
|
||||
}
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x,roomsize. Y - 1, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
|
||||
continue;
|
||||
vmanip->m_data[vi] = n_cobble;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill with air
|
||||
for (s16 z = 1; z < roomsize.Z - 1; z++)
|
||||
for (s16 y = 1; y < roomsize.Y - 1; y++)
|
||||
for (s16 x = 1; x < roomsize.X - 1; x++)
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x, y, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
vmanip->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
|
||||
vmanip->m_data[vi] = n_air;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::makeFill(v3s16 place, v3s16 size,
|
||||
u8 avoid_flags, MapNode n, u8 or_flags)
|
||||
{
|
||||
for (s16 z = 0; z < size.Z; z++)
|
||||
for (s16 y = 0; y < size.Y; y++)
|
||||
for (s16 x = 0; x < size.X; x++)
|
||||
{
|
||||
v3s16 p = place + v3s16(x, y, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip->m_area.index(p);
|
||||
if (vmanip->m_flags[vi] & avoid_flags)
|
||||
continue;
|
||||
vmanip->m_flags[vi] |= or_flags;
|
||||
vmanip->m_data[vi] = n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::makeHole(v3s16 place)
|
||||
{
|
||||
makeFill(place, v3s16(1, 2, 1), 0, MapNode(CONTENT_AIR),
|
||||
VMANIP_FLAG_DUNGEON_INSIDE);
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::makeDoor(v3s16 doorplace, v3s16 doordir)
|
||||
{
|
||||
makeHole(doorplace);
|
||||
// Place torch (for testing)
|
||||
//vmanip->m_data[vmanip->m_area.index(doorplace)] = MapNode(cid_torch);
|
||||
}
|
||||
|
||||
|
||||
void DungeonGen::makeCorridor(v3s16 doorplace,
|
||||
v3s16 doordir, v3s16 &result_place, v3s16 &result_dir)
|
||||
{
|
||||
makeHole(doorplace);
|
||||
v3s16 p0 = doorplace;
|
||||
v3s16 dir = doordir;
|
||||
u32 length;
|
||||
/*if (random.next() % 2)
|
||||
length = random.range(1, 13);
|
||||
else
|
||||
length = random.range(1, 6);*/
|
||||
length = random.range(1, 13);
|
||||
u32 partlength = random.range(1, 13);
|
||||
u32 partcount = 0;
|
||||
s16 make_stairs = 0;
|
||||
|
||||
if (random.next() % 2 == 0 && partlength >= 3)
|
||||
make_stairs = random.next() % 2 ? 1 : -1;
|
||||
|
||||
for (u32 i = 0; i < length; i++) {
|
||||
v3s16 p = p0 + dir;
|
||||
if (partcount != 0)
|
||||
p.Y += make_stairs;
|
||||
|
||||
if (vmanip->m_area.contains(p) == true &&
|
||||
vmanip->m_area.contains(p + v3s16(0, 1, 0)) == true) {
|
||||
if (make_stairs) {
|
||||
makeFill(p + v3s16(-1, -1, -1), v3s16(3, 5, 3),
|
||||
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(cid_cobble), 0);
|
||||
makeHole(p);
|
||||
makeHole(p - dir);
|
||||
|
||||
// TODO: fix stairs code so it works 100% (quite difficult)
|
||||
|
||||
// exclude stairs from the bottom step
|
||||
if (((make_stairs == 1) && i != 0) ||
|
||||
((make_stairs == -1) && i != length - 1)) {
|
||||
// rotate face 180 deg if making stairs backwards
|
||||
int facedir = dir_to_facedir(dir * make_stairs);
|
||||
|
||||
u32 vi = vmanip->m_area.index(p.X - dir.X, p.Y - 1, p.Z - dir.Z);
|
||||
if (vmanip->m_data[vi].getContent() == cid_cobble)
|
||||
vmanip->m_data[vi] = MapNode(cid_cobblestair, 0, facedir);
|
||||
|
||||
vi = vmanip->m_area.index(p.X, p.Y, p.Z);
|
||||
if (vmanip->m_data[vi].getContent() == cid_cobble)
|
||||
vmanip->m_data[vi] = MapNode(cid_cobblestair, 0, facedir);
|
||||
}
|
||||
} else {
|
||||
makeFill(p + v3s16(-1, -1, -1), v3s16(3, 4, 3),
|
||||
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(cid_cobble), 0);
|
||||
makeHole(p);
|
||||
}
|
||||
|
||||
p0 = p;
|
||||
} else {
|
||||
// Can't go here, turn away
|
||||
dir = turn_xz(dir, random.range(0, 1));
|
||||
make_stairs = -make_stairs;
|
||||
partcount = 0;
|
||||
partlength = random.range(1, length);
|
||||
continue;
|
||||
}
|
||||
|
||||
partcount++;
|
||||
if (partcount >= partlength) {
|
||||
partcount = 0;
|
||||
|
||||
dir = random_turn(random, dir);
|
||||
|
||||
partlength = random.range(1,length);
|
||||
|
||||
make_stairs = 0;
|
||||
if (random.next() % 2 == 0 && partlength >= 3)
|
||||
make_stairs = random.next() % 2 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
result_place = p0;
|
||||
result_dir = dir;
|
||||
}
|
||||
|
||||
|
||||
bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
|
||||
{
|
||||
for (u32 i = 0; i < 100; i++)
|
||||
{
|
||||
v3s16 p = m_pos + m_dir;
|
||||
v3s16 p1 = p + v3s16(0, 1, 0);
|
||||
if (vmanip->m_area.contains(p) == false
|
||||
|| vmanip->m_area.contains(p1) == false
|
||||
|| i % 4 == 0)
|
||||
{
|
||||
randomizeDir();
|
||||
continue;
|
||||
}
|
||||
if (vmanip->getNodeNoExNoEmerge(p).getContent() == cid_cobble
|
||||
&& vmanip->getNodeNoExNoEmerge(p1).getContent() == cid_cobble)
|
||||
{
|
||||
// Found wall, this is a good place!
|
||||
result_place = p;
|
||||
result_dir = m_dir;
|
||||
// Randomize next direction
|
||||
randomizeDir();
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
Determine where to move next
|
||||
*/
|
||||
// Jump one up if the actual space is there
|
||||
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == cid_cobble
|
||||
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR
|
||||
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR)
|
||||
p += v3s16(0,1,0);
|
||||
// Jump one down if the actual space is there
|
||||
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == cid_cobble
|
||||
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR
|
||||
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR)
|
||||
p += v3s16(0,-1,0);
|
||||
// Check if walking is now possible
|
||||
if (vmanip->getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR
|
||||
|| vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() != CONTENT_AIR)
|
||||
{
|
||||
// Cannot continue walking here
|
||||
randomizeDir();
|
||||
continue;
|
||||
}
|
||||
// Move there
|
||||
m_pos = p;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
|
||||
v3s16 &result_doordir, v3s16 &result_roomplace)
|
||||
{
|
||||
for (s16 trycount = 0; trycount < 30; trycount++)
|
||||
{
|
||||
v3s16 doorplace;
|
||||
v3s16 doordir;
|
||||
bool r = findPlaceForDoor(doorplace, doordir);
|
||||
if (r == false)
|
||||
continue;
|
||||
v3s16 roomplace;
|
||||
// X east, Z north, Y up
|
||||
#if 1
|
||||
if (doordir == v3s16(1, 0, 0)) // X+
|
||||
roomplace = doorplace +
|
||||
v3s16(0, -1, random.range(-roomsize.Z + 2, -2));
|
||||
if (doordir == v3s16(-1, 0, 0)) // X-
|
||||
roomplace = doorplace +
|
||||
v3s16(-roomsize.X + 1, -1, random.range(-roomsize.Z + 2, -2));
|
||||
if (doordir == v3s16(0, 0, 1)) // Z+
|
||||
roomplace = doorplace +
|
||||
v3s16(random.range(-roomsize.X + 2, -2), -1, 0);
|
||||
if (doordir == v3s16(0, 0, -1)) // Z-
|
||||
roomplace = doorplace +
|
||||
v3s16(random.range(-roomsize.X + 2, -2), -1, -roomsize.Z + 1);
|
||||
#endif
|
||||
#if 0
|
||||
if (doordir == v3s16(1, 0, 0)) // X+
|
||||
roomplace = doorplace + v3s16(0, -1, -roomsize.Z / 2);
|
||||
if (doordir == v3s16(-1, 0, 0)) // X-
|
||||
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z / 2);
|
||||
if (doordir == v3s16(0, 0, 1)) // Z+
|
||||
roomplace = doorplace + v3s16(-roomsize.X / 2, -1, 0);
|
||||
if (doordir == v3s16(0, 0, -1)) // Z-
|
||||
roomplace = doorplace + v3s16(-roomsize.X / 2, -1, -roomsize.Z + 1);
|
||||
#endif
|
||||
|
||||
// Check fit
|
||||
bool fits = true;
|
||||
for (s16 z = 1; z < roomsize.Z - 1; z++)
|
||||
for (s16 y = 1; y < roomsize.Y - 1; y++)
|
||||
for (s16 x = 1; x < roomsize.X - 1; x++)
|
||||
{
|
||||
v3s16 p = roomplace + v3s16(x, y, z);
|
||||
if (vmanip->m_area.contains(p) == false)
|
||||
{
|
||||
fits = false;
|
||||
break;
|
||||
}
|
||||
if (vmanip->m_flags[vmanip->m_area.index(p)]
|
||||
& VMANIP_FLAG_DUNGEON_INSIDE)
|
||||
{
|
||||
fits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(fits == false)
|
||||
{
|
||||
// Find new place
|
||||
continue;
|
||||
}
|
||||
result_doorplace = doorplace;
|
||||
result_doordir = doordir;
|
||||
result_roomplace = roomplace;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
v3s16 rand_ortho_dir(PseudoRandom &random)
|
||||
{
|
||||
if (random.next() % 2 == 0)
|
||||
return random.next() % 2 ? v3s16(-1, 0, 0) : v3s16(1, 0, 0);
|
||||
else
|
||||
return random.next() % 2 ? v3s16(0, 0, -1) : v3s16(0, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
v3s16 turn_xz(v3s16 olddir, int t)
|
||||
{
|
||||
v3s16 dir;
|
||||
if (t == 0)
|
||||
{
|
||||
// Turn right
|
||||
dir.X = olddir.Z;
|
||||
dir.Z = -olddir.X;
|
||||
dir.Y = olddir.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn left
|
||||
dir.X = -olddir.Z;
|
||||
dir.Z = olddir.X;
|
||||
dir.Y = olddir.Y;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
v3s16 random_turn(PseudoRandom &random, v3s16 olddir)
|
||||
{
|
||||
int turn = random.range(0, 2);
|
||||
v3s16 dir;
|
||||
if (turn == 0)
|
||||
{
|
||||
// Go straight
|
||||
dir = olddir;
|
||||
}
|
||||
else if (turn == 1)
|
||||
// Turn right
|
||||
dir = turn_xz(olddir, 0);
|
||||
else
|
||||
// Turn left
|
||||
dir = turn_xz(olddir, 1);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
int dir_to_facedir(v3s16 d) {
|
||||
if (abs(d.X) > abs(d.Z))
|
||||
return d.X < 0 ? 3 : 1;
|
||||
else
|
||||
return d.Z < 0 ? 2 : 0;
|
||||
}
|
128
src/dungeongen.h
Normal file
128
src/dungeongen.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DUNGEONGEN_HEADER
|
||||
#define DUNGEONGEN_HEADER
|
||||
|
||||
#include "voxel.h"
|
||||
#include "noise.h"
|
||||
|
||||
#define VMANIP_FLAG_DUNGEON_INSIDE VOXELFLAG_CHECKED1
|
||||
#define VMANIP_FLAG_DUNGEON_PRESERVE VOXELFLAG_CHECKED2
|
||||
#define VMANIP_FLAG_DUNGEON_UNTOUCHABLE (\
|
||||
VMANIP_FLAG_DUNGEON_INSIDE|VMANIP_FLAG_DUNGEON_PRESERVE)
|
||||
|
||||
class ManualMapVoxelManipulator;
|
||||
class INodeDefManager;
|
||||
|
||||
v3s16 rand_ortho_dir(PseudoRandom &random);
|
||||
v3s16 turn_xz(v3s16 olddir, int t);
|
||||
v3s16 random_turn(PseudoRandom &random, v3s16 olddir);
|
||||
int dir_to_facedir(v3s16 d);
|
||||
|
||||
class DungeonGen {
|
||||
public:
|
||||
u32 blockseed;
|
||||
u64 mapseed;
|
||||
ManualMapVoxelManipulator *vmanip;
|
||||
INodeDefManager *ndef;
|
||||
PseudoRandom random;
|
||||
v3s16 csize;
|
||||
s16 water_level;
|
||||
|
||||
NoiseParams *np_rarity;
|
||||
NoiseParams *np_wetness;
|
||||
NoiseParams *np_density;
|
||||
|
||||
content_t cid_water_source;
|
||||
content_t cid_cobble;
|
||||
content_t cid_mossycobble;
|
||||
content_t cid_torch;
|
||||
content_t cid_cobblestair;
|
||||
|
||||
//RoomWalker
|
||||
v3s16 m_pos;
|
||||
v3s16 m_dir;
|
||||
|
||||
DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel);
|
||||
void generate(ManualMapVoxelManipulator *vm, u32 bseed,
|
||||
v3s16 full_node_min, v3s16 full_node_max);
|
||||
//void generate(v3s16 full_node_min, v3s16 full_node_max, u32 bseed);
|
||||
|
||||
void makeDungeon(v3s16 start_padding);
|
||||
void makeRoom(v3s16 roomsize, v3s16 roomplace);
|
||||
void makeCorridor(v3s16 doorplace, v3s16 doordir,
|
||||
v3s16 &result_place, v3s16 &result_dir);
|
||||
void makeDoor(v3s16 doorplace, v3s16 doordir);
|
||||
void makeFill(v3s16 place, v3s16 size, u8 avoid_flags, MapNode n, u8 or_flags);
|
||||
void makeHole(v3s16 place);
|
||||
|
||||
bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir);
|
||||
bool findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
|
||||
v3s16 &result_doordir, v3s16 &result_roomplace);
|
||||
|
||||
void randomizeDir()
|
||||
{
|
||||
m_dir = rand_ortho_dir(random);
|
||||
}
|
||||
};
|
||||
|
||||
class RoomWalker
|
||||
{
|
||||
public:
|
||||
|
||||
RoomWalker(VoxelManipulator &vmanip_, v3s16 pos, PseudoRandom &random,
|
||||
INodeDefManager *ndef):
|
||||
vmanip(vmanip_),
|
||||
m_pos(pos),
|
||||
m_random(random),
|
||||
m_ndef(ndef)
|
||||
{
|
||||
randomizeDir();
|
||||
}
|
||||
|
||||
void randomizeDir()
|
||||
{
|
||||
m_dir = rand_ortho_dir(m_random);
|
||||
}
|
||||
|
||||
void setPos(v3s16 pos)
|
||||
{
|
||||
m_pos = pos;
|
||||
}
|
||||
|
||||
void setDir(v3s16 dir)
|
||||
{
|
||||
m_dir = dir;
|
||||
}
|
||||
|
||||
//bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir);
|
||||
//bool findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
|
||||
// v3s16 &result_doordir, v3s16 &result_roomplace);
|
||||
|
||||
private:
|
||||
VoxelManipulator &vmanip;
|
||||
v3s16 m_pos;
|
||||
v3s16 m_dir;
|
||||
PseudoRandom &m_random;
|
||||
INodeDefManager *m_ndef;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -39,6 +39,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "biome.h"
|
||||
#include "emerge.h"
|
||||
#include "mapgen_v6.h"
|
||||
#include "mapgen_indev.h"
|
||||
#include "mapgen_singlenode.h"
|
||||
|
||||
|
||||
/////////////////////////////// Emerge Manager ////////////////////////////////
|
||||
@ -46,6 +48,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) {
|
||||
//register built-in mapgens
|
||||
registerMapgen("v6", new MapgenFactoryV6());
|
||||
registerMapgen("indev", new MapgenFactoryIndev());
|
||||
registerMapgen("singlenode", new MapgenFactorySinglenode());
|
||||
|
||||
this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef);
|
||||
this->params = NULL;
|
||||
@ -359,7 +363,7 @@ void *EmergeThread::Thread() {
|
||||
*/
|
||||
BlockMakeData data;
|
||||
MapBlock *block = NULL;
|
||||
core::map<v3s16, MapBlock *> modified_blocks;
|
||||
std::map<v3s16, MapBlock *> modified_blocks;
|
||||
|
||||
if (getBlockOrStartGen(p, &block, &data, allow_generate)) {
|
||||
{
|
||||
@ -415,13 +419,13 @@ void *EmergeThread::Thread() {
|
||||
JMutexAutoLock lock(m_server->m_con_mutex);
|
||||
// Add the originally fetched block to the modified list
|
||||
if (block)
|
||||
modified_blocks.insert(p, block);
|
||||
modified_blocks[p] = block;
|
||||
|
||||
// Set the modified blocks unsent for all the clients
|
||||
for (core::map<u16, RemoteClient*>::Iterator
|
||||
i = m_server->m_clients.getIterator();
|
||||
i.atEnd() == false; i++) {
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
for (std::map<u16, RemoteClient*>::iterator
|
||||
i = m_server->m_clients.begin();
|
||||
i != m_server->m_clients.end(); ++i) {
|
||||
RemoteClient *client = i->second;
|
||||
if (modified_blocks.size() > 0) {
|
||||
// Remove block from sent history
|
||||
client->SetBlocksNotSent(modified_blocks);
|
||||
|
@ -63,8 +63,9 @@ public:
|
||||
std::map<v3s16, BlockEmergeData *> blocks_enqueued;
|
||||
std::map<u16, u16> peer_queue_count;
|
||||
|
||||
//biome manager
|
||||
//Mapgen-related structures
|
||||
BiomeDefManager *biomedef;
|
||||
std::vector<Ore *> ores;
|
||||
|
||||
EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef);
|
||||
~EmergeManager();
|
||||
|
@ -58,8 +58,8 @@ Environment::Environment():
|
||||
Environment::~Environment()
|
||||
{
|
||||
// Deallocate players
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
delete (*i);
|
||||
}
|
||||
@ -86,8 +86,8 @@ void Environment::removePlayer(u16 peer_id)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
re_search:
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
if(player->peer_id != peer_id)
|
||||
@ -103,8 +103,8 @@ re_search:
|
||||
|
||||
Player * Environment::getPlayer(u16 peer_id)
|
||||
{
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
if(player->peer_id == peer_id)
|
||||
@ -115,8 +115,8 @@ Player * Environment::getPlayer(u16 peer_id)
|
||||
|
||||
Player * Environment::getPlayer(const char *name)
|
||||
{
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
if(strcmp(player->getName(), name) == 0)
|
||||
@ -127,12 +127,12 @@ Player * Environment::getPlayer(const char *name)
|
||||
|
||||
Player * Environment::getRandomConnectedPlayer()
|
||||
{
|
||||
core::list<Player*> connected_players = getPlayers(true);
|
||||
std::list<Player*> connected_players = getPlayers(true);
|
||||
u32 chosen_one = myrand() % connected_players.size();
|
||||
u32 j = 0;
|
||||
for(core::list<Player*>::Iterator
|
||||
for(std::list<Player*>::iterator
|
||||
i = connected_players.begin();
|
||||
i != connected_players.end(); i++)
|
||||
i != connected_players.end(); ++i)
|
||||
{
|
||||
if(j == chosen_one)
|
||||
{
|
||||
@ -146,12 +146,12 @@ Player * Environment::getRandomConnectedPlayer()
|
||||
|
||||
Player * Environment::getNearestConnectedPlayer(v3f pos)
|
||||
{
|
||||
core::list<Player*> connected_players = getPlayers(true);
|
||||
std::list<Player*> connected_players = getPlayers(true);
|
||||
f32 nearest_d = 0;
|
||||
Player *nearest_player = NULL;
|
||||
for(core::list<Player*>::Iterator
|
||||
for(std::list<Player*>::iterator
|
||||
i = connected_players.begin();
|
||||
i != connected_players.end(); i++)
|
||||
i != connected_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
f32 d = player->getPosition().getDistanceFrom(pos);
|
||||
@ -164,17 +164,17 @@ Player * Environment::getNearestConnectedPlayer(v3f pos)
|
||||
return nearest_player;
|
||||
}
|
||||
|
||||
core::list<Player*> Environment::getPlayers()
|
||||
std::list<Player*> Environment::getPlayers()
|
||||
{
|
||||
return m_players;
|
||||
}
|
||||
|
||||
core::list<Player*> Environment::getPlayers(bool ignore_disconnected)
|
||||
std::list<Player*> Environment::getPlayers(bool ignore_disconnected)
|
||||
{
|
||||
core::list<Player*> newlist;
|
||||
for(core::list<Player*>::Iterator
|
||||
std::list<Player*> newlist;
|
||||
for(std::list<Player*>::iterator
|
||||
i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
@ -193,7 +193,7 @@ core::list<Player*> Environment::getPlayers(bool ignore_disconnected)
|
||||
void Environment::printPlayers(std::ostream &o)
|
||||
{
|
||||
o<<"Players in environment:"<<std::endl;
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
@ -251,7 +251,7 @@ ABMWithState::ABMWithState(ActiveBlockModifier *abm_):
|
||||
ActiveBlockList
|
||||
*/
|
||||
|
||||
void fillRadiusBlock(v3s16 p0, s16 r, core::map<v3s16, bool> &list)
|
||||
void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
|
||||
{
|
||||
v3s16 p;
|
||||
for(p.X=p0.X-r; p.X<=p0.X+r; p.X++)
|
||||
@ -259,21 +259,21 @@ void fillRadiusBlock(v3s16 p0, s16 r, core::map<v3s16, bool> &list)
|
||||
for(p.Z=p0.Z-r; p.Z<=p0.Z+r; p.Z++)
|
||||
{
|
||||
// Set in list
|
||||
list[p] = true;
|
||||
list.insert(p);
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveBlockList::update(core::list<v3s16> &active_positions,
|
||||
void ActiveBlockList::update(std::list<v3s16> &active_positions,
|
||||
s16 radius,
|
||||
core::map<v3s16, bool> &blocks_removed,
|
||||
core::map<v3s16, bool> &blocks_added)
|
||||
std::set<v3s16> &blocks_removed,
|
||||
std::set<v3s16> &blocks_added)
|
||||
{
|
||||
/*
|
||||
Create the new list
|
||||
*/
|
||||
core::map<v3s16, bool> newlist;
|
||||
for(core::list<v3s16>::Iterator i = active_positions.begin();
|
||||
i != active_positions.end(); i++)
|
||||
std::set<v3s16> newlist;
|
||||
for(std::list<v3s16>::iterator i = active_positions.begin();
|
||||
i != active_positions.end(); ++i)
|
||||
{
|
||||
fillRadiusBlock(*i, radius, newlist);
|
||||
}
|
||||
@ -282,37 +282,37 @@ void ActiveBlockList::update(core::list<v3s16> &active_positions,
|
||||
Find out which blocks on the old list are not on the new list
|
||||
*/
|
||||
// Go through old list
|
||||
for(core::map<v3s16, bool>::Iterator i = m_list.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator i = m_list.begin();
|
||||
i != m_list.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
// If not on new list, it's been removed
|
||||
if(newlist.find(p) == NULL)
|
||||
blocks_removed.insert(p, true);
|
||||
if(newlist.find(p) == newlist.end())
|
||||
blocks_removed.insert(p);
|
||||
}
|
||||
|
||||
/*
|
||||
Find out which blocks on the new list are not on the old list
|
||||
*/
|
||||
// Go through new list
|
||||
for(core::map<v3s16, bool>::Iterator i = newlist.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator i = newlist.begin();
|
||||
i != newlist.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
// If not on old list, it's been added
|
||||
if(m_list.find(p) == NULL)
|
||||
blocks_added.insert(p, true);
|
||||
if(m_list.find(p) == m_list.end())
|
||||
blocks_added.insert(p);
|
||||
}
|
||||
|
||||
/*
|
||||
Update m_list
|
||||
*/
|
||||
m_list.clear();
|
||||
for(core::map<v3s16, bool>::Iterator i = newlist.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator i = newlist.begin();
|
||||
i != newlist.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
m_list.insert(p, true);
|
||||
v3s16 p = *i;
|
||||
m_list.insert(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,8 +348,8 @@ ServerEnvironment::~ServerEnvironment()
|
||||
m_map->drop();
|
||||
|
||||
// Delete ActiveBlockModifiers
|
||||
for(core::list<ABMWithState>::Iterator
|
||||
i = m_abms.begin(); i != m_abms.end(); i++){
|
||||
for(std::list<ABMWithState>::iterator
|
||||
i = m_abms.begin(); i != m_abms.end(); ++i){
|
||||
delete i->abm;
|
||||
}
|
||||
}
|
||||
@ -370,7 +370,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||
std::string players_path = savedir + "/players";
|
||||
fs::CreateDir(players_path);
|
||||
|
||||
core::map<Player*, bool> saved_players;
|
||||
std::set<Player*> saved_players;
|
||||
|
||||
std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
|
||||
for(u32 i=0; i<player_files.size(); i++)
|
||||
@ -419,15 +419,15 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||
continue;
|
||||
}
|
||||
player->serialize(os);
|
||||
saved_players.insert(player, true);
|
||||
saved_players.insert(player);
|
||||
}
|
||||
}
|
||||
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
if(saved_players.find(player) != NULL)
|
||||
if(saved_players.find(player) != saved_players.end())
|
||||
{
|
||||
/*infostream<<"Player "<<player->getName()
|
||||
<<" was already saved."<<std::endl;*/
|
||||
@ -473,7 +473,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||
continue;
|
||||
}
|
||||
player->serialize(os);
|
||||
saved_players.insert(player, true);
|
||||
saved_players.insert(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -484,8 +484,6 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
{
|
||||
std::string players_path = savedir + "/players";
|
||||
|
||||
core::map<Player*, bool> saved_players;
|
||||
|
||||
std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
|
||||
for(u32 i=0; i<player_files.size(); i++)
|
||||
{
|
||||
@ -627,7 +625,7 @@ private:
|
||||
ServerEnvironment *m_env;
|
||||
std::map<content_t, std::list<ActiveABM> > m_aabms;
|
||||
public:
|
||||
ABMHandler(core::list<ABMWithState> &abms,
|
||||
ABMHandler(std::list<ABMWithState> &abms,
|
||||
float dtime_s, ServerEnvironment *env,
|
||||
bool use_timers):
|
||||
m_env(env)
|
||||
@ -635,8 +633,8 @@ public:
|
||||
if(dtime_s < 0.001)
|
||||
return;
|
||||
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||
for(core::list<ABMWithState>::Iterator
|
||||
i = abms.begin(); i != abms.end(); i++){
|
||||
for(std::list<ABMWithState>::iterator
|
||||
i = abms.begin(); i != abms.end(); ++i){
|
||||
ActiveBlockModifier *abm = i->abm;
|
||||
float trigger_interval = abm->getTriggerInterval();
|
||||
if(trigger_interval < 0.001)
|
||||
@ -862,12 +860,12 @@ bool ServerEnvironment::removeNode(v3s16 p)
|
||||
std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
|
||||
{
|
||||
std::set<u16> objects;
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::map<u16, ServerActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
u16 id = i.getNode()->getKey();
|
||||
ServerActiveObject* obj = i->second;
|
||||
u16 id = i->first;
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
if(objectpos.getDistanceFrom(pos) > radius)
|
||||
continue;
|
||||
@ -880,16 +878,16 @@ void ServerEnvironment::clearAllObjects()
|
||||
{
|
||||
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||
<<"Removing all active objects"<<std::endl;
|
||||
core::list<u16> objects_to_remove;
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
std::list<u16> objects_to_remove;
|
||||
for(std::map<u16, ServerActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
ServerActiveObject* obj = i->second;
|
||||
if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||
continue;
|
||||
u16 id = i.getNode()->getKey();
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
u16 id = i->first;
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
// Delete static object if block is loaded
|
||||
if(obj->m_static_exists){
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||
@ -919,13 +917,13 @@ void ServerEnvironment::clearAllObjects()
|
||||
objects_to_remove.push_back(id);
|
||||
}
|
||||
// Remove references from m_active_objects
|
||||
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); i++)
|
||||
for(std::list<u16>::iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); ++i)
|
||||
{
|
||||
m_active_objects.remove(*i);
|
||||
m_active_objects.erase(*i);
|
||||
}
|
||||
|
||||
core::list<v3s16> loadable_blocks;
|
||||
std::list<v3s16> loadable_blocks;
|
||||
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||
<<"Listing all loadable blocks"<<std::endl;
|
||||
m_map->listAllLoadableBlocks(loadable_blocks);
|
||||
@ -937,8 +935,8 @@ void ServerEnvironment::clearAllObjects()
|
||||
u32 num_blocks_checked = 0;
|
||||
u32 num_blocks_cleared = 0;
|
||||
u32 num_objs_cleared = 0;
|
||||
for(core::list<v3s16>::Iterator i = loadable_blocks.begin();
|
||||
i != loadable_blocks.end(); i++)
|
||||
for(std::list<v3s16>::iterator i = loadable_blocks.begin();
|
||||
i != loadable_blocks.end(); ++i)
|
||||
{
|
||||
v3s16 p = *i;
|
||||
MapBlock *block = m_map->emergeBlock(p, false);
|
||||
@ -1002,8 +1000,8 @@ void ServerEnvironment::step(float dtime)
|
||||
*/
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
@ -1027,10 +1025,10 @@ void ServerEnvironment::step(float dtime)
|
||||
/*
|
||||
Get player block positions
|
||||
*/
|
||||
core::list<v3s16> players_blockpos;
|
||||
for(core::list<Player*>::Iterator
|
||||
std::list<v3s16> players_blockpos;
|
||||
for(std::list<Player*>::iterator
|
||||
i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
// Ignore disconnected players
|
||||
@ -1045,8 +1043,8 @@ void ServerEnvironment::step(float dtime)
|
||||
Update list of active blocks, collecting changes
|
||||
*/
|
||||
const s16 active_block_range = g_settings->getS16("active_block_range");
|
||||
core::map<v3s16, bool> blocks_removed;
|
||||
core::map<v3s16, bool> blocks_added;
|
||||
std::set<v3s16> blocks_removed;
|
||||
std::set<v3s16> blocks_added;
|
||||
m_active_blocks.update(players_blockpos, active_block_range,
|
||||
blocks_removed, blocks_added);
|
||||
|
||||
@ -1057,11 +1055,11 @@ void ServerEnvironment::step(float dtime)
|
||||
// Convert active objects that are no more in active blocks to static
|
||||
deactivateFarObjects(false);
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = blocks_removed.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator
|
||||
i = blocks_removed.begin();
|
||||
i != blocks_removed.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") became inactive"<<std::endl;*/
|
||||
@ -1078,11 +1076,11 @@ void ServerEnvironment::step(float dtime)
|
||||
Handle added blocks
|
||||
*/
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = blocks_added.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator
|
||||
i = blocks_added.begin();
|
||||
i != blocks_added.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") became active"<<std::endl;*/
|
||||
@ -1091,7 +1089,7 @@ void ServerEnvironment::step(float dtime)
|
||||
if(block==NULL){
|
||||
// Block needs to be fetched first
|
||||
m_emerger->queueBlockEmerge(p, false);
|
||||
m_active_blocks.m_list.remove(p);
|
||||
m_active_blocks.m_list.erase(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1108,11 +1106,11 @@ void ServerEnvironment::step(float dtime)
|
||||
|
||||
float dtime = 1.0;
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.m_list.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator
|
||||
i = m_active_blocks.m_list.begin();
|
||||
i != m_active_blocks.m_list.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") being handled"<<std::endl;*/
|
||||
@ -1163,11 +1161,11 @@ void ServerEnvironment::step(float dtime)
|
||||
// Initialize handling of ActiveBlockModifiers
|
||||
ABMHandler abmhandler(m_abms, abm_interval, this, true);
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.m_list.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator
|
||||
i = m_active_blocks.m_list.begin();
|
||||
i != m_active_blocks.m_list.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") being handled"<<std::endl;*/
|
||||
@ -1216,11 +1214,11 @@ void ServerEnvironment::step(float dtime)
|
||||
send_recommended = true;
|
||||
}
|
||||
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::map<u16, ServerActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
ServerActiveObject* obj = i->second;
|
||||
// Remove non-peaceful mobs on peaceful mode
|
||||
if(g_settings->getBool("only_peaceful_mobs")){
|
||||
if(!obj->isPeaceful())
|
||||
@ -1232,7 +1230,7 @@ void ServerEnvironment::step(float dtime)
|
||||
// Step object
|
||||
obj->step(dtime, send_recommended);
|
||||
// Read messages from object
|
||||
while(obj->m_messages_out.size() > 0)
|
||||
while(!obj->m_messages_out.empty())
|
||||
{
|
||||
m_active_object_messages.push_back(
|
||||
obj->m_messages_out.pop_front());
|
||||
@ -1255,31 +1253,24 @@ void ServerEnvironment::step(float dtime)
|
||||
|
||||
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
|
||||
{
|
||||
core::map<u16, ServerActiveObject*>::Node *n;
|
||||
std::map<u16, ServerActiveObject*>::iterator n;
|
||||
n = m_active_objects.find(id);
|
||||
if(n == NULL)
|
||||
if(n == m_active_objects.end())
|
||||
return NULL;
|
||||
return n->getValue();
|
||||
return n->second;
|
||||
}
|
||||
|
||||
bool isFreeServerActiveObjectId(u16 id,
|
||||
core::map<u16, ServerActiveObject*> &objects)
|
||||
std::map<u16, ServerActiveObject*> &objects)
|
||||
{
|
||||
if(id == 0)
|
||||
return false;
|
||||
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
if(i.getNode()->getKey() == id)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return objects.find(id) == objects.end();
|
||||
}
|
||||
|
||||
u16 getFreeServerActiveObjectId(
|
||||
core::map<u16, ServerActiveObject*> &objects)
|
||||
std::map<u16, ServerActiveObject*> &objects)
|
||||
{
|
||||
u16 new_id = 1;
|
||||
for(;;)
|
||||
@ -1351,8 +1342,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
|
||||
inside a radius around a position
|
||||
*/
|
||||
void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||
core::map<u16, bool> ¤t_objects,
|
||||
core::map<u16, bool> &added_objects)
|
||||
std::set<u16> ¤t_objects,
|
||||
std::set<u16> &added_objects)
|
||||
{
|
||||
v3f pos_f = intToFloat(pos, BS);
|
||||
f32 radius_f = radius * BS;
|
||||
@ -1363,13 +1354,13 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||
- discard objects that are found in current_objects.
|
||||
- add remaining objects to added_objects
|
||||
*/
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::map<u16, ServerActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
u16 id = i.getNode()->getKey();
|
||||
u16 id = i->first;
|
||||
// Get object
|
||||
ServerActiveObject *object = i.getNode()->getValue();
|
||||
ServerActiveObject *object = i->second;
|
||||
if(object == NULL)
|
||||
continue;
|
||||
// Discard if removed
|
||||
@ -1382,12 +1373,12 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||
continue;
|
||||
}
|
||||
// Discard if already on current_objects
|
||||
core::map<u16, bool>::Node *n;
|
||||
std::set<u16>::iterator n;
|
||||
n = current_objects.find(id);
|
||||
if(n != NULL)
|
||||
if(n != current_objects.end())
|
||||
continue;
|
||||
// Add to added_objects
|
||||
added_objects.insert(id, false);
|
||||
added_objects.insert(id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1396,8 +1387,8 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||
inside a radius around a position
|
||||
*/
|
||||
void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||
core::map<u16, bool> ¤t_objects,
|
||||
core::map<u16, bool> &removed_objects)
|
||||
std::set<u16> ¤t_objects,
|
||||
std::set<u16> &removed_objects)
|
||||
{
|
||||
v3f pos_f = intToFloat(pos, BS);
|
||||
f32 radius_f = radius * BS;
|
||||
@ -1409,23 +1400,23 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||
- object has m_removed=true, or
|
||||
- object is too far away
|
||||
*/
|
||||
for(core::map<u16, bool>::Iterator
|
||||
i = current_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<u16>::iterator
|
||||
i = current_objects.begin();
|
||||
i != current_objects.end(); ++i)
|
||||
{
|
||||
u16 id = i.getNode()->getKey();
|
||||
u16 id = *i;
|
||||
ServerActiveObject *object = getActiveObject(id);
|
||||
|
||||
if(object == NULL){
|
||||
infostream<<"ServerEnvironment::getRemovedActiveObjects():"
|
||||
<<" object in current_objects is NULL"<<std::endl;
|
||||
removed_objects.insert(id, false);
|
||||
removed_objects.insert(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(object->m_removed)
|
||||
{
|
||||
removed_objects.insert(id, false);
|
||||
removed_objects.insert(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1437,7 +1428,7 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||
|
||||
if(distance_f >= radius_f)
|
||||
{
|
||||
removed_objects.insert(id, false);
|
||||
removed_objects.insert(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1447,7 +1438,7 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||
|
||||
ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
|
||||
{
|
||||
if(m_active_object_messages.size() == 0)
|
||||
if(m_active_object_messages.empty())
|
||||
return ActiveObjectMessage(0);
|
||||
|
||||
return m_active_object_messages.pop_front();
|
||||
@ -1488,7 +1479,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
/*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"added (id="<<object->getId()<<")"<<std::endl;*/
|
||||
|
||||
m_active_objects.insert(object->getId(), object);
|
||||
m_active_objects[object->getId()] = object;
|
||||
|
||||
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"Added id="<<object->getId()<<"; there are now "
|
||||
@ -1512,7 +1503,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.m_active.insert(object->getId(), s_obj);
|
||||
block->m_static_objects.m_active[object->getId()] = s_obj;
|
||||
object->m_static_exists = true;
|
||||
object->m_static_block = blockpos;
|
||||
|
||||
@ -1536,13 +1527,13 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
*/
|
||||
void ServerEnvironment::removeRemovedObjects()
|
||||
{
|
||||
core::list<u16> objects_to_remove;
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
std::list<u16> objects_to_remove;
|
||||
for(std::map<u16, ServerActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
u16 id = i.getNode()->getKey();
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
u16 id = i->first;
|
||||
ServerActiveObject* obj = i->second;
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
@ -1593,10 +1584,10 @@ void ServerEnvironment::removeRemovedObjects()
|
||||
objects_to_remove.push_back(id);
|
||||
}
|
||||
// Remove references from m_active_objects
|
||||
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); i++)
|
||||
for(std::list<u16>::iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); ++i)
|
||||
{
|
||||
m_active_objects.remove(*i);
|
||||
m_active_objects.erase(*i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1663,11 +1654,11 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||
}
|
||||
// A list for objects that couldn't be converted to active for some
|
||||
// reason. They will be stored back.
|
||||
core::list<StaticObject> new_stored;
|
||||
std::list<StaticObject> new_stored;
|
||||
// Loop through stored static objects
|
||||
for(core::list<StaticObject>::Iterator
|
||||
for(std::list<StaticObject>::iterator
|
||||
i = block->m_static_objects.m_stored.begin();
|
||||
i != block->m_static_objects.m_stored.end(); i++)
|
||||
i != block->m_static_objects.m_stored.end(); ++i)
|
||||
{
|
||||
/*infostream<<"Server: Creating an active object from "
|
||||
<<"static data"<<std::endl;*/
|
||||
@ -1696,9 +1687,9 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||
// Clear stored list
|
||||
block->m_static_objects.m_stored.clear();
|
||||
// Add leftover failed stuff to stored list
|
||||
for(core::list<StaticObject>::Iterator
|
||||
for(std::list<StaticObject>::iterator
|
||||
i = new_stored.begin();
|
||||
i != new_stored.end(); i++)
|
||||
i != new_stored.end(); ++i)
|
||||
{
|
||||
StaticObject &s_obj = *i;
|
||||
block->m_static_objects.m_stored.push_back(s_obj);
|
||||
@ -1726,12 +1717,12 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||
*/
|
||||
void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
{
|
||||
core::list<u16> objects_to_remove;
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
std::list<u16> objects_to_remove;
|
||||
for(std::map<u16, ServerActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
ServerActiveObject* obj = i->second;
|
||||
assert(obj);
|
||||
|
||||
// Do not deactivate if static data creation not allowed
|
||||
@ -1742,7 +1733,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
if(!force_delete && obj->m_pending_deactivation)
|
||||
continue;
|
||||
|
||||
u16 id = i.getNode()->getKey();
|
||||
u16 id = i->first;
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
|
||||
// The block in which the object resides in
|
||||
@ -1778,10 +1769,10 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
|
||||
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||
|
||||
core::map<u16, StaticObject>::Node *n =
|
||||
std::map<u16, StaticObject>::iterator n =
|
||||
block->m_static_objects.m_active.find(id);
|
||||
if(n){
|
||||
StaticObject static_old = n->getValue();
|
||||
if(n != block->m_static_objects.m_active.end()){
|
||||
StaticObject static_old = n->second;
|
||||
|
||||
float save_movem = obj->getMinimumSavedMovement();
|
||||
|
||||
@ -1840,7 +1831,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
// This shouldn't happen, but happens rarely for some
|
||||
// unknown reason. Unsuccessful attempts have been made to
|
||||
// find said reason.
|
||||
if(new_id && block->m_static_objects.m_active.find(new_id)){
|
||||
if(new_id && block->m_static_objects.m_active.find(new_id) != block->m_static_objects.m_active.end()){
|
||||
infostream<<"ServerEnv: WARNING: Performing hack #83274"
|
||||
<<std::endl;
|
||||
block->m_static_objects.remove(new_id);
|
||||
@ -1900,10 +1891,10 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
}
|
||||
|
||||
// Remove references from m_active_objects
|
||||
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); i++)
|
||||
for(std::list<u16>::iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); ++i)
|
||||
{
|
||||
m_active_objects.remove(*i);
|
||||
m_active_objects.erase(*i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1930,15 +1921,15 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
|
||||
ClientEnvironment::~ClientEnvironment()
|
||||
{
|
||||
// delete active objects
|
||||
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::map<u16, ClientActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
delete i.getNode()->getValue();
|
||||
delete i->second;
|
||||
}
|
||||
|
||||
for(core::list<ClientSimpleObject*>::Iterator
|
||||
i = m_simple_objects.begin(); i != m_simple_objects.end(); i++)
|
||||
for(std::list<ClientSimpleObject*>::iterator
|
||||
i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
@ -1971,8 +1962,8 @@ void ClientEnvironment::addPlayer(Player *player)
|
||||
|
||||
LocalPlayer * ClientEnvironment::getLocalPlayer()
|
||||
{
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
if(player->isLocal())
|
||||
@ -1996,7 +1987,7 @@ void ClientEnvironment::step(float dtime)
|
||||
LocalPlayer *lplayer = getLocalPlayer();
|
||||
assert(lplayer);
|
||||
// collision info queue
|
||||
core::list<CollisionInfo> player_collisions;
|
||||
std::list<CollisionInfo> player_collisions;
|
||||
|
||||
/*
|
||||
Get the speed the player is going
|
||||
@ -2105,7 +2096,7 @@ void ClientEnvironment::step(float dtime)
|
||||
Move the lplayer.
|
||||
This also does collision detection.
|
||||
*/
|
||||
lplayer->move(dtime_part, *m_map, position_max_increment,
|
||||
lplayer->move(dtime_part, this, position_max_increment,
|
||||
&player_collisions);
|
||||
}
|
||||
}
|
||||
@ -2113,9 +2104,9 @@ void ClientEnvironment::step(float dtime)
|
||||
|
||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||
|
||||
for(core::list<CollisionInfo>::Iterator
|
||||
for(std::list<CollisionInfo>::iterator
|
||||
i = player_collisions.begin();
|
||||
i != player_collisions.end(); i++)
|
||||
i != player_collisions.end(); ++i)
|
||||
{
|
||||
CollisionInfo &info = *i;
|
||||
v3f speed_diff = info.new_speed - info.old_speed;;
|
||||
@ -2179,8 +2170,8 @@ void ClientEnvironment::step(float dtime)
|
||||
/*
|
||||
Stuff that can be done in an arbitarily large dtime
|
||||
*/
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
for(std::list<Player*>::iterator i = m_players.begin();
|
||||
i != m_players.end(); ++i)
|
||||
{
|
||||
Player *player = *i;
|
||||
v3f playerpos = player->getPosition();
|
||||
@ -2214,11 +2205,11 @@ void ClientEnvironment::step(float dtime)
|
||||
*/
|
||||
|
||||
bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21);
|
||||
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::map<u16, ClientActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
ClientActiveObject* obj = i.getNode()->getValue();
|
||||
ClientActiveObject* obj = i->second;
|
||||
// Step object
|
||||
obj->step(dtime, this);
|
||||
|
||||
@ -2242,12 +2233,12 @@ void ClientEnvironment::step(float dtime)
|
||||
/*
|
||||
Step and handle simple objects
|
||||
*/
|
||||
for(core::list<ClientSimpleObject*>::Iterator
|
||||
for(std::list<ClientSimpleObject*>::iterator
|
||||
i = m_simple_objects.begin(); i != m_simple_objects.end();)
|
||||
{
|
||||
ClientSimpleObject *simple = *i;
|
||||
core::list<ClientSimpleObject*>::Iterator cur = i;
|
||||
i++;
|
||||
std::list<ClientSimpleObject*>::iterator cur = i;
|
||||
++i;
|
||||
simple->step(dtime);
|
||||
if(simple->m_to_be_removed){
|
||||
delete simple;
|
||||
@ -2263,31 +2254,24 @@ void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple)
|
||||
|
||||
ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
|
||||
{
|
||||
core::map<u16, ClientActiveObject*>::Node *n;
|
||||
std::map<u16, ClientActiveObject*>::iterator n;
|
||||
n = m_active_objects.find(id);
|
||||
if(n == NULL)
|
||||
if(n == m_active_objects.end())
|
||||
return NULL;
|
||||
return n->getValue();
|
||||
return n->second;
|
||||
}
|
||||
|
||||
bool isFreeClientActiveObjectId(u16 id,
|
||||
core::map<u16, ClientActiveObject*> &objects)
|
||||
std::map<u16, ClientActiveObject*> &objects)
|
||||
{
|
||||
if(id == 0)
|
||||
return false;
|
||||
|
||||
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||
i = objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
if(i.getNode()->getKey() == id)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return objects.find(id) == objects.end();
|
||||
}
|
||||
|
||||
u16 getFreeClientActiveObjectId(
|
||||
core::map<u16, ClientActiveObject*> &objects)
|
||||
std::map<u16, ClientActiveObject*> &objects)
|
||||
{
|
||||
u16 new_id = 1;
|
||||
for(;;)
|
||||
@ -2326,7 +2310,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
||||
}
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"added (id="<<object->getId()<<")"<<std::endl;
|
||||
m_active_objects.insert(object->getId(), object);
|
||||
m_active_objects[object->getId()] = object;
|
||||
object->addToScene(m_smgr, m_texturesource, m_irr);
|
||||
{ // Update lighting immediately
|
||||
u8 light = 0;
|
||||
@ -2389,7 +2373,7 @@ void ClientEnvironment::removeActiveObject(u16 id)
|
||||
}
|
||||
obj->removeFromScene(true);
|
||||
delete obj;
|
||||
m_active_objects.remove(id);
|
||||
m_active_objects.erase(id);
|
||||
}
|
||||
|
||||
void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||
@ -2445,13 +2429,13 @@ void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
|
||||
*/
|
||||
|
||||
void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
|
||||
core::array<DistanceSortedActiveObject> &dest)
|
||||
std::vector<DistanceSortedActiveObject> &dest)
|
||||
{
|
||||
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::map<u16, ClientActiveObject*>::iterator
|
||||
i = m_active_objects.begin();
|
||||
i != m_active_objects.end(); ++i)
|
||||
{
|
||||
ClientActiveObject* obj = i.getNode()->getValue();
|
||||
ClientActiveObject* obj = i->second;
|
||||
|
||||
f32 d = (obj->getPosition() - origin).getLength();
|
||||
|
||||
@ -2466,7 +2450,7 @@ void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
|
||||
|
||||
ClientEnvEvent ClientEnvironment::getClientEvent()
|
||||
{
|
||||
if(m_client_event_queue.size() == 0)
|
||||
if(m_client_event_queue.empty())
|
||||
{
|
||||
ClientEnvEvent event;
|
||||
event.type = CEE_NONE;
|
||||
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "player.h"
|
||||
#include <ostream>
|
||||
@ -73,8 +74,8 @@ public:
|
||||
Player * getPlayer(const char *name);
|
||||
Player * getRandomConnectedPlayer();
|
||||
Player * getNearestConnectedPlayer(v3f pos);
|
||||
core::list<Player*> getPlayers();
|
||||
core::list<Player*> getPlayers(bool ignore_disconnected);
|
||||
std::list<Player*> getPlayers();
|
||||
std::list<Player*> getPlayers(bool ignore_disconnected);
|
||||
void printPlayers(std::ostream &o);
|
||||
|
||||
u32 getDayNightRatio();
|
||||
@ -102,7 +103,7 @@ public:
|
||||
|
||||
protected:
|
||||
// peer_ids in here should be unique, except that there may be many 0s
|
||||
core::list<Player*> m_players;
|
||||
std::list<Player*> m_players;
|
||||
// Time of day in milli-hours (0-23999); determines day and night
|
||||
u32 m_time_of_day;
|
||||
// Time of day in 0...1
|
||||
@ -156,20 +157,20 @@ struct ABMWithState
|
||||
class ActiveBlockList
|
||||
{
|
||||
public:
|
||||
void update(core::list<v3s16> &active_positions,
|
||||
void update(std::list<v3s16> &active_positions,
|
||||
s16 radius,
|
||||
core::map<v3s16, bool> &blocks_removed,
|
||||
core::map<v3s16, bool> &blocks_added);
|
||||
std::set<v3s16> &blocks_removed,
|
||||
std::set<v3s16> &blocks_added);
|
||||
|
||||
bool contains(v3s16 p){
|
||||
return (m_list.find(p) != NULL);
|
||||
return (m_list.find(p) != m_list.end());
|
||||
}
|
||||
|
||||
void clear(){
|
||||
m_list.clear();
|
||||
}
|
||||
|
||||
core::map<v3s16, bool> m_list;
|
||||
std::set<v3s16> m_list;
|
||||
|
||||
private:
|
||||
};
|
||||
@ -249,16 +250,16 @@ public:
|
||||
inside a radius around a position
|
||||
*/
|
||||
void getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||
core::map<u16, bool> ¤t_objects,
|
||||
core::map<u16, bool> &added_objects);
|
||||
std::set<u16> ¤t_objects,
|
||||
std::set<u16> &added_objects);
|
||||
|
||||
/*
|
||||
Find out what new objects have been removed from
|
||||
inside a radius around a position
|
||||
*/
|
||||
void getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||
core::map<u16, bool> ¤t_objects,
|
||||
core::map<u16, bool> &removed_objects);
|
||||
std::set<u16> ¤t_objects,
|
||||
std::set<u16> &removed_objects);
|
||||
|
||||
/*
|
||||
Get the next message emitted by some active object.
|
||||
@ -350,7 +351,7 @@ private:
|
||||
// Background block emerger (the server, in practice)
|
||||
IBackgroundBlockEmerger *m_emerger;
|
||||
// Active object list
|
||||
core::map<u16, ServerActiveObject*> m_active_objects;
|
||||
std::map<u16, ServerActiveObject*> m_active_objects;
|
||||
// Outgoing network message buffer for active objects
|
||||
Queue<ActiveObjectMessage> m_active_object_messages;
|
||||
// Some timers
|
||||
@ -368,7 +369,7 @@ private:
|
||||
u32 m_game_time;
|
||||
// A helper variable for incrementing the latter
|
||||
float m_game_time_fraction_counter;
|
||||
core::list<ABMWithState> m_abms;
|
||||
std::list<ABMWithState> m_abms;
|
||||
// An interval for generally sending object positions and stuff
|
||||
float m_recommended_send_interval;
|
||||
};
|
||||
@ -463,7 +464,7 @@ public:
|
||||
|
||||
// Get all nearby objects
|
||||
void getActiveObjects(v3f origin, f32 max_d,
|
||||
core::array<DistanceSortedActiveObject> &dest);
|
||||
std::vector<DistanceSortedActiveObject> &dest);
|
||||
|
||||
// Get event from queue. CEE_NONE is returned if queue is empty.
|
||||
ClientEnvEvent getClientEvent();
|
||||
@ -476,8 +477,8 @@ private:
|
||||
ITextureSource *m_texturesource;
|
||||
IGameDef *m_gamedef;
|
||||
IrrlichtDevice *m_irr;
|
||||
core::map<u16, ClientActiveObject*> m_active_objects;
|
||||
core::list<ClientSimpleObject*> m_simple_objects;
|
||||
std::map<u16, ClientActiveObject*> m_active_objects;
|
||||
std::list<ClientSimpleObject*> m_simple_objects;
|
||||
Queue<ClientEnvEvent> m_client_event_queue;
|
||||
IntervalLimiter m_active_object_light_update_interval;
|
||||
IntervalLimiter m_lava_hurt_interval;
|
||||
|
@ -112,13 +112,13 @@ struct HeightPoint
|
||||
float have_sand;
|
||||
float tree_amount;
|
||||
};
|
||||
core::map<v2s16, HeightPoint> g_heights;
|
||||
std::map<v2s16, HeightPoint> g_heights;
|
||||
|
||||
HeightPoint ground_height(u64 seed, v2s16 p2d)
|
||||
{
|
||||
core::map<v2s16, HeightPoint>::Node *n = g_heights.find(p2d);
|
||||
if(n)
|
||||
return n->getValue();
|
||||
std::map<v2s16, HeightPoint>::iterator n = g_heights.find(p2d);
|
||||
if(n != g_heights.end())
|
||||
return n->second;
|
||||
HeightPoint hp;
|
||||
s16 level = Mapgen::find_ground_level_from_noise(seed, p2d, 3);
|
||||
hp.gh = (level-4)*BS;
|
||||
|
57
src/game.cpp
57
src/game.cpp
@ -2186,6 +2186,47 @@ void the_game(
|
||||
{
|
||||
update_wielded_item_trigger = true;
|
||||
}
|
||||
else if(event.type == CE_SPAWN_PARTICLE)
|
||||
{
|
||||
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
||||
AtlasPointer ap =
|
||||
gamedef->tsrc()->getTexture(*(event.spawn_particle.texture));
|
||||
|
||||
new Particle(gamedef, smgr, player, client.getEnv(),
|
||||
*event.spawn_particle.pos,
|
||||
*event.spawn_particle.vel,
|
||||
*event.spawn_particle.acc,
|
||||
event.spawn_particle.expirationtime,
|
||||
event.spawn_particle.size,
|
||||
event.spawn_particle.collisiondetection, ap);
|
||||
}
|
||||
else if(event.type == CE_ADD_PARTICLESPAWNER)
|
||||
{
|
||||
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
||||
AtlasPointer ap =
|
||||
gamedef->tsrc()->getTexture(*(event.add_particlespawner.texture));
|
||||
|
||||
new ParticleSpawner(gamedef, smgr, player,
|
||||
event.add_particlespawner.amount,
|
||||
event.add_particlespawner.spawntime,
|
||||
*event.add_particlespawner.minpos,
|
||||
*event.add_particlespawner.maxpos,
|
||||
*event.add_particlespawner.minvel,
|
||||
*event.add_particlespawner.maxvel,
|
||||
*event.add_particlespawner.minacc,
|
||||
*event.add_particlespawner.maxacc,
|
||||
event.add_particlespawner.minexptime,
|
||||
event.add_particlespawner.maxexptime,
|
||||
event.add_particlespawner.minsize,
|
||||
event.add_particlespawner.maxsize,
|
||||
event.add_particlespawner.collisiondetection,
|
||||
ap,
|
||||
event.add_particlespawner.id);
|
||||
}
|
||||
else if(event.type == CE_DELETE_PARTICLESPAWNER)
|
||||
{
|
||||
delete_particlespawner (event.delete_particlespawner.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2353,11 +2394,6 @@ void the_game(
|
||||
}
|
||||
}
|
||||
|
||||
// We can't actually know, but assume the sound of right-clicking
|
||||
// to be the sound of placing a node
|
||||
soundmaker.m_player_rightpunch_sound.gain = 0.5;
|
||||
soundmaker.m_player_rightpunch_sound.name = "default_place_node";
|
||||
|
||||
/*
|
||||
Handle digging
|
||||
*/
|
||||
@ -2415,7 +2451,8 @@ void the_game(
|
||||
const ContentFeatures &features =
|
||||
client.getNodeDefManager()->get(n);
|
||||
addPunchingParticles
|
||||
(gamedef, smgr, player, nodepos, features.tiles);
|
||||
(gamedef, smgr, player, client.getEnv(),
|
||||
nodepos, features.tiles);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2453,7 +2490,8 @@ void the_game(
|
||||
const ContentFeatures &features =
|
||||
client.getNodeDefManager()->get(wasnode);
|
||||
addDiggingParticles
|
||||
(gamedef, smgr, player, nodepos, features.tiles);
|
||||
(gamedef, smgr, player, client.getEnv(),
|
||||
nodepos, features.tiles);
|
||||
}
|
||||
|
||||
dig_time = 0;
|
||||
@ -2574,6 +2612,9 @@ void the_game(
|
||||
<<") - Position not loaded"<<std::endl;
|
||||
}
|
||||
}while(0);
|
||||
|
||||
// Read the sound
|
||||
soundmaker.m_player_rightpunch_sound = def.sound_place;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2734,6 +2775,7 @@ void the_game(
|
||||
*/
|
||||
|
||||
allparticles_step(dtime, client.getEnv());
|
||||
allparticlespawners_step(dtime, client.getEnv());
|
||||
|
||||
/*
|
||||
Fog
|
||||
@ -3220,6 +3262,7 @@ void the_game(
|
||||
clouds->drop();
|
||||
if(gui_chat_console)
|
||||
gui_chat_console->drop();
|
||||
clear_particles ();
|
||||
|
||||
/*
|
||||
Draw a "shutting down" screen, which will be shown while the map
|
||||
|
25
src/game.h
25
src/game.h
@ -23,17 +23,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include <string>
|
||||
#include "keycode.h"
|
||||
#include <list>
|
||||
|
||||
class KeyList : protected core::list<KeyPress>
|
||||
class KeyList : protected std::list<KeyPress>
|
||||
{
|
||||
typedef core::list<KeyPress> super;
|
||||
typedef super::Iterator Iterator;
|
||||
typedef super::ConstIterator ConstIterator;
|
||||
typedef std::list<KeyPress> super;
|
||||
typedef super::iterator iterator;
|
||||
typedef super::const_iterator const_iterator;
|
||||
|
||||
virtual ConstIterator find(const KeyPress &key) const
|
||||
virtual const_iterator find(const KeyPress &key) const
|
||||
{
|
||||
ConstIterator f(begin());
|
||||
ConstIterator e(end());
|
||||
const_iterator f(begin());
|
||||
const_iterator e(end());
|
||||
while (f!=e) {
|
||||
if (*f == key)
|
||||
return f;
|
||||
@ -42,10 +43,10 @@ class KeyList : protected core::list<KeyPress>
|
||||
return e;
|
||||
}
|
||||
|
||||
virtual Iterator find(const KeyPress &key)
|
||||
virtual iterator find(const KeyPress &key)
|
||||
{
|
||||
Iterator f(begin());
|
||||
Iterator e(end());
|
||||
iterator f(begin());
|
||||
iterator e(end());
|
||||
while (f!=e) {
|
||||
if (*f == key)
|
||||
return f;
|
||||
@ -65,14 +66,14 @@ public:
|
||||
|
||||
void unset(const KeyPress &key)
|
||||
{
|
||||
Iterator p(find(key));
|
||||
iterator p(find(key));
|
||||
if (p != end())
|
||||
erase(p);
|
||||
}
|
||||
|
||||
void toggle(const KeyPress &key)
|
||||
{
|
||||
Iterator p(this->find(key));
|
||||
iterator p(this->find(key));
|
||||
if (p != end())
|
||||
erase(p);
|
||||
else
|
||||
|
@ -31,7 +31,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
Normal build: main.cpp
|
||||
Server build: servermain.cpp
|
||||
*/
|
||||
enum TimePrecision {
|
||||
PRECISION_SECONDS,
|
||||
PRECISION_MILLI,
|
||||
PRECISION_MICRO,
|
||||
PRECISION_NANO
|
||||
};
|
||||
|
||||
extern u32 getTimeMs();
|
||||
extern u32 getTime(TimePrecision prec);
|
||||
|
||||
/*
|
||||
Timestamp stuff
|
||||
|
@ -535,7 +535,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
|
||||
{
|
||||
// Tab or Shift-Tab pressed
|
||||
// Nick completion
|
||||
core::list<std::wstring> names = m_client->getConnectedPlayerNames();
|
||||
std::list<std::wstring> names = m_client->getConnectedPlayerNames();
|
||||
bool backwards = event.KeyInput.Shift;
|
||||
m_chat_backend->getPrompt().nickCompletion(names, backwards);
|
||||
return true;
|
||||
|
@ -207,18 +207,18 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
Strfnd f(m_formspec_string);
|
||||
while(f.atend() == false)
|
||||
{
|
||||
std::string type = trim(f.next("["));
|
||||
std::string type = trim(f.next_esc("["));
|
||||
if(type == "invsize" || type == "size")
|
||||
{
|
||||
v2f invsize;
|
||||
invsize.X = stof(f.next(","));
|
||||
invsize.X = stof(f.next_esc(","));
|
||||
if(type == "size")
|
||||
{
|
||||
invsize.Y = stof(f.next("]"));
|
||||
invsize.Y = stof(f.next_esc("]"));
|
||||
}
|
||||
else{
|
||||
invsize.Y = stof(f.next(";"));
|
||||
f.next("]");
|
||||
invsize.Y = stof(f.next_esc(";"));
|
||||
f.next_esc("]");
|
||||
}
|
||||
infostream<<"Form size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||
|
||||
@ -242,24 +242,24 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
}
|
||||
else if(type == "list")
|
||||
{
|
||||
std::string name = f.next(";");
|
||||
std::string name = f.next_esc(";");
|
||||
InventoryLocation loc;
|
||||
if(name == "context" || name == "current_name")
|
||||
loc = m_current_inventory_location;
|
||||
else
|
||||
loc.deSerialize(name);
|
||||
std::string listname = f.next(";");
|
||||
std::string listname = f.next_esc(";");
|
||||
v2s32 pos = basepos;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
v2s32 geom;
|
||||
geom.X = stoi(f.next(","));
|
||||
geom.Y = stoi(f.next(";"));
|
||||
geom.X = stoi(f.next_esc(","));
|
||||
geom.Y = stoi(f.next_esc(";"));
|
||||
infostream<<"list inv="<<name<<", listname="<<listname
|
||||
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
||||
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
||||
<<std::endl;
|
||||
std::string start_i_s = f.next("]");
|
||||
std::string start_i_s = f.next_esc("]");
|
||||
s32 start_i = 0;
|
||||
if(start_i_s != "")
|
||||
start_i = stoi(start_i_s);
|
||||
@ -270,12 +270,12 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "image")
|
||||
{
|
||||
v2s32 pos = basepos;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
v2s32 geom;
|
||||
geom.X = stof(f.next(",")) * (float)imgsize.X;
|
||||
geom.Y = stof(f.next(";")) * (float)imgsize.Y;
|
||||
std::string name = f.next("]");
|
||||
geom.X = stof(f.next_esc(",")) * (float)imgsize.X;
|
||||
geom.Y = stof(f.next_esc(";")) * (float)imgsize.Y;
|
||||
std::string name = f.next_esc("]");
|
||||
infostream<<"image name="<<name
|
||||
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
||||
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
||||
@ -287,12 +287,12 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "item_image")
|
||||
{
|
||||
v2s32 pos = basepos;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
v2s32 geom;
|
||||
geom.X = stof(f.next(",")) * (float)imgsize.X;
|
||||
geom.Y = stof(f.next(";")) * (float)imgsize.Y;
|
||||
std::string name = f.next("]");
|
||||
geom.X = stof(f.next_esc(",")) * (float)imgsize.X;
|
||||
geom.Y = stof(f.next_esc(";")) * (float)imgsize.Y;
|
||||
std::string name = f.next_esc("]");
|
||||
infostream<<"item name="<<name
|
||||
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
||||
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
||||
@ -304,12 +304,12 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "background")
|
||||
{
|
||||
v2s32 pos = basepos;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2;
|
||||
v2s32 geom;
|
||||
geom.X = stof(f.next(",")) * (float)spacing.X;
|
||||
geom.Y = stof(f.next(";")) * (float)spacing.Y;
|
||||
std::string name = f.next("]");
|
||||
geom.X = stof(f.next_esc(",")) * (float)spacing.X;
|
||||
geom.Y = stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
std::string name = f.next_esc("]");
|
||||
infostream<<"image name="<<name
|
||||
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
||||
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
||||
@ -320,8 +320,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
}
|
||||
else if(type == "field" || type == "textarea")
|
||||
{
|
||||
std::string fname = f.next(";");
|
||||
std::string flabel = f.next(";");
|
||||
std::string fname = f.next_esc(";");
|
||||
std::string flabel = f.next_esc(";");
|
||||
|
||||
if(fname.find(",") == std::string::npos && flabel.find(",") == std::string::npos)
|
||||
{
|
||||
@ -372,14 +372,14 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
|
||||
|
||||
|
||||
fname = f.next(";");
|
||||
flabel = f.next(";");
|
||||
fname = f.next_esc(";");
|
||||
flabel = f.next_esc(";");
|
||||
if(bp_set != 2)
|
||||
errorstream<<"WARNING: invalid use of positioned "<<type<<" without a size[] element"<<std::endl;
|
||||
|
||||
}
|
||||
|
||||
std::string odefault = f.next("]");
|
||||
std::string odefault = f.next_esc("]");
|
||||
std::string fdefault;
|
||||
|
||||
// fdefault may contain a variable reference, which
|
||||
@ -389,6 +389,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else
|
||||
fdefault = odefault;
|
||||
|
||||
fdefault = unescape_string(fdefault);
|
||||
flabel = unescape_string(flabel);
|
||||
|
||||
FieldSpec spec = FieldSpec(
|
||||
narrow_to_wide(fname.c_str()),
|
||||
narrow_to_wide(flabel.c_str()),
|
||||
@ -434,15 +437,17 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "label")
|
||||
{
|
||||
v2s32 pos = padding;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
|
||||
rect = core::rect<s32>(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+300, pos.Y+((imgsize.Y/2)+15));
|
||||
|
||||
std::string flabel = f.next("]");
|
||||
std::string flabel = f.next_esc("]");
|
||||
if(bp_set != 2)
|
||||
errorstream<<"WARNING: invalid use of label without a size[] element"<<std::endl;
|
||||
|
||||
flabel = unescape_string(flabel);
|
||||
|
||||
FieldSpec spec = FieldSpec(
|
||||
narrow_to_wide(""),
|
||||
narrow_to_wide(flabel.c_str()),
|
||||
@ -455,19 +460,21 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "button" || type == "button_exit")
|
||||
{
|
||||
v2s32 pos = padding;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
v2s32 geom;
|
||||
geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||
pos.Y += (stof(f.next(";")) * (float)imgsize.Y)/2;
|
||||
geom.X = (stof(f.next_esc(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||
pos.Y += (stof(f.next_esc(";")) * (float)imgsize.Y)/2;
|
||||
|
||||
rect = core::rect<s32>(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15);
|
||||
|
||||
std::string fname = f.next(";");
|
||||
std::string flabel = f.next("]");
|
||||
std::string fname = f.next_esc(";");
|
||||
std::string flabel = f.next_esc("]");
|
||||
if(bp_set != 2)
|
||||
errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl;
|
||||
|
||||
flabel = unescape_string(flabel);
|
||||
|
||||
FieldSpec spec = FieldSpec(
|
||||
narrow_to_wide(fname.c_str()),
|
||||
narrow_to_wide(flabel.c_str()),
|
||||
@ -483,20 +490,22 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "image_button" || type == "image_button_exit")
|
||||
{
|
||||
v2s32 pos = padding;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
v2s32 geom;
|
||||
geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||
geom.Y = (stof(f.next(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
|
||||
geom.X = (stof(f.next_esc(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||
geom.Y = (stof(f.next_esc(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
|
||||
|
||||
rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
|
||||
|
||||
std::string fimage = f.next(";");
|
||||
std::string fname = f.next(";");
|
||||
std::string flabel = f.next("]");
|
||||
std::string fimage = f.next_esc(";");
|
||||
std::string fname = f.next_esc(";");
|
||||
std::string flabel = f.next_esc("]");
|
||||
if(bp_set != 2)
|
||||
errorstream<<"WARNING: invalid use of image_button without a size[] element"<<std::endl;
|
||||
|
||||
flabel = unescape_string(flabel);
|
||||
|
||||
FieldSpec spec = FieldSpec(
|
||||
narrow_to_wide(fname.c_str()),
|
||||
narrow_to_wide(flabel.c_str()),
|
||||
@ -519,15 +528,15 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else if(type == "item_image_button")
|
||||
{
|
||||
v2s32 pos = padding;
|
||||
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||
pos.X += stof(f.next_esc(",")) * (float)spacing.X;
|
||||
pos.Y += stof(f.next_esc(";")) * (float)spacing.Y;
|
||||
v2s32 geom;
|
||||
geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||
geom.Y = (stof(f.next(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
|
||||
geom.X = (stof(f.next_esc(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||
geom.Y = (stof(f.next_esc(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
|
||||
rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
|
||||
std::string fimage = f.next(";");
|
||||
std::string fname = f.next(";");
|
||||
std::string flabel = f.next("]");
|
||||
std::string fimage = f.next_esc(";");
|
||||
std::string fname = f.next_esc(";");
|
||||
std::string flabel = f.next_esc("]");
|
||||
if(bp_set != 2)
|
||||
errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<<std::endl;
|
||||
IItemDefManager *idef = m_gamedef->idef();
|
||||
@ -535,6 +544,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
item.deSerialize(fimage, idef);
|
||||
video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
|
||||
std::string tooltip = item.getDefinition(idef).description;
|
||||
flabel = unescape_string(flabel);
|
||||
FieldSpec spec = FieldSpec(
|
||||
narrow_to_wide(fname.c_str()),
|
||||
narrow_to_wide(flabel.c_str()),
|
||||
@ -556,7 +566,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
else
|
||||
{
|
||||
// Ignore others
|
||||
std::string ts = f.next("]");
|
||||
std::string ts = f.next_esc("]");
|
||||
infostream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -209,11 +209,11 @@ protected:
|
||||
IFormSource *m_form_src;
|
||||
TextDest *m_text_dst;
|
||||
|
||||
core::array<ListDrawSpec> m_inventorylists;
|
||||
core::array<ImageDrawSpec> m_backgrounds;
|
||||
core::array<ImageDrawSpec> m_images;
|
||||
core::array<ImageDrawSpec> m_itemimages;
|
||||
core::array<FieldSpec> m_fields;
|
||||
std::vector<ListDrawSpec> m_inventorylists;
|
||||
std::vector<ImageDrawSpec> m_backgrounds;
|
||||
std::vector<ImageDrawSpec> m_images;
|
||||
std::vector<ImageDrawSpec> m_itemimages;
|
||||
std::vector<FieldSpec> m_fields;
|
||||
|
||||
ItemSpec *m_selected_item;
|
||||
u32 m_selected_amount;
|
||||
|
@ -42,6 +42,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "util/string.h"
|
||||
#include "subgame.h"
|
||||
|
||||
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define LSTRING(x) LSTRING_(x)
|
||||
#define LSTRING_(x) L##x
|
||||
|
||||
const wchar_t *contrib_core_strs[] = {
|
||||
L"Perttu Ahola (celeron55) <celeron55@gmail.com>",
|
||||
L"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
|
||||
L"PilzAdam <pilzadam@minetest.net>",
|
||||
L"Ilya Zhuravlev (thexyz) <xyz@minetest.net>",
|
||||
L"Lisa Milne (darkrose) <lisa@ltmnet.com>",
|
||||
L"Maciej Kasatkin (RealBadAngel) <mk@realbadangel.pl>",
|
||||
L"proller <proler@gmail.com>"
|
||||
};
|
||||
|
||||
const wchar_t *contrib_active_strs[] = {
|
||||
L"sfan5 <sfan5@live.de>",
|
||||
L"sapier <sapier@gmx.net>",
|
||||
L"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>",
|
||||
L"Jurgen Doser (doserj) <jurgen.doser@gmail.com>",
|
||||
L"Jeija <jeija@mesecons.net>",
|
||||
L"MirceaKitsune <mirceakitsune@gmail.com>",
|
||||
L"ShadowNinja",
|
||||
L"dannydark <the_skeleton_of_a_child@yahoo.co.uk>",
|
||||
L"0gb.us <0gb.us@0gb.us>"
|
||||
};
|
||||
|
||||
const wchar_t *contrib_previous_strs[] = {
|
||||
L"kahrl <kahrl@gmx.net>",
|
||||
L"Giuseppe Bilotta (Oblomov) <giuseppe.bilotta@gmail.com>",
|
||||
L"Jonathan Neuschafer <j.neuschaefer@gmx.net>",
|
||||
L"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>",
|
||||
L"Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>",
|
||||
L"matttpt <matttpt@gmail.com>",
|
||||
L"JacobF <queatz@gmail.com>"
|
||||
};
|
||||
|
||||
|
||||
struct CreateWorldDestMainMenu : public CreateWorldDest
|
||||
{
|
||||
CreateWorldDestMainMenu(GUIMainMenu *menu):
|
||||
@ -106,6 +143,7 @@ enum
|
||||
GUI_ID_SHADERS_CB,
|
||||
GUI_ID_PRELOAD_ITEM_VISUALS_CB,
|
||||
GUI_ID_ENABLE_PARTICLES_CB,
|
||||
GUI_ID_LIQUID_FINITE_CB,
|
||||
GUI_ID_DAMAGE_CB,
|
||||
GUI_ID_CREATIVE_CB,
|
||||
GUI_ID_PUBLIC_CB,
|
||||
@ -119,6 +157,7 @@ enum
|
||||
GUI_ID_SERVERLIST,
|
||||
GUI_ID_SERVERLIST_TOGGLE,
|
||||
GUI_ID_SERVERLIST_DELETE,
|
||||
GUI_ID_SERVERLIST_TITLE,
|
||||
};
|
||||
|
||||
enum
|
||||
@ -209,7 +248,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
changeCtype("");
|
||||
|
||||
// Version
|
||||
//if(m_data->selected_tab != TAB_CREDITS)
|
||||
{
|
||||
core::rect<s32> rect(0, 0, size.X, 40);
|
||||
rect += v2s32(4, 0);
|
||||
@ -219,7 +257,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
}
|
||||
|
||||
//v2s32 center(size.X/2, size.Y/2);
|
||||
v2s32 c800(size.X/2-400, size.Y/2-300);
|
||||
v2s32 c800(size.X/2-400, size.Y/2-270);
|
||||
|
||||
m_topleft_client = c800 + v2s32(90, 70+50+30);
|
||||
m_size_client = v2s32(620, 270);
|
||||
@ -237,7 +275,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20);
|
||||
|
||||
// Tabs
|
||||
#if 1
|
||||
{
|
||||
core::rect<s32> rect(0, 0, m_size_client.X, 30);
|
||||
rect += m_topleft_client + v2s32(0, -30);
|
||||
@ -250,7 +287,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
e->addTab(wgettext("Credits"));
|
||||
e->setActiveTab(m_data->selected_tab);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(m_data->selected_tab == TAB_SINGLEPLAYER)
|
||||
{
|
||||
@ -259,7 +295,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
core::rect<s32> rect(0, 0, 10, m_size_client.Y);
|
||||
rect += m_topleft_client + v2s32(15, 0);
|
||||
//const wchar_t *text = L"H\nY\nB\nR\nI\nD";
|
||||
const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
|
||||
const wchar_t *text = L"S\nI\nN\nG\nL\nE\n \nP\nL\nA\nY\nE\nR\n";
|
||||
gui::IGUIStaticText *t =
|
||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||
t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
||||
@ -392,13 +428,38 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
changeCtype("");
|
||||
// Server List
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 390, 160);
|
||||
rect += m_topleft_client + v2s32(50, 10);
|
||||
core::rect<s32> rect(0, 0, 390, 140);
|
||||
rect += m_topleft_client + v2s32(50, 30);
|
||||
gui::IGUIListBox *e = Environment->addListBox(rect, this,
|
||||
GUI_ID_SERVERLIST);
|
||||
e->setDrawBackground(true);
|
||||
if (m_data->serverlist_show_available == false)
|
||||
#if USE_CURL
|
||||
if(m_data->selected_serverlist == SERVERLIST_FAVORITES) {
|
||||
m_data->servers = ServerList::getLocal();
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 390, 20);
|
||||
rect += m_topleft_client + v2s32(50, 10);
|
||||
Environment->addStaticText(wgettext("Favorites:"),
|
||||
rect, false, true, this, GUI_ID_SERVERLIST_TITLE);
|
||||
}
|
||||
} else {
|
||||
m_data->servers = ServerList::getOnline();
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 390, 20);
|
||||
rect += m_topleft_client + v2s32(50, 10);
|
||||
Environment->addStaticText(wgettext("Public Server List:"),
|
||||
rect, false, true, this, GUI_ID_SERVERLIST_TITLE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
m_data->servers = ServerList::getLocal();
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 390, 20);
|
||||
rect += m_topleft_client + v2s32(50, 10);
|
||||
Environment->addStaticText(wgettext("Favorites:"),
|
||||
rect, false, true, this, GUI_ID_SERVERLIST_TITLE);
|
||||
}
|
||||
#endif
|
||||
updateGuiServerList();
|
||||
e->setSelected(0);
|
||||
}
|
||||
@ -435,7 +496,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
|
||||
wgettext("Show Public"));
|
||||
e->setIsPushButton(true);
|
||||
if (m_data->serverlist_show_available)
|
||||
if (m_data->selected_serverlist == SERVERLIST_PUBLIC)
|
||||
{
|
||||
e->setText(wgettext("Show Favorites"));
|
||||
e->setPressed();
|
||||
@ -448,7 +509,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
rect += m_topleft_client + v2s32(50+260+10, 180);
|
||||
gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
|
||||
wgettext("Delete"));
|
||||
if (m_data->serverlist_show_available) // Hidden on Show-Online mode
|
||||
if (m_data->selected_serverlist == SERVERLIST_PUBLIC) // Hidden when on public list
|
||||
e->setVisible(false);
|
||||
}
|
||||
// Start game button
|
||||
@ -691,6 +752,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
|
||||
}
|
||||
|
||||
{
|
||||
core::rect<s32> rect(0, 0, option_w+20+20, 30);
|
||||
rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*3);
|
||||
Environment->addCheckBox(m_data->liquid_finite, rect, this,
|
||||
GUI_ID_LIQUID_FINITE_CB, wgettext("Finite liquid"));
|
||||
}
|
||||
|
||||
// Key change button
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 120, 30);
|
||||
@ -706,7 +774,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
// CREDITS
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 10, m_size_client.Y);
|
||||
core::rect<s32> rect(0, 0, 9, m_size_client.Y);
|
||||
rect += m_topleft_client + v2s32(15, 0);
|
||||
const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
|
||||
gui::IGUIStaticText *t =
|
||||
@ -714,15 +782,34 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
||||
t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 454, 250);
|
||||
rect += m_topleft_client + v2s32(110, 50+35);
|
||||
Environment->addStaticText(narrow_to_wide(
|
||||
"Minetest " VERSION_STRING "\n"
|
||||
"http://minetest.net/\n"
|
||||
"\n"
|
||||
"by Perttu Ahola <celeron55@gmail.com>\n"
|
||||
"and contributors: PilzAdam, Taoki, tango_, kahrl (kaaaaaahrl?), darkrose, matttpt, erlehmann, SpeedProg, JacobF, teddydestodes, marktraceur, Jonathan Neuschäfer, thexyz, VanessaE, sfan5... and tens of more random people."
|
||||
).c_str(), rect, false, true, this, -1);
|
||||
core::rect<s32> rect(0, 0, 130, 70);
|
||||
rect += m_topleft_client + v2s32(35, 160);
|
||||
Environment->addStaticText(
|
||||
L"Minetest " LSTRING(VERSION_STRING) L"\nhttp://minetest.net/",
|
||||
rect, false, true, this, -1);
|
||||
}
|
||||
{
|
||||
video::SColor yellow(255, 255, 255, 0);
|
||||
core::rect<s32> rect(0, 0, 450, 260);
|
||||
rect += m_topleft_client + v2s32(168, 5);
|
||||
|
||||
irr::gui::IGUIListBox *list = Environment->addListBox(rect, this);
|
||||
|
||||
list->addItem(L"Core Developers");
|
||||
list->setItemOverrideColor(list->getItemCount() - 1, yellow);
|
||||
for (int i = 0; i != ARRAYLEN(contrib_core_strs); i++)
|
||||
list->addItem(contrib_core_strs[i]);
|
||||
list->addItem(L"");
|
||||
list->addItem(L"Active Contributors");
|
||||
list->setItemOverrideColor(list->getItemCount() - 1, yellow);
|
||||
for (int i = 0; i != ARRAYLEN(contrib_active_strs); i++)
|
||||
list->addItem(contrib_active_strs[i]);
|
||||
list->addItem(L"");
|
||||
list->addItem(L"Previous Contributors");
|
||||
list->setItemOverrideColor(list->getItemCount() - 1, yellow);
|
||||
for (int i = 0; i != ARRAYLEN(contrib_previous_strs); i++)
|
||||
list->addItem(contrib_previous_strs[i]);
|
||||
list->addItem(L"");
|
||||
}
|
||||
}
|
||||
|
||||
@ -786,15 +873,15 @@ void GUIMainMenu::drawMenu()
|
||||
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
|
||||
}
|
||||
video::ITexture *logotexture =
|
||||
driver->getTexture(getTexturePath("menulogo.png").c_str());
|
||||
driver->getTexture(getTexturePath("logo.png").c_str());
|
||||
if(logotexture)
|
||||
{
|
||||
v2s32 logosize(logotexture->getOriginalSize().Width,
|
||||
logotexture->getOriginalSize().Height);
|
||||
logosize *= 2;
|
||||
|
||||
core::rect<s32> rect(0,0,logosize.X,logosize.Y);
|
||||
rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
|
||||
rect += v2s32(130, 50);
|
||||
rect += v2s32(50, 60);
|
||||
driver->draw2DImage(logotexture, rect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(logotexture->getSize())),
|
||||
@ -918,6 +1005,12 @@ void GUIMainMenu::readInput(MainMenuData *dst)
|
||||
dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_LIQUID_FINITE_CB);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
dst->liquid_finite = ((gui::IGUICheckBox*)e)->isChecked();
|
||||
}
|
||||
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
|
||||
if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
|
||||
@ -1083,25 +1176,28 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
|
||||
gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
|
||||
gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
|
||||
gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
|
||||
if (m_data->serverlist_show_available) // switch to favorite list
|
||||
gui::IGUIElement *title = getElementFromId(GUI_ID_SERVERLIST_TITLE);
|
||||
if (m_data->selected_serverlist == SERVERLIST_PUBLIC) // switch to favorite list
|
||||
{
|
||||
m_data->servers = ServerList::getLocal();
|
||||
togglebutton->setText(wgettext("Show Public"));
|
||||
title->setText(wgettext("Favorites:"));
|
||||
deletebutton->setVisible(true);
|
||||
updateGuiServerList();
|
||||
serverlist->setSelected(0);
|
||||
m_data->selected_serverlist = SERVERLIST_FAVORITES;
|
||||
}
|
||||
else // switch to online list
|
||||
{
|
||||
m_data->servers = ServerList::getOnline();
|
||||
togglebutton->setText(wgettext("Show Favorites"));
|
||||
title->setText(wgettext("Public Server List:"));
|
||||
deletebutton->setVisible(false);
|
||||
updateGuiServerList();
|
||||
serverlist->setSelected(0);
|
||||
m_data->selected_serverlist = SERVERLIST_PUBLIC;
|
||||
}
|
||||
serverListOnSelected();
|
||||
|
||||
m_data->serverlist_show_available = !m_data->serverlist_show_available;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -29,6 +29,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
class IGameCallback;
|
||||
|
||||
enum {
|
||||
SERVERLIST_FAVORITES,
|
||||
SERVERLIST_PUBLIC,
|
||||
};
|
||||
|
||||
struct MainMenuData
|
||||
{
|
||||
// These are in the native format of the gui elements
|
||||
@ -52,6 +57,7 @@ struct MainMenuData
|
||||
int enable_shaders;
|
||||
bool preload_item_visuals;
|
||||
bool enable_particles;
|
||||
bool liquid_finite;
|
||||
// Server options
|
||||
bool creative_mode;
|
||||
bool enable_damage;
|
||||
@ -63,7 +69,7 @@ struct MainMenuData
|
||||
std::string create_world_gameid;
|
||||
bool only_refresh;
|
||||
|
||||
bool serverlist_show_available; // if false show local favorites only
|
||||
int selected_serverlist;
|
||||
|
||||
std::vector<WorldSpec> worlds;
|
||||
std::vector<SubgameSpec> games;
|
||||
@ -84,7 +90,7 @@ struct MainMenuData
|
||||
// Actions
|
||||
only_refresh(false),
|
||||
|
||||
serverlist_show_available(false)
|
||||
selected_serverlist(SERVERLIST_FAVORITES)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -903,6 +903,10 @@ void Inventory::deSerialize(std::istream &is)
|
||||
|
||||
m_lists.push_back(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SerializationError("invalid inventory specifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
||||
}
|
||||
groups = def.groups;
|
||||
node_placement_prediction = def.node_placement_prediction;
|
||||
sound_place = def.sound_place;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -107,13 +108,17 @@ void ItemDefinition::reset()
|
||||
tool_capabilities = NULL;
|
||||
}
|
||||
groups.clear();
|
||||
sound_place = SimpleSoundSpec();
|
||||
|
||||
node_placement_prediction = "";
|
||||
}
|
||||
|
||||
void ItemDefinition::serialize(std::ostream &os) const
|
||||
void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
writeU8(os, 1); // version
|
||||
if(protocol_version <= 17)
|
||||
writeU8(os, 1); // version
|
||||
else
|
||||
writeU8(os, 2); // version
|
||||
writeU8(os, type);
|
||||
os<<serializeString(name);
|
||||
os<<serializeString(description);
|
||||
@ -126,7 +131,7 @@ void ItemDefinition::serialize(std::ostream &os) const
|
||||
std::string tool_capabilities_s = "";
|
||||
if(tool_capabilities){
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
tool_capabilities->serialize(tmp_os);
|
||||
tool_capabilities->serialize(tmp_os, protocol_version);
|
||||
tool_capabilities_s = tmp_os.str();
|
||||
}
|
||||
os<<serializeString(tool_capabilities_s);
|
||||
@ -137,6 +142,11 @@ void ItemDefinition::serialize(std::ostream &os) const
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
os<<serializeString(node_placement_prediction);
|
||||
if(protocol_version > 17){
|
||||
//serializeSimpleSoundSpec(sound_place, os);
|
||||
os<<serializeString(sound_place.name);
|
||||
writeF1000(os, sound_place.gain);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemDefinition::deSerialize(std::istream &is)
|
||||
@ -146,7 +156,7 @@ void ItemDefinition::deSerialize(std::istream &is)
|
||||
|
||||
// Deserialize
|
||||
int version = readU8(is);
|
||||
if(version != 1)
|
||||
if(version != 1 && version != 2)
|
||||
throw SerializationError("unsupported ItemDefinition version");
|
||||
type = (enum ItemType)readU8(is);
|
||||
name = deSerializeString(is);
|
||||
@ -171,10 +181,24 @@ void ItemDefinition::deSerialize(std::istream &is)
|
||||
int value = readS16(is);
|
||||
groups[name] = value;
|
||||
}
|
||||
if(version == 1){
|
||||
// We cant be sure that node_placement_prediction is send in version 1
|
||||
try{
|
||||
node_placement_prediction = deSerializeString(is);
|
||||
}catch(SerializationError &e) {};
|
||||
// Set the old default sound
|
||||
sound_place.name = "default_place_node";
|
||||
sound_place.gain = 0.5;
|
||||
} else if(version == 2) {
|
||||
node_placement_prediction = deSerializeString(is);
|
||||
//deserializeSimpleSoundSpec(sound_place, is);
|
||||
sound_place.name = deSerializeString(is);
|
||||
sound_place.gain = readF1000(is);
|
||||
}
|
||||
// If you add anything here, insert it primarily inside the try-catch
|
||||
// block to not need to increase the version.
|
||||
try{
|
||||
node_placement_prediction = deSerializeString(is);
|
||||
|
||||
}catch(SerializationError &e) {};
|
||||
}
|
||||
|
||||
@ -211,8 +235,8 @@ public:
|
||||
virtual ~CItemDefManager()
|
||||
{
|
||||
#ifndef SERVER
|
||||
const core::list<ClientCached*> &values = m_clientcached.getValues();
|
||||
for(core::list<ClientCached*>::ConstIterator
|
||||
const std::list<ClientCached*> &values = m_clientcached.getValues();
|
||||
for(std::list<ClientCached*>::const_iterator
|
||||
i = values.begin(); i != values.end(); ++i)
|
||||
{
|
||||
ClientCached *cc = *i;
|
||||
@ -547,7 +571,7 @@ public:
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
}
|
||||
void serialize(std::ostream &os)
|
||||
void serialize(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
u16 count = m_item_definitions.size();
|
||||
@ -559,7 +583,7 @@ public:
|
||||
ItemDefinition *def = i->second;
|
||||
// Serialize ItemDefinition and write wrapped in a string
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
def->serialize(tmp_os);
|
||||
def->serialize(tmp_os, protocol_version);
|
||||
os<<serializeString(tmp_os.str());
|
||||
}
|
||||
writeU16(os, m_aliases.size());
|
||||
@ -599,7 +623,7 @@ public:
|
||||
void processQueue(IGameDef *gamedef)
|
||||
{
|
||||
#ifndef SERVER
|
||||
while(m_get_clientcached_queue.size() > 0)
|
||||
while(!m_get_clientcached_queue.empty())
|
||||
{
|
||||
GetRequest<std::string, ClientCached*, u8, u8>
|
||||
request = m_get_clientcached_queue.pop();
|
||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include "itemgroup.h"
|
||||
#include "sound.h"
|
||||
class IGameDef;
|
||||
struct ToolCapabilities;
|
||||
|
||||
@ -66,6 +67,7 @@ struct ItemDefinition
|
||||
// May be NULL. If non-NULL, deleted by destructor
|
||||
ToolCapabilities *tool_capabilities;
|
||||
ItemGroupList groups;
|
||||
SimpleSoundSpec sound_place;
|
||||
|
||||
// Client shall immediately place this node when player places the item.
|
||||
// Server will update the precise end result a moment later.
|
||||
@ -80,7 +82,7 @@ struct ItemDefinition
|
||||
ItemDefinition& operator=(const ItemDefinition &def);
|
||||
~ItemDefinition();
|
||||
void reset();
|
||||
void serialize(std::ostream &os) const;
|
||||
void serialize(std::ostream &os, u16 protocol_version) const;
|
||||
void deSerialize(std::istream &is);
|
||||
private:
|
||||
void resetInitial();
|
||||
@ -109,7 +111,7 @@ public:
|
||||
IGameDef *gamedef) const=0;
|
||||
#endif
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||
};
|
||||
|
||||
class IWritableItemDefManager : public IItemDefManager
|
||||
@ -146,7 +148,7 @@ public:
|
||||
virtual void registerAlias(const std::string &name,
|
||||
const std::string &convert_to)=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
|
||||
// Do stuff asked by threads that can only be done in the main thread
|
||||
|
@ -6,9 +6,9 @@ else( UNIX )
|
||||
set(json_platform_LIBS "")
|
||||
endif( UNIX )
|
||||
|
||||
add_library(json ${json_SRCS})
|
||||
add_library(jsoncpp ${json_SRCS})
|
||||
|
||||
target_link_libraries(
|
||||
json
|
||||
jsoncpp
|
||||
${json_platform_LIBS}
|
||||
)
|
||||
|
@ -345,17 +345,16 @@ const KeyPress NumberKey[] = {
|
||||
*/
|
||||
|
||||
// A simple cache for quicker lookup
|
||||
core::map<std::string, KeyPress> g_key_setting_cache;
|
||||
std::map<std::string, KeyPress> g_key_setting_cache;
|
||||
|
||||
KeyPress getKeySetting(const char *settingname)
|
||||
{
|
||||
core::map<std::string, KeyPress>::Node *n;
|
||||
std::map<std::string, KeyPress>::iterator n;
|
||||
n = g_key_setting_cache.find(settingname);
|
||||
if(n)
|
||||
return n->getValue();
|
||||
g_key_setting_cache.insert(settingname,
|
||||
g_settings->get(settingname).c_str());
|
||||
return g_key_setting_cache.find(settingname)->getValue();
|
||||
if(n != g_key_setting_cache.end())
|
||||
return n->second;
|
||||
g_key_setting_cache[settingname] = g_settings->get(settingname).c_str();
|
||||
return g_key_setting_cache.find(settingname)->second;
|
||||
}
|
||||
|
||||
void clearKeyCache()
|
||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gamedef.h"
|
||||
#include "nodedef.h"
|
||||
#include "settings.h"
|
||||
#include "environment.h"
|
||||
#include "map.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
@ -57,9 +58,10 @@ LocalPlayer::~LocalPlayer()
|
||||
{
|
||||
}
|
||||
|
||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
core::list<CollisionInfo> *collision_info)
|
||||
void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
||||
std::list<CollisionInfo> *collision_info)
|
||||
{
|
||||
Map *map = &env->getMap();
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
|
||||
v3f position = getPosition();
|
||||
@ -97,15 +99,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
if(in_liquid)
|
||||
{
|
||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
|
||||
in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
|
||||
in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
|
||||
}
|
||||
// If not in liquid, the threshold of going in is at lower y
|
||||
else
|
||||
{
|
||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
|
||||
in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
|
||||
in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
@ -118,7 +120,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
*/
|
||||
try{
|
||||
v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
|
||||
in_liquid_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
|
||||
in_liquid_stable = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
@ -132,8 +134,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
try {
|
||||
v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
|
||||
v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
|
||||
is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable ||
|
||||
nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move);
|
||||
is_climbing = ((nodemgr->get(map->getNode(pp).getContent()).climbable ||
|
||||
nodemgr->get(map->getNode(pp2).getContent()).climbable) && !free_move);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
@ -197,7 +199,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(&map, m_gamedef,
|
||||
collisionMoveResult result = collisionMoveSimple(env, m_gamedef,
|
||||
pos_max_d, playerbox, player_stepheight, dtime,
|
||||
position, m_speed, accel_f);
|
||||
|
||||
@ -219,7 +221,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
*/
|
||||
v3s16 current_node = floatToInt(position - v3f(0,BS/2,0), BS);
|
||||
if(m_sneak_node_exists &&
|
||||
nodemgr->get(map.getNodeNoEx(m_old_node_below)).name == "air" &&
|
||||
nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" &&
|
||||
m_old_node_below_type != "air")
|
||||
{
|
||||
// Old node appears to have been removed; that is,
|
||||
@ -227,7 +229,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
m_need_to_get_new_sneak_node = false;
|
||||
m_sneak_node_exists = false;
|
||||
}
|
||||
else if(nodemgr->get(map.getNodeNoEx(current_node)).name != "air")
|
||||
else if(nodemgr->get(map->getNodeNoEx(current_node)).name != "air")
|
||||
{
|
||||
// We are on something, so make sure to recalculate the sneak
|
||||
// node.
|
||||
@ -267,10 +269,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
|
||||
try{
|
||||
// The node to be sneaked on has to be walkable
|
||||
if(nodemgr->get(map.getNode(p)).walkable == false)
|
||||
if(nodemgr->get(map->getNode(p)).walkable == false)
|
||||
continue;
|
||||
// And the node above it has to be nonwalkable
|
||||
if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true)
|
||||
if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
@ -331,7 +333,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
{
|
||||
camera_barely_in_ceiling = false;
|
||||
v3s16 camera_np = floatToInt(getEyePosition(), BS);
|
||||
MapNode n = map.getNodeNoEx(camera_np);
|
||||
MapNode n = map->getNodeNoEx(camera_np);
|
||||
if(n.getContent() != CONTENT_IGNORE){
|
||||
if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){
|
||||
camera_barely_in_ceiling = true;
|
||||
@ -343,21 +345,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
Update the node last under the player
|
||||
*/
|
||||
m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS);
|
||||
m_old_node_below_type = nodemgr->get(map.getNodeNoEx(m_old_node_below)).name;
|
||||
m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name;
|
||||
|
||||
/*
|
||||
Check properties of the node on which the player is standing
|
||||
*/
|
||||
const ContentFeatures &f = nodemgr->get(map.getNodeNoEx(getStandingNodePos()));
|
||||
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
|
||||
// Determine if jumping is possible
|
||||
m_can_jump = touching_ground && !in_liquid;
|
||||
if(itemgroup_get(f.groups, "disable_jump"))
|
||||
m_can_jump = false;
|
||||
}
|
||||
|
||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d)
|
||||
{
|
||||
move(dtime, map, pos_max_d, NULL);
|
||||
move(dtime, env, pos_max_d, NULL);
|
||||
}
|
||||
|
||||
void LocalPlayer::applyControl(float dtime)
|
||||
|
@ -21,6 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define LOCALPLAYER_HEADER
|
||||
|
||||
#include "player.h"
|
||||
#include <list>
|
||||
|
||||
class ClientEnvironment;
|
||||
|
||||
class LocalPlayer : public Player
|
||||
{
|
||||
@ -37,9 +40,9 @@ public:
|
||||
|
||||
v3f overridePosition;
|
||||
|
||||
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);
|
||||
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
||||
std::list<CollisionInfo> *collision_info);
|
||||
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d);
|
||||
|
||||
void applyControl(float dtime);
|
||||
|
||||
|
379
src/main.cpp
379
src/main.cpp
@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "debug.h"
|
||||
#include "test.h"
|
||||
#include "clouds.h"
|
||||
#include "server.h"
|
||||
#include "constants.h"
|
||||
#include "porting.h"
|
||||
@ -132,7 +133,12 @@ MainGameCallback *g_gamecallback = NULL;
|
||||
u32 getTimeMs()
|
||||
{
|
||||
/* Use imprecise system calls directly (from porting.h) */
|
||||
return porting::getTimeMs();
|
||||
return porting::getTime(PRECISION_MILLI);
|
||||
}
|
||||
|
||||
u32 getTime(TimePrecision prec)
|
||||
{
|
||||
return porting::getTime(prec);
|
||||
}
|
||||
|
||||
#else
|
||||
@ -141,7 +147,7 @@ u32 getTimeMs()
|
||||
class TimeGetter
|
||||
{
|
||||
public:
|
||||
virtual u32 getTime() = 0;
|
||||
virtual u32 getTime(TimePrecision prec) = 0;
|
||||
};
|
||||
|
||||
// A precise irrlicht one
|
||||
@ -151,11 +157,15 @@ public:
|
||||
IrrlichtTimeGetter(IrrlichtDevice *device):
|
||||
m_device(device)
|
||||
{}
|
||||
u32 getTime()
|
||||
u32 getTime(TimePrecision prec)
|
||||
{
|
||||
if(m_device == NULL)
|
||||
return 0;
|
||||
return m_device->getTimer()->getRealTime();
|
||||
if (prec == PRECISION_MILLI) {
|
||||
if(m_device == NULL)
|
||||
return 0;
|
||||
return m_device->getTimer()->getRealTime();
|
||||
} else {
|
||||
return porting::getTime(prec);
|
||||
}
|
||||
}
|
||||
private:
|
||||
IrrlichtDevice *m_device;
|
||||
@ -164,9 +174,9 @@ private:
|
||||
class SimpleTimeGetter: public TimeGetter
|
||||
{
|
||||
public:
|
||||
u32 getTime()
|
||||
u32 getTime(TimePrecision prec)
|
||||
{
|
||||
return porting::getTimeMs();
|
||||
return porting::getTime(prec);
|
||||
}
|
||||
};
|
||||
|
||||
@ -178,7 +188,13 @@ u32 getTimeMs()
|
||||
{
|
||||
if(g_timegetter == NULL)
|
||||
return 0;
|
||||
return g_timegetter->getTime();
|
||||
return g_timegetter->getTime(PRECISION_MILLI);
|
||||
}
|
||||
|
||||
u32 getTime(TimePrecision prec) {
|
||||
if (g_timegetter == NULL)
|
||||
return 0;
|
||||
return g_timegetter->getTime(prec);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -596,50 +612,120 @@ private:
|
||||
bool rightreleased;
|
||||
};
|
||||
|
||||
void drawMenuBackground(video::IVideoDriver* driver)
|
||||
{
|
||||
//Draw the tiled menu background
|
||||
void drawMenuBackground(video::IVideoDriver* driver) {
|
||||
core::dimension2d<u32> screensize = driver->getScreenSize();
|
||||
|
||||
std::string path = getTexturePath("menubg.png");
|
||||
if (path[0]) {
|
||||
video::ITexture *bgtexture =
|
||||
driver->getTexture(path.c_str());
|
||||
|
||||
if (bgtexture) {
|
||||
s32 scaledsize = 128;
|
||||
|
||||
video::ITexture *bgtexture =
|
||||
driver->getTexture(getTexturePath("menubg.png").c_str());
|
||||
if(bgtexture)
|
||||
{
|
||||
s32 scaledsize = 128;
|
||||
// The important difference between destsize and screensize is
|
||||
// that destsize is rounded to whole scaled pixels.
|
||||
// These formulas use component-wise multiplication and division of v2u32.
|
||||
v2u32 texturesize = bgtexture->getSize();
|
||||
v2u32 sourcesize = texturesize * screensize / scaledsize + v2u32(1,1);
|
||||
v2u32 destsize = scaledsize * sourcesize / texturesize;
|
||||
|
||||
// The important difference between destsize and screensize is
|
||||
// that destsize is rounded to whole scaled pixels.
|
||||
// These formulas use component-wise multiplication and division of v2u32.
|
||||
v2u32 texturesize = bgtexture->getSize();
|
||||
v2u32 sourcesize = texturesize * screensize / scaledsize + v2u32(1,1);
|
||||
v2u32 destsize = scaledsize * sourcesize / texturesize;
|
||||
|
||||
// Default texture wrapping mode in Irrlicht is ETC_REPEAT.
|
||||
driver->draw2DImage(bgtexture,
|
||||
core::rect<s32>(0, 0, destsize.X, destsize.Y),
|
||||
core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
|
||||
NULL, NULL, true);
|
||||
// Default texture wrapping mode in Irrlicht is ETC_REPEAT.
|
||||
driver->draw2DImage(bgtexture,
|
||||
core::rect<s32>(0, 0, destsize.X, destsize.Y),
|
||||
core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
video::ITexture *logotexture =
|
||||
driver->getTexture(getTexturePath("menulogo.png").c_str());
|
||||
if(logotexture)
|
||||
{
|
||||
v2s32 logosize(logotexture->getOriginalSize().Width,
|
||||
logotexture->getOriginalSize().Height);
|
||||
logosize *= 4;
|
||||
}
|
||||
|
||||
video::SColor bgcolor(255,50,50,50);
|
||||
core::rect<s32> bgrect(0, screensize.Height-logosize.Y-20,
|
||||
screensize.Width, screensize.Height);
|
||||
driver->draw2DRectangle(bgcolor, bgrect, NULL);
|
||||
//Draw the footer at the bottom of the window
|
||||
void drawMenuFooter(video::IVideoDriver* driver, bool clouds) {
|
||||
core::dimension2d<u32> screensize = driver->getScreenSize();
|
||||
std::string path = getTexturePath(clouds ?
|
||||
"menufooter_clouds.png" : "menufooter.png");
|
||||
if (path[0]) {
|
||||
video::ITexture *footertexture =
|
||||
driver->getTexture(path.c_str());
|
||||
|
||||
core::rect<s32> rect(0,0,logosize.X,logosize.Y);
|
||||
rect += v2s32(screensize.Width/2,screensize.Height-10-logosize.Y);
|
||||
rect -= v2s32(logosize.X/2, 0);
|
||||
driver->draw2DImage(logotexture, rect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(logotexture->getSize())),
|
||||
NULL, NULL, true);
|
||||
if (footertexture) {
|
||||
f32 mult = (((f32)screensize.Width)) /
|
||||
((f32)footertexture->getOriginalSize().Width);
|
||||
|
||||
v2s32 footersize(((f32)footertexture->getOriginalSize().Width) * mult,
|
||||
((f32)footertexture->getOriginalSize().Height) * mult);
|
||||
|
||||
// Don't draw the footer if there isn't enough room
|
||||
s32 free_space = (((s32)screensize.Height)-320)/2;
|
||||
if (free_space > footersize.Y) {
|
||||
core::rect<s32> rect(0,0,footersize.X,footersize.Y);
|
||||
rect += v2s32(screensize.Width/2,screensize.Height-footersize.Y);
|
||||
rect -= v2s32(footersize.X/2, 0);
|
||||
|
||||
driver->draw2DImage(footertexture, rect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(footertexture->getSize())),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the Header over the main menu
|
||||
void drawMenuHeader(video::IVideoDriver* driver) {
|
||||
core::dimension2d<u32> screensize = driver->getScreenSize();
|
||||
|
||||
std::string path = getTexturePath("menuheader.png");
|
||||
if (path[0]) {
|
||||
video::ITexture *splashtexture =
|
||||
driver->getTexture(path.c_str());
|
||||
|
||||
if(splashtexture) {
|
||||
//v2s32 splashsize((splashtexture->getOriginalSize().Width*100)/
|
||||
// splashtexture->getOriginalSize().Height, 80);
|
||||
|
||||
f32 mult = (((f32)screensize.Width / 2)) /
|
||||
((f32)splashtexture->getOriginalSize().Width);
|
||||
|
||||
v2s32 splashsize(((f32)splashtexture->getOriginalSize().Width) * mult,
|
||||
((f32)splashtexture->getOriginalSize().Height) * mult);
|
||||
|
||||
// Don't draw the header is there isn't enough room
|
||||
s32 free_space = (((s32)screensize.Height)-320)/2;
|
||||
if (free_space > splashsize.Y) {
|
||||
core::rect<s32> splashrect(0, 0, splashsize.X, splashsize.Y);
|
||||
splashrect += v2s32((screensize.Width/2)-(splashsize.X/2),
|
||||
((free_space/2)-splashsize.Y/2)+10);
|
||||
|
||||
video::SColor bgcolor(255,50,50,50);
|
||||
|
||||
driver->draw2DImage(splashtexture, splashrect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(splashtexture->getSize())),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the Splash over the clouds and under the main menu
|
||||
void drawMenuSplash(video::IVideoDriver* driver) {
|
||||
core::dimension2d<u32> screensize = driver->getScreenSize();
|
||||
if (getTexturePath("menusplash.png") != "") {
|
||||
video::ITexture *splashtexture =
|
||||
driver->getTexture(getTexturePath("menusplash.png").c_str());
|
||||
|
||||
if(splashtexture) {
|
||||
core::rect<s32> splashrect(0, 0, screensize.Width, screensize.Height);
|
||||
|
||||
video::SColor bgcolor(255,50,50,50);
|
||||
|
||||
driver->draw2DImage(splashtexture, splashrect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(splashtexture->getSize())),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,14 +786,14 @@ void SpeedTests()
|
||||
}
|
||||
|
||||
{
|
||||
TimeTaker timer("Testing core::map speed");
|
||||
TimeTaker timer("Testing std::map speed");
|
||||
|
||||
core::map<v2s16, f32> map1;
|
||||
std::map<v2s16, f32> map1;
|
||||
tempf = -324;
|
||||
const s16 ii=300;
|
||||
for(s16 y=0; y<ii; y++){
|
||||
for(s16 x=0; x<ii; x++){
|
||||
map1.insert(v2s16(x,y), tempf);
|
||||
map1[v2s16(x,y)] = tempf;
|
||||
tempf += 1;
|
||||
}
|
||||
}
|
||||
@ -734,7 +820,7 @@ void SpeedTests()
|
||||
}
|
||||
}
|
||||
// Do at least 10ms
|
||||
while(timer.getTime() < 10);
|
||||
while(timer.getTimerTime() < 10);
|
||||
|
||||
u32 dtime = timer.stop();
|
||||
u32 per_ms = n / dtime;
|
||||
@ -788,48 +874,48 @@ int main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
// List all allowed options
|
||||
core::map<std::string, ValueSpec> allowed_options;
|
||||
allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Show allowed options")));
|
||||
allowed_options.insert("config", ValueSpec(VALUETYPE_STRING,
|
||||
_("Load configuration from specified file")));
|
||||
allowed_options.insert("port", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set network port (UDP)")));
|
||||
allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Disable unit tests")));
|
||||
allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Enable unit tests")));
|
||||
allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING,
|
||||
_("Same as --world (deprecated)")));
|
||||
allowed_options.insert("world", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set world path (implies local game) ('list' lists all)")));
|
||||
allowed_options.insert("worldname", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set world by name (implies local game)")));
|
||||
allowed_options.insert("info", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Print more information to console")));
|
||||
allowed_options.insert("verbose", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Print even more information to console")));
|
||||
allowed_options.insert("trace", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Print enormous amounts of information to log and console")));
|
||||
allowed_options.insert("logfile", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set logfile path ('' = no logging)")));
|
||||
allowed_options.insert("gameid", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set gameid (\"--gameid list\" prints available ones)")));
|
||||
std::map<std::string, ValueSpec> allowed_options;
|
||||
allowed_options.insert(std::make_pair("help", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Show allowed options"))));
|
||||
allowed_options.insert(std::make_pair("config", ValueSpec(VALUETYPE_STRING,
|
||||
_("Load configuration from specified file"))));
|
||||
allowed_options.insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set network port (UDP)"))));
|
||||
allowed_options.insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Disable unit tests"))));
|
||||
allowed_options.insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Enable unit tests"))));
|
||||
allowed_options.insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING,
|
||||
_("Same as --world (deprecated)"))));
|
||||
allowed_options.insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set world path (implies local game) ('list' lists all)"))));
|
||||
allowed_options.insert(std::make_pair("worldname", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set world by name (implies local game)"))));
|
||||
allowed_options.insert(std::make_pair("info", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Print more information to console"))));
|
||||
allowed_options.insert(std::make_pair("verbose", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Print even more information to console"))));
|
||||
allowed_options.insert(std::make_pair("trace", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Print enormous amounts of information to log and console"))));
|
||||
allowed_options.insert(std::make_pair("logfile", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set logfile path ('' = no logging)"))));
|
||||
allowed_options.insert(std::make_pair("gameid", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set gameid (\"--gameid list\" prints available ones)"))));
|
||||
#ifndef SERVER
|
||||
allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Run speed tests")));
|
||||
allowed_options.insert("address", ValueSpec(VALUETYPE_STRING,
|
||||
_("Address to connect to. ('' = local game)")));
|
||||
allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Enable random user input, for testing")));
|
||||
allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Run dedicated server")));
|
||||
allowed_options.insert("name", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set player name")));
|
||||
allowed_options.insert("password", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set password")));
|
||||
allowed_options.insert("go", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Disable main menu")));
|
||||
allowed_options.insert(std::make_pair("speedtests", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Run speed tests"))));
|
||||
allowed_options.insert(std::make_pair("address", ValueSpec(VALUETYPE_STRING,
|
||||
_("Address to connect to. ('' = local game)"))));
|
||||
allowed_options.insert(std::make_pair("random-input", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Enable random user input, for testing"))));
|
||||
allowed_options.insert(std::make_pair("server", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Run dedicated server"))));
|
||||
allowed_options.insert(std::make_pair("name", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set player name"))));
|
||||
allowed_options.insert(std::make_pair("password", ValueSpec(VALUETYPE_STRING,
|
||||
_("Set password"))));
|
||||
allowed_options.insert(std::make_pair("go", ValueSpec(VALUETYPE_FLAG,
|
||||
_("Disable main menu"))));
|
||||
#endif
|
||||
|
||||
Settings cmd_args;
|
||||
@ -839,20 +925,20 @@ int main(int argc, char *argv[])
|
||||
if(ret == false || cmd_args.getFlag("help") || cmd_args.exists("nonopt1"))
|
||||
{
|
||||
dstream<<_("Allowed options:")<<std::endl;
|
||||
for(core::map<std::string, ValueSpec>::Iterator
|
||||
i = allowed_options.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<std::string, ValueSpec>::iterator
|
||||
i = allowed_options.begin();
|
||||
i != allowed_options.end(); ++i)
|
||||
{
|
||||
std::ostringstream os1(std::ios::binary);
|
||||
os1<<" --"<<i.getNode()->getKey();
|
||||
if(i.getNode()->getValue().type == VALUETYPE_FLAG)
|
||||
os1<<" --"<<i->first;
|
||||
if(i->second.type == VALUETYPE_FLAG)
|
||||
{}
|
||||
else
|
||||
os1<<_(" <value>");
|
||||
dstream<<padStringRight(os1.str(), 24);
|
||||
|
||||
if(i.getNode()->getValue().help != NULL)
|
||||
dstream<<i.getNode()->getValue().help;
|
||||
if(i->second.help != NULL)
|
||||
dstream<<i->second.help;
|
||||
dstream<<std::endl;
|
||||
}
|
||||
|
||||
@ -953,7 +1039,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
core::array<std::string> filenames;
|
||||
std::vector<std::string> filenames;
|
||||
filenames.push_back(porting::path_user +
|
||||
DIR_DELIM + "minetest.conf");
|
||||
// Legacy configuration file location
|
||||
@ -1279,6 +1365,14 @@ int main(int argc, char *argv[])
|
||||
driverType = video::EDT_DIRECT3D9;
|
||||
else if(driverstring == "opengl")
|
||||
driverType = video::EDT_OPENGL;
|
||||
#ifdef _IRR_COMPILE_WITH_OGLES1_
|
||||
else if(driverstring == "ogles1")
|
||||
driverType = video::EDT_OGLES1;
|
||||
#endif
|
||||
#ifdef _IRR_COMPILE_WITH_OGLES2_
|
||||
else if(driverstring == "ogles2")
|
||||
driverType = video::EDT_OGLES2;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
errorstream<<"WARNING: Invalid video_driver specified; defaulting "
|
||||
@ -1462,6 +1556,8 @@ int main(int argc, char *argv[])
|
||||
MainMenuData menudata;
|
||||
if(g_settings->exists("selected_mainmenu_tab"))
|
||||
menudata.selected_tab = g_settings->getS32("selected_mainmenu_tab");
|
||||
if(g_settings->exists("selected_serverlist"))
|
||||
menudata.selected_serverlist = g_settings->getS32("selected_serverlist");
|
||||
menudata.address = narrow_to_wide(address);
|
||||
menudata.name = narrow_to_wide(playername);
|
||||
menudata.port = narrow_to_wide(itos(port));
|
||||
@ -1478,6 +1574,7 @@ int main(int argc, char *argv[])
|
||||
menudata.enable_shaders = g_settings->getS32("enable_shaders");
|
||||
menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals");
|
||||
menudata.enable_particles = g_settings->getBool("enable_particles");
|
||||
menudata.liquid_finite = g_settings->getBool("liquid_finite");
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map);
|
||||
menudata.creative_mode = g_settings->getBool("creative_mode");
|
||||
menudata.enable_damage = g_settings->getBool("enable_damage");
|
||||
@ -1518,7 +1615,7 @@ int main(int argc, char *argv[])
|
||||
if(skip_main_menu == false)
|
||||
{
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
|
||||
float fps_max = g_settings->getFloat("fps_max");
|
||||
infostream<<"Waiting for other menus"<<std::endl;
|
||||
while(device->run() && kill == false)
|
||||
{
|
||||
@ -1540,6 +1637,22 @@ int main(int argc, char *argv[])
|
||||
&g_menumgr, &menudata, g_gamecallback);
|
||||
menu->allowFocusRemoval(true);
|
||||
|
||||
// Clouds for the main menu
|
||||
bool cloud_menu_background = false;
|
||||
Clouds *clouds = NULL;
|
||||
if (g_settings->getBool("menu_clouds")) {
|
||||
cloud_menu_background = true;
|
||||
clouds = new Clouds(smgr->getRootSceneNode(),
|
||||
smgr, -1, rand(), 100);
|
||||
clouds->update(v2f(0, 0), video::SColor(255,200,200,255));
|
||||
|
||||
// A camera to see the clouds
|
||||
scene::ICameraSceneNode* camera;
|
||||
camera = smgr->addCameraSceneNode(0,
|
||||
v3f(0,0,0), v3f(0, 60, 100));
|
||||
camera->setFarValue(10000);
|
||||
}
|
||||
|
||||
if(error_message != L"")
|
||||
{
|
||||
verbosestream<<"error_message = "
|
||||
@ -1552,6 +1665,9 @@ int main(int argc, char *argv[])
|
||||
error_message = L"";
|
||||
}
|
||||
|
||||
// Time is in milliseconds, for clouds
|
||||
u32 lasttime = device->getTimer()->getTime();
|
||||
|
||||
infostream<<"Created main menu"<<std::endl;
|
||||
|
||||
while(device->run() && kill == false)
|
||||
@ -1559,26 +1675,75 @@ int main(int argc, char *argv[])
|
||||
if(menu->getStatus() == true)
|
||||
break;
|
||||
|
||||
//driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||
driver->beginScene(true, true, video::SColor(255,128,128,128));
|
||||
// Time calc for the clouds
|
||||
f32 dtime; // in seconds
|
||||
if (cloud_menu_background) {
|
||||
u32 time = device->getTimer()->getTime();
|
||||
if(time > lasttime)
|
||||
dtime = (time - lasttime) / 1000.0;
|
||||
else
|
||||
dtime = 0;
|
||||
lasttime = time;
|
||||
}
|
||||
|
||||
drawMenuBackground(driver);
|
||||
//driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||
driver->beginScene(true, true, video::SColor(255,140,186,250));
|
||||
|
||||
if (cloud_menu_background) {
|
||||
// *3 otherwise the clouds would move very slowly
|
||||
clouds->step(dtime*3);
|
||||
clouds->render();
|
||||
smgr->drawAll();
|
||||
drawMenuSplash(driver);
|
||||
drawMenuFooter(driver, true);
|
||||
drawMenuHeader(driver);
|
||||
} else {
|
||||
drawMenuBackground(driver);
|
||||
drawMenuFooter(driver, false);
|
||||
}
|
||||
|
||||
guienv->drawAll();
|
||||
|
||||
|
||||
driver->endScene();
|
||||
|
||||
// On some computers framerate doesn't seem to be
|
||||
// automatically limited
|
||||
sleep_ms(25);
|
||||
if (cloud_menu_background) {
|
||||
// Time of frame without fps limit
|
||||
float busytime;
|
||||
u32 busytime_u32;
|
||||
// not using getRealTime is necessary for wine
|
||||
u32 time = device->getTimer()->getTime();
|
||||
if(time > lasttime)
|
||||
busytime_u32 = time - lasttime;
|
||||
else
|
||||
busytime_u32 = 0;
|
||||
busytime = busytime_u32 / 1000.0;
|
||||
|
||||
// FPS limiter
|
||||
u32 frametime_min = 1000./fps_max;
|
||||
|
||||
if(busytime_u32 < frametime_min) {
|
||||
u32 sleeptime = frametime_min - busytime_u32;
|
||||
device->sleep(sleeptime);
|
||||
}
|
||||
} else {
|
||||
sleep_ms(25);
|
||||
}
|
||||
}
|
||||
|
||||
infostream<<"Dropping main menu"<<std::endl;
|
||||
|
||||
menu->drop();
|
||||
if (cloud_menu_background) {
|
||||
clouds->drop();
|
||||
smgr->clear();
|
||||
}
|
||||
}
|
||||
|
||||
playername = wide_to_narrow(menudata.name);
|
||||
if (playername == "")
|
||||
playername = std::string("Guest") + itos(myrand_range(1000,9999));
|
||||
password = translatePassword(playername, menudata.password);
|
||||
//infostream<<"Main: password hash: '"<<password<<"'"<<std::endl;
|
||||
|
||||
@ -1589,6 +1754,7 @@ int main(int argc, char *argv[])
|
||||
simple_singleplayer_mode = menudata.simple_singleplayer_mode;
|
||||
// Save settings
|
||||
g_settings->setS32("selected_mainmenu_tab", menudata.selected_tab);
|
||||
g_settings->setS32("selected_serverlist", menudata.selected_serverlist);
|
||||
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));
|
||||
@ -1602,6 +1768,7 @@ int main(int argc, char *argv[])
|
||||
g_settings->setS32("enable_shaders", menudata.enable_shaders);
|
||||
g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals));
|
||||
g_settings->set("enable_particles", itos(menudata.enable_particles));
|
||||
g_settings->set("liquid_finite", itos(menudata.liquid_finite));
|
||||
|
||||
g_settings->set("creative_mode", itos(menudata.creative_mode));
|
||||
g_settings->set("enable_damage", itos(menudata.enable_damage));
|
||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "debug.h" // assert
|
||||
#include "modalMenu.h"
|
||||
#include "guiPauseMenu.h" //For IGameCallback
|
||||
#include <list>
|
||||
|
||||
extern gui::IGUIEnvironment* guienv;
|
||||
extern gui::IGUIStaticText *guiroot;
|
||||
@ -37,15 +38,15 @@ class MainMenuManager : public IMenuManager
|
||||
public:
|
||||
virtual void createdMenu(GUIModalMenu *menu)
|
||||
{
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
for(std::list<GUIModalMenu*>::iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
i != m_stack.end(); ++i)
|
||||
{
|
||||
assert(*i != menu);
|
||||
}
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(false);
|
||||
m_stack.back()->setVisible(false);
|
||||
m_stack.push_back(menu);
|
||||
}
|
||||
|
||||
@ -55,9 +56,9 @@ public:
|
||||
bool removed_entry;
|
||||
do{
|
||||
removed_entry = false;
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
for(std::list<GUIModalMenu*>::iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
i != m_stack.end(); ++i)
|
||||
{
|
||||
if(*i == menu)
|
||||
{
|
||||
@ -73,7 +74,7 @@ public:
|
||||
m_stack.erase(i);*/
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(true);
|
||||
m_stack.back()->setVisible(true);
|
||||
}
|
||||
|
||||
u32 menuCount()
|
||||
@ -81,7 +82,7 @@ public:
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
core::list<GUIModalMenu*> m_stack;
|
||||
std::list<GUIModalMenu*> m_stack;
|
||||
};
|
||||
|
||||
extern MainMenuManager g_menumgr;
|
||||
|
452
src/map.cpp
452
src/map.cpp
File diff suppressed because it is too large
Load Diff
94
src/map.h
94
src/map.h
@ -25,6 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <jthread.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "mapnode.h"
|
||||
@ -47,7 +50,7 @@ class NodeMetadata;
|
||||
class IGameDef;
|
||||
class IRollbackReportSink;
|
||||
class EmergeManager;
|
||||
class BlockMakeData;
|
||||
struct BlockMakeData;
|
||||
|
||||
|
||||
/*
|
||||
@ -75,7 +78,7 @@ struct MapEditEvent
|
||||
MapEditEventType type;
|
||||
v3s16 p;
|
||||
MapNode n;
|
||||
core::map<v3s16, bool> modified_blocks;
|
||||
std::set<v3s16> modified_blocks;
|
||||
u16 already_known_by_peer;
|
||||
|
||||
MapEditEvent():
|
||||
@ -90,14 +93,7 @@ struct MapEditEvent
|
||||
event->type = type;
|
||||
event->p = p;
|
||||
event->n = n;
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
bool v = i.getNode()->getValue();
|
||||
event->modified_blocks.insert(p, v);
|
||||
}
|
||||
event->modified_blocks = modified_blocks;
|
||||
return event;
|
||||
}
|
||||
|
||||
@ -117,11 +113,11 @@ struct MapEditEvent
|
||||
case MEET_OTHER:
|
||||
{
|
||||
VoxelArea a;
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
for(std::set<v3s16>::iterator
|
||||
i = modified_blocks.begin();
|
||||
i != modified_blocks.end(); ++i)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
v3s16 p = *i;
|
||||
v3s16 np1 = p*MAP_BLOCKSIZE;
|
||||
v3s16 np2 = np1 + v3s16(1,1,1)*MAP_BLOCKSIZE - v3s16(1,1,1);
|
||||
a.addPoint(np1);
|
||||
@ -186,7 +182,7 @@ public:
|
||||
*/
|
||||
virtual MapSector * emergeSector(v2s16 p){ return NULL; }
|
||||
virtual MapSector * emergeSector(v2s16 p,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
|
||||
std::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
|
||||
|
||||
// Returns InvalidPositionException if not found
|
||||
MapBlock * getBlockNoCreate(v3s16 p);
|
||||
@ -212,42 +208,42 @@ public:
|
||||
MapNode getNodeNoEx(v3s16 p);
|
||||
|
||||
void unspreadLight(enum LightBank bank,
|
||||
core::map<v3s16, u8> & from_nodes,
|
||||
core::map<v3s16, bool> & light_sources,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
std::map<v3s16, u8> & from_nodes,
|
||||
std::set<v3s16> & light_sources,
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
void unLightNeighbors(enum LightBank bank,
|
||||
v3s16 pos, u8 lightwas,
|
||||
core::map<v3s16, bool> & light_sources,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
std::set<v3s16> & light_sources,
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
void spreadLight(enum LightBank bank,
|
||||
core::map<v3s16, bool> & from_nodes,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
std::set<v3s16> & from_nodes,
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
void lightNeighbors(enum LightBank bank,
|
||||
v3s16 pos,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
|
||||
|
||||
s16 propagateSunlight(v3s16 start,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
void updateLighting(enum LightBank bank,
|
||||
core::map<v3s16, MapBlock*> & a_blocks,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
std::map<v3s16, MapBlock*> & a_blocks,
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
|
||||
core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
void updateLighting(std::map<v3s16, MapBlock*> & a_blocks,
|
||||
std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
/*
|
||||
These handle lighting but not faces.
|
||||
*/
|
||||
void addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
std::map<v3s16, MapBlock*> &modified_blocks);
|
||||
void removeNodeAndUpdate(v3s16 p,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
std::map<v3s16, MapBlock*> &modified_blocks);
|
||||
|
||||
/*
|
||||
Wrappers for the latter ones.
|
||||
@ -281,12 +277,12 @@ public:
|
||||
Saves modified blocks before unloading on MAPTYPE_SERVER.
|
||||
*/
|
||||
void timerUpdate(float dtime, float unload_timeout,
|
||||
core::list<v3s16> *unloaded_blocks=NULL);
|
||||
std::list<v3s16> *unloaded_blocks=NULL);
|
||||
|
||||
// Deletes sectors and their blocks from memory
|
||||
// Takes cache into account
|
||||
// If deleted sector is in sector cache, clears cache
|
||||
void deleteSectors(core::list<v2s16> &list);
|
||||
void deleteSectors(std::list<v2s16> &list);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
@ -301,8 +297,8 @@ public:
|
||||
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
||||
virtual void PrintInfo(std::ostream &out);
|
||||
|
||||
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
void transformLiquidsFinite(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
void transformLiquidsFinite(std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
/*
|
||||
Node metadata
|
||||
@ -325,7 +321,7 @@ public:
|
||||
/*
|
||||
Misc.
|
||||
*/
|
||||
core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
|
||||
std::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
|
||||
|
||||
/*
|
||||
Variables
|
||||
@ -340,9 +336,9 @@ protected:
|
||||
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
core::map<MapEventReceiver*, bool> m_event_receivers;
|
||||
std::set<MapEventReceiver*> m_event_receivers;
|
||||
|
||||
core::map<v2s16, MapSector*> m_sectors;
|
||||
std::map<v2s16, MapSector*> m_sectors;
|
||||
|
||||
// Be sure to set this to NULL when the cached sector is deleted
|
||||
MapSector *m_sector_cache;
|
||||
@ -385,13 +381,7 @@ public:
|
||||
*/
|
||||
bool initBlockMake(BlockMakeData *data, v3s16 blockpos);
|
||||
MapBlock *finishBlockMake(BlockMakeData *data,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks);
|
||||
|
||||
// A non-threaded wrapper to the above - DEFUNCT
|
||||
/* MapBlock * generateBlock(
|
||||
v3s16 p,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks
|
||||
);*/
|
||||
std::map<v3s16, MapBlock*> &changed_blocks);
|
||||
|
||||
/*
|
||||
Get a block from somewhere.
|
||||
@ -444,9 +434,7 @@ public:
|
||||
|
||||
void save(ModifiedState save_level);
|
||||
//void loadAll();
|
||||
|
||||
void listAllLoadableBlocks(core::list<v3s16> &dst);
|
||||
|
||||
void listAllLoadableBlocks(std::list<v3s16> &dst);
|
||||
// Saves map seed and possibly other stuff
|
||||
void saveMapMeta();
|
||||
void loadMapMeta();
|
||||
@ -538,15 +526,15 @@ public:
|
||||
|
||||
virtual void emerge(VoxelArea a, s32 caller_id=-1);
|
||||
|
||||
void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
void blitBack(std::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
||||
protected:
|
||||
Map *m_map;
|
||||
/*
|
||||
key = blockpos
|
||||
value = flags describing the block
|
||||
*/
|
||||
core::map<v3s16, u8> m_loaded_blocks;
|
||||
protected:
|
||||
Map *m_map;
|
||||
std::map<v3s16, u8> m_loaded_blocks;
|
||||
};
|
||||
|
||||
class ManualMapVoxelManipulator : public MapVoxelManipulator
|
||||
@ -563,7 +551,7 @@ public:
|
||||
void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
|
||||
|
||||
// This is much faster with big chunks of generated data
|
||||
void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
|
||||
void blitBackAll(std::map<v3s16, MapBlock*> * modified_blocks);
|
||||
|
||||
protected:
|
||||
bool m_create_area;
|
||||
|
@ -168,7 +168,7 @@ MapNode MapBlock::getNodeParentNoEx(v3s16 p)
|
||||
if black_air_left!=NULL, it is set to true if non-sunlighted
|
||||
air is left in block.
|
||||
*/
|
||||
bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
|
||||
bool MapBlock::propagateSunlight(std::set<v3s16> & light_sources,
|
||||
bool remove_light, bool *black_air_left)
|
||||
{
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
@ -287,7 +287,7 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
|
||||
|
||||
if(diminish_light(current_light) != 0)
|
||||
{
|
||||
light_sources.insert(pos_relative + pos, true);
|
||||
light_sources.insert(pos_relative + pos);
|
||||
}
|
||||
|
||||
if(current_light == 0 && stopped_to_solid_object)
|
||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include <exception>
|
||||
#include <set>
|
||||
#include "debug.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include "irr_v3d.h"
|
||||
@ -352,7 +353,7 @@ public:
|
||||
}
|
||||
|
||||
// See comments in mapblock.cpp
|
||||
bool propagateSunlight(core::map<v3s16, bool> & light_sources,
|
||||
bool propagateSunlight(std::set<v3s16> & light_sources,
|
||||
bool remove_light=false, bool *black_air_left=NULL);
|
||||
|
||||
// Copies data to VoxelManipulator to getPosRelative()
|
||||
|
@ -445,7 +445,7 @@ struct FastFace
|
||||
};
|
||||
|
||||
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
||||
v3f p, v3s16 dir, v3f scale, u8 light_source, core::array<FastFace> &dest)
|
||||
v3f p, v3s16 dir, v3f scale, u8 light_source, std::vector<FastFace> &dest)
|
||||
{
|
||||
FastFace face;
|
||||
|
||||
@ -455,6 +455,80 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
||||
v3f vertex_pos[4];
|
||||
v3s16 vertex_dirs[4];
|
||||
getNodeVertexDirs(dir, vertex_dirs);
|
||||
v3s16 t;
|
||||
switch (tile.rotation)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1: //R90
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[3];
|
||||
vertex_dirs[3] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[1];
|
||||
vertex_dirs[1] = t;
|
||||
break;
|
||||
case 2: //R180
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[2];
|
||||
vertex_dirs[2] = t;
|
||||
t = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
break;
|
||||
case 3: //R270
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
break;
|
||||
case 4: //FXR90
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[3];
|
||||
vertex_dirs[3] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[1];
|
||||
vertex_dirs[1] = t;
|
||||
tile.texture.pos.Y += tile.texture.size.Y;
|
||||
tile.texture.size.Y *= -1;
|
||||
break;
|
||||
case 5: //FXR270
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
tile.texture.pos.Y += tile.texture.size.Y;
|
||||
tile.texture.size.Y *= -1;
|
||||
break;
|
||||
case 6: //FYR90
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[3];
|
||||
vertex_dirs[3] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[1];
|
||||
vertex_dirs[1] = t;
|
||||
tile.texture.pos.X += tile.texture.size.X;
|
||||
tile.texture.size.X *= -1;
|
||||
break;
|
||||
case 7: //FYR270
|
||||
t = vertex_dirs[0];
|
||||
vertex_dirs[0] = vertex_dirs[1];
|
||||
vertex_dirs[1] = vertex_dirs[2];
|
||||
vertex_dirs[2] = vertex_dirs[3];
|
||||
vertex_dirs[3] = t;
|
||||
tile.texture.pos.X += tile.texture.size.X;
|
||||
tile.texture.size.X *= -1;
|
||||
break;
|
||||
case 8: //FX
|
||||
tile.texture.pos.Y += tile.texture.size.Y;
|
||||
tile.texture.size.Y *= -1;
|
||||
break;
|
||||
case 9: //FY
|
||||
tile.texture.pos.X += tile.texture.size.X;
|
||||
tile.texture.size.X *= -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertex_pos[i] = v3f(
|
||||
@ -601,60 +675,50 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
|
||||
// 5 = (0,0,-1)
|
||||
// 6 = (0,-1,0)
|
||||
// 7 = (-1,0,0)
|
||||
u8 dir_i = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7;
|
||||
u8 dir_i = ((dir.X + 2 * dir.Y + 3 * dir.Z) & 7)*2;
|
||||
|
||||
// Get rotation for things like chests
|
||||
u8 facedir = mn.getFaceDir(ndef);
|
||||
assert(facedir <= 3);
|
||||
|
||||
static const u8 dir_to_tile[4 * 8] =
|
||||
assert(facedir <= 23);
|
||||
static const u16 dir_to_tile[24 * 16] =
|
||||
{
|
||||
// 0 +X +Y +Z 0 -Z -Y -X
|
||||
0, 2, 0, 4, 0, 5, 1, 3, // facedir = 0
|
||||
0, 4, 0, 3, 0, 2, 1, 5, // facedir = 1
|
||||
0, 3, 0, 5, 0, 4, 1, 2, // facedir = 2
|
||||
0, 5, 0, 2, 0, 3, 1, 4, // facedir = 3
|
||||
// 0 +X +Y +Z -Z -Y -X -> value=tile,rotation
|
||||
0,0, 2,0 , 0,0 , 4,0 , 0,0, 5,0 , 1,0 , 3,0 , // rotate around y+ 0 - 3
|
||||
0,0, 4,0 , 0,3 , 3,0 , 0,0, 2,0 , 1,1 , 5,0 ,
|
||||
0,0, 3,0 , 0,2 , 5,0 , 0,0, 4,0 , 1,2 , 2,0 ,
|
||||
0,0, 5,0 , 0,1 , 2,0 , 0,0, 3,0 , 1,3 , 4,0 ,
|
||||
|
||||
0,0, 2,3 , 5,0 , 0,2 , 0,0, 1,0 , 4,2 , 3,1 , // rotate around z+ 4 - 7
|
||||
0,0, 4,3 , 2,0 , 0,3 , 0,0, 1,1 , 3,2 , 5,1 ,
|
||||
0,0, 3,3 , 4,0 , 0,0 , 0,0, 1,2 , 5,2 , 2,1 ,
|
||||
0,0, 5,3 , 3,0 , 0,1 , 0,0, 1,3 , 2,2 , 4,1 ,
|
||||
|
||||
0,0, 2,1 , 4,2 , 1,2 , 0,0, 0,0 , 5,0 , 3,3 , // rotate around z- 8 - 11
|
||||
0,0, 4,1 , 3,2 , 1,3 , 0,0, 0,3 , 2,0 , 5,3 ,
|
||||
0,0, 3,1 , 5,2 , 1,0 , 0,0, 0,2 , 4,0 , 2,3 ,
|
||||
0,0, 5,1 , 2,2 , 1,1 , 0,0, 0,1 , 3,0 , 4,3 ,
|
||||
|
||||
0,0, 0,3 , 3,3 , 4,1 , 0,0, 5,3 , 2,3 , 1,3 , // rotate around x+ 12 - 15
|
||||
0,0, 0,2 , 5,3 , 3,1 , 0,0, 2,3 , 4,3 , 1,0 ,
|
||||
0,0, 0,1 , 2,3 , 5,1 , 0,0, 4,3 , 3,3 , 1,1 ,
|
||||
0,0, 0,0 , 4,3 , 2,1 , 0,0, 3,3 , 5,3 , 1,2 ,
|
||||
|
||||
0,0, 1,1 , 2,1 , 4,3 , 0,0, 5,1 , 3,1 , 0,1 , // rotate around x- 16 - 19
|
||||
0,0, 1,2 , 4,1 , 3,3 , 0,0, 2,1 , 5,1 , 0,0 ,
|
||||
0,0, 1,3 , 3,1 , 5,3 , 0,0, 4,1 , 2,1 , 0,3 ,
|
||||
0,0, 1,0 , 5,1 , 2,3 , 0,0, 3,1 , 4,1 , 0,2 ,
|
||||
|
||||
0,0, 3,2 , 1,2 , 4,2 , 0,0, 5,2 , 0,2 , 2,2 , // rotate around y- 20 - 23
|
||||
0,0, 5,2 , 1,3 , 3,2 , 0,0, 2,2 , 0,1 , 4,2 ,
|
||||
0,0, 2,2 , 1,0 , 5,2 , 0,0, 4,2 , 0,0 , 3,2 ,
|
||||
0,0, 4,2 , 1,1 , 2,2 , 0,0, 3,2 , 0,3 , 5,2
|
||||
|
||||
};
|
||||
u8 tileindex = dir_to_tile[facedir*8 + dir_i];
|
||||
|
||||
// If not rotated or is side tile, we're done
|
||||
if(facedir == 0 || (tileindex != 0 && tileindex != 1))
|
||||
return getNodeTileN(mn, p, tileindex, data);
|
||||
|
||||
// This is the top or bottom tile, and it shall be rotated; thus rotate it
|
||||
TileSpec spec = getNodeTileN(mn, p, tileindex, data);
|
||||
if(tileindex == 0){
|
||||
if(facedir == 1){ // -90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR270";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
else if(facedir == 2){ // 180
|
||||
spec.texture.pos += spec.texture.size;
|
||||
spec.texture.size *= -1;
|
||||
}
|
||||
else if(facedir == 3){ // 90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR90";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
}
|
||||
else if(tileindex == 1){
|
||||
if(facedir == 1){ // -90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR90";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
else if(facedir == 2){ // 180
|
||||
spec.texture.pos += spec.texture.size;
|
||||
spec.texture.size *= -1;
|
||||
}
|
||||
else if(facedir == 3){ // 90
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
name += "^[transformR270";
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
}
|
||||
}
|
||||
u16 tile_index=facedir*16 + dir_i;
|
||||
TileSpec spec = getNodeTileN(mn, p, dir_to_tile[tile_index], data);
|
||||
spec.rotation=dir_to_tile[tile_index + 1];
|
||||
std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
|
||||
spec.texture = data->m_gamedef->tsrc()->getTexture(name);
|
||||
return spec;
|
||||
}
|
||||
|
||||
@ -745,7 +809,7 @@ static void updateFastFaceRow(
|
||||
v3f translate_dir_f,
|
||||
v3s16 face_dir,
|
||||
v3f face_dir_f,
|
||||
core::array<FastFace> &dest)
|
||||
std::vector<FastFace> &dest)
|
||||
{
|
||||
v3s16 p = startpos;
|
||||
|
||||
@ -794,6 +858,7 @@ static void updateFastFaceRow(
|
||||
&& next_lights[2] == lights[2]
|
||||
&& next_lights[3] == lights[3]
|
||||
&& next_tile == tile
|
||||
&& tile.rotation == 0
|
||||
&& next_light_source == light_source)
|
||||
{
|
||||
next_is_different = false;
|
||||
@ -897,7 +962,7 @@ static void updateFastFaceRow(
|
||||
}
|
||||
|
||||
static void updateAllFastFaceRows(MeshMakeData *data,
|
||||
core::array<FastFace> &dest)
|
||||
std::vector<FastFace> &dest)
|
||||
{
|
||||
/*
|
||||
Go through every y,z and get top(y+) faces in rows of x+
|
||||
@ -962,7 +1027,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
||||
// 24-155ms for MAP_BLOCKSIZE=32 (NOTE: probably outdated)
|
||||
//TimeTaker timer1("MapBlockMesh()");
|
||||
|
||||
core::array<FastFace> fastfaces_new;
|
||||
std::vector<FastFace> fastfaces_new;
|
||||
|
||||
/*
|
||||
We are including the faces of the trailing edges of the block.
|
||||
@ -1124,8 +1189,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
||||
m_mesh->addMeshBuffer(buf);
|
||||
// Mesh grabbed it
|
||||
buf->drop();
|
||||
buf->append(p.vertices.pointer(), p.vertices.size(),
|
||||
p.indices.pointer(), p.indices.size());
|
||||
buf->append(&p.vertices[0], p.vertices.size(),
|
||||
&p.indices[0], p.indices.size());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -143,13 +143,13 @@ private:
|
||||
struct PreMeshBuffer
|
||||
{
|
||||
TileSpec tile;
|
||||
core::array<u16> indices;
|
||||
core::array<video::S3DVertex> vertices;
|
||||
std::vector<u16> indices;
|
||||
std::vector<video::S3DVertex> vertices;
|
||||
};
|
||||
|
||||
struct MeshCollector
|
||||
{
|
||||
core::array<PreMeshBuffer> prebuffers;
|
||||
std::vector<PreMeshBuffer> prebuffers;
|
||||
|
||||
void append(const TileSpec &material,
|
||||
const video::S3DVertex *vertices, u32 numVertices,
|
||||
|
3034
src/mapgen.cpp
3034
src/mapgen.cpp
File diff suppressed because it is too large
Load Diff
56
src/mapgen.h
56
src/mapgen.h
@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MG_TREES 0x01
|
||||
#define MG_CAVES 0x02
|
||||
#define MG_DUNGEONS 0x04
|
||||
#define MGV6_FORESTS 0x08
|
||||
#define MGV6_JUNGLES 0x08
|
||||
#define MGV6_BIOME_BLEND 0x10
|
||||
#define MG_FLAT 0x20
|
||||
|
||||
@ -45,7 +45,8 @@ class MapBlock;
|
||||
class ManualMapVoxelManipulator;
|
||||
class VoxelManipulator;
|
||||
class INodeDefManager;
|
||||
class BlockMakeData;
|
||||
struct BlockMakeData;
|
||||
class VoxelArea;
|
||||
|
||||
struct MapgenParams {
|
||||
std::string mg_name;
|
||||
@ -72,6 +73,14 @@ public:
|
||||
int water_level;
|
||||
bool generating;
|
||||
int id;
|
||||
ManualMapVoxelManipulator *vm;
|
||||
INodeDefManager *ndef;
|
||||
|
||||
void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax);
|
||||
void setLighting(v3s16 nmin, v3s16 nmax, u8 light);
|
||||
void lightSpread(VoxelArea &a, v3s16 p, u8 light);
|
||||
void calcLighting(v3s16 nmin, v3s16 nmax);
|
||||
void calcLightingOld(v3s16 nmin, v3s16 nmax);
|
||||
|
||||
virtual void makeChunk(BlockMakeData *data) {};
|
||||
virtual int getGroundLevelAtPoint(v2s16 p) = 0;
|
||||
@ -88,5 +97,48 @@ struct MapgenFactory {
|
||||
virtual MapgenParams *createMapgenParams() = 0;
|
||||
};
|
||||
|
||||
enum OreType {
|
||||
ORE_SCATTER,
|
||||
ORE_SHEET,
|
||||
ORE_CLAYLIKE
|
||||
};
|
||||
|
||||
class Ore {
|
||||
public:
|
||||
std::string ore_name;
|
||||
std::string wherein_name;
|
||||
|
||||
content_t ore;
|
||||
content_t wherein; // the node to be replaced
|
||||
s16 clust_scarcity; //
|
||||
s16 clust_num_ores; // how many ore nodes are in a chunk
|
||||
s16 clust_size; // how large (in nodes) a chunk of ore is
|
||||
s16 height_min;
|
||||
s16 height_max;
|
||||
float nthresh; // threshhold for noise at which an ore is placed
|
||||
NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering)
|
||||
Noise *noise;
|
||||
|
||||
Ore() {
|
||||
ore = CONTENT_IGNORE;
|
||||
wherein = CONTENT_IGNORE;
|
||||
np = NULL;
|
||||
noise = NULL;
|
||||
}
|
||||
|
||||
void resolveNodeNames(INodeDefManager *ndef);
|
||||
virtual void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
|
||||
};
|
||||
|
||||
class OreScatter : public Ore {
|
||||
void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
class OreSheet : public Ore {
|
||||
void generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
Ore *createOre(OreType type);
|
||||
|
||||
#endif
|
||||
|
||||
|
371
src/mapgen_indev.cpp
Normal file
371
src/mapgen_indev.cpp
Normal file
@ -0,0 +1,371 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "mapgen_indev.h"
|
||||
#include "constants.h"
|
||||
#include "map.h"
|
||||
#include "main.h"
|
||||
#include "log.h"
|
||||
|
||||
/////////////////// Mapgen Indev perlin noise (default values - not used, from config or defaultsettings)
|
||||
|
||||
NoiseIndevParams nparams_indev_def;
|
||||
|
||||
/*
|
||||
NoiseIndevParams nparams_indev_def_terrain_base;
|
||||
// (-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_terrain_higher;
|
||||
// (20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_steepness;
|
||||
// (0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 1);
|
||||
NoiseIndevParams nparams_indev_def_mud;
|
||||
// (AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 1);
|
||||
NoiseIndevParams nparams_indev_def_float_islands;
|
||||
// (1, 10.0, v3f(500.0, 500.0, 500.0), 32451, 5, 0.6, 1);
|
||||
NoiseIndevParams nparams_indev_def_biome;
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void NoiseIndev::init(NoiseIndevParams *np, int seed, int sx, int sy, int sz) {
|
||||
Noise::init((NoiseParams*)np, seed, sx, sy, sz);
|
||||
this->npindev = np;
|
||||
}
|
||||
|
||||
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {
|
||||
init(np, seed, sx, sy, 1);
|
||||
}
|
||||
|
||||
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz) : Noise(np, seed, sx, sy, sz) {
|
||||
init(np, seed, sx, sy, sz);
|
||||
}
|
||||
|
||||
float farscale(float scale, float z) {
|
||||
return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 1 - (fabs(z)) ) / (MAP_GENERATION_LIMIT * 1) ) * (scale - 1) );
|
||||
}
|
||||
|
||||
float farscale(float scale, float x, float z) {
|
||||
return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 2 - (fabs(x) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 2) ) * (scale - 1) );
|
||||
}
|
||||
|
||||
float farscale(float scale, float x, float y, float z) {
|
||||
return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 3 - (fabs(x) + fabs(y) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 3) ) * (scale - 1) );
|
||||
}
|
||||
|
||||
void NoiseIndev::transformNoiseMapFarScale(float xx, float yy, float zz) {
|
||||
int i = 0;
|
||||
for (int z = 0; z != sz; z++) {
|
||||
for (int y = 0; y != sy; y++) {
|
||||
for (int x = 0; x != sx; x++) {
|
||||
result[i] = result[i] * npindev->scale * farscale(npindev->farscale, xx, yy, zz) + npindev->offset;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MapgenIndev::MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge)
|
||||
: MapgenV6(mapgenid, params, emerge)
|
||||
{
|
||||
noiseindev_terrain_base = new NoiseIndev(params->npindev_terrain_base, seed, csize.X, csize.Z);
|
||||
noiseindev_terrain_higher = new NoiseIndev(params->npindev_terrain_higher, seed, csize.X, csize.Z);
|
||||
noiseindev_steepness = new NoiseIndev(params->npindev_steepness, seed, csize.X, csize.Z);
|
||||
// noise_height_select = new Noise(params->np_height_select, seed, csize.X, csize.Y);
|
||||
// noise_trees = new Noise(params->np_trees, seed, csize.X, csize.Y);
|
||||
noiseindev_mud = new NoiseIndev(params->npindev_mud, seed, csize.X, csize.Z);
|
||||
// noise_beach = new Noise(params->np_beach, seed, csize.X, csize.Y);
|
||||
noiseindev_float_islands1 = new NoiseIndev(params->npindev_float_islands1, seed, csize.X, csize.Y, csize.Z);
|
||||
noiseindev_float_islands2 = new NoiseIndev(params->npindev_float_islands2, seed, csize.X, csize.Y, csize.Z);
|
||||
noiseindev_float_islands3 = new NoiseIndev(params->npindev_float_islands3, seed, csize.X, csize.Z);
|
||||
noiseindev_biome = new NoiseIndev(params->npindev_biome, seed, csize.X, csize.Z);
|
||||
}
|
||||
|
||||
MapgenIndev::~MapgenIndev() {
|
||||
delete noiseindev_terrain_base;
|
||||
delete noiseindev_terrain_higher;
|
||||
delete noiseindev_steepness;
|
||||
//delete noise_height_select;
|
||||
//delete noise_trees;
|
||||
delete noiseindev_mud;
|
||||
//delete noise_beach;
|
||||
delete noiseindev_float_islands1;
|
||||
delete noiseindev_float_islands2;
|
||||
delete noiseindev_float_islands3;
|
||||
delete noiseindev_biome;
|
||||
}
|
||||
|
||||
void MapgenIndev::calculateNoise() {
|
||||
int x = node_min.X;
|
||||
int y = node_min.Y;
|
||||
int z = node_min.Z;
|
||||
// Need to adjust for the original implementation's +.5 offset...
|
||||
if (!(flags & MG_FLAT)) {
|
||||
noiseindev_terrain_base->perlinMap2D(
|
||||
x + 0.5 * noiseindev_terrain_base->npindev->spread.X * farscale(noiseindev_terrain_base->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_terrain_base->npindev->spread.Z * farscale(noiseindev_terrain_base->npindev->farspread, x, z));
|
||||
noiseindev_terrain_base->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noiseindev_terrain_higher->perlinMap2D(
|
||||
x + 0.5 * noiseindev_terrain_higher->npindev->spread.X * farscale(noiseindev_terrain_higher->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_terrain_higher->npindev->spread.Z * farscale(noiseindev_terrain_higher->npindev->farspread, x, z));
|
||||
noiseindev_terrain_higher->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noiseindev_steepness->perlinMap2D(
|
||||
x + 0.5 * noiseindev_steepness->npindev->spread.X * farscale(noiseindev_steepness->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_steepness->npindev->spread.Z * farscale(noiseindev_steepness->npindev->farspread, x, z));
|
||||
noiseindev_steepness->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noise_height_select->perlinMap2D(
|
||||
x + 0.5 * noise_height_select->np->spread.X,
|
||||
z + 0.5 * noise_height_select->np->spread.Z);
|
||||
|
||||
noiseindev_float_islands1->perlinMap3D(
|
||||
x + 0.33 * noiseindev_float_islands1->npindev->spread.X * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
|
||||
y + 0.33 * noiseindev_float_islands1->npindev->spread.Y * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
|
||||
z + 0.33 * noiseindev_float_islands1->npindev->spread.Z * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z)
|
||||
);
|
||||
noiseindev_float_islands1->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noiseindev_float_islands2->perlinMap3D(
|
||||
x + 0.33 * noiseindev_float_islands2->npindev->spread.X * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
|
||||
y + 0.33 * noiseindev_float_islands2->npindev->spread.Y * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
|
||||
z + 0.33 * noiseindev_float_islands2->npindev->spread.Z * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z)
|
||||
);
|
||||
noiseindev_float_islands2->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
noiseindev_float_islands3->perlinMap2D(
|
||||
x + 0.5 * noiseindev_float_islands3->npindev->spread.X * farscale(noiseindev_float_islands3->npindev->farspread, x, z),
|
||||
z + 0.5 * noiseindev_float_islands3->npindev->spread.Z * farscale(noiseindev_float_islands3->npindev->farspread, x, z));
|
||||
noiseindev_float_islands3->transformNoiseMapFarScale(x, y, z);
|
||||
|
||||
}
|
||||
|
||||
if (!(flags & MG_FLAT)) {
|
||||
noiseindev_mud->perlinMap2D(
|
||||
x + 0.5 * noiseindev_mud->npindev->spread.X * farscale(noiseindev_mud->npindev->farspread, x, y, z),
|
||||
z + 0.5 * noiseindev_mud->npindev->spread.Z * farscale(noiseindev_mud->npindev->farspread, x, y, z));
|
||||
noiseindev_mud->transformNoiseMapFarScale(x, y, z);
|
||||
}
|
||||
noise_beach->perlinMap2D(
|
||||
x + 0.2 * noise_beach->np->spread.X,
|
||||
z + 0.7 * noise_beach->np->spread.Z);
|
||||
|
||||
noise_biome->perlinMap2D(
|
||||
x + 0.6 * noiseindev_biome->npindev->spread.X * farscale(noiseindev_biome->npindev->farspread, x, z),
|
||||
z + 0.2 * noiseindev_biome->npindev->spread.Z * farscale(noiseindev_biome->npindev->farspread, x, z));
|
||||
}
|
||||
|
||||
bool MapgenIndevParams::readParams(Settings *settings) {
|
||||
freq_desert = settings->getFloat("mgv6_freq_desert");
|
||||
freq_beach = settings->getFloat("mgv6_freq_beach");
|
||||
|
||||
npindev_terrain_base = settings->getNoiseIndevParams("mgindev_np_terrain_base");
|
||||
npindev_terrain_higher = settings->getNoiseIndevParams("mgindev_np_terrain_higher");
|
||||
npindev_steepness = settings->getNoiseIndevParams("mgindev_np_steepness");
|
||||
np_height_select = settings->getNoiseParams("mgv6_np_height_select");
|
||||
np_trees = settings->getNoiseParams("mgv6_np_trees");
|
||||
npindev_mud = settings->getNoiseIndevParams("mgindev_np_mud");
|
||||
np_beach = settings->getNoiseParams("mgv6_np_beach");
|
||||
npindev_biome = settings->getNoiseIndevParams("mgindev_np_biome");
|
||||
np_cave = settings->getNoiseParams("mgv6_np_cave");
|
||||
npindev_float_islands1 = settings->getNoiseIndevParams("mgindev_np_float_islands1");
|
||||
npindev_float_islands2 = settings->getNoiseIndevParams("mgindev_np_float_islands2");
|
||||
npindev_float_islands3 = settings->getNoiseIndevParams("mgindev_np_float_islands3");
|
||||
|
||||
bool success =
|
||||
npindev_terrain_base && npindev_terrain_higher && npindev_steepness &&
|
||||
np_height_select && np_trees && npindev_mud &&
|
||||
np_beach && np_biome && np_cave &&
|
||||
npindev_float_islands1 && npindev_float_islands2 && npindev_float_islands3;
|
||||
return success;
|
||||
}
|
||||
|
||||
void MapgenIndevParams::writeParams(Settings *settings) {
|
||||
settings->setFloat("mgv6_freq_desert", freq_desert);
|
||||
settings->setFloat("mgv6_freq_beach", freq_beach);
|
||||
|
||||
settings->setNoiseIndevParams("mgindev_np_terrain_base", npindev_terrain_base);
|
||||
settings->setNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher);
|
||||
settings->setNoiseIndevParams("mgindev_np_steepness", npindev_steepness);
|
||||
settings->setNoiseParams("mgv6_np_height_select", np_height_select);
|
||||
settings->setNoiseParams("mgv6_np_trees", np_trees);
|
||||
settings->setNoiseIndevParams("mgindev_np_mud", npindev_mud);
|
||||
settings->setNoiseParams("mgv6_np_beach", np_beach);
|
||||
settings->setNoiseIndevParams("mgindev_np_biome", npindev_biome);
|
||||
settings->setNoiseParams("mgv6_np_cave", np_cave);
|
||||
settings->setNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1);
|
||||
settings->setNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2);
|
||||
settings->setNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3);
|
||||
}
|
||||
|
||||
|
||||
float MapgenIndev::baseTerrainLevelFromNoise(v2s16 p) {
|
||||
if (flags & MG_FLAT)
|
||||
return water_level;
|
||||
|
||||
float terrain_base = NoisePerlin2DPosOffset(noiseindev_terrain_base->npindev,
|
||||
p.X, 0.5, p.Y, 0.5, seed);
|
||||
float terrain_higher = NoisePerlin2DPosOffset(noiseindev_terrain_higher->npindev,
|
||||
p.X, 0.5, p.Y, 0.5, seed);
|
||||
float steepness = NoisePerlin2DPosOffset(noiseindev_steepness->npindev,
|
||||
p.X, 0.5, p.Y, 0.5, seed);
|
||||
float height_select = NoisePerlin2DNoTxfmPosOffset(noise_height_select->np,
|
||||
p.X, 0.5, p.Y, 0.5, seed);
|
||||
|
||||
return baseTerrainLevel(terrain_base, terrain_higher,
|
||||
steepness, height_select);
|
||||
}
|
||||
|
||||
float MapgenIndev::baseTerrainLevelFromMap(int index) {
|
||||
if (flags & MG_FLAT)
|
||||
return water_level;
|
||||
|
||||
float terrain_base = noiseindev_terrain_base->result[index];
|
||||
float terrain_higher = noiseindev_terrain_higher->result[index];
|
||||
float steepness = noiseindev_steepness->result[index];
|
||||
float height_select = noise_height_select->result[index];
|
||||
|
||||
return baseTerrainLevel(terrain_base, terrain_higher,
|
||||
steepness, height_select);
|
||||
}
|
||||
|
||||
float MapgenIndev::getMudAmount(int index) {
|
||||
if (flags & MG_FLAT)
|
||||
return AVERAGE_MUD_AMOUNT;
|
||||
|
||||
/*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin(
|
||||
0.5+(float)p.X/200, 0.5+(float)p.Y/200,
|
||||
seed+91013, 3, 0.55));*/
|
||||
|
||||
return noiseindev_mud->result[index];
|
||||
}
|
||||
|
||||
void MapgenIndev::defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave) {
|
||||
cave.min_tunnel_diameter = 2;
|
||||
cave.max_tunnel_diameter = ps.range(2,6);
|
||||
cave.dswitchint = ps.range(1,14);
|
||||
cave.flooded = large_cave && ps.range(0,4);
|
||||
if(large_cave){
|
||||
cave.part_max_length_rs = ps.range(2,4);
|
||||
if (node_min.Y < -100 && !ps.range(0, farscale(0.2, node_min.X,node_min.Y,node_min.Z)*30)) { //huge
|
||||
cave.flooded = !ps.range(0, 3);
|
||||
cave.tunnel_routepoints = ps.range(5, 20);
|
||||
cave.min_tunnel_diameter = 30;
|
||||
cave.max_tunnel_diameter = ps.range(40, ps.range(80,120));
|
||||
} else {
|
||||
cave.tunnel_routepoints = ps.range(5, ps.range(15,30));
|
||||
cave.min_tunnel_diameter = 5;
|
||||
cave.max_tunnel_diameter = ps.range(7, ps.range(8,24));
|
||||
}
|
||||
} else {
|
||||
cave.part_max_length_rs = ps.range(2,9);
|
||||
cave.tunnel_routepoints = ps.range(10, ps.range(15,30));
|
||||
}
|
||||
cave.large_cave_is_flat = (ps.range(0,1) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
// version with one perlin3d. use with good params like
|
||||
settings->setDefault("mgindev_np_float_islands1", "-9.5, 10, (20, 50, 50 ), 45123, 5, 0.6, 1.5, 5");
|
||||
void MapgenIndev::generateFloatIslands(int min_y) {
|
||||
if (node_min.Y < min_y) return;
|
||||
v3s16 p0(node_min.X, node_min.Y, node_min.Z);
|
||||
MapNode n1(c_stone), n2(c_desert_stone);
|
||||
int xl = node_max.X - node_min.X;
|
||||
int yl = node_max.Y - node_min.Y;
|
||||
int zl = node_max.Z - node_min.Z;
|
||||
u32 index = 0;
|
||||
for (int x1 = 0; x1 <= xl; x1++)
|
||||
{
|
||||
//int x = x1 + node_min.Y;
|
||||
for (int z1 = 0; z1 <= zl; z1++)
|
||||
{
|
||||
//int z = z1 + node_min.Z;
|
||||
for (int y1 = 0; y1 <= yl; y1++, index++)
|
||||
{
|
||||
//int y = y1 + node_min.Y;
|
||||
float noise = noiseindev_float_islands1->result[index];
|
||||
//dstream << " y1="<<y1<< " x1="<<x1<<" z1="<<z1<< " noise="<<noise << std::endl;
|
||||
if (noise > 0 ) {
|
||||
v3s16 p = p0 + v3s16(x1, y1, z1);
|
||||
u32 i = vm->m_area.index(p);
|
||||
if (!vm->m_area.contains(i))
|
||||
continue;
|
||||
// Cancel if not air
|
||||
if (vm->m_data[i].getContent() != CONTENT_AIR)
|
||||
continue;
|
||||
vm->m_data[i] = noise > 1 ? n1 : n2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void MapgenIndev::generateFloatIslands(int min_y) {
|
||||
if (node_min.Y < min_y) return;
|
||||
PseudoRandom pr(blockseed + 985);
|
||||
// originally from http://forum.minetest.net/viewtopic.php?id=4776
|
||||
float RAR = 0.8 * farscale(0.4, node_min.Y); // 0.4; // Island rarity in chunk layer. -0.4 = thick layer with holes, 0 = 50%, 0.4 = desert rarity, 0.7 = very rare.
|
||||
float AMPY = 24; // 24; // Amplitude of island centre y variation.
|
||||
float TGRAD = 24; // 24; // Noise gradient to create top surface. Tallness of island top.
|
||||
float BGRAD = 24; // 24; // Noise gradient to create bottom surface. Tallness of island bottom.
|
||||
|
||||
v3s16 p0(node_min.X, node_min.Y, node_min.Z);
|
||||
MapNode n1(c_stone);
|
||||
|
||||
float xl = node_max.X - node_min.X;
|
||||
float yl = node_max.Y - node_min.Y;
|
||||
float zl = node_max.Z - node_min.Z;
|
||||
float midy = node_min.Y + yl * 0.5;
|
||||
u32 index = 0, index2d = 0;
|
||||
for (int x1 = 0; x1 <= xl; ++x1)
|
||||
{
|
||||
for (int z1 = 0; z1 <= zl; ++z1, ++index2d)
|
||||
{
|
||||
float noise3 = noiseindev_float_islands3->result[index2d];
|
||||
float pmidy = midy + noise3 / 1.5 * AMPY;
|
||||
for (int y1 = 0; y1 <= yl; ++y1, ++index)
|
||||
{
|
||||
int y = y1 + node_min.Y;
|
||||
float noise1 = noiseindev_float_islands1->result[index];
|
||||
float offset = y > pmidy ? (y - pmidy) / TGRAD : (pmidy - y) / BGRAD;
|
||||
float noise1off = noise1 - offset - RAR;
|
||||
if (noise1off > 0 && noise1off < 0.7) {
|
||||
float noise2 = noiseindev_float_islands2->result[index];
|
||||
if (noise2 - noise1off > -0.7){
|
||||
v3s16 p = p0 + v3s16(x1, y1, z1);
|
||||
u32 i = vm->m_area.index(p);
|
||||
if (!vm->m_area.contains(i))
|
||||
continue;
|
||||
// Cancel if not air
|
||||
if (vm->m_data[i].getContent() != CONTENT_AIR)
|
||||
continue;
|
||||
vm->m_data[i] = n1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapgenIndev::generateSomething() {
|
||||
int float_islands = g_settings->getS16("mgindev_float_islands");
|
||||
if(float_islands) generateFloatIslands(float_islands);
|
||||
}
|
152
src/mapgen_indev.h
Normal file
152
src/mapgen_indev.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPGENINDEV_HEADER
|
||||
#define MAPGENINDEV_HEADER
|
||||
|
||||
#include "mapgen.h"
|
||||
#include "mapgen_v6.h"
|
||||
|
||||
float farscale(float scale, float z);
|
||||
float farscale(float scale, float x, float z);
|
||||
float farscale(float scale, float x, float y, float z);
|
||||
|
||||
struct NoiseIndevParams : public NoiseParams {
|
||||
float farscale;
|
||||
float farspread;
|
||||
|
||||
NoiseIndevParams(){}
|
||||
NoiseIndevParams(float offset_, float scale_, v3f spread_, int seed_, int octaves_, float persist_, float farscale_ = 1, float farspread_ = 1)
|
||||
{
|
||||
offset = offset_;
|
||||
scale = scale_;
|
||||
spread = spread_;
|
||||
seed = seed_;
|
||||
octaves = octaves_;
|
||||
persist = persist_;
|
||||
|
||||
farscale = farscale_;
|
||||
farspread = farspread_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#define getNoiseIndevParams(x) getStruct<NoiseIndevParams>((x), "f,f,v3,s32,s32,f,f,f")
|
||||
#define setNoiseIndevParams(x, y) setStruct((x), "f,f,v3,s32,s32,f,f,f", (y))
|
||||
|
||||
class NoiseIndev : public Noise {
|
||||
public:
|
||||
NoiseIndevParams *npindev;
|
||||
|
||||
//NoiseIndev() {};
|
||||
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy);
|
||||
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz);
|
||||
void init(NoiseIndevParams *np, int seed, int sx, int sy, int sz);
|
||||
void transformNoiseMapFarScale(float xx = 0, float yy = 0, float zz = 0);
|
||||
};
|
||||
|
||||
extern NoiseIndevParams nparams_indev_def;
|
||||
/*
|
||||
extern NoiseIndevParams nparams_indev_def_terrain_base;
|
||||
extern NoiseIndevParams nparams_indev_def_terrain_higher;
|
||||
extern NoiseIndevParams nparams_indev_def_steepness;
|
||||
//extern NoiseIndevParams nparams_indev_def_height_select;
|
||||
//extern NoiseIndevParams nparams_indev_def_trees;
|
||||
extern NoiseIndevParams nparams_indev_def_mud;
|
||||
//extern NoiseIndevParams nparams_indev_def_beach;
|
||||
extern NoiseIndevParams nparams_indev_def_biome;
|
||||
//extern NoiseIndevParams nparams_indev_def_cave;
|
||||
extern NoiseIndevParams nparams_indev_def_float_islands;
|
||||
*/
|
||||
|
||||
struct MapgenIndevParams : public MapgenV6Params {
|
||||
NoiseIndevParams *npindev_terrain_base;
|
||||
NoiseIndevParams *npindev_terrain_higher;
|
||||
NoiseIndevParams *npindev_steepness;
|
||||
//NoiseParams *np_height_select;
|
||||
//NoiseParams *np_trees;
|
||||
NoiseIndevParams *npindev_mud;
|
||||
//NoiseParams *np_beach;
|
||||
NoiseIndevParams *npindev_biome;
|
||||
//NoiseParams *np_cave;
|
||||
NoiseIndevParams *npindev_float_islands1;
|
||||
NoiseIndevParams *npindev_float_islands2;
|
||||
NoiseIndevParams *npindev_float_islands3;
|
||||
|
||||
MapgenIndevParams() {
|
||||
//freq_desert = 0.45;
|
||||
//freq_beach = 0.15;
|
||||
npindev_terrain_base = &nparams_indev_def; //&nparams_indev_def_terrain_base;
|
||||
npindev_terrain_higher = &nparams_indev_def; //&nparams_indev_def_terrain_higher;
|
||||
npindev_steepness = &nparams_indev_def; //&nparams_indev_def_steepness;
|
||||
//np_height_select = &nparams_v6_def_height_select;
|
||||
//np_trees = &nparams_v6_def_trees;
|
||||
npindev_mud = &nparams_indev_def; //&nparams_indev_def_mud;
|
||||
//np_beach = &nparams_v6_def_beach;
|
||||
npindev_biome = &nparams_indev_def; //&nparams_indev_def_biome;
|
||||
//np_cave = &nparams_v6_def_cave;
|
||||
npindev_float_islands1 = &nparams_indev_def; //&nparams_indev_def_float_islands;
|
||||
npindev_float_islands2 = &nparams_indev_def; //&nparams_indev_def_float_islands;
|
||||
npindev_float_islands3 = &nparams_indev_def; //&nparams_indev_def_float_islands;
|
||||
|
||||
}
|
||||
|
||||
bool readParams(Settings *settings);
|
||||
void writeParams(Settings *settings);
|
||||
};
|
||||
|
||||
class MapgenIndev : public MapgenV6 {
|
||||
public:
|
||||
NoiseIndev *noiseindev_terrain_base;
|
||||
NoiseIndev *noiseindev_terrain_higher;
|
||||
NoiseIndev *noiseindev_steepness;
|
||||
//NoiseIndev *noise_height_select;
|
||||
//NoiseIndev *noise_trees;
|
||||
NoiseIndev *noiseindev_mud;
|
||||
//NoiseIndev *noise_beach;
|
||||
NoiseIndev *noiseindev_biome;
|
||||
//NoiseIndevParams *np_cave;
|
||||
NoiseIndev *noiseindev_float_islands1;
|
||||
NoiseIndev *noiseindev_float_islands2;
|
||||
NoiseIndev *noiseindev_float_islands3;
|
||||
|
||||
MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge);
|
||||
~MapgenIndev();
|
||||
void calculateNoise();
|
||||
|
||||
float baseTerrainLevelFromNoise(v2s16 p);
|
||||
float baseTerrainLevelFromMap(int index);
|
||||
float getMudAmount(int index);
|
||||
void defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave);
|
||||
void generateSomething();
|
||||
|
||||
void generateFloatIslands(int min_y);
|
||||
};
|
||||
|
||||
struct MapgenFactoryIndev : public MapgenFactoryV6 {
|
||||
Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) {
|
||||
return new MapgenIndev(mgid, (MapgenIndevParams *)params, emerge);
|
||||
};
|
||||
|
||||
MapgenParams *createMapgenParams() {
|
||||
return new MapgenIndevParams();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
102
src/mapgen_singlenode.cpp
Normal file
102
src/mapgen_singlenode.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "mapgen_singlenode.h"
|
||||
#include "voxel.h"
|
||||
#include "mapblock.h"
|
||||
#include "mapnode.h"
|
||||
#include "map.h"
|
||||
#include "nodedef.h"
|
||||
#include "voxelalgorithms.h"
|
||||
#include "profiler.h"
|
||||
#include "settings.h" // For g_settings
|
||||
#include "main.h" // For g_profiler
|
||||
#include "emerge.h"
|
||||
|
||||
//////////////////////// Mapgen Singlenode parameter read/write
|
||||
|
||||
bool MapgenSinglenodeParams::readParams(Settings *settings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MapgenSinglenodeParams::writeParams(Settings *settings) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MapgenSinglenode::MapgenSinglenode(int mapgenid, MapgenSinglenodeParams *params) {
|
||||
}
|
||||
|
||||
|
||||
MapgenSinglenode::~MapgenSinglenode() {
|
||||
}
|
||||
|
||||
//////////////////////// Map generator
|
||||
|
||||
void MapgenSinglenode::makeChunk(BlockMakeData *data) {
|
||||
assert(data->vmanip);
|
||||
assert(data->nodedef);
|
||||
assert(data->blockpos_requested.X >= data->blockpos_min.X &&
|
||||
data->blockpos_requested.Y >= data->blockpos_min.Y &&
|
||||
data->blockpos_requested.Z >= data->blockpos_min.Z);
|
||||
assert(data->blockpos_requested.X <= data->blockpos_max.X &&
|
||||
data->blockpos_requested.Y <= data->blockpos_max.Y &&
|
||||
data->blockpos_requested.Z <= data->blockpos_max.Z);
|
||||
|
||||
this->generating = true;
|
||||
this->vm = data->vmanip;
|
||||
this->ndef = data->nodedef;
|
||||
|
||||
v3s16 blockpos_min = data->blockpos_min;
|
||||
v3s16 blockpos_max = data->blockpos_max;
|
||||
|
||||
// Area of central chunk
|
||||
v3s16 node_min = blockpos_min*MAP_BLOCKSIZE;
|
||||
v3s16 node_max = (blockpos_max+v3s16(1,1,1))*MAP_BLOCKSIZE-v3s16(1,1,1);
|
||||
|
||||
content_t c_node = ndef->getId("mapgen_singlenode");
|
||||
if (c_node == CONTENT_IGNORE)
|
||||
c_node = CONTENT_AIR;
|
||||
|
||||
MapNode n_node(c_node);
|
||||
|
||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||
for (s16 y = node_min.Y; y <= node_max.Y; y++) {
|
||||
u32 i = vm->m_area.index(node_min.X, y, z);
|
||||
for (s16 x = node_min.X; x <= node_max.X; x++) {
|
||||
if (vm->m_data[i].getContent() == CONTENT_IGNORE)
|
||||
vm->m_data[i] = n_node;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add top and bottom side of water to transforming_liquid queue
|
||||
updateLiquid(&data->transforming_liquid, node_min, node_max);
|
||||
|
||||
// Calculate lighting
|
||||
calcLighting(node_min, node_max);
|
||||
|
||||
this->generating = false;
|
||||
}
|
||||
|
||||
int MapgenSinglenode::getGroundLevelAtPoint(v2s16 p) {
|
||||
return 0;
|
||||
}
|
||||
|
53
src/mapgen_singlenode.h
Normal file
53
src/mapgen_singlenode.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPGEN_SINGLENODE_HEADER
|
||||
#define MAPGEN_SINGLENODE_HEADER
|
||||
|
||||
#include "mapgen.h"
|
||||
|
||||
struct MapgenSinglenodeParams : public MapgenParams {
|
||||
|
||||
MapgenSinglenodeParams() {
|
||||
}
|
||||
|
||||
bool readParams(Settings *settings);
|
||||
void writeParams(Settings *settings);
|
||||
};
|
||||
|
||||
class MapgenSinglenode : public Mapgen {
|
||||
public:
|
||||
MapgenSinglenode(int mapgenid, MapgenSinglenodeParams *params);
|
||||
~MapgenSinglenode();
|
||||
|
||||
void makeChunk(BlockMakeData *data);
|
||||
int getGroundLevelAtPoint(v2s16 p);
|
||||
};
|
||||
|
||||
struct MapgenFactorySinglenode : public MapgenFactory {
|
||||
Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) {
|
||||
return new MapgenSinglenode(mgid, (MapgenSinglenodeParams *)params);
|
||||
};
|
||||
|
||||
MapgenParams *createMapgenParams() {
|
||||
return new MapgenSinglenodeParams();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
1788
src/mapgen_v6.cpp
1788
src/mapgen_v6.cpp
File diff suppressed because it is too large
Load Diff
108
src/mapgen_v6.h
108
src/mapgen_v6.h
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapgen.h"
|
||||
|
||||
#define AVERAGE_MUD_AMOUNT 4
|
||||
#define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
|
||||
|
||||
enum BiomeType
|
||||
{
|
||||
@ -34,11 +35,23 @@ extern NoiseParams nparams_v6_def_terrain_base;
|
||||
extern NoiseParams nparams_v6_def_terrain_higher;
|
||||
extern NoiseParams nparams_v6_def_steepness;
|
||||
extern NoiseParams nparams_v6_def_height_select;
|
||||
extern NoiseParams nparams_v6_def_trees;
|
||||
extern NoiseParams nparams_v6_def_mud;
|
||||
extern NoiseParams nparams_v6_def_beach;
|
||||
extern NoiseParams nparams_v6_def_biome;
|
||||
extern NoiseParams nparams_v6_def_cave;
|
||||
extern NoiseParams nparams_v6_def_humidity;
|
||||
extern NoiseParams nparams_v6_def_trees;
|
||||
extern NoiseParams nparams_v6_def_apple_trees;
|
||||
|
||||
struct Cave {
|
||||
s16 min_tunnel_diameter;
|
||||
s16 max_tunnel_diameter;
|
||||
int dswitchint;
|
||||
u16 tunnel_routepoints;
|
||||
int part_max_length_rs;
|
||||
bool large_cave_is_flat;
|
||||
bool flooded;
|
||||
};
|
||||
|
||||
struct MapgenV6Params : public MapgenParams {
|
||||
float freq_desert;
|
||||
@ -47,12 +60,14 @@ struct MapgenV6Params : public MapgenParams {
|
||||
NoiseParams *np_terrain_higher;
|
||||
NoiseParams *np_steepness;
|
||||
NoiseParams *np_height_select;
|
||||
NoiseParams *np_trees;
|
||||
NoiseParams *np_mud;
|
||||
NoiseParams *np_beach;
|
||||
NoiseParams *np_biome;
|
||||
NoiseParams *np_cave;
|
||||
|
||||
NoiseParams *np_humidity;
|
||||
NoiseParams *np_trees;
|
||||
NoiseParams *np_apple_trees;
|
||||
|
||||
MapgenV6Params() {
|
||||
freq_desert = 0.45;
|
||||
freq_beach = 0.15;
|
||||
@ -60,11 +75,14 @@ struct MapgenV6Params : public MapgenParams {
|
||||
np_terrain_higher = &nparams_v6_def_terrain_higher;
|
||||
np_steepness = &nparams_v6_def_steepness;
|
||||
np_height_select = &nparams_v6_def_height_select;
|
||||
np_trees = &nparams_v6_def_trees;
|
||||
np_mud = &nparams_v6_def_mud;
|
||||
np_beach = &nparams_v6_def_beach;
|
||||
np_biome = &nparams_v6_def_biome;
|
||||
np_cave = &nparams_v6_def_cave;
|
||||
np_humidity = &nparams_v6_def_humidity;
|
||||
np_trees = &nparams_v6_def_trees;
|
||||
np_apple_trees = &nparams_v6_def_apple_trees;
|
||||
|
||||
}
|
||||
|
||||
bool readParams(Settings *settings);
|
||||
@ -73,64 +91,90 @@ struct MapgenV6Params : public MapgenParams {
|
||||
|
||||
class MapgenV6 : public Mapgen {
|
||||
public:
|
||||
//ManualMapVoxelManipulator &vmanip;
|
||||
EmergeManager *emerge;
|
||||
|
||||
int ystride;
|
||||
v3s16 csize;
|
||||
u32 flags;
|
||||
|
||||
u32 blockseed;
|
||||
v3s16 node_min;
|
||||
v3s16 node_max;
|
||||
v3s16 full_node_min;
|
||||
v3s16 full_node_max;
|
||||
v3s16 central_area_size;
|
||||
int volume_nodes;
|
||||
|
||||
Noise *noise_terrain_base;
|
||||
Noise *noise_terrain_higher;
|
||||
Noise *noise_steepness;
|
||||
Noise *noise_height_select;
|
||||
Noise *noise_trees;
|
||||
Noise *noise_mud;
|
||||
Noise *noise_beach;
|
||||
Noise *noise_biome;
|
||||
|
||||
float *map_terrain_base;
|
||||
float *map_terrain_higher;
|
||||
float *map_steepness;
|
||||
float *map_height_select;
|
||||
float *map_trees;
|
||||
float *map_mud;
|
||||
float *map_beach;
|
||||
float *map_biome;
|
||||
|
||||
NoiseParams *np_cave;
|
||||
|
||||
u32 flags;
|
||||
NoiseParams *np_humidity;
|
||||
NoiseParams *np_trees;
|
||||
NoiseParams *np_apple_trees;
|
||||
float freq_desert;
|
||||
float freq_beach;
|
||||
|
||||
content_t c_stone;
|
||||
content_t c_dirt;
|
||||
content_t c_dirt_with_grass;
|
||||
content_t c_sand;
|
||||
content_t c_water_source;
|
||||
content_t c_lava_source;
|
||||
content_t c_gravel;
|
||||
content_t c_cobble;
|
||||
content_t c_desert_sand;
|
||||
content_t c_desert_stone;
|
||||
|
||||
MapgenV6(int mapgenid, MapgenV6Params *params);
|
||||
MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge);
|
||||
~MapgenV6();
|
||||
|
||||
void makeChunk(BlockMakeData *data);
|
||||
int getGroundLevelAtPoint(v2s16 p);
|
||||
|
||||
double baseRockLevelFromNoise(v2s16 p);
|
||||
static s16 find_ground_level(VoxelManipulator &vmanip,
|
||||
v2s16 p2d, INodeDefManager *ndef);
|
||||
static s16 find_stone_level(VoxelManipulator &vmanip,
|
||||
v2s16 p2d, INodeDefManager *ndef);
|
||||
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
|
||||
bool is_apple_tree, INodeDefManager *ndef);
|
||||
double tree_amount_2d(u64 seed, v2s16 p);
|
||||
float baseTerrainLevel(float terrain_base, float terrain_higher,
|
||||
float steepness, float height_select);
|
||||
virtual float baseTerrainLevelFromNoise(v2s16 p);
|
||||
virtual float baseTerrainLevelFromMap(v2s16 p);
|
||||
virtual float baseTerrainLevelFromMap(int index);
|
||||
|
||||
s16 find_ground_level(v2s16 p2d);
|
||||
s16 find_stone_level(v2s16 p2d);
|
||||
bool block_is_underground(u64 seed, v3s16 blockpos);
|
||||
double base_rock_level_2d(u64 seed, v2s16 p);
|
||||
s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
|
||||
double get_mud_add_amount(u64 seed, v2s16 p);
|
||||
bool get_have_beach(u64 seed, v2s16 p2d);
|
||||
BiomeType get_biome(u64 seed, v2s16 p2d);
|
||||
|
||||
float getHumidity(v2s16 p);
|
||||
float getTreeAmount(v2s16 p);
|
||||
bool getHaveAppleTree(v2s16 p);
|
||||
float getMudAmount(v2s16 p);
|
||||
virtual float getMudAmount(int index);
|
||||
bool getHaveBeach(v2s16 p);
|
||||
bool getHaveBeach(int index);
|
||||
BiomeType getBiome(v2s16 p);
|
||||
BiomeType getBiome(int index, v2s16 p);
|
||||
|
||||
u32 get_blockseed(u64 seed, v3s16 p);
|
||||
|
||||
virtual void calculateNoise();
|
||||
int generateGround();
|
||||
void addMud();
|
||||
void flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos);
|
||||
void addDirtGravelBlobs();
|
||||
void growGrass();
|
||||
void placeTreesAndJungleGrass();
|
||||
virtual void defineCave(Cave &cave, PseudoRandom ps,
|
||||
v3s16 node_min, bool large_cave);
|
||||
void generateCaves(int max_stone_y);
|
||||
virtual void generateSomething() {}; //for next mapgen
|
||||
};
|
||||
|
||||
struct MapgenFactoryV6 : public MapgenFactory {
|
||||
Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) {
|
||||
return new MapgenV6(mgid, (MapgenV6Params *)params);
|
||||
return new MapgenV6(mgid, (MapgenV6Params *)params, emerge);
|
||||
};
|
||||
|
||||
MapgenParams *createMapgenParams() {
|
||||
|
136
src/mapnode.cpp
136
src/mapnode.cpp
@ -107,7 +107,7 @@ u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
|
||||
{
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
if(f.param_type_2 == CPT2_FACEDIR)
|
||||
return getParam2() & 0x03;
|
||||
return getParam2() & 0x1F;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -140,29 +140,131 @@ static std::vector<aabb3f> transformNodeBox(const MapNode &n,
|
||||
{
|
||||
const std::vector<aabb3f> &fixed = nodebox.fixed;
|
||||
int facedir = n.getFaceDir(nodemgr);
|
||||
u8 axisdir = facedir>>2;
|
||||
facedir&=0x03;
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = fixed.begin();
|
||||
i != fixed.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
if(facedir == 1)
|
||||
switch (axisdir)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
box.repair();
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
box.repair();
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
box.repair();
|
||||
case 0:
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
}
|
||||
break;
|
||||
case 1: // z+
|
||||
box.MinEdge.rotateYZBy(90);
|
||||
box.MaxEdge.rotateYZBy(90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(90);
|
||||
box.MaxEdge.rotateXYBy(90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(180);
|
||||
box.MaxEdge.rotateXYBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(-90);
|
||||
box.MaxEdge.rotateXYBy(-90);
|
||||
}
|
||||
break;
|
||||
case 2: //z-
|
||||
box.MinEdge.rotateYZBy(-90);
|
||||
box.MaxEdge.rotateYZBy(-90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(-90);
|
||||
box.MaxEdge.rotateXYBy(-90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(180);
|
||||
box.MaxEdge.rotateXYBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXYBy(90);
|
||||
box.MaxEdge.rotateXYBy(90);
|
||||
}
|
||||
break;
|
||||
case 3: //x+
|
||||
box.MinEdge.rotateXYBy(-90);
|
||||
box.MaxEdge.rotateXYBy(-90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(90);
|
||||
box.MaxEdge.rotateYZBy(90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(180);
|
||||
box.MaxEdge.rotateYZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(-90);
|
||||
box.MaxEdge.rotateYZBy(-90);
|
||||
}
|
||||
break;
|
||||
case 4: //x-
|
||||
box.MinEdge.rotateXYBy(90);
|
||||
box.MaxEdge.rotateXYBy(90);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(-90);
|
||||
box.MaxEdge.rotateYZBy(-90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(180);
|
||||
box.MaxEdge.rotateYZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateYZBy(90);
|
||||
box.MaxEdge.rotateYZBy(90);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
box.MinEdge.rotateXYBy(-180);
|
||||
box.MaxEdge.rotateXYBy(-180);
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
box.repair();
|
||||
boxes.push_back(box);
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ void MapSector::deleteBlocks()
|
||||
m_block_cache = NULL;
|
||||
|
||||
// Delete all
|
||||
core::map<s16, MapBlock*>::Iterator i = m_blocks.getIterator();
|
||||
for(; i.atEnd() == false; i++)
|
||||
for(std::map<s16, MapBlock*>::iterator i = m_blocks.begin();
|
||||
i != m_blocks.end(); ++i)
|
||||
{
|
||||
delete i.getNode()->getValue();
|
||||
delete i->second;
|
||||
}
|
||||
|
||||
// Clear container
|
||||
@ -64,14 +64,14 @@ MapBlock * MapSector::getBlockBuffered(s16 y)
|
||||
}
|
||||
|
||||
// If block doesn't exist, return NULL
|
||||
core::map<s16, MapBlock*>::Node *n = m_blocks.find(y);
|
||||
if(n == NULL)
|
||||
std::map<s16, MapBlock*>::iterator n = m_blocks.find(y);
|
||||
if(n == m_blocks.end())
|
||||
{
|
||||
block = NULL;
|
||||
}
|
||||
// If block exists, return it
|
||||
else{
|
||||
block = n->getValue();
|
||||
block = n->second;
|
||||
}
|
||||
|
||||
// Cache the last result
|
||||
@ -101,7 +101,7 @@ MapBlock * MapSector::createBlankBlock(s16 y)
|
||||
{
|
||||
MapBlock *block = createBlankBlockNoInsert(y);
|
||||
|
||||
m_blocks.insert(y, block);
|
||||
m_blocks[y] = block;
|
||||
|
||||
return block;
|
||||
}
|
||||
@ -119,7 +119,7 @@ void MapSector::insertBlock(MapBlock *block)
|
||||
assert(p2d == m_pos);
|
||||
|
||||
// Insert into container
|
||||
m_blocks.insert(block_y, block);
|
||||
m_blocks[block_y] = block;
|
||||
}
|
||||
|
||||
void MapSector::deleteBlock(MapBlock *block)
|
||||
@ -130,23 +130,18 @@ void MapSector::deleteBlock(MapBlock *block)
|
||||
m_block_cache = NULL;
|
||||
|
||||
// Remove from container
|
||||
m_blocks.remove(block_y);
|
||||
m_blocks.erase(block_y);
|
||||
|
||||
// Delete
|
||||
delete block;
|
||||
}
|
||||
|
||||
void MapSector::getBlocks(core::list<MapBlock*> &dest)
|
||||
void MapSector::getBlocks(std::list<MapBlock*> &dest)
|
||||
{
|
||||
core::list<MapBlock*> ref_list;
|
||||
|
||||
core::map<s16, MapBlock*>::Iterator bi;
|
||||
|
||||
bi = m_blocks.getIterator();
|
||||
for(; bi.atEnd() == false; bi++)
|
||||
for(std::map<s16, MapBlock*>::iterator bi = m_blocks.begin();
|
||||
bi != m_blocks.end(); ++bi)
|
||||
{
|
||||
MapBlock *b = bi.getNode()->getValue();
|
||||
dest.push_back(b);
|
||||
dest.push_back(bi->second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +184,7 @@ ServerMapSector* ServerMapSector::deSerialize(
|
||||
std::istream &is,
|
||||
Map *parent,
|
||||
v2s16 p2d,
|
||||
core::map<v2s16, MapSector*> & sectors,
|
||||
std::map<v2s16, MapSector*> & sectors,
|
||||
IGameDef *gamedef
|
||||
)
|
||||
{
|
||||
@ -219,22 +214,22 @@ ServerMapSector* ServerMapSector::deSerialize(
|
||||
|
||||
ServerMapSector *sector = NULL;
|
||||
|
||||
core::map<v2s16, MapSector*>::Node *n = sectors.find(p2d);
|
||||
std::map<v2s16, MapSector*>::iterator n = sectors.find(p2d);
|
||||
|
||||
if(n != NULL)
|
||||
if(n != sectors.end())
|
||||
{
|
||||
dstream<<"WARNING: deSerializing existent sectors not supported "
|
||||
"at the moment, because code hasn't been tested."
|
||||
<<std::endl;
|
||||
|
||||
MapSector *sector = n->getValue();
|
||||
MapSector *sector = n->second;
|
||||
assert(sector->getId() == MAPSECTOR_SERVER);
|
||||
return (ServerMapSector*)sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector = new ServerMapSector(parent, p2d, gamedef);
|
||||
sectors.insert(p2d, sector);
|
||||
sectors[p2d] = sector;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "exceptions.h"
|
||||
#include <ostream>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
class MapBlock;
|
||||
class Map;
|
||||
@ -60,7 +62,7 @@ public:
|
||||
|
||||
void deleteBlock(MapBlock *block);
|
||||
|
||||
void getBlocks(core::list<MapBlock*> &dest);
|
||||
void getBlocks(std::list<MapBlock*> &dest);
|
||||
|
||||
// Always false at the moment, because sector contains no metadata.
|
||||
bool differs_from_disk;
|
||||
@ -68,7 +70,7 @@ public:
|
||||
protected:
|
||||
|
||||
// The pile of MapBlocks
|
||||
core::map<s16, MapBlock*> m_blocks;
|
||||
std::map<s16, MapBlock*> m_blocks;
|
||||
|
||||
Map *m_parent;
|
||||
// Position on parent (in MapBlock widths)
|
||||
@ -110,7 +112,7 @@ public:
|
||||
std::istream &is,
|
||||
Map *parent,
|
||||
v2s16 p2d,
|
||||
core::map<v2s16, MapSector*> & sectors,
|
||||
std::map<v2s16, MapSector*> & sectors,
|
||||
IGameDef *gamedef
|
||||
);
|
||||
|
||||
|
52
src/mods.cpp
52
src/mods.cpp
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include "subgame.h"
|
||||
#include "settings.h"
|
||||
#include "strfnd.h"
|
||||
|
||||
std::map<std::string, ModSpec> getModsInPath(std::string path)
|
||||
{
|
||||
@ -188,11 +189,58 @@ void ModConfiguration::addMods(std::vector<ModSpec> new_mods)
|
||||
}
|
||||
}
|
||||
|
||||
// If failed, returned modspec has name==""
|
||||
static ModSpec findCommonMod(const std::string &modname)
|
||||
{
|
||||
// Try to find in {$user,$share}/games/common/$modname
|
||||
std::vector<std::string> find_paths;
|
||||
find_paths.push_back(porting::path_user + DIR_DELIM + "games" +
|
||||
DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname);
|
||||
find_paths.push_back(porting::path_share + DIR_DELIM + "games" +
|
||||
DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname);
|
||||
for(u32 i=0; i<find_paths.size(); i++){
|
||||
const std::string &try_path = find_paths[i];
|
||||
if(fs::PathExists(try_path))
|
||||
return ModSpec(modname, try_path);
|
||||
}
|
||||
// Failed to find mod
|
||||
return ModSpec();
|
||||
}
|
||||
|
||||
ModConfiguration::ModConfiguration(std::string worldpath)
|
||||
{
|
||||
SubgameSpec gamespec = findWorldSubgame(worldpath);
|
||||
|
||||
// Add common mods without dependency handling
|
||||
std::vector<std::string> inexistent_common_mods;
|
||||
Settings gameconf;
|
||||
if(getGameConfig(gamespec.path, gameconf)){
|
||||
if(gameconf.exists("common_mods")){
|
||||
Strfnd f(gameconf.get("common_mods"));
|
||||
while(!f.atend()){
|
||||
std::string modname = trim(f.next(","));
|
||||
if(modname.empty())
|
||||
continue;
|
||||
ModSpec spec = findCommonMod(modname);
|
||||
if(spec.name.empty())
|
||||
inexistent_common_mods.push_back(modname);
|
||||
else
|
||||
m_sorted_mods.push_back(spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!inexistent_common_mods.empty()){
|
||||
std::string s = "Required common mods ";
|
||||
for(u32 i=0; i<inexistent_common_mods.size(); i++){
|
||||
if(i != 0) s += ", ";
|
||||
s += std::string("\"") + inexistent_common_mods[i] + "\"";
|
||||
}
|
||||
s += " could not be found.";
|
||||
throw ModError(s);
|
||||
}
|
||||
|
||||
// Add all world mods and all game mods
|
||||
addModsInPath(worldpath + DIR_DELIM + "worldmods");
|
||||
SubgameSpec gamespec = findWorldSubgame(worldpath);
|
||||
addModsInPath(gamespec.gamemods_path);
|
||||
|
||||
// check world.mt file for mods explicitely declared to be
|
||||
@ -217,6 +265,6 @@ ModConfiguration::ModConfiguration(std::string worldpath)
|
||||
}
|
||||
|
||||
for(std::set<std::string>::const_iterator i = gamespec.addon_mods_paths.begin();
|
||||
i != gamespec.addon_mods_paths.end(); ++i)
|
||||
i != gamespec.addon_mods_paths.end(); ++i)
|
||||
addModsInPathFiltered((*i),exclude_mod_names);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <exception>
|
||||
#include <list>
|
||||
|
||||
class ModError : public std::exception
|
||||
{
|
||||
@ -68,7 +69,6 @@ struct ModSpec
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
std::map<std::string,ModSpec> getModsInPath(std::string path);
|
||||
|
||||
// expands modpack contents, but does not replace them.
|
||||
@ -140,6 +140,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -107,26 +107,31 @@ void NodeBox::deSerialize(std::istream &is)
|
||||
TileDef
|
||||
*/
|
||||
|
||||
void TileDef::serialize(std::ostream &os) const
|
||||
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
if(protocol_version >= 17)
|
||||
writeU8(os, 1);
|
||||
else
|
||||
writeU8(os, 0);
|
||||
os<<serializeString(name);
|
||||
writeU8(os, animation.type);
|
||||
writeU16(os, animation.aspect_w);
|
||||
writeU16(os, animation.aspect_h);
|
||||
writeF1000(os, animation.length);
|
||||
if(protocol_version >= 17)
|
||||
writeU8(os, backface_culling);
|
||||
}
|
||||
|
||||
void TileDef::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0)
|
||||
throw SerializationError("unsupported TileDef version");
|
||||
name = deSerializeString(is);
|
||||
animation.type = (TileAnimationType)readU8(is);
|
||||
animation.aspect_w = readU16(is);
|
||||
animation.aspect_h = readU16(is);
|
||||
animation.length = readF1000(is);
|
||||
if(version >= 1)
|
||||
backface_culling = readU8(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -235,10 +240,10 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i=0; i<6; i++)
|
||||
tiledef[i].serialize(os);
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
tiledef_special[i].serialize(os);
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
@ -270,9 +275,9 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
|
||||
serializeSimpleSoundSpec(sound_footstep, os);
|
||||
serializeSimpleSoundSpec(sound_dig, os);
|
||||
serializeSimpleSoundSpec(sound_dug, os);
|
||||
writeU8(os, rightclickable);
|
||||
// Stuff below should be moved to correct place in a version that otherwise changes
|
||||
// the protocol version
|
||||
writeU8(os, rightclickable);
|
||||
}
|
||||
|
||||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
@ -331,12 +336,12 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||
rightclickable = readU8(is);
|
||||
// If you add anything here, insert it primarily inside the try-catch
|
||||
// block to not need to increase the version.
|
||||
try{
|
||||
// Stuff below should be moved to correct place in a version that
|
||||
// otherwise changes the protocol version
|
||||
rightclickable = readU8(is);
|
||||
}catch(SerializationError &e) {};
|
||||
}
|
||||
|
||||
@ -809,10 +814,10 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i=0; i<6; i++)
|
||||
tiledef[i].serialize(os);
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
tiledef_special[i].serialize(os);
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
|
@ -119,7 +119,7 @@ struct TileDef
|
||||
animation.length = 1.0;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os) const;
|
||||
void serialize(std::ostream &os, u16 protocol_version) const;
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
|
||||
~Noise();
|
||||
|
||||
void init(NoiseParams *np, int seed, int sx, int sy, int sz);
|
||||
virtual void init(NoiseParams *np, int seed, int sx, int sy, int sz);
|
||||
void setSize(int sx, int sy);
|
||||
void setSize(int sx, int sy, int sz);
|
||||
void setSpreadFactor(v3f spread);
|
||||
@ -157,7 +157,7 @@ inline float easeCurve(float t) {
|
||||
(s) + (np)->seed, (np)->octaves, (np)->persist))
|
||||
|
||||
#define NoisePerlin3D(np, x, y, z, s) ((np)->offset + (np)->scale * \
|
||||
noise2d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
|
||||
noise3d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
|
||||
(float)(z) / (np)->spread.Z, (s) + (np)->seed, (np)->octaves, (np)->persist))
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
struct ObjectProperties
|
||||
{
|
||||
@ -35,8 +36,8 @@ struct ObjectProperties
|
||||
std::string visual;
|
||||
std::string mesh;
|
||||
v2f visual_size;
|
||||
core::array<std::string> textures;
|
||||
core::array<video::SColor> colors;
|
||||
std::vector<std::string> textures;
|
||||
std::vector<video::SColor> colors;
|
||||
v2s16 spritediv;
|
||||
v2s16 initial_sprite_basepos;
|
||||
bool is_visible;
|
||||
|
@ -32,19 +32,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "clientmap.h"
|
||||
#include "mapnode.h"
|
||||
|
||||
/*
|
||||
Utility
|
||||
*/
|
||||
|
||||
v3f random_v3f(v3f min, v3f max)
|
||||
{
|
||||
return v3f( rand()/(float)RAND_MAX*(max.X-min.X)+min.X,
|
||||
rand()/(float)RAND_MAX*(max.Y-min.Y)+min.Y,
|
||||
rand()/(float)RAND_MAX*(max.Z-min.Z)+min.Z);
|
||||
}
|
||||
|
||||
std::vector<Particle*> all_particles;
|
||||
std::map<u32, ParticleSpawner*> all_particlespawners;
|
||||
|
||||
Particle::Particle(
|
||||
IGameDef *gamedef,
|
||||
scene::ISceneManager* smgr,
|
||||
LocalPlayer *player,
|
||||
s32 id,
|
||||
ClientEnvironment &env,
|
||||
v3f pos,
|
||||
v3f velocity,
|
||||
v3f acceleration,
|
||||
float expirationtime,
|
||||
float size,
|
||||
bool collisiondetection,
|
||||
AtlasPointer ap
|
||||
):
|
||||
scene::ISceneNode(smgr->getRootSceneNode(), smgr, id)
|
||||
scene::ISceneNode(smgr->getRootSceneNode(), smgr)
|
||||
{
|
||||
// Misc
|
||||
m_gamedef = gamedef;
|
||||
@ -57,7 +72,6 @@ Particle::Particle(
|
||||
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
m_material.setTexture(0, ap.atlas);
|
||||
m_ap = ap;
|
||||
m_light = 0;
|
||||
|
||||
|
||||
// Particle related
|
||||
@ -68,10 +82,20 @@ Particle::Particle(
|
||||
m_time = 0;
|
||||
m_player = player;
|
||||
m_size = size;
|
||||
m_collisiondetection = collisiondetection;
|
||||
|
||||
// Irrlicht stuff (TODO)
|
||||
m_collisionbox = core::aabbox3d<f32>(-size/2,-size/2,-size/2,size/2,size/2,size/2);
|
||||
// Irrlicht stuff
|
||||
m_collisionbox = core::aabbox3d<f32>
|
||||
(-size/2,-size/2,-size/2,size/2,size/2,size/2);
|
||||
this->setAutomaticCulling(scene::EAC_OFF);
|
||||
|
||||
// Init lighting
|
||||
updateLight(env);
|
||||
|
||||
// Init model
|
||||
updateVertices();
|
||||
|
||||
all_particles.push_back(this);
|
||||
}
|
||||
|
||||
Particle::~Particle()
|
||||
@ -82,8 +106,10 @@ void Particle::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
|
||||
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
|
||||
SceneManager->registerNodeForRendering
|
||||
(this, scene::ESNRP_TRANSPARENT);
|
||||
SceneManager->registerNodeForRendering
|
||||
(this, scene::ESNRP_SOLID);
|
||||
}
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
@ -96,45 +122,45 @@ void Particle::render()
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
driver->setMaterial(m_material);
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SColor c(255, m_light, m_light, m_light);
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x0(), m_ap.y1()),
|
||||
video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y1()),
|
||||
video::S3DVertex(m_size/2,m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y0()),
|
||||
video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0, c ,m_ap.x0(), m_ap.y0()),
|
||||
};
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertices[i].Pos.rotateYZBy(m_player->getPitch());
|
||||
vertices[i].Pos.rotateXZBy(m_player->getYaw());
|
||||
m_box.addInternalPoint(vertices[i].Pos);
|
||||
vertices[i].Pos += m_pos*BS;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2, 2,3,0};
|
||||
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
|
||||
driver->drawVertexPrimitiveList(m_vertices, 4,
|
||||
indices, 2, video::EVT_STANDARD,
|
||||
scene::EPT_TRIANGLES, video::EIT_16BIT);
|
||||
}
|
||||
|
||||
void Particle::step(float dtime, ClientEnvironment &env)
|
||||
{
|
||||
core::aabbox3d<f32> box = m_collisionbox;
|
||||
v3f p_pos = m_pos*BS;
|
||||
v3f p_velocity = m_velocity*BS;
|
||||
v3f p_acceleration = m_acceleration*BS;
|
||||
collisionMoveSimple(&env.getClientMap(), m_gamedef,
|
||||
BS*0.5, box,
|
||||
0, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
m_pos = p_pos/BS;
|
||||
m_velocity = p_velocity/BS;
|
||||
m_acceleration = p_acceleration/BS;
|
||||
m_time += dtime;
|
||||
if (m_collisiondetection)
|
||||
{
|
||||
core::aabbox3d<f32> box = m_collisionbox;
|
||||
v3f p_pos = m_pos*BS;
|
||||
v3f p_velocity = m_velocity*BS;
|
||||
v3f p_acceleration = m_acceleration*BS;
|
||||
collisionMoveSimple(&env, m_gamedef,
|
||||
BS*0.5, box,
|
||||
0, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
m_pos = p_pos/BS;
|
||||
m_velocity = p_velocity/BS;
|
||||
m_acceleration = p_acceleration/BS;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_velocity += m_acceleration * dtime;
|
||||
m_pos += m_velocity * dtime;
|
||||
}
|
||||
|
||||
// Update lighting
|
||||
updateLight(env);
|
||||
|
||||
// Update model
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
void Particle::updateLight(ClientEnvironment &env)
|
||||
{
|
||||
u8 light = 0;
|
||||
try{
|
||||
v3s16 p = v3s16(
|
||||
@ -151,11 +177,37 @@ void Particle::step(float dtime, ClientEnvironment &env)
|
||||
m_light = decode_light(light);
|
||||
}
|
||||
|
||||
std::vector<Particle*> all_particles;
|
||||
void Particle::updateVertices()
|
||||
{
|
||||
video::SColor c(255, m_light, m_light, m_light);
|
||||
m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
|
||||
c, m_ap.x0(), m_ap.y1());
|
||||
m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
|
||||
c, m_ap.x1(), m_ap.y1());
|
||||
m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
|
||||
c, m_ap.x1(), m_ap.y0());
|
||||
m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
|
||||
c ,m_ap.x0(), m_ap.y0());
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
m_vertices[i].Pos.rotateYZBy(m_player->getPitch());
|
||||
m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
|
||||
m_box.addInternalPoint(m_vertices[i].Pos);
|
||||
m_vertices[i].Pos += m_pos*BS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Helpers
|
||||
*/
|
||||
|
||||
|
||||
void allparticles_step (float dtime, ClientEnvironment &env)
|
||||
{
|
||||
for(std::vector<Particle*>::iterator i = all_particles.begin(); i != all_particles.end();)
|
||||
for(std::vector<Particle*>::iterator i = all_particles.begin();
|
||||
i != all_particles.end();)
|
||||
{
|
||||
if ((*i)->get_expired())
|
||||
{
|
||||
@ -171,22 +223,28 @@ void allparticles_step (float dtime, ClientEnvironment &env)
|
||||
}
|
||||
}
|
||||
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[])
|
||||
{
|
||||
for (u16 j = 0; j < 32; j++) // set the amount of particles here
|
||||
{
|
||||
addNodeParticle(gamedef, smgr, player, pos, tiles);
|
||||
addNodeParticle(gamedef, smgr, player, env, pos, tiles);
|
||||
}
|
||||
}
|
||||
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env,
|
||||
v3s16 pos, const TileSpec tiles[])
|
||||
{
|
||||
addNodeParticle(gamedef, smgr, player, pos, tiles);
|
||||
addNodeParticle(gamedef, smgr, player, env, pos, tiles);
|
||||
}
|
||||
|
||||
// add a particle of a node
|
||||
// used by digging and punching particles
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[])
|
||||
{
|
||||
// Texture
|
||||
u8 texid = myrand_range(0,5);
|
||||
@ -205,7 +263,10 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer
|
||||
ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
|
||||
|
||||
// Physics
|
||||
v3f velocity((rand()%100/50.-1)/1.5, rand()%100/35., (rand()%100/50.-1)/1.5);
|
||||
v3f velocity( (rand()%100/50.-1)/1.5,
|
||||
rand()%100/35.,
|
||||
(rand()%100/50.-1)/1.5);
|
||||
|
||||
v3f acceleration(0,-9,0);
|
||||
v3f particlepos = v3f(
|
||||
(f32)pos.X+rand()%100/200.-0.25,
|
||||
@ -213,17 +274,180 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer
|
||||
(f32)pos.Z+rand()%100/200.-0.25
|
||||
);
|
||||
|
||||
Particle *particle = new Particle(
|
||||
new Particle(
|
||||
gamedef,
|
||||
smgr,
|
||||
player,
|
||||
0,
|
||||
env,
|
||||
particlepos,
|
||||
velocity,
|
||||
acceleration,
|
||||
rand()%100/100., // expiration time
|
||||
visual_size,
|
||||
true,
|
||||
ap);
|
||||
|
||||
all_particles.push_back(particle);
|
||||
}
|
||||
|
||||
/*
|
||||
ParticleSpawner
|
||||
*/
|
||||
|
||||
ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, LocalPlayer *player,
|
||||
u16 amount, float time,
|
||||
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime, float minsize, float maxsize,
|
||||
bool collisiondetection, AtlasPointer ap, u32 id)
|
||||
{
|
||||
m_gamedef = gamedef;
|
||||
m_smgr = smgr;
|
||||
m_player = player;
|
||||
m_amount = amount;
|
||||
m_spawntime = time;
|
||||
m_minpos = minpos;
|
||||
m_maxpos = maxpos;
|
||||
m_minvel = minvel;
|
||||
m_maxvel = maxvel;
|
||||
m_minacc = minacc;
|
||||
m_maxacc = maxacc;
|
||||
m_minexptime = minexptime;
|
||||
m_maxexptime = maxexptime;
|
||||
m_minsize = minsize;
|
||||
m_maxsize = maxsize;
|
||||
m_collisiondetection = collisiondetection;
|
||||
m_ap = ap;
|
||||
m_time = 0;
|
||||
|
||||
for (u16 i = 0; i<=m_amount; i++)
|
||||
{
|
||||
float spawntime = (float)rand()/(float)RAND_MAX*m_spawntime;
|
||||
m_spawntimes.push_back(spawntime);
|
||||
}
|
||||
|
||||
all_particlespawners.insert(std::pair<u32, ParticleSpawner*>(id, this));
|
||||
}
|
||||
|
||||
ParticleSpawner::~ParticleSpawner() {}
|
||||
|
||||
void ParticleSpawner::step(float dtime, ClientEnvironment &env)
|
||||
{
|
||||
m_time += dtime;
|
||||
|
||||
if (m_spawntime != 0) // Spawner exists for a predefined timespan
|
||||
{
|
||||
for(std::vector<float>::iterator i = m_spawntimes.begin();
|
||||
i != m_spawntimes.end();)
|
||||
{
|
||||
if ((*i) <= m_time && m_amount > 0)
|
||||
{
|
||||
m_amount--;
|
||||
|
||||
v3f pos = random_v3f(m_minpos, m_maxpos);
|
||||
v3f vel = random_v3f(m_minvel, m_maxvel);
|
||||
v3f acc = random_v3f(m_minacc, m_maxacc);
|
||||
float exptime = rand()/(float)RAND_MAX
|
||||
*(m_maxexptime-m_minexptime)
|
||||
+m_minexptime;
|
||||
float size = rand()/(float)RAND_MAX
|
||||
*(m_maxsize-m_minsize)
|
||||
+m_minsize;
|
||||
|
||||
new Particle(
|
||||
m_gamedef,
|
||||
m_smgr,
|
||||
m_player,
|
||||
env,
|
||||
pos,
|
||||
vel,
|
||||
acc,
|
||||
exptime,
|
||||
size,
|
||||
m_collisiondetection,
|
||||
m_ap);
|
||||
m_spawntimes.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Spawner exists for an infinity timespan, spawn on a per-second base
|
||||
{
|
||||
for (int i = 0; i <= m_amount; i++)
|
||||
{
|
||||
if (rand()/(float)RAND_MAX < dtime)
|
||||
{
|
||||
v3f pos = random_v3f(m_minpos, m_maxpos);
|
||||
v3f vel = random_v3f(m_minvel, m_maxvel);
|
||||
v3f acc = random_v3f(m_minacc, m_maxacc);
|
||||
float exptime = rand()/(float)RAND_MAX
|
||||
*(m_maxexptime-m_minexptime)
|
||||
+m_minexptime;
|
||||
float size = rand()/(float)RAND_MAX
|
||||
*(m_maxsize-m_minsize)
|
||||
+m_minsize;
|
||||
|
||||
new Particle(
|
||||
m_gamedef,
|
||||
m_smgr,
|
||||
m_player,
|
||||
env,
|
||||
pos,
|
||||
vel,
|
||||
acc,
|
||||
exptime,
|
||||
size,
|
||||
m_collisiondetection,
|
||||
m_ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void allparticlespawners_step (float dtime, ClientEnvironment &env)
|
||||
{
|
||||
for(std::map<u32, ParticleSpawner*>::iterator i =
|
||||
all_particlespawners.begin();
|
||||
i != all_particlespawners.end();)
|
||||
{
|
||||
if (i->second->get_expired())
|
||||
{
|
||||
delete i->second;
|
||||
all_particlespawners.erase(i++);
|
||||
}
|
||||
else
|
||||
{
|
||||
i->second->step(dtime, env);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delete_particlespawner (u32 id)
|
||||
{
|
||||
if (all_particlespawners.find(id) != all_particlespawners.end())
|
||||
{
|
||||
delete all_particlespawners.find(id)->second;
|
||||
all_particlespawners.erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_particles ()
|
||||
{
|
||||
for(std::map<u32, ParticleSpawner*>::iterator i =
|
||||
all_particlespawners.begin();
|
||||
i != all_particlespawners.end();)
|
||||
{
|
||||
delete i->second;
|
||||
all_particlespawners.erase(i++);
|
||||
}
|
||||
|
||||
for(std::vector<Particle*>::iterator i =
|
||||
all_particles.begin();
|
||||
i != all_particles.end();)
|
||||
{
|
||||
(*i)->remove();
|
||||
delete *i;
|
||||
all_particles.erase(i);
|
||||
}
|
||||
}
|
||||
|
@ -35,12 +35,13 @@ class Particle : public scene::ISceneNode
|
||||
IGameDef* gamedef,
|
||||
scene::ISceneManager* mgr,
|
||||
LocalPlayer *player,
|
||||
s32 id,
|
||||
ClientEnvironment &env,
|
||||
v3f pos,
|
||||
v3f velocity,
|
||||
v3f acceleration,
|
||||
float expirationtime,
|
||||
float size,
|
||||
bool collisiondetection,
|
||||
AtlasPointer texture
|
||||
);
|
||||
~Particle();
|
||||
@ -69,6 +70,10 @@ class Particle : public scene::ISceneNode
|
||||
{ return m_expiration < m_time; }
|
||||
|
||||
private:
|
||||
void updateLight(ClientEnvironment &env);
|
||||
void updateVertices();
|
||||
|
||||
video::S3DVertex m_vertices[4];
|
||||
float m_time;
|
||||
float m_expiration;
|
||||
|
||||
@ -87,12 +92,71 @@ private:
|
||||
float m_size;
|
||||
AtlasPointer m_ap;
|
||||
u8 m_light;
|
||||
bool m_collisiondetection;
|
||||
};
|
||||
|
||||
class ParticleSpawner
|
||||
{
|
||||
public:
|
||||
ParticleSpawner(IGameDef* gamedef,
|
||||
scene::ISceneManager *smgr,
|
||||
LocalPlayer *player,
|
||||
u16 amount,
|
||||
float time,
|
||||
v3f minp, v3f maxp,
|
||||
v3f minvel, v3f maxvel,
|
||||
v3f minacc, v3f maxacc,
|
||||
float minexptime, float maxexptime,
|
||||
float minsize, float maxsize,
|
||||
bool collisiondetection,
|
||||
AtlasPointer ap,
|
||||
u32 id);
|
||||
|
||||
~ParticleSpawner();
|
||||
|
||||
void step(float dtime, ClientEnvironment &env);
|
||||
|
||||
bool get_expired ()
|
||||
{ return (m_amount <= 0) && m_spawntime != 0; }
|
||||
|
||||
private:
|
||||
float m_time;
|
||||
IGameDef *m_gamedef;
|
||||
scene::ISceneManager *m_smgr;
|
||||
LocalPlayer *m_player;
|
||||
u16 m_amount;
|
||||
float m_spawntime;
|
||||
v3f m_minpos;
|
||||
v3f m_maxpos;
|
||||
v3f m_minvel;
|
||||
v3f m_maxvel;
|
||||
v3f m_minacc;
|
||||
v3f m_maxacc;
|
||||
float m_minexptime;
|
||||
float m_maxexptime;
|
||||
float m_minsize;
|
||||
float m_maxsize;
|
||||
AtlasPointer m_ap;
|
||||
std::vector<float> m_spawntimes;
|
||||
bool m_collisiondetection;
|
||||
};
|
||||
|
||||
void allparticles_step (float dtime, ClientEnvironment &env);
|
||||
void allparticlespawners_step (float dtime, ClientEnvironment &env);
|
||||
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
|
||||
void delete_particlespawner (u32 id);
|
||||
void clear_particles ();
|
||||
|
||||
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[]);
|
||||
|
||||
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[]);
|
||||
|
||||
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
|
||||
LocalPlayer *player, ClientEnvironment &env, v3s16 pos,
|
||||
const TileSpec tiles[]);
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes.h" // u32
|
||||
#include "debug.h"
|
||||
#include "constants.h"
|
||||
#include "gettime.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define SWPRINTF_CHARSTRING L"%S"
|
||||
@ -153,18 +154,65 @@ bool threadSetPriority(threadid_t tid, int prio);
|
||||
*/
|
||||
#ifdef _WIN32 // Windows
|
||||
#include <windows.h>
|
||||
|
||||
inline u32 getTimeS()
|
||||
{
|
||||
return GetTickCount() / 1000;
|
||||
}
|
||||
|
||||
inline u32 getTimeMs()
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
|
||||
inline u32 getTimeUs()
|
||||
{
|
||||
LARGE_INTEGER freq, t;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&t);
|
||||
return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000.0);
|
||||
}
|
||||
|
||||
inline u32 getTimeNs()
|
||||
{
|
||||
LARGE_INTEGER freq, t;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&t);
|
||||
return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000000.0);
|
||||
}
|
||||
|
||||
#else // Posix
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
inline u32 getTimeS()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec;
|
||||
}
|
||||
|
||||
inline u32 getTimeMs()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
inline u32 getTimeUs()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
inline u32 getTimeNs()
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return ts.tv_sec * 1000000000 + ts.tv_nsec;
|
||||
}
|
||||
|
||||
/*#include <sys/timeb.h>
|
||||
inline u32 getTimeMs()
|
||||
{
|
||||
@ -174,6 +222,22 @@ bool threadSetPriority(threadid_t tid, int prio);
|
||||
}*/
|
||||
#endif
|
||||
|
||||
inline u32 getTime(TimePrecision prec)
|
||||
{
|
||||
switch (prec) {
|
||||
case PRECISION_SECONDS:
|
||||
return getTimeS();
|
||||
case PRECISION_MILLI:
|
||||
return getTimeMs();
|
||||
case PRECISION_MICRO:
|
||||
return getTimeUs();
|
||||
case PRECISION_NANO:
|
||||
return getTimeNs();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} // namespace porting
|
||||
|
||||
#endif // PORTING_HEADER
|
||||
|
@ -45,21 +45,21 @@ public:
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
{
|
||||
/* 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)
|
||||
std::map<std::string, int>::iterator n = m_avgcounts.find(name);
|
||||
if(n == m_avgcounts.end())
|
||||
m_avgcounts[name] = -2;
|
||||
else{
|
||||
if(n->getValue() == -1)
|
||||
n->setValue(-2);
|
||||
assert(n->getValue() == -2);
|
||||
if(n->second == -1)
|
||||
n->second = -2;
|
||||
assert(n->second == -2);
|
||||
}
|
||||
}
|
||||
{
|
||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||
if(n == NULL)
|
||||
std::map<std::string, float>::iterator n = m_data.find(name);
|
||||
if(n == m_data.end())
|
||||
m_data[name] = value;
|
||||
else
|
||||
n->setValue(n->getValue() + value);
|
||||
n->second += value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,35 +67,32 @@ public:
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
{
|
||||
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||
if(n == NULL)
|
||||
std::map<std::string, int>::iterator n = m_avgcounts.find(name);
|
||||
if(n == m_avgcounts.end())
|
||||
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);
|
||||
assert(n->second != -2);
|
||||
n->second = (std::max)(n->second, 0) + 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||
if(n == NULL)
|
||||
std::map<std::string, float>::iterator n = m_data.find(name);
|
||||
if(n == m_data.end())
|
||||
m_data[name] = value;
|
||||
else
|
||||
n->setValue(n->getValue() + value);
|
||||
n->second += value;
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
for(core::map<std::string, float>::Iterator
|
||||
i = m_data.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<std::string, float>::iterator
|
||||
i = m_data.begin();
|
||||
i != m_data.end(); ++i)
|
||||
{
|
||||
i.getNode()->setValue(0);
|
||||
i->second = 0;
|
||||
}
|
||||
m_avgcounts.clear();
|
||||
}
|
||||
@ -112,9 +109,9 @@ public:
|
||||
u32 minindex, maxindex;
|
||||
paging(m_data.size(), page, pagecount, minindex, maxindex);
|
||||
|
||||
for(core::map<std::string, float>::Iterator
|
||||
i = m_data.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
for(std::map<std::string, float>::iterator
|
||||
i = m_data.begin();
|
||||
i != m_data.end(); ++i)
|
||||
{
|
||||
if(maxindex == 0)
|
||||
break;
|
||||
@ -126,12 +123,12 @@ public:
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string name = i->first;
|
||||
int avgcount = 1;
|
||||
core::map<std::string, int>::Node *n = m_avgcounts.find(name);
|
||||
if(n){
|
||||
if(n->getValue() >= 1)
|
||||
avgcount = n->getValue();
|
||||
std::map<std::string, int>::iterator n = m_avgcounts.find(name);
|
||||
if(n != m_avgcounts.end()){
|
||||
if(n->second >= 1)
|
||||
avgcount = n->second;
|
||||
}
|
||||
o<<" "<<name<<": ";
|
||||
s32 clampsize = 40;
|
||||
@ -143,7 +140,7 @@ public:
|
||||
else
|
||||
o<<" ";
|
||||
}
|
||||
o<<(i.getNode()->getValue() / avgcount);
|
||||
o<<(i->second / avgcount);
|
||||
o<<std::endl;
|
||||
}
|
||||
}
|
||||
@ -169,8 +166,8 @@ public:
|
||||
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
core::map<std::string, float> m_data;
|
||||
core::map<std::string, int> m_avgcounts;
|
||||
std::map<std::string, float> m_data;
|
||||
std::map<std::string, int> m_avgcounts;
|
||||
std::map<std::string, float> m_graphvalues;
|
||||
};
|
||||
|
||||
|
7526
src/scriptapi.cpp
7526
src/scriptapi.cpp
File diff suppressed because it is too large
Load Diff
141
src/scriptapi.h
141
src/scriptapi.h
@ -20,41 +20,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef SCRIPTAPI_HEADER
|
||||
#define SCRIPTAPI_HEADER
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
#include "mapnode.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include "irr_v3d.h"
|
||||
#include "irr_v2d.h"
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
}
|
||||
#include "scriptapi_inventory.h"
|
||||
#include "scriptapi_nodemeta.h"
|
||||
#include "scriptapi_entity.h"
|
||||
#include "scriptapi_object.h"
|
||||
#include "scriptapi_env.h"
|
||||
#include "scriptapi_item.h"
|
||||
#include "scriptapi_node.h"
|
||||
|
||||
#define luamethod(class, name) {#name, class::l_##name}
|
||||
|
||||
class Server;
|
||||
class ServerEnvironment;
|
||||
class ServerActiveObject;
|
||||
typedef struct lua_State lua_State;
|
||||
struct ObjectProperties;
|
||||
struct ItemStack;
|
||||
struct PointedThing;
|
||||
//class IGameDef;
|
||||
struct ToolCapabilities;
|
||||
|
||||
void scriptapi_export(lua_State *L, Server *server);
|
||||
bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
|
||||
const std::string &modname);
|
||||
void scriptapi_add_environment(lua_State *L, ServerEnvironment *env);
|
||||
|
||||
void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj);
|
||||
void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj);
|
||||
|
||||
// Returns true if script handled message
|
||||
bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
|
||||
const std::string &message);
|
||||
|
||||
/* environment */
|
||||
// On environment step
|
||||
void scriptapi_environment_step(lua_State *L, float dtime);
|
||||
// After generating a piece of map
|
||||
void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp,
|
||||
u32 blockseed);
|
||||
|
||||
/* server */
|
||||
void scriptapi_on_shutdown(lua_State *L);
|
||||
|
||||
@ -77,110 +71,5 @@ void scriptapi_on_player_receive_fields(lua_State *L,
|
||||
const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields);
|
||||
|
||||
/* item callbacks */
|
||||
bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *dropper, v3f pos);
|
||||
bool scriptapi_item_on_place(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *placer, const PointedThing &pointed);
|
||||
bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *user, const PointedThing &pointed);
|
||||
|
||||
/* node callbacks */
|
||||
bool scriptapi_node_on_punch(lua_State *L, v3s16 p, MapNode node,
|
||||
ServerActiveObject *puncher);
|
||||
bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node,
|
||||
ServerActiveObject *digger);
|
||||
// Node constructor
|
||||
void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node);
|
||||
// Node destructor
|
||||
void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node);
|
||||
// Node post-destructor
|
||||
void scriptapi_node_after_destruct(lua_State *L, v3s16 p, MapNode node);
|
||||
// Node Timer event
|
||||
bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime);
|
||||
// Called when a metadata form returns values
|
||||
void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p,
|
||||
const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields,
|
||||
ServerActiveObject *sender);
|
||||
|
||||
/* Node metadata inventory callbacks */
|
||||
// Return number of accepted items to be moved
|
||||
int scriptapi_nodemeta_inventory_allow_move(lua_State *L, v3s16 p,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Return number of accepted items to be put
|
||||
int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Return number of accepted items to be taken
|
||||
int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Report moved items
|
||||
void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Report put items
|
||||
void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Report taken items
|
||||
void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
|
||||
/* Detached inventory callbacks */
|
||||
// Return number of accepted items to be moved
|
||||
int scriptapi_detached_inventory_allow_move(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Return number of accepted items to be put
|
||||
int scriptapi_detached_inventory_allow_put(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Return number of accepted items to be taken
|
||||
int scriptapi_detached_inventory_allow_take(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Report moved items
|
||||
void scriptapi_detached_inventory_on_move(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Report put items
|
||||
void scriptapi_detached_inventory_on_put(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Report taken items
|
||||
void scriptapi_detached_inventory_on_take(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
|
||||
/* luaentity */
|
||||
// Returns true if succesfully added into Lua; false otherwise.
|
||||
bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name);
|
||||
void scriptapi_luaentity_activate(lua_State *L, u16 id,
|
||||
const std::string &staticdata, u32 dtime_s);
|
||||
void scriptapi_luaentity_rm(lua_State *L, u16 id);
|
||||
std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id);
|
||||
void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
|
||||
ObjectProperties *prop);
|
||||
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime);
|
||||
void scriptapi_luaentity_punch(lua_State *L, u16 id,
|
||||
ServerActiveObject *puncher, float time_from_last_punch,
|
||||
const ToolCapabilities *toolcap, v3f dir);
|
||||
void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
|
||||
ServerActiveObject *clicker);
|
||||
|
||||
#endif
|
||||
|
||||
|
311
src/scriptapi_common.cpp
Normal file
311
src/scriptapi_common.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "scriptapi.h"
|
||||
#include "scriptapi_common.h"
|
||||
|
||||
extern "C" {
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
#include "script.h"
|
||||
#include "scriptapi_types.h"
|
||||
#include "scriptapi_object.h"
|
||||
|
||||
|
||||
Server* get_server(lua_State *L)
|
||||
{
|
||||
// Get server from registry
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
||||
Server *server = (Server*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return server;
|
||||
}
|
||||
|
||||
ServerEnvironment* get_env(lua_State *L)
|
||||
{
|
||||
// Get environment from registry
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
|
||||
ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return env;
|
||||
}
|
||||
|
||||
void warn_if_field_exists(lua_State *L, int table,
|
||||
const char *fieldname, const std::string &message)
|
||||
{
|
||||
lua_getfield(L, table, fieldname);
|
||||
if(!lua_isnil(L, -1)){
|
||||
infostream<<script_get_backtrace(L)<<std::endl;
|
||||
infostream<<"WARNING: field \""<<fieldname<<"\": "
|
||||
<<message<<std::endl;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
ToolCapabilities
|
||||
*/
|
||||
|
||||
ToolCapabilities read_tool_capabilities(
|
||||
lua_State *L, int table)
|
||||
{
|
||||
ToolCapabilities toolcap;
|
||||
getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
|
||||
getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
|
||||
lua_getfield(L, table, "groupcaps");
|
||||
if(lua_istable(L, -1)){
|
||||
int table_groupcaps = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table_groupcaps) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
std::string groupname = luaL_checkstring(L, -2);
|
||||
if(lua_istable(L, -1)){
|
||||
int table_groupcap = lua_gettop(L);
|
||||
// This will be created
|
||||
ToolGroupCap groupcap;
|
||||
// Read simple parameters
|
||||
getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
|
||||
getintfield(L, table_groupcap, "uses", groupcap.uses);
|
||||
// DEPRECATED: maxwear
|
||||
float maxwear = 0;
|
||||
if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){
|
||||
if(maxwear != 0)
|
||||
groupcap.uses = 1.0/maxwear;
|
||||
else
|
||||
groupcap.uses = 0;
|
||||
infostream<<script_get_backtrace(L)<<std::endl;
|
||||
infostream<<"WARNING: field \"maxwear\" is deprecated; "
|
||||
<<"should replace with uses=1/maxwear"<<std::endl;
|
||||
}
|
||||
// Read "times" table
|
||||
lua_getfield(L, table_groupcap, "times");
|
||||
if(lua_istable(L, -1)){
|
||||
int table_times = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table_times) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
int rating = luaL_checkinteger(L, -2);
|
||||
float time = luaL_checknumber(L, -1);
|
||||
groupcap.times[rating] = time;
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
// Insert groupcap into toolcap
|
||||
toolcap.groupcaps[groupname] = groupcap;
|
||||
}
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, table, "damage_groups");
|
||||
if(lua_istable(L, -1)){
|
||||
int table_damage_groups = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table_damage_groups) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
std::string groupname = luaL_checkstring(L, -2);
|
||||
u16 value = luaL_checkinteger(L, -1);
|
||||
toolcap.damageGroups[groupname] = value;
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return toolcap;
|
||||
}
|
||||
|
||||
void set_tool_capabilities(lua_State *L, int table,
|
||||
const ToolCapabilities &toolcap)
|
||||
{
|
||||
setfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
|
||||
setintfield(L, table, "max_drop_level", toolcap.max_drop_level);
|
||||
// Create groupcaps table
|
||||
lua_newtable(L);
|
||||
// For each groupcap
|
||||
for(std::map<std::string, ToolGroupCap>::const_iterator
|
||||
i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
|
||||
// Create groupcap table
|
||||
lua_newtable(L);
|
||||
const std::string &name = i->first;
|
||||
const ToolGroupCap &groupcap = i->second;
|
||||
// Create subtable "times"
|
||||
lua_newtable(L);
|
||||
for(std::map<int, float>::const_iterator
|
||||
i = groupcap.times.begin(); i != groupcap.times.end(); i++){
|
||||
int rating = i->first;
|
||||
float time = i->second;
|
||||
lua_pushinteger(L, rating);
|
||||
lua_pushnumber(L, time);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
// Set subtable "times"
|
||||
lua_setfield(L, -2, "times");
|
||||
// Set simple parameters
|
||||
setintfield(L, -1, "maxlevel", groupcap.maxlevel);
|
||||
setintfield(L, -1, "uses", groupcap.uses);
|
||||
// Insert groupcap table into groupcaps table
|
||||
lua_setfield(L, -2, name.c_str());
|
||||
}
|
||||
// Set groupcaps table
|
||||
lua_setfield(L, -2, "groupcaps");
|
||||
//Create damage_groups table
|
||||
lua_newtable(L);
|
||||
// For each damage group
|
||||
for(std::map<std::string, s16>::const_iterator
|
||||
i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
|
||||
// Create damage group table
|
||||
lua_pushinteger(L, i->second);
|
||||
lua_setfield(L, -2, i->first.c_str());
|
||||
}
|
||||
lua_setfield(L, -2, "damage_groups");
|
||||
}
|
||||
|
||||
void push_tool_capabilities(lua_State *L,
|
||||
const ToolCapabilities &prop)
|
||||
{
|
||||
lua_newtable(L);
|
||||
set_tool_capabilities(L, -1, prop);
|
||||
}
|
||||
|
||||
void realitycheck(lua_State *L)
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
if(top >= 30){
|
||||
dstream<<"Stack is over 30:"<<std::endl;
|
||||
stackDump(L, dstream);
|
||||
script_error(L, "Stack is over 30 (reality check)");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PointedThing
|
||||
*/
|
||||
|
||||
void push_pointed_thing(lua_State *L, const PointedThing& pointed)
|
||||
{
|
||||
lua_newtable(L);
|
||||
if(pointed.type == POINTEDTHING_NODE)
|
||||
{
|
||||
lua_pushstring(L, "node");
|
||||
lua_setfield(L, -2, "type");
|
||||
push_v3s16(L, pointed.node_undersurface);
|
||||
lua_setfield(L, -2, "under");
|
||||
push_v3s16(L, pointed.node_abovesurface);
|
||||
lua_setfield(L, -2, "above");
|
||||
}
|
||||
else if(pointed.type == POINTEDTHING_OBJECT)
|
||||
{
|
||||
lua_pushstring(L, "object");
|
||||
lua_setfield(L, -2, "type");
|
||||
objectref_get(L, pointed.object_id);
|
||||
lua_setfield(L, -2, "ref");
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushstring(L, "nothing");
|
||||
lua_setfield(L, -2, "type");
|
||||
}
|
||||
}
|
||||
|
||||
void stackDump(lua_State *L, std::ostream &o)
|
||||
{
|
||||
int i;
|
||||
int top = lua_gettop(L);
|
||||
for (i = 1; i <= top; i++) { /* repeat for each level */
|
||||
int t = lua_type(L, i);
|
||||
switch (t) {
|
||||
|
||||
case LUA_TSTRING: /* strings */
|
||||
o<<"\""<<lua_tostring(L, i)<<"\"";
|
||||
break;
|
||||
|
||||
case LUA_TBOOLEAN: /* booleans */
|
||||
o<<(lua_toboolean(L, i) ? "true" : "false");
|
||||
break;
|
||||
|
||||
case LUA_TNUMBER: /* numbers */ {
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%g", lua_tonumber(L, i));
|
||||
o<<buf;
|
||||
break; }
|
||||
|
||||
default: /* other values */
|
||||
o<<lua_typename(L, t);
|
||||
break;
|
||||
|
||||
}
|
||||
o<<" ";
|
||||
}
|
||||
o<<std::endl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Dump stack top with the dump2 function
|
||||
static void dump2(lua_State *L, const char *name)
|
||||
{
|
||||
// Dump object (debug)
|
||||
lua_getglobal(L, "dump2");
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
lua_pushvalue(L, -2); // Get previous stack top as first parameter
|
||||
lua_pushstring(L, name);
|
||||
if(lua_pcall(L, 2, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool string_to_enum(const EnumString *spec, int &result,
|
||||
const std::string &str)
|
||||
{
|
||||
const EnumString *esp = spec;
|
||||
while(esp->str){
|
||||
if(str == std::string(esp->str)){
|
||||
result = esp->num;
|
||||
return true;
|
||||
}
|
||||
esp++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*bool enum_to_string(const EnumString *spec, std::string &result,
|
||||
int num)
|
||||
{
|
||||
const EnumString *esp = spec;
|
||||
while(esp){
|
||||
if(num == esp->num){
|
||||
result = esp->str;
|
||||
return true;
|
||||
}
|
||||
esp++;
|
||||
}
|
||||
return false;
|
||||
}*/
|
||||
|
||||
int getenumfield(lua_State *L, int table,
|
||||
const char *fieldname, const EnumString *spec, int default_)
|
||||
{
|
||||
int result = default_;
|
||||
string_to_enum(spec, result,
|
||||
getstringfield_default(L, table, fieldname, ""));
|
||||
return result;
|
||||
}
|
112
src/scriptapi_common.h
Normal file
112
src/scriptapi_common.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef LUA_COMMON_H_
|
||||
#define LUA_COMMON_H_
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
}
|
||||
|
||||
#include "server.h"
|
||||
#include "environment.h"
|
||||
#include "nodedef.h"
|
||||
#include "util/pointedthing.h"
|
||||
#include "tool.h"
|
||||
|
||||
Server* get_server(lua_State *L);
|
||||
ServerEnvironment* get_env(lua_State *L);
|
||||
|
||||
void warn_if_field_exists(lua_State *L, int table,
|
||||
const char *fieldname, const std::string &message);
|
||||
|
||||
ToolCapabilities read_tool_capabilities (lua_State *L, int table);
|
||||
void push_tool_capabilities (lua_State *L,
|
||||
const ToolCapabilities &prop);
|
||||
void set_tool_capabilities (lua_State *L, int table,
|
||||
const ToolCapabilities &toolcap);
|
||||
|
||||
void realitycheck (lua_State *L);
|
||||
|
||||
void push_pointed_thing (lua_State *L,
|
||||
const PointedThing& pointed);
|
||||
|
||||
void stackDump (lua_State *L, std::ostream &o);
|
||||
|
||||
class StackUnroller
|
||||
{
|
||||
private:
|
||||
lua_State *m_lua;
|
||||
int m_original_top;
|
||||
public:
|
||||
StackUnroller(lua_State *L):
|
||||
m_lua(L),
|
||||
m_original_top(-1)
|
||||
{
|
||||
m_original_top = lua_gettop(m_lua); // store stack height
|
||||
}
|
||||
~StackUnroller()
|
||||
{
|
||||
lua_settop(m_lua, m_original_top); // restore stack height
|
||||
}
|
||||
};
|
||||
|
||||
/* definitions */
|
||||
// What scriptapi_run_callbacks does with the return values of callbacks.
|
||||
// Regardless of the mode, if only one callback is defined,
|
||||
// its return value is the total return value.
|
||||
// Modes only affect the case where 0 or >= 2 callbacks are defined.
|
||||
enum RunCallbacksMode
|
||||
{
|
||||
// Returns the return value of the first callback
|
||||
// Returns nil if list of callbacks is empty
|
||||
RUN_CALLBACKS_MODE_FIRST,
|
||||
// Returns the return value of the last callback
|
||||
// Returns nil if list of callbacks is empty
|
||||
RUN_CALLBACKS_MODE_LAST,
|
||||
// If any callback returns a false value, the first such is returned
|
||||
// Otherwise, the first callback's return value (trueish) is returned
|
||||
// Returns true if list of callbacks is empty
|
||||
RUN_CALLBACKS_MODE_AND,
|
||||
// Like above, but stops calling callbacks (short circuit)
|
||||
// after seeing the first false value
|
||||
RUN_CALLBACKS_MODE_AND_SC,
|
||||
// If any callback returns a true value, the first such is returned
|
||||
// Otherwise, the first callback's return value (falseish) is returned
|
||||
// Returns false if list of callbacks is empty
|
||||
RUN_CALLBACKS_MODE_OR,
|
||||
// Like above, but stops calling callbacks (short circuit)
|
||||
// after seeing the first true value
|
||||
RUN_CALLBACKS_MODE_OR_SC,
|
||||
// Note: "a true value" and "a false value" refer to values that
|
||||
// are converted by lua_toboolean to true or false, respectively.
|
||||
};
|
||||
|
||||
struct EnumString
|
||||
{
|
||||
int num;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
bool string_to_enum(const EnumString *spec, int &result,
|
||||
const std::string &str);
|
||||
|
||||
int getenumfield(lua_State *L, int table,
|
||||
const char *fieldname, const EnumString *spec, int default_);
|
||||
#endif /* LUA_COMMON_H_ */
|
322
src/scriptapi_content.cpp
Normal file
322
src/scriptapi_content.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "scriptapi.h"
|
||||
#include "scriptapi_content.h"
|
||||
#include "scriptapi_types.h"
|
||||
#include "scriptapi_common.h"
|
||||
#include "scriptapi_node.h"
|
||||
|
||||
|
||||
NodeBox read_nodebox(lua_State *L, int index)
|
||||
{
|
||||
NodeBox nodebox;
|
||||
if(lua_istable(L, -1)){
|
||||
nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
|
||||
es_NodeBoxType, NODEBOX_REGULAR);
|
||||
|
||||
lua_getfield(L, index, "fixed");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.fixed = read_aabb3f_vector(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "wall_top");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.wall_top = read_aabb3f(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "wall_bottom");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.wall_bottom = read_aabb3f(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "wall_side");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.wall_side = read_aabb3f(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return nodebox;
|
||||
}
|
||||
|
||||
/*
|
||||
SimpleSoundSpec
|
||||
*/
|
||||
|
||||
void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
|
||||
{
|
||||
if(index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
if(lua_isnil(L, index)){
|
||||
} else if(lua_istable(L, index)){
|
||||
getstringfield(L, index, "name", spec.name);
|
||||
getfloatfield(L, index, "gain", spec.gain);
|
||||
} else if(lua_isstring(L, index)){
|
||||
spec.name = lua_tostring(L, index);
|
||||
}
|
||||
}
|
||||
|
||||
struct EnumString es_TileAnimationType[] =
|
||||
{
|
||||
{TAT_NONE, "none"},
|
||||
{TAT_VERTICAL_FRAMES, "vertical_frames"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
/*
|
||||
TileDef
|
||||
*/
|
||||
|
||||
TileDef read_tiledef(lua_State *L, int index)
|
||||
{
|
||||
if(index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
TileDef tiledef;
|
||||
|
||||
// key at index -2 and value at index
|
||||
if(lua_isstring(L, index)){
|
||||
// "default_lava.png"
|
||||
tiledef.name = lua_tostring(L, index);
|
||||
}
|
||||
else if(lua_istable(L, index))
|
||||
{
|
||||
// {name="default_lava.png", animation={}}
|
||||
tiledef.name = "";
|
||||
getstringfield(L, index, "name", tiledef.name);
|
||||
getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
|
||||
tiledef.backface_culling = getboolfield_default(
|
||||
L, index, "backface_culling", true);
|
||||
// animation = {}
|
||||
lua_getfield(L, index, "animation");
|
||||
if(lua_istable(L, -1)){
|
||||
// {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
|
||||
tiledef.animation.type = (TileAnimationType)
|
||||
getenumfield(L, -1, "type", es_TileAnimationType,
|
||||
TAT_NONE);
|
||||
tiledef.animation.aspect_w =
|
||||
getintfield_default(L, -1, "aspect_w", 16);
|
||||
tiledef.animation.aspect_h =
|
||||
getintfield_default(L, -1, "aspect_h", 16);
|
||||
tiledef.animation.length =
|
||||
getfloatfield_default(L, -1, "length", 1.0);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return tiledef;
|
||||
}
|
||||
|
||||
/*
|
||||
ContentFeatures
|
||||
*/
|
||||
|
||||
ContentFeatures read_content_features(lua_State *L, int index)
|
||||
{
|
||||
if(index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
ContentFeatures f;
|
||||
|
||||
/* Cache existence of some callbacks */
|
||||
lua_getfield(L, index, "on_construct");
|
||||
if(!lua_isnil(L, -1)) f.has_on_construct = true;
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "on_destruct");
|
||||
if(!lua_isnil(L, -1)) f.has_on_destruct = true;
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "after_destruct");
|
||||
if(!lua_isnil(L, -1)) f.has_after_destruct = true;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "on_rightclick");
|
||||
f.rightclickable = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
/* Name */
|
||||
getstringfield(L, index, "name", f.name);
|
||||
|
||||
/* Groups */
|
||||
lua_getfield(L, index, "groups");
|
||||
read_groups(L, -1, f.groups);
|
||||
lua_pop(L, 1);
|
||||
|
||||
/* Visual definition */
|
||||
|
||||
f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType,
|
||||
NDT_NORMAL);
|
||||
getfloatfield(L, index, "visual_scale", f.visual_scale);
|
||||
|
||||
// tiles = {}
|
||||
lua_getfield(L, index, "tiles");
|
||||
// If nil, try the deprecated name "tile_images" instead
|
||||
if(lua_isnil(L, -1)){
|
||||
lua_pop(L, 1);
|
||||
warn_if_field_exists(L, index, "tile_images",
|
||||
"Deprecated; new name is \"tiles\".");
|
||||
lua_getfield(L, index, "tile_images");
|
||||
}
|
||||
if(lua_istable(L, -1)){
|
||||
int table = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
int i = 0;
|
||||
while(lua_next(L, table) != 0){
|
||||
// Read tiledef from value
|
||||
f.tiledef[i] = read_tiledef(L, -1);
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
i++;
|
||||
if(i==6){
|
||||
lua_pop(L, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Copy last value to all remaining textures
|
||||
if(i >= 1){
|
||||
TileDef lasttile = f.tiledef[i-1];
|
||||
while(i < 6){
|
||||
f.tiledef[i] = lasttile;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
// special_tiles = {}
|
||||
lua_getfield(L, index, "special_tiles");
|
||||
// If nil, try the deprecated name "special_materials" instead
|
||||
if(lua_isnil(L, -1)){
|
||||
lua_pop(L, 1);
|
||||
warn_if_field_exists(L, index, "special_materials",
|
||||
"Deprecated; new name is \"special_tiles\".");
|
||||
lua_getfield(L, index, "special_materials");
|
||||
}
|
||||
if(lua_istable(L, -1)){
|
||||
int table = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
int i = 0;
|
||||
while(lua_next(L, table) != 0){
|
||||
// Read tiledef from value
|
||||
f.tiledef_special[i] = read_tiledef(L, -1);
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
i++;
|
||||
if(i==6){
|
||||
lua_pop(L, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
f.alpha = getintfield_default(L, index, "alpha", 255);
|
||||
|
||||
/* Other stuff */
|
||||
|
||||
lua_getfield(L, index, "post_effect_color");
|
||||
if(!lua_isnil(L, -1))
|
||||
f.post_effect_color = readARGB8(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
|
||||
es_ContentParamType, CPT_NONE);
|
||||
f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
|
||||
es_ContentParamType2, CPT2_NONE);
|
||||
|
||||
// Warn about some deprecated fields
|
||||
warn_if_field_exists(L, index, "wall_mounted",
|
||||
"deprecated: use paramtype2 = 'wallmounted'");
|
||||
warn_if_field_exists(L, index, "light_propagates",
|
||||
"deprecated: determined from paramtype");
|
||||
warn_if_field_exists(L, index, "dug_item",
|
||||
"deprecated: use 'drop' field");
|
||||
warn_if_field_exists(L, index, "extra_dug_item",
|
||||
"deprecated: use 'drop' field");
|
||||
warn_if_field_exists(L, index, "extra_dug_item_rarity",
|
||||
"deprecated: use 'drop' field");
|
||||
warn_if_field_exists(L, index, "metadata_name",
|
||||
"deprecated: use on_add and metadata callbacks");
|
||||
|
||||
// True for all ground-like things like stone and mud, false for eg. trees
|
||||
getboolfield(L, index, "is_ground_content", f.is_ground_content);
|
||||
f.light_propagates = (f.param_type == CPT_LIGHT);
|
||||
getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
|
||||
// This is used for collision detection.
|
||||
// Also for general solidness queries.
|
||||
getboolfield(L, index, "walkable", f.walkable);
|
||||
// Player can point to these
|
||||
getboolfield(L, index, "pointable", f.pointable);
|
||||
// Player can dig these
|
||||
getboolfield(L, index, "diggable", f.diggable);
|
||||
// Player can climb these
|
||||
getboolfield(L, index, "climbable", f.climbable);
|
||||
// Player can build on these
|
||||
getboolfield(L, index, "buildable_to", f.buildable_to);
|
||||
// Whether the node is non-liquid, source liquid or flowing liquid
|
||||
f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
|
||||
es_LiquidType, LIQUID_NONE);
|
||||
// If the content is liquid, this is the flowing version of the liquid.
|
||||
getstringfield(L, index, "liquid_alternative_flowing",
|
||||
f.liquid_alternative_flowing);
|
||||
// If the content is liquid, this is the source version of the liquid.
|
||||
getstringfield(L, index, "liquid_alternative_source",
|
||||
f.liquid_alternative_source);
|
||||
// Viscosity for fluid flow, ranging from 1 to 7, with
|
||||
// 1 giving almost instantaneous propagation and 7 being
|
||||
// the slowest possible
|
||||
f.liquid_viscosity = getintfield_default(L, index,
|
||||
"liquid_viscosity", f.liquid_viscosity);
|
||||
getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
|
||||
// Amount of light the node emits
|
||||
f.light_source = getintfield_default(L, index,
|
||||
"light_source", f.light_source);
|
||||
f.damage_per_second = getintfield_default(L, index,
|
||||
"damage_per_second", f.damage_per_second);
|
||||
|
||||
lua_getfield(L, index, "node_box");
|
||||
if(lua_istable(L, -1))
|
||||
f.node_box = read_nodebox(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "selection_box");
|
||||
if(lua_istable(L, -1))
|
||||
f.selection_box = read_nodebox(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Set to true if paramtype used to be 'facedir_simple'
|
||||
getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
|
||||
// Set to true if wall_mounted used to be set to true
|
||||
getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
|
||||
|
||||
// Sound table
|
||||
lua_getfield(L, index, "sounds");
|
||||
if(lua_istable(L, -1)){
|
||||
lua_getfield(L, -1, "footstep");
|
||||
read_soundspec(L, -1, f.sound_footstep);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, -1, "dig");
|
||||
read_soundspec(L, -1, f.sound_dig);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, -1, "dug");
|
||||
read_soundspec(L, -1, f.sound_dug);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
return f;
|
||||
}
|
37
src/scriptapi_content.h
Normal file
37
src/scriptapi_content.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2013 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 Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef LUA_CONTENT_H_
|
||||
#define LUA_CONTENT_H_
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
}
|
||||
|
||||
#include "nodedef.h"
|
||||
|
||||
ContentFeatures read_content_features (lua_State *L, int index);
|
||||
TileDef read_tiledef (lua_State *L, int index);
|
||||
void read_soundspec (lua_State *L, int index,
|
||||
SimpleSoundSpec &spec);
|
||||
NodeBox read_nodebox (lua_State *L, int index);
|
||||
|
||||
extern struct EnumString es_TileAnimationType[];
|
||||
|
||||
#endif /* LUA_CONTENT_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user