Merge branch 'master' of git://github.com/celeron55/minetest
Conflicts: src/client.cpp src/clientserver.h src/content_mapnode.cpp src/content_mapnode.h src/game.cpp src/map.cpp src/player.cpp src/server.cppmaster
|
@ -7,11 +7,14 @@ endif(${CMAKE_VERSION} STREQUAL "2.8.2")
|
|||
# This can be read from ${PROJECT_NAME} after project() is called
|
||||
project(minetest)
|
||||
|
||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 2)
|
||||
set(VERSION_PATCH 20110922_1)
|
||||
set(VERSION_MINOR 3)
|
||||
set(VERSION_PATCH dev-20111016)
|
||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
|
||||
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
||||
|
||||
# Configuration options
|
||||
|
||||
if(WIN32)
|
||||
|
|
After Width: | Height: | Size: 224 B |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 603 B |
After Width: | Height: | Size: 502 B |
Before Width: | Height: | Size: 209 B After Width: | Height: | Size: 927 B |
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 931 B |
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 927 B |
|
@ -53,12 +53,12 @@ Compiling on GNU/Linux:
|
|||
-----------------------
|
||||
|
||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev
|
||||
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev
|
||||
|
||||
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
|
||||
$ wget https://bitbucket.org/celeron55/minetest/get/tip.tar.gz
|
||||
$ tar xf tip.tar.gz
|
||||
$ cd minetest
|
||||
$ wget https://github.com/celeron55/minetest/tarball/master -O master.tar.gz
|
||||
$ tar xf master.tar.gz
|
||||
$ cd celeron55-minetest-286edd4 (or similar)
|
||||
|
||||
Build a version that runs directly from the source directory:
|
||||
$ cmake . -DRUN_IN_PLACE=1
|
||||
|
@ -163,6 +163,22 @@ Compiling on Windows:
|
|||
- You should now have a working game with the executable in
|
||||
DIR/minetest/bin/minetest.exe
|
||||
|
||||
Windows releases of minetest are built using a bat script like this:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
set installpath="C:\tmp\minetest_install"
|
||||
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
|
||||
|
||||
set sourcedir=%CD%
|
||||
set builddir=%sourcedir%\bvc10
|
||||
mkdir %builddir%
|
||||
pushd %builddir%
|
||||
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=1 -DCMAKE_INSTALL_PREFIX=%installpath%
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
|
||||
popd
|
||||
|
||||
License of Minetest-c55
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -3,6 +3,19 @@ Minetest-c55 changelog
|
|||
This should contain all the major changes.
|
||||
For minor stuff, refer to the commit log of the repository.
|
||||
|
||||
0.3.dev-20111016:
|
||||
- Locked chest
|
||||
- Server user limit setting (max_users)
|
||||
- Wielded tool is shown in HUD
|
||||
- View bobbing
|
||||
- Saplings that drop from leaf blocks and when placed on ground will grow to trees
|
||||
- Optimized map saving (does not re-save everything all the time)
|
||||
- New mob system and new mob: dungeon master
|
||||
- Death/respawn screen
|
||||
|
||||
0.2.20110922_3:
|
||||
- Fix the build for MSVC2010; also released for windows using MSVC2010.
|
||||
|
||||
0.2.20110922_1:
|
||||
- Make client report a newer version number to the server than 2011-07-31 does and make server disallow old clients
|
||||
|
||||
|
|
|
@ -85,5 +85,10 @@ Furnace metadata:
|
|||
Chest metadata:
|
||||
TBD
|
||||
|
||||
Locking Chest metadata:
|
||||
u16 string_len
|
||||
u8[string_len] string
|
||||
TBD
|
||||
|
||||
// END
|
||||
|
||||
|
|
|
@ -103,33 +103,43 @@ screenH# = 600
|
|||
#invisible_stone = false
|
||||
# Path for screenshots
|
||||
#screenshot_path = .
|
||||
# Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double)
|
||||
#view_bobbing_amount = 1.0
|
||||
|
||||
#
|
||||
# Server stuff
|
||||
#
|
||||
|
||||
# Map directory (everything in the world is stored here)
|
||||
#map-#dir = /custom/map
|
||||
#map-dir = /custom/map
|
||||
# Message of the Day
|
||||
#motd = Welcome to this awesome Minetest server!
|
||||
# Maximum number of players connected simultaneously
|
||||
#max_users = 20
|
||||
# Set to false to allow old clients to connect
|
||||
#strict_protocol_version_checking = true
|
||||
# Set to true to enable creative mode (unlimited inventory)
|
||||
#creative_mode = false
|
||||
# Enable players getting damage and dying
|
||||
#enable_damage = false
|
||||
# Despawn all non-peaceful mobs
|
||||
#only_peaceful_mobs = false
|
||||
# A chosen map seed for a new map, leave empty for random
|
||||
#fixed_map_seed =
|
||||
# Gives some stuff to players at the beginning
|
||||
#give_initial_stuff = false
|
||||
# New users need to input this password
|
||||
#default_password =
|
||||
# Available privileges: build, teleport, settime, privs, shout
|
||||
#default_privs = build, shout
|
||||
|
||||
# Set to true to enable experimental features or stuff that is tested
|
||||
# (varies from version to version, usually not useful at all)
|
||||
#enable_experimental = false
|
||||
# Profiler data print interval. #0 = disable.
|
||||
#profiler_print_interval = 0
|
||||
#enable_mapgen_debug_info = false
|
||||
# Player and object positions are sent at intervals specified by this
|
||||
#objectdata_interval = 0.2
|
||||
#active_object_range = 2
|
||||
#active_object_send_range_blocks = 3
|
||||
#active_block_range = 5
|
||||
#max_simultaneous_block_sends_per_client = 2
|
||||
#max_simultaneous_block_sends_server_total = 8
|
||||
#max_block_send_distance = 8
|
||||
|
@ -140,4 +150,7 @@ screenH# = 600
|
|||
#server_unload_unused_data_timeout = 60
|
||||
#server_map_save_interval = 60
|
||||
#full_block_send_enable_min_time_from_building = 2.0
|
||||
# Set to true to enable experimental features or stuff that is tested
|
||||
# (varies from version to version, usually not useful at all)
|
||||
#enable_experimental = false
|
||||
|
||||
|
|
|
@ -90,12 +90,12 @@ configure_file(
|
|||
)
|
||||
|
||||
set(common_SRCS
|
||||
log.cpp
|
||||
content_sao.cpp
|
||||
mapgen.cpp
|
||||
content_inventory.cpp
|
||||
content_nodemeta.cpp
|
||||
content_craft.cpp
|
||||
content_mapblock.cpp
|
||||
content_mapnode.cpp
|
||||
auth.cpp
|
||||
collision.cpp
|
||||
|
@ -108,7 +108,6 @@ set(common_SRCS
|
|||
defaultsettings.cpp
|
||||
mapnode.cpp
|
||||
voxel.cpp
|
||||
mapblockobject.cpp
|
||||
inventory.cpp
|
||||
debug.cpp
|
||||
serialization.cpp
|
||||
|
@ -132,17 +131,28 @@ set(common_SRCS
|
|||
)
|
||||
|
||||
# This gives us the icon
|
||||
if(WIN32 AND MSVC)
|
||||
set(common_SRCS ${common_SRCS} winresource.rc)
|
||||
if(WIN32)
|
||||
if(MINGW)
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
||||
COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-i${CMAKE_CURRENT_SOURCE_DIR}/winresource.rc
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
|
||||
SET(common_SRCS ${common_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
|
||||
else(MINGW) # Probably MSVC
|
||||
set(common_SRCS ${common_SRCS} winresource.rc)
|
||||
endif(MINGW)
|
||||
endif()
|
||||
|
||||
# Client sources
|
||||
set(minetest_SRCS
|
||||
${common_SRCS}
|
||||
MyBillboardSceneNode.cpp
|
||||
content_mapblock.cpp
|
||||
content_cao.cpp
|
||||
mapblock_mesh.cpp
|
||||
farmesh.cpp
|
||||
keycode.cpp
|
||||
camera.cpp
|
||||
clouds.cpp
|
||||
clientobject.cpp
|
||||
guiMainMenu.cpp
|
||||
|
@ -152,6 +162,7 @@ set(minetest_SRCS
|
|||
guiInventoryMenu.cpp
|
||||
guiPauseMenu.cpp
|
||||
guiPasswordChange.cpp
|
||||
guiDeathScreen.cpp
|
||||
client.cpp
|
||||
tile.cpp
|
||||
game.cpp
|
||||
|
@ -217,13 +228,17 @@ if(MSVC)
|
|||
# Visual Studio
|
||||
|
||||
# EHa enables SEH exceptions (used for catching segfaults)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/EHa /MD /O2 /Ob2 /Oi /Ot /Oy /GL /FD /MT /GS- /arch:SSE /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0 /TP")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/EHa /O2 /Ob2 /Oi /Ot /Oy /GL /FD /MT /GS- /arch:SSE /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0 /TP")
|
||||
#set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG /NODEFAULTLIB:\"libcmtd.lib\" /NODEFAULTLIB:\"libcmt.lib\"")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG")
|
||||
|
||||
# Debug build doesn't catch exceptions by itself
|
||||
# Add some optimizations because otherwise it's VERY slow
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1")
|
||||
|
||||
# Flags for C files (sqlite)
|
||||
# /MT = Link statically with standard library stuff
|
||||
set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /MT")
|
||||
|
||||
if(BUILD_SERVER)
|
||||
set_target_properties(${PROJECT_NAME}server PROPERTIES
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
// Copyright (C) 2002-2010 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "MyBillboardSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
MyBillboardSceneNode::MyBillboardSceneNode(ISceneNode* parent,
|
||||
ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size)
|
||||
: IBillboardSceneNode(parent, mgr, id, position)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("MyBillboardSceneNode");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
|
||||
indices[0] = 0;
|
||||
indices[1] = 2;
|
||||
indices[2] = 1;
|
||||
indices[3] = 0;
|
||||
indices[4] = 3;
|
||||
indices[5] = 2;
|
||||
|
||||
video::SColor colorTop = video::SColor(0xFFFFFFFF);
|
||||
video::SColor colorBottom = video::SColor(0xFFFFFFFF);
|
||||
|
||||
vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
vertices[0].Color = colorBottom;
|
||||
|
||||
vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
vertices[1].Color = colorTop;
|
||||
|
||||
vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
vertices[2].Color = colorTop;
|
||||
|
||||
vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void MyBillboardSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void MyBillboardSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||
|
||||
if (!camera || !driver)
|
||||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
core::vector3df target = camera->getTarget();
|
||||
core::vector3df up = camera->getUpVector();
|
||||
core::vector3df view = target - campos;
|
||||
view.normalize();
|
||||
|
||||
core::vector3df horizontal = up.crossProduct(view);
|
||||
if ( horizontal.getLength() == 0 )
|
||||
{
|
||||
horizontal.set(up.Y,up.X,up.Z);
|
||||
}
|
||||
horizontal.normalize();
|
||||
horizontal *= 0.5f * Size.Width;
|
||||
|
||||
core::vector3df vertical = horizontal.crossProduct(view);
|
||||
vertical.normalize();
|
||||
vertical *= 0.5f * Size.Height;
|
||||
|
||||
view *= -1.0f;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
vertices[0].Pos = pos + horizontal + vertical;
|
||||
vertices[1].Pos = pos + horizontal - vertical;
|
||||
vertices[2].Pos = pos - horizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
// draw
|
||||
|
||||
if ( DebugDataVisible & scene::EDS_BBOX )
|
||||
{
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->draw3DBox(BBox, video::SColor(0,208,195,152));
|
||||
}
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
|
||||
driver->setMaterial(Material);
|
||||
|
||||
driver->drawIndexedTriangleList(vertices, 4, indices, 2);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& MyBillboardSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BBox;
|
||||
}
|
||||
|
||||
|
||||
//! sets the size of the billboard
|
||||
void MyBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
||||
if (Size.Width == 0.0f)
|
||||
Size.Width = 1.0f;
|
||||
|
||||
if (Size.Height == 0.0f )
|
||||
Size.Height = 1.0f;
|
||||
|
||||
f32 avg = (size.Width + size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
video::SMaterial& MyBillboardSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Material;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 MyBillboardSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! gets the size of the billboard
|
||||
const core::dimension2d<f32>& MyBillboardSceneNode::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
void MyBillboardSceneNode::setColor(const video::SColor & overallColor)
|
||||
{
|
||||
for(u32 vertex = 0; vertex < 4; ++vertex)
|
||||
vertices[vertex].Color = overallColor;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
void MyBillboardSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor)
|
||||
{
|
||||
vertices[0].Color = bottomColor;
|
||||
vertices[1].Color = topColor;
|
||||
vertices[2].Color = topColor;
|
||||
vertices[3].Color = bottomColor;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
void MyBillboardSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const
|
||||
{
|
||||
bottomColor = vertices[0].Color;
|
||||
topColor = vertices[1].Color;
|
||||
}
|
||||
|
||||
void MyBillboardSceneNode::setTCoords(u32 i, core::vector2d<f32> c)
|
||||
{
|
||||
vertices[i].TCoords = c;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (C) 2002-2010 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "S3DVertex.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||
//! which always looks to the camera.
|
||||
class MyBillboardSceneNode : virtual public IBillboardSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
MyBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size);
|
||||
|
||||
//! pre render event
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! render
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! sets the size of the billboard
|
||||
virtual void setSize(const core::dimension2d<f32>& size);
|
||||
|
||||
//! gets the size of the billboard
|
||||
virtual const core::dimension2d<f32>& getSize() const;
|
||||
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
virtual void setColor(const video::SColor & overallColor);
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor);
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const;
|
||||
|
||||
virtual void setTCoords(u32 i, core::vector2d<f32> c);
|
||||
|
||||
private:
|
||||
|
||||
core::dimension2d<f32> Size;
|
||||
core::aabbox3d<f32> BBox;
|
||||
video::SMaterial Material;
|
||||
|
||||
video::S3DVertex vertices[4];
|
||||
u16 indices[6];
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,901 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "camera.h"
|
||||
#include "debug.h"
|
||||
#include "client.h"
|
||||
#include "main.h" // for g_settings
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include <cmath>
|
||||
#include <SAnimatedMesh.h>
|
||||
#include "settings.h"
|
||||
|
||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
|
||||
m_smgr(smgr),
|
||||
m_playernode(NULL),
|
||||
m_headnode(NULL),
|
||||
m_cameranode(NULL),
|
||||
|
||||
m_wieldmgr(NULL),
|
||||
m_wieldnode(NULL),
|
||||
|
||||
m_draw_control(draw_control),
|
||||
m_viewing_range_min(5.0),
|
||||
m_viewing_range_max(5.0),
|
||||
|
||||
m_camera_position(0,0,0),
|
||||
m_camera_direction(0,0,0),
|
||||
|
||||
m_aspect(1.0),
|
||||
m_fov_x(1.0),
|
||||
m_fov_y(1.0),
|
||||
|
||||
m_wanted_frametime(0.0),
|
||||
m_added_frametime(0),
|
||||
m_added_frames(0),
|
||||
m_range_old(0),
|
||||
m_frametime_old(0),
|
||||
m_frametime_counter(0),
|
||||
m_time_per_range(30. / 50), // a sane default of 30ms per 50 nodes of range
|
||||
|
||||
m_view_bobbing_anim(0),
|
||||
m_view_bobbing_state(0),
|
||||
m_view_bobbing_speed(0),
|
||||
|
||||
m_digging_anim(0),
|
||||
m_digging_button(-1)
|
||||
{
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
|
||||
// note: making the camera node a child of the player node
|
||||
// would lead to unexpected behaviour, so we don't do that.
|
||||
m_playernode = smgr->addEmptySceneNode(smgr->getRootSceneNode());
|
||||
m_headnode = smgr->addEmptySceneNode(m_playernode);
|
||||
m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode());
|
||||
m_cameranode->bindTargetAndRotation(true);
|
||||
|
||||
// This needs to be in its own scene manager. It is drawn after
|
||||
// all other 3D scene nodes and before the GUI.
|
||||
m_wieldmgr = smgr->createNewSceneManager();
|
||||
m_wieldmgr->addCameraSceneNode();
|
||||
m_wieldnode = new ExtrudedSpriteSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr);
|
||||
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
m_wieldmgr->drop();
|
||||
m_wieldnode->drop();
|
||||
}
|
||||
|
||||
bool Camera::successfullyCreated(std::wstring& error_message)
|
||||
{
|
||||
if (m_playernode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the player scene node";
|
||||
return false;
|
||||
}
|
||||
if (m_headnode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the head scene node";
|
||||
return false;
|
||||
}
|
||||
if (m_cameranode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the camera scene node";
|
||||
return false;
|
||||
}
|
||||
if (m_wieldmgr == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the wielded item scene manager";
|
||||
return false;
|
||||
}
|
||||
if (m_wieldnode == NULL)
|
||||
{
|
||||
error_message = L"Failed to create the wielded item scene node";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the fractional part of x
|
||||
inline f32 my_modf(f32 x)
|
||||
{
|
||||
double dummy;
|
||||
return modf(x, &dummy);
|
||||
}
|
||||
|
||||
void Camera::step(f32 dtime)
|
||||
{
|
||||
if (m_view_bobbing_state != 0)
|
||||
{
|
||||
//f32 offset = dtime * m_view_bobbing_speed * 0.035;
|
||||
f32 offset = dtime * m_view_bobbing_speed * 0.030;
|
||||
if (m_view_bobbing_state == 2)
|
||||
{
|
||||
#if 0
|
||||
// Animation is getting turned off
|
||||
if (m_view_bobbing_anim < 0.5)
|
||||
m_view_bobbing_anim -= offset;
|
||||
else
|
||||
m_view_bobbing_anim += offset;
|
||||
if (m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1)
|
||||
{
|
||||
m_view_bobbing_anim = 0;
|
||||
m_view_bobbing_state = 0;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
// Animation is getting turned off
|
||||
if(m_view_bobbing_anim < 0.25){
|
||||
m_view_bobbing_anim -= offset;
|
||||
} else if(m_view_bobbing_anim > 0.75){
|
||||
m_view_bobbing_anim += offset;
|
||||
} if(m_view_bobbing_anim < 0.5){
|
||||
m_view_bobbing_anim += offset;
|
||||
if(m_view_bobbing_anim > 0.5)
|
||||
m_view_bobbing_anim = 0.5;
|
||||
} else {
|
||||
m_view_bobbing_anim -= offset;
|
||||
if(m_view_bobbing_anim < 0.5)
|
||||
m_view_bobbing_anim = 0.5;
|
||||
}
|
||||
if(m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1 ||
|
||||
fabs(m_view_bobbing_anim - 0.5) < 0.01)
|
||||
{
|
||||
m_view_bobbing_anim = 0;
|
||||
m_view_bobbing_state = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
m_view_bobbing_anim = my_modf(m_view_bobbing_anim + offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 offset = dtime * 3.5;
|
||||
m_digging_anim += offset;
|
||||
if (m_digging_anim >= 1)
|
||||
{
|
||||
m_digging_anim = 0;
|
||||
m_digging_button = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
|
||||
{
|
||||
// Set player node transformation
|
||||
m_playernode->setPosition(player->getPosition());
|
||||
m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
|
||||
m_playernode->updateAbsolutePosition();
|
||||
|
||||
// Set head node transformation
|
||||
m_headnode->setPosition(player->getEyeOffset());
|
||||
m_headnode->setRotation(v3f(player->getPitch(), 0, 0));
|
||||
m_headnode->updateAbsolutePosition();
|
||||
|
||||
// Compute relative camera position and target
|
||||
v3f rel_cam_pos = v3f(0,0,0);
|
||||
v3f rel_cam_target = v3f(0,0,1);
|
||||
v3f rel_cam_up = v3f(0,1,0);
|
||||
|
||||
if (m_view_bobbing_anim != 0)
|
||||
{
|
||||
f32 bobfrac = my_modf(m_view_bobbing_anim * 2);
|
||||
f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0;
|
||||
|
||||
#if 1
|
||||
f32 bobknob = 1.2;
|
||||
f32 bobtmp = sin(pow(bobfrac, bobknob) * PI);
|
||||
//f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI);
|
||||
|
||||
v3f bobvec = v3f(
|
||||
0.3 * bobdir * sin(bobfrac * PI),
|
||||
-0.28 * bobtmp * bobtmp,
|
||||
0.);
|
||||
|
||||
//rel_cam_pos += 0.2 * bobvec;
|
||||
//rel_cam_target += 0.03 * bobvec;
|
||||
//rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI);
|
||||
float f = 1.0;
|
||||
f *= g_settings->getFloat("view_bobbing_amount");
|
||||
rel_cam_pos += bobvec * f;
|
||||
//rel_cam_target += 0.995 * bobvec * f;
|
||||
rel_cam_target += bobvec * f;
|
||||
rel_cam_target.Z -= 0.005 * bobvec.Z * f;
|
||||
//rel_cam_target.X -= 0.005 * bobvec.X * f;
|
||||
//rel_cam_target.Y -= 0.005 * bobvec.Y * f;
|
||||
rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f);
|
||||
#else
|
||||
f32 angle_deg = 1 * bobdir * sin(bobfrac * PI);
|
||||
f32 angle_rad = angle_deg * PI / 180;
|
||||
f32 r = 0.05;
|
||||
v3f off = v3f(
|
||||
r * sin(angle_rad),
|
||||
r * (cos(angle_rad) - 1),
|
||||
0);
|
||||
rel_cam_pos += off;
|
||||
//rel_cam_target += off;
|
||||
rel_cam_up.rotateXYBy(angle_deg);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Compute absolute camera position and target
|
||||
m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos);
|
||||
m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos);
|
||||
|
||||
v3f abs_cam_up;
|
||||
m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up);
|
||||
|
||||
// Set camera node transformation
|
||||
m_cameranode->setPosition(m_camera_position);
|
||||
m_cameranode->setUpVector(abs_cam_up);
|
||||
// *100.0 helps in large map coordinates
|
||||
m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction);
|
||||
|
||||
// FOV and and aspect ratio
|
||||
m_aspect = (f32)screensize.X / (f32) screensize.Y;
|
||||
m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y));
|
||||
m_cameranode->setAspectRatio(m_aspect);
|
||||
m_cameranode->setFOV(m_fov_y);
|
||||
// Just so big a value that everything rendered is visible
|
||||
// Some more allowance that m_viewing_range_max * BS because of active objects etc.
|
||||
m_cameranode->setFarValue(m_viewing_range_max * BS * 10);
|
||||
|
||||
// Position the wielded item
|
||||
v3f wield_position = v3f(45, -35, 65);
|
||||
v3f wield_rotation = v3f(-100, 110, -100);
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 digfrac = m_digging_anim;
|
||||
wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI);
|
||||
wield_position.Y += 15 * sin(digfrac * 2 * PI);
|
||||
wield_position.Z += 5 * digfrac;
|
||||
|
||||
// Euler angles are PURE EVIL, so why not use quaternions?
|
||||
core::quaternion quat_begin(wield_rotation * core::DEGTORAD);
|
||||
core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD);
|
||||
core::quaternion quat_slerp;
|
||||
quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI));
|
||||
quat_slerp.toEuler(wield_rotation);
|
||||
wield_rotation *= core::RADTODEG;
|
||||
}
|
||||
else {
|
||||
f32 bobfrac = my_modf(m_view_bobbing_anim);
|
||||
wield_position.X -= sin(bobfrac*PI*2.0) * 3.0;
|
||||
wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0;
|
||||
}
|
||||
m_wieldnode->setPosition(wield_position);
|
||||
m_wieldnode->setRotation(wield_rotation);
|
||||
m_wieldnode->updateLight(player->light);
|
||||
|
||||
// Render distance feedback loop
|
||||
updateViewingRange(frametime);
|
||||
|
||||
// If the player seems to be walking on solid ground,
|
||||
// view bobbing is enabled and free_move is off,
|
||||
// start (or continue) the view bobbing animation.
|
||||
v3f speed = player->getSpeed();
|
||||
if ((hypot(speed.X, speed.Z) > BS) &&
|
||||
(player->touching_ground) &&
|
||||
(g_settings->getBool("view_bobbing") == true) &&
|
||||
(g_settings->getBool("free_move") == false))
|
||||
{
|
||||
// Start animation
|
||||
m_view_bobbing_state = 1;
|
||||
m_view_bobbing_speed = MYMIN(speed.getLength(), 40);
|
||||
}
|
||||
else if (m_view_bobbing_state == 1)
|
||||
{
|
||||
// Stop animation
|
||||
m_view_bobbing_state = 2;
|
||||
m_view_bobbing_speed = 60;
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::updateViewingRange(f32 frametime_in)
|
||||
{
|
||||
if (m_draw_control.range_all)
|
||||
return;
|
||||
|
||||
m_added_frametime += frametime_in;
|
||||
m_added_frames += 1;
|
||||
|
||||
// Actually this counter kind of sucks because frametime is busytime
|
||||
m_frametime_counter -= frametime_in;
|
||||
if (m_frametime_counter > 0)
|
||||
return;
|
||||
m_frametime_counter = 0.2;
|
||||
|
||||
/*dstream<<__FUNCTION_NAME
|
||||
<<": Collected "<<m_added_frames<<" frames, total of "
|
||||
<<m_added_frametime<<"s."<<std::endl;
|
||||
|
||||
dstream<<"m_draw_control.blocks_drawn="
|
||||
<<m_draw_control.blocks_drawn
|
||||
<<", m_draw_control.blocks_would_have_drawn="
|
||||
<<m_draw_control.blocks_would_have_drawn
|
||||
<<std::endl;*/
|
||||
|
||||
m_draw_control.wanted_min_range = m_viewing_range_min;
|
||||
m_draw_control.wanted_max_blocks = (1.5*m_draw_control.blocks_would_have_drawn)+1;
|
||||
if (m_draw_control.wanted_max_blocks < 10)
|
||||
m_draw_control.wanted_max_blocks = 10;
|
||||
|
||||
f32 block_draw_ratio = 1.0;
|
||||
if (m_draw_control.blocks_would_have_drawn != 0)
|
||||
{
|
||||
block_draw_ratio = (f32)m_draw_control.blocks_drawn
|
||||
/ (f32)m_draw_control.blocks_would_have_drawn;
|
||||
}
|
||||
|
||||
// Calculate the average frametime in the case that all wanted
|
||||
// blocks had been drawn
|
||||
f32 frametime = m_added_frametime / m_added_frames / block_draw_ratio;
|
||||
|
||||
m_added_frametime = 0.0;
|
||||
m_added_frames = 0;
|
||||
|
||||
f32 wanted_frametime_change = m_wanted_frametime - frametime;
|
||||
//dstream<<"wanted_frametime_change="<<wanted_frametime_change<<std::endl;
|
||||
|
||||
// If needed frametime change is small, just return
|
||||
if (fabs(wanted_frametime_change) < m_wanted_frametime*0.4)
|
||||
{
|
||||
//dstream<<"ignoring small wanted_frametime_change"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
f32 range = m_draw_control.wanted_range;
|
||||
f32 new_range = range;
|
||||
|
||||
f32 d_range = range - m_range_old;
|
||||
f32 d_frametime = frametime - m_frametime_old;
|
||||
if (d_range != 0)
|
||||
{
|
||||
m_time_per_range = d_frametime / d_range;
|
||||
}
|
||||
|
||||
// The minimum allowed calculated frametime-range derivative:
|
||||
// Practically this sets the maximum speed of changing the range.
|
||||
// The lower this value, the higher the maximum changing speed.
|
||||
// A low value here results in wobbly range (0.001)
|
||||
// A high value here results in slow changing range (0.0025)
|
||||
// SUGG: This could be dynamically adjusted so that when
|
||||
// the camera is turning, this is lower
|
||||
//f32 min_time_per_range = 0.0015;
|
||||
f32 min_time_per_range = 0.0010;
|
||||
//f32 min_time_per_range = 0.05 / range;
|
||||
if(m_time_per_range < min_time_per_range)
|
||||
{
|
||||
m_time_per_range = min_time_per_range;
|
||||
//dstream<<"m_time_per_range="<<m_time_per_range<<" (min)"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
//dstream<<"m_time_per_range="<<m_time_per_range<<std::endl;
|
||||
}
|
||||
|
||||
f32 wanted_range_change = wanted_frametime_change / m_time_per_range;
|
||||
// Dampen the change a bit to kill oscillations
|
||||
//wanted_range_change *= 0.9;
|
||||
//wanted_range_change *= 0.75;
|
||||
wanted_range_change *= 0.5;
|
||||
//dstream<<"wanted_range_change="<<wanted_range_change<<std::endl;
|
||||
|
||||
// If needed range change is very small, just return
|
||||
if(fabs(wanted_range_change) < 0.001)
|
||||
{
|
||||
//dstream<<"ignoring small wanted_range_change"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
new_range += wanted_range_change;
|
||||
|
||||
//f32 new_range_unclamped = new_range;
|
||||
new_range = MYMAX(new_range, m_viewing_range_min);
|
||||
new_range = MYMIN(new_range, m_viewing_range_max);
|
||||
/*dstream<<"new_range="<<new_range_unclamped
|
||||
<<", clamped to "<<new_range<<std::endl;*/
|
||||
|
||||
m_draw_control.wanted_range = new_range;
|
||||
|
||||
m_range_old = new_range;
|
||||
m_frametime_old = frametime;
|
||||
}
|
||||
|
||||
void Camera::updateSettings()
|
||||
{
|
||||
m_viewing_range_min = g_settings->getS16("viewing_range_nodes_min");
|
||||
m_viewing_range_min = MYMAX(5.0, m_viewing_range_min);
|
||||
|
||||
m_viewing_range_max = g_settings->getS16("viewing_range_nodes_max");
|
||||
m_viewing_range_max = MYMAX(m_viewing_range_min, m_viewing_range_max);
|
||||
|
||||
f32 fov_degrees = g_settings->getFloat("fov");
|
||||
fov_degrees = MYMAX(fov_degrees, 10.0);
|
||||
fov_degrees = MYMIN(fov_degrees, 170.0);
|
||||
m_fov_y = fov_degrees * PI / 180.0;
|
||||
|
||||
f32 wanted_fps = g_settings->getFloat("wanted_fps");
|
||||
wanted_fps = MYMAX(wanted_fps, 1.0);
|
||||
m_wanted_frametime = 1.0 / wanted_fps;
|
||||
}
|
||||
|
||||
void Camera::wield(const InventoryItem* item)
|
||||
{
|
||||
if (item != NULL)
|
||||
{
|
||||
bool isCube = false;
|
||||
|
||||
// Try to make a MaterialItem cube.
|
||||
if (std::string(item->getName()) == "MaterialItem")
|
||||
{
|
||||
// A block-type material
|
||||
MaterialItem* mat_item = (MaterialItem*) item;
|
||||
content_t content = mat_item->getMaterial();
|
||||
if (content_features(content).solidness || content_features(content).visual_solidness)
|
||||
{
|
||||
m_wieldnode->setCube(content_features(content).tiles);
|
||||
m_wieldnode->setScale(v3f(30));
|
||||
isCube = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, make an extruded sprite.
|
||||
if (!isCube)
|
||||
{
|
||||
m_wieldnode->setSprite(item->getImageRaw());
|
||||
m_wieldnode->setScale(v3f(40));
|
||||
}
|
||||
|
||||
m_wieldnode->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bare hands
|
||||
m_wieldnode->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::setDigging(s32 button)
|
||||
{
|
||||
if (m_digging_button == -1)
|
||||
m_digging_button = button;
|
||||
}
|
||||
|
||||
void Camera::drawWieldedTool()
|
||||
{
|
||||
m_wieldmgr->getVideoDriver()->clearZBuffer();
|
||||
|
||||
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
|
||||
cam->setAspectRatio(m_cameranode->getAspectRatio());
|
||||
cam->setFOV(m_cameranode->getFOV());
|
||||
cam->setNearValue(0.1);
|
||||
cam->setFarValue(100);
|
||||
m_wieldmgr->drawAll();
|
||||
}
|
||||
|
||||
|
||||
ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id,
|
||||
const v3f& position,
|
||||
const v3f& rotation,
|
||||
const v3f& scale
|
||||
):
|
||||
ISceneNode(parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
|
||||
m_thickness = 0.1;
|
||||
m_cubemesh = NULL;
|
||||
m_is_cube = false;
|
||||
m_light = LIGHT_MAX;
|
||||
}
|
||||
|
||||
ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
|
||||
{
|
||||
removeChild(m_meshnode);
|
||||
if (m_cubemesh)
|
||||
m_cubemesh->drop();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
|
||||
{
|
||||
if (texture == NULL)
|
||||
{
|
||||
m_meshnode->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
io::path name = getExtrudedName(texture);
|
||||
scene::IMeshCache* cache = SceneManager->getMeshCache();
|
||||
scene::IAnimatedMesh* mesh = cache->getMeshByName(name);
|
||||
if (mesh != NULL)
|
||||
{
|
||||
// Extruded texture has been found in cache.
|
||||
m_meshnode->setMesh(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Texture was not yet extruded, do it now and save in cache
|
||||
mesh = extrude(texture);
|
||||
if (mesh == NULL)
|
||||
{
|
||||
dstream << "Warning: failed to extrude sprite" << std::endl;
|
||||
m_meshnode->setVisible(false);
|
||||
return;
|
||||
}
|
||||
cache->addMesh(name, mesh);
|
||||
m_meshnode->setMesh(mesh);
|
||||
mesh->drop();
|
||||
}
|
||||
|
||||
m_meshnode->setScale(v3f(1, 1, m_thickness));
|
||||
m_meshnode->getMaterial(0).setTexture(0, texture);
|
||||
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
|
||||
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
m_meshnode->setVisible(true);
|
||||
m_is_cube = false;
|
||||
updateLight(m_light);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
|
||||
{
|
||||
if (m_cubemesh == NULL)
|
||||
m_cubemesh = createCubeMesh();
|
||||
|
||||
m_meshnode->setMesh(m_cubemesh);
|
||||
m_meshnode->setScale(v3f(1));
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// Get the tile texture and atlas transformation
|
||||
video::ITexture* atlas = tiles[i].texture.atlas;
|
||||
v2f pos = tiles[i].texture.pos;
|
||||
v2f size = tiles[i].texture.size;
|
||||
|
||||
// Set material flags and texture
|
||||
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
tiles[i].applyMaterialOptions(material);
|
||||
material.setTexture(0, atlas);
|
||||
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||
}
|
||||
m_meshnode->setVisible(true);
|
||||
m_is_cube = true;
|
||||
updateLight(m_light);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::updateLight(u8 light)
|
||||
{
|
||||
m_light = light;
|
||||
|
||||
u8 li = decode_light(light);
|
||||
// Set brightness one lower than incoming light
|
||||
diminish_light(li);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_meshnode->getMesh(), color);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
|
||||
{
|
||||
scene::IMeshCache* cache = SceneManager->getMeshCache();
|
||||
scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture));
|
||||
if (mesh != NULL)
|
||||
cache->removeMesh(mesh);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness)
|
||||
{
|
||||
m_thickness = thickness;
|
||||
if (!m_is_cube)
|
||||
m_meshnode->setScale(v3f(1, 1, thickness));
|
||||
}
|
||||
|
||||
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
|
||||
{
|
||||
return m_meshnode->getBoundingBox();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
|
||||
{
|
||||
io::path path = texture->getName();
|
||||
path.append("/[extruded]");
|
||||
return path;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height, u8* data)
|
||||
{
|
||||
const s32 argb_wstep = 4 * width;
|
||||
const s32 alpha_threshold = 1;
|
||||
|
||||
scene::IMeshBuffer* buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
|
||||
// Front and back
|
||||
{
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,+1, c, 1,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,+1, c, 1,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,+1, c, 0,0),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,+1, c, 0,1),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
}
|
||||
|
||||
// "Interior"
|
||||
// (add faces where a solid pixel is next to a transparent one)
|
||||
u8* solidity = new u8[(width+2) * (height+2)];
|
||||
u32 wstep = width + 2;
|
||||
for (u32 y = 0; y < height + 2; ++y)
|
||||
{
|
||||
u8* scanline = solidity + y * wstep;
|
||||
if (y == 0 || y == height + 1)
|
||||
{
|
||||
for (u32 x = 0; x < width + 2; ++x)
|
||||
scanline[x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanline[0] = 0;
|
||||
u8* argb_scanline = data + (y - 1) * argb_wstep;
|
||||
for (u32 x = 0; x < width; ++x)
|
||||
scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold);
|
||||
scanline[width + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// without this, there would be occasional "holes" in the mesh
|
||||
f32 eps = 0.01;
|
||||
|
||||
for (u32 y = 0; y <= height; ++y)
|
||||
{
|
||||
u8* scanline = solidity + y * wstep + 1;
|
||||
for (u32 x = 0; x <= width; ++x)
|
||||
{
|
||||
if (scanline[x] && !scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (scanline[xx] && !scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) width - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) width - 0.5;
|
||||
f32 vy = 0.5 - (y - eps) / (f32) height;
|
||||
f32 tx1 = x / (f32) width;
|
||||
f32 tx2 = xx / (f32) width;
|
||||
f32 ty = (y - 0.5) / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
if (!scanline[x] && scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (!scanline[xx] && scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) width - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) width - 0.5;
|
||||
f32 vy = 0.5 - (y + eps) / (f32) height;
|
||||
f32 tx1 = x / (f32) width;
|
||||
f32 tx2 = xx / (f32) width;
|
||||
f32 ty = (y + 0.5) / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 x = 0; x <= width; ++x)
|
||||
{
|
||||
u8* scancol = solidity + x + wstep;
|
||||
for (u32 y = 0; y <= height; ++y)
|
||||
{
|
||||
if (scancol[y * wstep] && !scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (scancol[yy * wstep] && !scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x - eps) / (f32) width - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) height;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) height;
|
||||
f32 tx = (x - 0.5) / (f32) width;
|
||||
f32 ty1 = y / (f32) height;
|
||||
f32 ty2 = yy / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
if (!scancol[y * wstep] && scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (!scancol[yy * wstep] && scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x + eps) / (f32) width - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) height;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) height;
|
||||
f32 tx = (x + 0.5) / (f32) width;
|
||||
f32 ty1 = y / (f32) height;
|
||||
f32 ty2 = yy / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mesh
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
buf->recalculateBoundingBox();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
mesh->recalculateBoundingBox();
|
||||
scene::SAnimatedMesh* anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture)
|
||||
{
|
||||
scene::IAnimatedMesh* mesh = NULL;
|
||||
core::dimension2d<u32> size = texture->getSize();
|
||||
video::ECOLOR_FORMAT format = texture->getColorFormat();
|
||||
if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
// Texture is in the correct color format, we can pass it
|
||||
// to extrudeARGB right away.
|
||||
void* data = texture->lock(true);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
|
||||
texture->unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(true));
|
||||
if (img1 == NULL)
|
||||
return NULL;
|
||||
|
||||
// img1 is in the texture's color format, convert to 8-bit ARGB
|
||||
video::IImage* img2 = driver->createImage(video::ECF_A8R8G8B8, size);
|
||||
if (img2 != NULL)
|
||||
{
|
||||
img1->copyTo(img2);
|
||||
img1->drop();
|
||||
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
|
||||
img2->unlock();
|
||||
img2->drop();
|
||||
}
|
||||
img1->drop();
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
scene::IMesh* ExtrudedSpriteSceneNode::createCubeMesh()
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer* buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
buf->recalculateBoundingBox();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
mesh->recalculateBoundingBox();
|
||||
return mesh;
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef CAMERA_HEADER
|
||||
#define CAMERA_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "inventory.h"
|
||||
#include "tile.h"
|
||||
#include "utility.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <IMeshCache.h>
|
||||
#include <IAnimatedMesh.h>
|
||||
|
||||
class LocalPlayer;
|
||||
class MapDrawControl;
|
||||
class ExtrudedSpriteSceneNode;
|
||||
|
||||
/*
|
||||
Client camera class, manages the player and camera scene nodes, the viewing distance
|
||||
and performs view bobbing etc. It also displays the wielded tool in front of the
|
||||
first-person camera.
|
||||
*/
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control);
|
||||
~Camera();
|
||||
|
||||
// Get player scene node.
|
||||
// This node is positioned at the player's torso (without any view bobbing),
|
||||
// as given by Player::m_position. Yaw is applied but not pitch.
|
||||
inline scene::ISceneNode* getPlayerNode() const
|
||||
{
|
||||
return m_playernode;
|
||||
}
|
||||
|
||||
// Get head scene node.
|
||||
// It has the eye transformation and pitch applied,
|
||||
// but no view bobbing.
|
||||
inline scene::ISceneNode* getHeadNode() const
|
||||
{
|
||||
return m_headnode;
|
||||
}
|
||||
|
||||
// Get camera scene node.
|
||||
// It has the eye transformation, pitch and view bobbing applied.
|
||||
inline scene::ICameraSceneNode* getCameraNode() const
|
||||
{
|
||||
return m_cameranode;
|
||||
}
|
||||
|
||||
// Get the camera position (in absolute scene coordinates).
|
||||
// This has view bobbing applied.
|
||||
inline v3f getPosition() const
|
||||
{
|
||||
return m_camera_position;
|
||||
}
|
||||
|
||||
// Get the camera direction (in absolute camera coordinates).
|
||||
// This has view bobbing applied.
|
||||
inline v3f getDirection() const
|
||||
{
|
||||
return m_camera_direction;
|
||||
}
|
||||
|
||||
// Horizontal field of view
|
||||
inline f32 getFovX() const
|
||||
{
|
||||
return m_fov_x;
|
||||
}
|
||||
|
||||
// Vertical field of view
|
||||
inline f32 getFovY() const
|
||||
{
|
||||
return m_fov_y;
|
||||
}
|
||||
|
||||
// Get maximum of getFovX() and getFovY()
|
||||
inline f32 getFovMax() const
|
||||
{
|
||||
return MYMAX(m_fov_x, m_fov_y);
|
||||
}
|
||||
|
||||
// Checks if the constructor was able to create the scene nodes
|
||||
bool successfullyCreated(std::wstring& error_message);
|
||||
|
||||
// Step the camera: updates the viewing range and view bobbing.
|
||||
void step(f32 dtime);
|
||||
|
||||
// Update the camera from the local player's position.
|
||||
// frametime is used to adjust the viewing range.
|
||||
void update(LocalPlayer* player, f32 frametime, v2u32 screensize);
|
||||
|
||||
// Render distance feedback loop
|
||||
void updateViewingRange(f32 frametime_in);
|
||||
|
||||
// Update settings from g_settings
|
||||
void updateSettings();
|
||||
|
||||
// Replace the wielded item mesh
|
||||
void wield(const InventoryItem* item);
|
||||
|
||||
// Start digging animation
|
||||
// Pass 0 for left click, 1 for right click
|
||||
void setDigging(s32 button);
|
||||
|
||||
// Draw the wielded tool.
|
||||
// This has to happen *after* the main scene is drawn.
|
||||
// Warning: This clears the Z buffer.
|
||||
void drawWieldedTool();
|
||||
|
||||
private:
|
||||
// Scene manager and nodes
|
||||
scene::ISceneManager* m_smgr;
|
||||
scene::ISceneNode* m_playernode;
|
||||
scene::ISceneNode* m_headnode;
|
||||
scene::ICameraSceneNode* m_cameranode;
|
||||
|
||||
scene::ISceneManager* m_wieldmgr;
|
||||
ExtrudedSpriteSceneNode* m_wieldnode;
|
||||
|
||||
// draw control
|
||||
MapDrawControl& m_draw_control;
|
||||
|
||||
// viewing_range_min_nodes setting
|
||||
f32 m_viewing_range_min;
|
||||
// viewing_range_max_nodes setting
|
||||
f32 m_viewing_range_max;
|
||||
|
||||
// Absolute camera position
|
||||
v3f m_camera_position;
|
||||
// Absolute camera direction
|
||||
v3f m_camera_direction;
|
||||
|
||||
// Field of view and aspect ratio stuff
|
||||
f32 m_aspect;
|
||||
f32 m_fov_x;
|
||||
f32 m_fov_y;
|
||||
|
||||
// Stuff for viewing range calculations
|
||||
f32 m_wanted_frametime;
|
||||
f32 m_added_frametime;
|
||||
s16 m_added_frames;
|
||||
f32 m_range_old;
|
||||
f32 m_frametime_old;
|
||||
f32 m_frametime_counter;
|
||||
f32 m_time_per_range;
|
||||
|
||||
// View bobbing animation frame (0 <= m_view_bobbing_anim < 1)
|
||||
f32 m_view_bobbing_anim;
|
||||
// If 0, view bobbing is off (e.g. player is standing).
|
||||
// If 1, view bobbing is on (player is walking).
|
||||
// If 2, view bobbing is getting switched off.
|
||||
s32 m_view_bobbing_state;
|
||||
// Speed of view bobbing animation
|
||||
f32 m_view_bobbing_speed;
|
||||
|
||||
// Digging animation frame (0 <= m_digging_anim < 1)
|
||||
f32 m_digging_anim;
|
||||
// If -1, no digging animation
|
||||
// If 0, left-click digging animation
|
||||
// If 1, right-click digging animation
|
||||
s32 m_digging_button;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A scene node that displays a 2D mesh extruded into the third dimension,
|
||||
to add an illusion of depth.
|
||||
|
||||
Since this class was created to display the wielded tool of the local
|
||||
player, and only tools and items are rendered like this (but not solid
|
||||
content like stone and mud, which are shown as cubes), the option to
|
||||
draw a textured cube instead is provided.
|
||||
*/
|
||||
class ExtrudedSpriteSceneNode: public scene::ISceneNode
|
||||
{
|
||||
public:
|
||||
ExtrudedSpriteSceneNode(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id = -1,
|
||||
const v3f& position = v3f(0,0,0),
|
||||
const v3f& rotation = v3f(0,0,0),
|
||||
const v3f& scale = v3f(1,1,1));
|
||||
~ExtrudedSpriteSceneNode();
|
||||
|
||||
void setSprite(video::ITexture* texture);
|
||||
void setCube(const TileSpec tiles[6]);
|
||||
|
||||
f32 getSpriteThickness() const { return m_thickness; }
|
||||
void setSpriteThickness(f32 thickness);
|
||||
|
||||
void updateLight(u8 light);
|
||||
|
||||
void removeSpriteFromCache(video::ITexture* texture);
|
||||
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
virtual void OnRegisterSceneNode();
|
||||
virtual void render();
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode* m_meshnode;
|
||||
f32 m_thickness;
|
||||
scene::IMesh* m_cubemesh;
|
||||
bool m_is_cube;
|
||||
u8 m_light;
|
||||
|
||||
// internal extrusion helper methods
|
||||
io::path getExtrudedName(video::ITexture* texture);
|
||||
scene::IAnimatedMesh* extrudeARGB(u32 width, u32 height, u8* data);
|
||||
scene::IAnimatedMesh* extrude(video::ITexture* texture);
|
||||
scene::IMesh* createCubeMesh();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,5 +1,27 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Author: Jan Cychnerski
|
||||
*/
|
||||
|
||||
#include "clans.h"
|
||||
#include "player.h"
|
||||
#include "settings.h"
|
||||
|
||||
ClansManager::ClansManager():
|
||||
m_maxId(0)
|
||||
|
|
|
@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
*/
|
||||
|
||||
/*
|
||||
Clans.h - author: jachoo <g.j.g@interia.pl>
|
||||
Clans.h - author: Jan Cychnerski
|
||||
*/
|
||||
|
||||
#ifndef CLANS_HEADER
|
||||
|
|
493
src/client.cpp
|
@ -28,6 +28,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapsector.h"
|
||||
#include "mapblock_mesh.h"
|
||||
#include "mapblock.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
QueuedMeshUpdate
|
||||
|
@ -129,6 +132,8 @@ void * MeshUpdateThread::Thread()
|
|||
{
|
||||
ThreadStarted();
|
||||
|
||||
log_register_thread("MeshUpdateThread");
|
||||
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
@ -151,7 +156,7 @@ void * MeshUpdateThread::Thread()
|
|||
continue;
|
||||
}
|
||||
|
||||
ScopeProfiler sp(&g_profiler, "mesh make");
|
||||
ScopeProfiler sp(g_profiler, "mesh make");
|
||||
|
||||
scene::SMesh *mesh_new = NULL;
|
||||
mesh_new = makeMapBlockMesh(q->data);
|
||||
|
@ -161,7 +166,7 @@ void * MeshUpdateThread::Thread()
|
|||
r.mesh = mesh_new;
|
||||
r.ack_block_to_server = q->ack_block_to_server;
|
||||
|
||||
/*dstream<<"MeshUpdateThread: Processed "
|
||||
/*infostream<<"MeshUpdateThread: Processed "
|
||||
<<"("<<q->p.X<<","<<q->p.Y<<","<<q->p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
|
@ -170,7 +175,7 @@ void * MeshUpdateThread::Thread()
|
|||
delete q;
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -189,8 +194,6 @@ Client::Client(
|
|||
),
|
||||
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
|
||||
m_device(device),
|
||||
camera_position(0,0,0),
|
||||
camera_direction(0,0,1),
|
||||
m_server_ser_ver(SER_FMT_VER_INVALID),
|
||||
m_inventory_updated(false),
|
||||
m_time_of_day(0),
|
||||
|
@ -273,7 +276,7 @@ void Client::step(float dtime)
|
|||
else
|
||||
m_ignore_damage_timer = 0.0;
|
||||
|
||||
//dstream<<"Client steps "<<dtime<<std::endl;
|
||||
//infostream<<"Client steps "<<dtime<<std::endl;
|
||||
|
||||
{
|
||||
//TimeTaker timer("ReceiveAll()", m_device);
|
||||
|
@ -298,8 +301,8 @@ void Client::step(float dtime)
|
|||
{
|
||||
counter = 20.0;
|
||||
|
||||
dout_client<<"Client packetcounter (20s):"<<std::endl;
|
||||
m_packetcounter.print(dout_client);
|
||||
infostream<<"Client packetcounter (20s):"<<std::endl;
|
||||
m_packetcounter.print(infostream);
|
||||
m_packetcounter.clear();
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +332,7 @@ void Client::step(float dtime)
|
|||
core::list<v3s16> deleted_blocks;
|
||||
|
||||
float delete_unused_sectors_timeout =
|
||||
g_settings.getFloat("client_delete_unused_sectors_timeout");
|
||||
g_settings->getFloat("client_delete_unused_sectors_timeout");
|
||||
|
||||
// Delete sector blocks
|
||||
/*u32 num = m_env.getMap().unloadUnusedData
|
||||
|
@ -343,9 +346,9 @@ void Client::step(float dtime)
|
|||
|
||||
if(deleted_blocks.size() > 0)
|
||||
{
|
||||
/*dstream<<DTIME<<"Client: Deleted blocks of "<<num
|
||||
/*infostream<<"Client: Deleted blocks of "<<num
|
||||
<<" unused sectors"<<std::endl;*/
|
||||
/*dstream<<DTIME<<"Client: Deleted "<<num
|
||||
/*infostream<<"Client: Deleted "<<num
|
||||
<<" unused sectors"<<std::endl;*/
|
||||
|
||||
/*
|
||||
|
@ -424,14 +427,14 @@ void Client::step(float dtime)
|
|||
memset((char*)&data[3], 0, PLAYERNAME_SIZE);
|
||||
snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName());
|
||||
|
||||
/*dstream<<"Client: sending initial password hash: \""<<m_password<<"\""
|
||||
/*infostream<<"Client: sending initial password hash: \""<<m_password<<"\""
|
||||
<<std::endl;*/
|
||||
|
||||
memset((char*)&data[23], 0, PASSWORD_SIZE);
|
||||
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
|
||||
|
||||
// This should be incremented in each version
|
||||
writeU16(&data[51], 2);
|
||||
writeU16(&data[51], 3);
|
||||
|
||||
// Send as unreliable
|
||||
Send(0, data, false);
|
||||
|
@ -451,14 +454,14 @@ void Client::step(float dtime)
|
|||
const float map_timer_and_unload_dtime = 5.25;
|
||||
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||
{
|
||||
ScopeProfiler sp(&g_profiler, "Client: map timer and unload");
|
||||
ScopeProfiler sp(g_profiler, "Client: map timer and unload");
|
||||
core::list<v3s16> deleted_blocks;
|
||||
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||
g_settings.getFloat("client_unload_unused_data_timeout"),
|
||||
g_settings->getFloat("client_unload_unused_data_timeout"),
|
||||
&deleted_blocks);
|
||||
|
||||
/*if(deleted_blocks.size() > 0)
|
||||
dstream<<"Client: Unloaded "<<deleted_blocks.size()
|
||||
infostream<<"Client: Unloaded "<<deleted_blocks.size()
|
||||
<<" unused blocks"<<std::endl;*/
|
||||
|
||||
/*
|
||||
|
@ -522,24 +525,6 @@ void Client::step(float dtime)
|
|||
// Step environment
|
||||
m_env.step(dtime);
|
||||
|
||||
/*
|
||||
Handle active blocks
|
||||
NOTE: These old objects are DEPRECATED. TODO: Remove
|
||||
*/
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
|
||||
if(block == NULL)
|
||||
continue;
|
||||
|
||||
// Step MapBlockObjects
|
||||
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
||||
}
|
||||
|
||||
/*
|
||||
Get events
|
||||
*/
|
||||
|
@ -579,7 +564,7 @@ void Client::step(float dtime)
|
|||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||
// connectedAndInitialized() is true, peer exists.
|
||||
con::Peer *peer = m_con.GetPeer(PEER_ID_SERVER);
|
||||
dstream<<DTIME<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
|
||||
infostream<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,7 +590,7 @@ void Client::step(float dtime)
|
|||
//TimeTaker timer("** Processing mesh update result queue");
|
||||
// 0ms
|
||||
|
||||
/*dstream<<"Mesh update result queue size is "
|
||||
/*infostream<<"Mesh update result queue size is "
|
||||
<<m_mesh_update_thread.m_queue_out.size()
|
||||
<<std::endl;*/
|
||||
|
||||
|
@ -619,7 +604,7 @@ void Client::step(float dtime)
|
|||
}
|
||||
if(r.ack_block_to_server)
|
||||
{
|
||||
/*dstream<<"Client: ACK block ("<<r.p.X<<","<<r.p.Y
|
||||
/*infostream<<"Client: ACK block ("<<r.p.X<<","<<r.p.Y
|
||||
<<","<<r.p.Z<<")"<<std::endl;*/
|
||||
/*
|
||||
Acknowledge block
|
||||
|
@ -646,12 +631,12 @@ void Client::step(float dtime)
|
|||
// Virtual methods from con::PeerHandler
|
||||
void Client::peerAdded(con::Peer *peer)
|
||||
{
|
||||
derr_client<<"Client::peerAdded(): peer->id="
|
||||
infostream<<"Client::peerAdded(): peer->id="
|
||||
<<peer->id<<std::endl;
|
||||
}
|
||||
void Client::deletingPeer(con::Peer *peer, bool timeout)
|
||||
{
|
||||
derr_client<<"Client::deletingPeer(): "
|
||||
infostream<<"Client::deletingPeer(): "
|
||||
"Server Peer is getting deleted "
|
||||
<<"(timeout="<<timeout<<")"<<std::endl;
|
||||
}
|
||||
|
@ -670,7 +655,7 @@ void Client::ReceiveAll()
|
|||
}
|
||||
catch(con::InvalidIncomingDataException &e)
|
||||
{
|
||||
dout_client<<DTIME<<"Client::ReceiveAll(): "
|
||||
infostream<<"Client::ReceiveAll(): "
|
||||
"InvalidIncomingDataException: what()="
|
||||
<<e.what()<<std::endl;
|
||||
}
|
||||
|
@ -709,7 +694,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
ToClientCommand command = (ToClientCommand)readU16(&data[0]);
|
||||
|
||||
//dstream<<"Client: received command="<<command<<std::endl;
|
||||
//infostream<<"Client: received command="<<command<<std::endl;
|
||||
m_packetcounter.add((u16)command);
|
||||
|
||||
/*
|
||||
|
@ -718,7 +703,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
*/
|
||||
if(sender_peer_id != PEER_ID_SERVER)
|
||||
{
|
||||
dout_client<<DTIME<<"Client::ProcessData(): Discarding data not "
|
||||
infostream<<"Client::ProcessData(): Discarding data not "
|
||||
"coming from server: peer_id="<<sender_peer_id
|
||||
<<std::endl;
|
||||
return;
|
||||
|
@ -734,7 +719,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
u8 ser_version = m_server_ser_ver;
|
||||
|
||||
//dstream<<"Client received command="<<(int)command<<std::endl;
|
||||
//infostream<<"Client received command="<<(int)command<<std::endl;
|
||||
|
||||
if(command == TOCLIENT_INIT)
|
||||
{
|
||||
|
@ -743,13 +728,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
u8 deployed = data[2];
|
||||
|
||||
dout_client<<DTIME<<"Client: TOCLIENT_INIT received with "
|
||||
infostream<<"Client: TOCLIENT_INIT received with "
|
||||
"deployed="<<((int)deployed&0xff)<<std::endl;
|
||||
|
||||
if(deployed < SER_FMT_VER_LOWEST
|
||||
|| deployed > SER_FMT_VER_HIGHEST)
|
||||
{
|
||||
derr_client<<DTIME<<"Client: TOCLIENT_INIT: Server sent "
|
||||
infostream<<"Client: TOCLIENT_INIT: Server sent "
|
||||
<<"unsupported ser_fmt_ver"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
@ -775,7 +760,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
{
|
||||
// Get map seed
|
||||
m_map_seed = readU64(&data[2+1+6]);
|
||||
dstream<<"Client: received map seed: "<<m_map_seed<<std::endl;
|
||||
infostream<<"Client: received map seed: "<<m_map_seed<<std::endl;
|
||||
}
|
||||
|
||||
// Reply to server
|
||||
|
@ -806,7 +791,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
if(ser_version == SER_FMT_VER_INVALID)
|
||||
{
|
||||
dout_client<<DTIME<<"WARNING: Client: Server serialization"
|
||||
infostream<<"Client: Server serialization"
|
||||
" format invalid or not initialized."
|
||||
" Skipping incoming command="<<command<<std::endl;
|
||||
return;
|
||||
|
@ -860,9 +845,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
p.Y = readS16(&data[4]);
|
||||
p.Z = readS16(&data[6]);
|
||||
|
||||
/*dout_client<<DTIME<<"Client: Thread: BLOCKDATA for ("
|
||||
/*infostream<<"Client: Thread: BLOCKDATA for ("
|
||||
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
|
||||
/*dstream<<DTIME<<"Client: Thread: BLOCKDATA for ("
|
||||
/*infostream<<"Client: Thread: BLOCKDATA for ("
|
||||
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
|
||||
|
||||
std::string datastring((char*)&data[8], datasize-8);
|
||||
|
@ -885,7 +870,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
/*
|
||||
Update an existing block
|
||||
*/
|
||||
//dstream<<"Updating"<<std::endl;
|
||||
//infostream<<"Updating"<<std::endl;
|
||||
block->deSerialize(istr, ser_version);
|
||||
}
|
||||
else
|
||||
|
@ -893,7 +878,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
/*
|
||||
Create a new block
|
||||
*/
|
||||
//dstream<<"Creating new"<<std::endl;
|
||||
//infostream<<"Creating new"<<std::endl;
|
||||
block = new MapBlock(&m_env.getMap(), p);
|
||||
block->deSerialize(istr, ser_version);
|
||||
sector->insertBlock(block);
|
||||
|
@ -939,12 +924,12 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
/*
|
||||
Add it to mesh update queue and set it to be acknowledged after update.
|
||||
*/
|
||||
//std::cerr<<"Adding mesh update task for received block"<<std::endl;
|
||||
//infostream<<"Adding mesh update task for received block"<<std::endl;
|
||||
addUpdateMeshTaskWithEdge(p, true);
|
||||
}
|
||||
else if(command == TOCLIENT_PLAYERPOS)
|
||||
{
|
||||
dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS"
|
||||
infostream<<"Received deprecated TOCLIENT_PLAYERPOS"
|
||||
<<std::endl;
|
||||
/*u16 our_peer_id;
|
||||
{
|
||||
|
@ -953,7 +938,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
}
|
||||
// Cancel if we don't have a peer id
|
||||
if(our_peer_id == PEER_ID_INEXISTENT){
|
||||
dout_client<<DTIME<<"TOCLIENT_PLAYERPOS cancelled: "
|
||||
infostream<<"TOCLIENT_PLAYERPOS cancelled: "
|
||||
"we have no peer id"
|
||||
<<std::endl;
|
||||
return;
|
||||
|
@ -990,7 +975,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
v3s32 ss = readV3S32(&data[start+2+12]);
|
||||
s32 pitch_i = readS32(&data[start+2+12+12]);
|
||||
s32 yaw_i = readS32(&data[start+2+12+12+4]);
|
||||
/*dstream<<"Client: got "
|
||||
/*infostream<<"Client: got "
|
||||
<<"pitch_i="<<pitch_i
|
||||
<<" yaw_i="<<yaw_i<<std::endl;*/
|
||||
f32 pitch = (f32)pitch_i / 100.0;
|
||||
|
@ -1002,7 +987,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
player->setPitch(pitch);
|
||||
player->setYaw(yaw);
|
||||
|
||||
/*dstream<<"Client: player "<<peer_id
|
||||
/*infostream<<"Client: player "<<peer_id
|
||||
<<" pitch="<<pitch
|
||||
<<" yaw="<<yaw<<std::endl;*/
|
||||
|
||||
|
@ -1019,13 +1004,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
}
|
||||
// Cancel if we don't have a peer id
|
||||
if(our_peer_id == PEER_ID_INEXISTENT){
|
||||
dout_client<<DTIME<<"TOCLIENT_PLAYERINFO cancelled: "
|
||||
infostream<<"TOCLIENT_PLAYERINFO cancelled: "
|
||||
"we have no peer id"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//dstream<<DTIME<<"Client: Server reports players:"<<std::endl;
|
||||
//infostream<<"Client: Server reports players:"<<std::endl;
|
||||
|
||||
{ //envlock
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
@ -1044,7 +1029,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
players_alive.push_back(peer_id);
|
||||
|
||||
/*dstream<<DTIME<<"peer_id="<<peer_id
|
||||
/*infostream<<"peer_id="<<peer_id
|
||||
<<" name="<<((char*)&data[start+2])<<std::endl;*/
|
||||
|
||||
// Don't update the info of the local player
|
||||
|
@ -1065,7 +1050,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
-1);
|
||||
player->peer_id = peer_id;
|
||||
m_env.addPlayer(player);
|
||||
dout_client<<DTIME<<"Client: Adding new player "
|
||||
infostream<<"Client: Adding new player "
|
||||
<<peer_id<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1063,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
Remove those players from the environment that
|
||||
weren't listed by the server.
|
||||
*/
|
||||
//dstream<<DTIME<<"Removing dead players"<<std::endl;
|
||||
//infostream<<"Removing dead players"<<std::endl;
|
||||
core::list<Player*> players = m_env.getPlayers();
|
||||
core::list<Player*>::Iterator ip;
|
||||
for(ip=players.begin(); ip!=players.end(); ip++)
|
||||
|
@ -1090,7 +1075,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
// Warn about a special case
|
||||
if((*ip)->peer_id == 0)
|
||||
{
|
||||
dstream<<DTIME<<"WARNING: Client: Removing "
|
||||
infostream<<"Client: Removing "
|
||||
"dead player with id=0"<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -1104,11 +1089,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
break;
|
||||
}
|
||||
}
|
||||
/*dstream<<DTIME<<"peer_id="<<((*ip)->peer_id)
|
||||
/*infostream<<"peer_id="<<((*ip)->peer_id)
|
||||
<<" is_alive="<<is_alive<<std::endl;*/
|
||||
if(is_alive)
|
||||
continue;
|
||||
dstream<<DTIME<<"Removing dead player "<<(*ip)->peer_id
|
||||
infostream<<"Removing dead player "<<(*ip)->peer_id
|
||||
<<std::endl;
|
||||
m_env.removePlayer((*ip)->peer_id);
|
||||
}
|
||||
|
@ -1116,7 +1101,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
}
|
||||
else if(command == TOCLIENT_SECTORMETA)
|
||||
{
|
||||
dstream<<"Client received DEPRECATED TOCLIENT_SECTORMETA"<<std::endl;
|
||||
infostream<<"Client received DEPRECATED TOCLIENT_SECTORMETA"<<std::endl;
|
||||
#if 0
|
||||
/*
|
||||
[0] u16 command
|
||||
|
@ -1126,7 +1111,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
if(datasize < 3)
|
||||
return;
|
||||
|
||||
//dstream<<"Client received TOCLIENT_SECTORMETA"<<std::endl;
|
||||
//infostream<<"Client received TOCLIENT_SECTORMETA"<<std::endl;
|
||||
|
||||
{ //envlock
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
@ -1139,14 +1124,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
is.read((char*)buf, 1);
|
||||
u16 sector_count = readU8(buf);
|
||||
|
||||
//dstream<<"sector_count="<<sector_count<<std::endl;
|
||||
//infostream<<"sector_count="<<sector_count<<std::endl;
|
||||
|
||||
for(u16 i=0; i<sector_count; i++)
|
||||
{
|
||||
// Read position
|
||||
is.read((char*)buf, 4);
|
||||
v2s16 pos = readV2S16(buf);
|
||||
/*dstream<<"Client: deserializing sector at "
|
||||
/*infostream<<"Client: deserializing sector at "
|
||||
<<"("<<pos.X<<","<<pos.Y<<")"<<std::endl;*/
|
||||
// Create sector
|
||||
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
||||
|
@ -1172,7 +1157,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
//t3.stop();
|
||||
|
||||
//m_env.printPlayers(dstream);
|
||||
//m_env.printPlayers(infostream);
|
||||
|
||||
//TimeTaker t4("player get", m_device);
|
||||
Player *player = m_env.getLocalPlayer();
|
||||
|
@ -1185,22 +1170,17 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
m_inventory_updated = true;
|
||||
|
||||
//dstream<<"Client got player inventory:"<<std::endl;
|
||||
//player->inventory.print(dstream);
|
||||
//infostream<<"Client got player inventory:"<<std::endl;
|
||||
//player->inventory.print(infostream);
|
||||
}
|
||||
}
|
||||
//DEBUG
|
||||
else if(command == TOCLIENT_OBJECTDATA)
|
||||
//else if(0)
|
||||
{
|
||||
// Strip command word and create a stringstream
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
{ //envlock
|
||||
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
||||
u8 buf[12];
|
||||
|
||||
/*
|
||||
|
@ -1250,106 +1230,16 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
/*
|
||||
Read block objects
|
||||
NOTE: Deprecated stuff here, TODO: Remove
|
||||
NOTE: Deprecated stuff
|
||||
*/
|
||||
|
||||
// Read active block count
|
||||
is.read((char*)buf, 2);
|
||||
u16 blockcount = readU16(buf);
|
||||
|
||||
// Initialize delete queue with all active blocks
|
||||
core::map<v3s16, bool> abs_to_delete;
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
/*dstream<<"adding "
|
||||
<<"("<<p.x<<","<<p.y<<","<<p.z<<") "
|
||||
<<" to abs_to_delete"
|
||||
<<std::endl;*/
|
||||
abs_to_delete.insert(p, true);
|
||||
u16 blockcount = readU16(is);
|
||||
if(blockcount != 0){
|
||||
infostream<<"TOCLIENT_OBJECTDATA: blockcount != 0 "
|
||||
"not supported"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*dstream<<"Initial delete queue size: "<<abs_to_delete.size()
|
||||
<<std::endl;*/
|
||||
|
||||
for(u16 i=0; i<blockcount; i++)
|
||||
{
|
||||
// Read blockpos
|
||||
is.read((char*)buf, 6);
|
||||
v3s16 p = readV3S16(buf);
|
||||
// Get block from somewhere
|
||||
MapBlock *block = NULL;
|
||||
try{
|
||||
block = m_env.getMap().getBlockNoCreate(p);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
//TODO: Create a dummy block?
|
||||
}
|
||||
if(block == NULL)
|
||||
{
|
||||
dstream<<"WARNING: "
|
||||
<<"Could not get block at blockpos "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
|
||||
<<"in TOCLIENT_OBJECTDATA. Ignoring "
|
||||
<<"following block object data."
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*dstream<<"Client updating objects for block "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
// Insert to active block list
|
||||
m_active_blocks.insert(p, true);
|
||||
|
||||
// Remove from deletion queue
|
||||
if(abs_to_delete.find(p) != NULL)
|
||||
abs_to_delete.remove(p);
|
||||
|
||||
/*
|
||||
Update objects of block
|
||||
|
||||
NOTE: Be sure this is done in the main thread.
|
||||
*/
|
||||
block->updateObjects(is, m_server_ser_ver,
|
||||
m_device->getSceneManager(), m_env.getDayNightRatio());
|
||||
}
|
||||
|
||||
/*dstream<<"Final delete queue size: "<<abs_to_delete.size()
|
||||
<<std::endl;*/
|
||||
|
||||
// Delete objects of blocks in delete queue
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = abs_to_delete.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
try
|
||||
{
|
||||
MapBlock *block = m_env.getMap().getBlockNoCreate(p);
|
||||
|
||||
// Clear objects
|
||||
block->clearObjects();
|
||||
// Remove from active blocks list
|
||||
m_active_blocks.remove(p);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
dstream<<"WARNAING: Client: "
|
||||
<<"Couldn't clear objects of active->inactive"
|
||||
<<" block "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<" because block was not found"
|
||||
<<std::endl;
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
} //envlock
|
||||
}
|
||||
else if(command == TOCLIENT_TIME_OF_DAY)
|
||||
{
|
||||
|
@ -1358,7 +1248,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
u16 time_of_day = readU16(&data[2]);
|
||||
time_of_day = time_of_day % 24000;
|
||||
//dstream<<"Client: time_of_day="<<time_of_day<<std::endl;
|
||||
//infostream<<"Client: time_of_day="<<time_of_day<<std::endl;
|
||||
|
||||
/*
|
||||
time_of_day:
|
||||
|
@ -1370,7 +1260,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
u32 dr = m_env.getDayNightRatio();
|
||||
|
||||
dstream<<"Client: time_of_day="<<time_of_day
|
||||
infostream<<"Client: time_of_day="<<time_of_day
|
||||
<<", dr="<<dr
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -1398,14 +1288,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
message += (wchar_t)readU16(buf);
|
||||
}
|
||||
|
||||
/*dstream<<"Client received chat message: "
|
||||
/*infostream<<"Client received chat message: "
|
||||
<<wide_to_narrow(message)<<std::endl;*/
|
||||
|
||||
m_chat_queue.push_back(message);
|
||||
}
|
||||
else if(command == TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD)
|
||||
{
|
||||
//if(g_settings.getBool("enable_experimental"))
|
||||
//if(g_settings->getBool("enable_experimental"))
|
||||
{
|
||||
/*
|
||||
u16 command
|
||||
|
@ -1464,7 +1354,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
}
|
||||
else if(command == TOCLIENT_ACTIVE_OBJECT_MESSAGES)
|
||||
{
|
||||
//if(g_settings.getBool("enable_experimental"))
|
||||
//if(g_settings->getBool("enable_experimental"))
|
||||
{
|
||||
/*
|
||||
u16 command
|
||||
|
@ -1527,7 +1417,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
/*player->setPitch(pitch);
|
||||
player->setYaw(yaw);*/
|
||||
|
||||
dstream<<"Client got TOCLIENT_MOVE_PLAYER"
|
||||
infostream<<"Client got TOCLIENT_MOVE_PLAYER"
|
||||
<<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
|
||||
<<" pitch="<<pitch
|
||||
<<" yaw="<<yaw
|
||||
|
@ -1562,13 +1452,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
if (player == NULL)
|
||||
{
|
||||
dout_client<<DTIME<<"Client: ignoring player item "
|
||||
infostream<<"Client: ignoring player item "
|
||||
<< deSerializeString(is)
|
||||
<< " for non-existing peer id " << peer_id
|
||||
<< std::endl;
|
||||
continue;
|
||||
} else if (player->isLocal()) {
|
||||
dout_client<<DTIME<<"Client: ignoring player item "
|
||||
infostream<<"Client: ignoring player item "
|
||||
<< deSerializeString(is)
|
||||
<< " for local player" << std::endl;
|
||||
continue;
|
||||
|
@ -1577,19 +1467,35 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
std::string itemstring(deSerializeString(is));
|
||||
if (itemstring.empty()) {
|
||||
inv->deleteItem(0);
|
||||
dout_client<<DTIME
|
||||
infostream
|
||||
<<"Client: empty player item for peer "
|
||||
<< peer_id << std::endl;
|
||||
} else {
|
||||
std::istringstream iss(itemstring);
|
||||
delete inv->changeItem(0, InventoryItem::deSerialize(iss));
|
||||
dout_client<<DTIME<<"Client: player item for peer " << peer_id << ": ";
|
||||
player->getWieldItem()->serialize(dout_client);
|
||||
dout_client<<std::endl;
|
||||
infostream<<"Client: player item for peer " << peer_id << ": ";
|
||||
player->getWieldItem()->serialize(infostream);
|
||||
infostream<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(command == TOCLIENT_DEATHSCREEN)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
bool set_camera_point_target = readU8(is);
|
||||
v3f camera_point_target = readV3F1000(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_DEATHSCREEN;
|
||||
event.deathscreen.set_camera_point_target = set_camera_point_target;
|
||||
event.deathscreen.camera_point_target_x = camera_point_target.X;
|
||||
event.deathscreen.camera_point_target_y = camera_point_target.Y;
|
||||
event.deathscreen.camera_point_target_z = camera_point_target.Z;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_PLAYER_CLAN) //j
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
|
@ -1680,7 +1586,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
}
|
||||
else
|
||||
{
|
||||
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
<<command<<std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1695,7 +1601,7 @@ void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
|
|||
v3s16 nodepos_oversurface, u16 item)
|
||||
{
|
||||
if(connectedAndInitialized() == false){
|
||||
dout_client<<DTIME<<"Client::groundAction() "
|
||||
infostream<<"Client::groundAction() "
|
||||
"cancelled (not connected)"
|
||||
<<std::endl;
|
||||
return;
|
||||
|
@ -1724,39 +1630,45 @@ void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
|
|||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item)
|
||||
void Client::clickActiveObject(u8 button, u16 id, u16 item_i)
|
||||
{
|
||||
if(connectedAndInitialized() == false){
|
||||
dout_client<<DTIME<<"Client::clickObject() "
|
||||
infostream<<"Client::clickActiveObject() "
|
||||
"cancelled (not connected)"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
[0] u16 command=TOSERVER_CLICK_OBJECT
|
||||
[2] u8 button (0=left, 1=right)
|
||||
[3] v3s16 block
|
||||
[9] s16 id
|
||||
[11] u16 item
|
||||
*/
|
||||
u8 datasize = 2 + 1 + 6 + 2 + 2;
|
||||
SharedBuffer<u8> data(datasize);
|
||||
writeU16(&data[0], TOSERVER_CLICK_OBJECT);
|
||||
writeU8(&data[2], button);
|
||||
writeV3S16(&data[3], blockpos);
|
||||
writeS16(&data[9], id);
|
||||
writeU16(&data[11], item);
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::clickActiveObject(u8 button, u16 id, u16 item)
|
||||
{
|
||||
if(connectedAndInitialized() == false){
|
||||
dout_client<<DTIME<<"Client::clickActiveObject() "
|
||||
"cancelled (not connected)"
|
||||
<<std::endl;
|
||||
Player *player = m_env.getLocalPlayer();
|
||||
if(player == NULL)
|
||||
return;
|
||||
|
||||
ClientActiveObject *obj = m_env.getActiveObject(id);
|
||||
if(obj){
|
||||
if(button == 0){
|
||||
ToolItem *titem = NULL;
|
||||
std::string toolname = "";
|
||||
|
||||
InventoryList *mlist = player->inventory.getList("main");
|
||||
if(mlist != NULL)
|
||||
{
|
||||
InventoryItem *item = mlist->getItem(item_i);
|
||||
if(item && (std::string)item->getName() == "ToolItem")
|
||||
{
|
||||
titem = (ToolItem*)item;
|
||||
toolname = titem->getToolName();
|
||||
}
|
||||
}
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
v3f objpos = obj->getPosition();
|
||||
v3f dir = (objpos - playerpos).normalize();
|
||||
|
||||
bool disable_send = obj->directReportPunch(toolname, dir);
|
||||
|
||||
if(disable_send)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1771,49 +1683,10 @@ void Client::clickActiveObject(u8 button, u16 id, u16 item)
|
|||
writeU16(&data[0], TOSERVER_CLICK_ACTIVEOBJECT);
|
||||
writeU8(&data[2], button);
|
||||
writeU16(&data[3], id);
|
||||
writeU16(&data[5], item);
|
||||
writeU16(&data[5], item_i);
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendSignText(v3s16 blockpos, s16 id, std::string text)
|
||||
{
|
||||
/*
|
||||
u16 command
|
||||
v3s16 blockpos
|
||||
s16 id
|
||||
u16 textlen
|
||||
textdata
|
||||
*/
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
u8 buf[12];
|
||||
|
||||
// Write command
|
||||
writeU16(buf, TOSERVER_SIGNTEXT);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
// Write blockpos
|
||||
writeV3S16(buf, blockpos);
|
||||
os.write((char*)buf, 6);
|
||||
|
||||
// Write id
|
||||
writeS16(buf, id);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
u16 textlen = text.size();
|
||||
// Write text length
|
||||
writeS16(buf, textlen);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
// Write text
|
||||
os.write((char*)text.c_str(), textlen);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendSignNodeText(v3s16 p, std::string text)
|
||||
{
|
||||
/*
|
||||
|
@ -1946,6 +1819,20 @@ void Client::sendDamage(u8 damage)
|
|||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendRespawn()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
||||
writeU16(os, TOSERVER_RESPAWN);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
Send(0, data, true);
|
||||
}
|
||||
|
||||
void Client::sendPlayerPos()
|
||||
{
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
@ -2051,7 +1938,8 @@ void Client::addNode(v3s16 p, MapNode n)
|
|||
try
|
||||
{
|
||||
//TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
|
||||
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
|
||||
std::string st = std::string("");
|
||||
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks, st);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{}
|
||||
|
@ -2068,11 +1956,14 @@ void Client::addNode(v3s16 p, MapNode n)
|
|||
}
|
||||
}
|
||||
|
||||
void Client::updateCamera(v3f pos, v3f dir)
|
||||
void Client::updateCamera(v3f pos, v3f dir, f32 fov)
|
||||
{
|
||||
m_env.getClientMap().updateCamera(pos, dir);
|
||||
camera_position = pos;
|
||||
camera_direction = dir;
|
||||
m_env.getClientMap().updateCamera(pos, dir, fov);
|
||||
}
|
||||
|
||||
void Client::renderPostFx()
|
||||
{
|
||||
m_env.getClientMap().renderPostFx();
|
||||
}
|
||||
|
||||
MapNode Client::getNode(v3s16 p)
|
||||
|
@ -2086,14 +1977,9 @@ NodeMetadata* Client::getNodeMetadata(v3s16 p)
|
|||
return m_env.getMap().getNodeMetadata(p);
|
||||
}
|
||||
|
||||
v3f Client::getPlayerPosition(v3f *eye_position)
|
||||
LocalPlayer* Client::getLocalPlayer()
|
||||
{
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
LocalPlayer *player = m_env.getLocalPlayer();
|
||||
assert(player != NULL);
|
||||
if (eye_position)
|
||||
*eye_position = player->getEyePosition();
|
||||
return player->getPosition();
|
||||
return m_env.getLocalPlayer();
|
||||
}
|
||||
|
||||
void Client::setPlayerControl(PlayerControl &control)
|
||||
|
@ -2159,12 +2045,12 @@ Inventory* Client::getInventory(InventoryContext *c, std::string id)
|
|||
NodeMetadata* meta = getNodeMetadata(p);
|
||||
if(meta)
|
||||
return meta->getInventory();
|
||||
dstream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
|
||||
infostream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
|
||||
<<"no metadata found"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
void Client::inventoryAction(InventoryAction *a)
|
||||
|
@ -2172,71 +2058,6 @@ void Client::inventoryAction(InventoryAction *a)
|
|||
sendInventoryAction(a);
|
||||
}
|
||||
|
||||
MapBlockObject * Client::getSelectedObject(
|
||||
f32 max_d,
|
||||
v3f from_pos_f_on_map,
|
||||
core::line3d<f32> shootline_on_map
|
||||
)
|
||||
{
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
||||
core::array<DistanceSortedObject> objects;
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
MapBlock *block = NULL;
|
||||
try
|
||||
{
|
||||
block = m_env.getMap().getBlockNoCreate(p);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate from_pos relative to block
|
||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
||||
v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map;
|
||||
|
||||
block->getObjects(from_pos_f_on_block, max_d, objects);
|
||||
//block->getPseudoObjects(from_pos_f_on_block, max_d, objects);
|
||||
}
|
||||
|
||||
//dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl;
|
||||
|
||||
// Sort them.
|
||||
// After this, the closest object is the first in the array.
|
||||
objects.sort();
|
||||
|
||||
for(u32 i=0; i<objects.size(); i++)
|
||||
{
|
||||
MapBlockObject *obj = objects[i].obj;
|
||||
MapBlock *block = obj->getBlock();
|
||||
|
||||
// Calculate shootline relative to block
|
||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
||||
core::line3d<f32> shootline_on_block(
|
||||
shootline_on_map.start - block_pos_f_on_map,
|
||||
shootline_on_map.end - block_pos_f_on_map
|
||||
);
|
||||
|
||||
if(obj->isSelected(shootline_on_block))
|
||||
{
|
||||
//dstream<<"Returning selected object"<<std::endl;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
//dstream<<"No object selected; returning NULL."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClientActiveObject * Client::getSelectedActiveObject(
|
||||
f32 max_d,
|
||||
v3f from_pos_f_on_map,
|
||||
|
@ -2247,7 +2068,7 @@ ClientActiveObject * Client::getSelectedActiveObject(
|
|||
|
||||
m_env.getActiveObjects(from_pos_f_on_map, max_d, objects);
|
||||
|
||||
//dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl;
|
||||
//infostream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl;
|
||||
|
||||
// Sort them.
|
||||
// After this, the closest object is the first in the array.
|
||||
|
@ -2270,12 +2091,12 @@ ClientActiveObject * Client::getSelectedActiveObject(
|
|||
|
||||
if(offsetted_box.intersectsWithLine(shootline_on_map))
|
||||
{
|
||||
//dstream<<"Returning selected object"<<std::endl;
|
||||
//infostream<<"Returning selected object"<<std::endl;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
//dstream<<"No object selected; returning NULL."<<std::endl;
|
||||
//infostream<<"No object selected; returning NULL."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2339,7 +2160,7 @@ void Client::clearTempMod(v3s16 p)
|
|||
|
||||
void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
||||
{
|
||||
/*dstream<<"Client::addUpdateMeshTask(): "
|
||||
/*infostream<<"Client::addUpdateMeshTask(): "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
|
@ -2366,7 +2187,7 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
|||
// Add task to queue
|
||||
m_mesh_update_thread.m_queue_in.addBlock(p, data, ack_to_server);
|
||||
|
||||
/*dstream<<"Mesh update input queue size is "
|
||||
/*infostream<<"Mesh update input queue size is "
|
||||
<<m_mesh_update_thread.m_queue_in.size()
|
||||
<<std::endl;*/
|
||||
|
||||
|
@ -2393,7 +2214,7 @@ void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server)
|
|||
{
|
||||
/*{
|
||||
v3s16 p = blockpos;
|
||||
dstream<<"Client::addUpdateMeshTaskWithEdge(): "
|
||||
infostream<<"Client::addUpdateMeshTaskWithEdge(): "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;
|
||||
}*/
|
||||
|
|
42
src/client.h
|
@ -113,7 +113,8 @@ enum ClientEventType
|
|||
{
|
||||
CE_NONE,
|
||||
CE_PLAYER_DAMAGE,
|
||||
CE_PLAYER_FORCE_MOVE
|
||||
CE_PLAYER_FORCE_MOVE,
|
||||
CE_DEATHSCREEN,
|
||||
};
|
||||
|
||||
struct ClientEvent
|
||||
|
@ -129,6 +130,12 @@ struct ClientEvent
|
|||
f32 pitch;
|
||||
f32 yaw;
|
||||
} player_force_move;
|
||||
struct{
|
||||
bool set_camera_point_target;
|
||||
f32 camera_point_target_x;
|
||||
f32 camera_point_target_y;
|
||||
f32 camera_point_target_z;
|
||||
} deathscreen;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -183,32 +190,31 @@ public:
|
|||
|
||||
void groundAction(u8 action, v3s16 nodepos_undersurface,
|
||||
v3s16 nodepos_oversurface, u16 item);
|
||||
void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item);
|
||||
void clickActiveObject(u8 button, u16 id, u16 item);
|
||||
void clickActiveObject(u8 button, u16 id, u16 item_i);
|
||||
|
||||
void sendSignText(v3s16 blockpos, s16 id, std::string text);
|
||||
void sendSignNodeText(v3s16 p, std::string text);
|
||||
void sendInventoryAction(InventoryAction *a);
|
||||
void sendChatMessage(const std::wstring &message);
|
||||
void sendChangePassword(const std::wstring oldpassword,
|
||||
const std::wstring newpassword);
|
||||
void sendDamage(u8 damage);
|
||||
void sendRespawn();
|
||||
|
||||
// locks envlock
|
||||
void removeNode(v3s16 p);
|
||||
// locks envlock
|
||||
void addNode(v3s16 p, MapNode n);
|
||||
|
||||
void updateCamera(v3f pos, v3f dir);
|
||||
void updateCamera(v3f pos, v3f dir, f32 fov);
|
||||
|
||||
void renderPostFx();
|
||||
|
||||
// Returns InvalidPositionException if not found
|
||||
MapNode getNode(v3s16 p);
|
||||
// Wrapper to Map
|
||||
NodeMetadata* getNodeMetadata(v3s16 p);
|
||||
|
||||
// Get the player position, and optionally put the
|
||||
// eye position in *eye_position
|
||||
v3f getPlayerPosition(v3f *eye_position=NULL);
|
||||
LocalPlayer* getLocalPlayer();
|
||||
|
||||
void setPlayerControl(PlayerControl &control);
|
||||
|
||||
|
@ -225,14 +231,6 @@ public:
|
|||
Inventory* getInventory(InventoryContext *c, std::string id);
|
||||
void inventoryAction(InventoryAction *a);
|
||||
|
||||
// Gets closest object pointed by the shootline
|
||||
// Returns NULL if not found
|
||||
MapBlockObject * getSelectedObject(
|
||||
f32 max_d,
|
||||
v3f from_pos_f_on_map,
|
||||
core::line3d<f32> shootline_on_map
|
||||
);
|
||||
|
||||
// Gets closest object pointed by the shootline
|
||||
// Returns NULL if not found
|
||||
ClientActiveObject * getSelectedActiveObject(
|
||||
|
@ -302,12 +300,9 @@ public:
|
|||
{
|
||||
return m_access_denied_reason;
|
||||
}
|
||||
|
||||
/*
|
||||
This should only be used for calling the special drawing stuff in
|
||||
ClientEnvironment
|
||||
*/
|
||||
ClientEnvironment * getEnv()
|
||||
|
||||
//j
|
||||
inline ClientEnvironment * getEnv()
|
||||
{
|
||||
return &m_env;
|
||||
}
|
||||
|
@ -342,9 +337,6 @@ private:
|
|||
|
||||
IrrlichtDevice *m_device;
|
||||
|
||||
v3f camera_position;
|
||||
v3f camera_direction;
|
||||
|
||||
// Server serialization version
|
||||
u8 m_server_ser_ver;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ ClientActiveObject* ClientActiveObject::create(u8 type)
|
|||
{
|
||||
// If factory is not found, just return.
|
||||
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
||||
<<type<<std::endl;
|
||||
<<(int)type<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
|
||||
virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;}
|
||||
virtual v3f getPosition(){return v3f(0,0,0);}
|
||||
virtual bool doShowSelectionBox(){return true;}
|
||||
|
||||
// Step object in time
|
||||
virtual void step(float dtime, ClientEnvironment *env){}
|
||||
|
@ -59,7 +60,7 @@ public:
|
|||
virtual void processMessage(const std::string &data){}
|
||||
|
||||
virtual std::string infoText() {return "";}
|
||||
|
||||
|
||||
/*
|
||||
This takes the return value of
|
||||
ServerActiveObject::getClientInitializationData
|
||||
|
@ -69,6 +70,10 @@ public:
|
|||
// Create a certain type of ClientActiveObject
|
||||
static ClientActiveObject* create(u8 type);
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
virtual bool directReportPunch(const std::string &toolname, v3f dir)
|
||||
{ return false; }
|
||||
|
||||
protected:
|
||||
// Used for creating objects based on type
|
||||
typedef ClientActiveObject* (*Factory)();
|
||||
|
|
|
@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#include "utility.h"
|
||||
|
||||
#define PROTOCOL_VERSION 3
|
||||
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
|
||||
|
@ -172,9 +174,16 @@ enum ToClientCommand
|
|||
string serialized item
|
||||
}
|
||||
*/
|
||||
|
||||
TOCLIENT_DEATHSCREEN = 0x37,
|
||||
/*
|
||||
u16 command
|
||||
u8 bool set camera point target
|
||||
v3f1000 camera point target (to point the death cause or whatever)
|
||||
*/
|
||||
|
||||
|
||||
TOCLIENT_PLAYER_CLAN = 0x37,
|
||||
TOCLIENT_PLAYER_CLAN = 0x38,
|
||||
/*
|
||||
u16 command
|
||||
u16 count
|
||||
|
@ -184,7 +193,7 @@ enum ToClientCommand
|
|||
...
|
||||
*/
|
||||
|
||||
TOCLIENT_CLAN_NAMES = 0x38,
|
||||
TOCLIENT_CLAN_NAMES = 0x39,
|
||||
/*
|
||||
u16 command
|
||||
u16 count
|
||||
|
@ -195,7 +204,7 @@ enum ToClientCommand
|
|||
...
|
||||
*/
|
||||
|
||||
TOCLIENT_CLAN_DELETED = 0x39,
|
||||
TOCLIENT_CLAN_DELETED = 0x3A,
|
||||
/*
|
||||
u16 command
|
||||
u16 clan id
|
||||
|
@ -349,7 +358,11 @@ enum ToServerCommand
|
|||
[0] u16 TOSERVER_PLAYERITEM
|
||||
[2] u16 item
|
||||
*/
|
||||
|
||||
|
||||
TOSERVER_RESPAWN=0x38,
|
||||
/*
|
||||
u16 TOSERVER_RESPAWN
|
||||
*/
|
||||
};
|
||||
|
||||
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
|
||||
|
|
|
@ -23,7 +23,26 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\
|
||||
video::SColor(255,30,30,30));d->endScene();}
|
||||
|
||||
#include <irrlicht.h>
|
||||
#include <irrTypes.h>
|
||||
#include <vector2d.h>
|
||||
#include <vector3d.h>
|
||||
#include <irrMap.h>
|
||||
#include <irrList.h>
|
||||
#include <irrArray.h>
|
||||
#include <aabbox3d.h>
|
||||
#ifndef SERVER
|
||||
#include <SColor.h>
|
||||
#include <IMesh.h>
|
||||
#include <IImage.h>
|
||||
#include <IrrlichtDevice.h>
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <SMesh.h>
|
||||
#include <ISceneManager.h>
|
||||
#include <IMeshBuffer.h>
|
||||
#include <SMeshBuffer.h>
|
||||
#include <IGUIElement.h>
|
||||
#include <IGUIEnvironment.h>
|
||||
#endif
|
||||
using namespace irr;
|
||||
typedef core::vector3df v3f;
|
||||
typedef core::vector3d<s16> v3s16;
|
||||
|
|
|
@ -44,9 +44,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#define PI 3.14159
|
||||
|
||||
// This is the same as in minecraft and everything else
|
||||
#define FOV_ANGLE (PI/2.5)
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's
|
||||
// going near the limit or not, so this is lower.
|
||||
|
|
|
@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_cao.h"
|
||||
#include "tile.h"
|
||||
#include "environment.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
|
||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||
|
||||
|
@ -114,7 +116,7 @@ void TestCAO::step(float dtime, ClientEnvironment *env)
|
|||
if(m_node)
|
||||
{
|
||||
v3f rot = m_node->getRotation();
|
||||
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||
//infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||
rot.Y += dtime * 180;
|
||||
m_node->setRotation(rot);
|
||||
}
|
||||
|
@ -122,7 +124,7 @@ void TestCAO::step(float dtime, ClientEnvironment *env)
|
|||
|
||||
void TestCAO::processMessage(const std::string &data)
|
||||
{
|
||||
dstream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||
infostream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
u16 cmd;
|
||||
is>>cmd;
|
||||
|
@ -224,22 +226,7 @@ void ItemCAO::updateLight(u8 light_at_pos)
|
|||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 ItemCAO::getLightPosition()
|
||||
|
@ -272,7 +259,7 @@ void ItemCAO::step(float dtime, ClientEnvironment *env)
|
|||
|
||||
void ItemCAO::processMessage(const std::string &data)
|
||||
{
|
||||
dstream<<"ItemCAO: Got message"<<std::endl;
|
||||
infostream<<"ItemCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
|
@ -286,7 +273,7 @@ void ItemCAO::processMessage(const std::string &data)
|
|||
|
||||
void ItemCAO::initialize(const std::string &data)
|
||||
{
|
||||
dstream<<"ItemCAO: Got init data"<<std::endl;
|
||||
infostream<<"ItemCAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
|
@ -326,7 +313,7 @@ void ItemCAO::initialize(const std::string &data)
|
|||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(is);
|
||||
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
if(item)
|
||||
|
@ -337,7 +324,7 @@ void ItemCAO::initialize(const std::string &data)
|
|||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<"WARNING: "<<__FUNCTION_NAME
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": error deSerializing inventorystring \""
|
||||
<<m_inventorystring<<"\""<<std::endl;
|
||||
}
|
||||
|
@ -430,22 +417,7 @@ void RatCAO::updateLight(u8 light_at_pos)
|
|||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 RatCAO::getLightPosition()
|
||||
|
@ -474,7 +446,7 @@ void RatCAO::step(float dtime, ClientEnvironment *env)
|
|||
|
||||
void RatCAO::processMessage(const std::string &data)
|
||||
{
|
||||
//dstream<<"RatCAO: Got message"<<std::endl;
|
||||
//infostream<<"RatCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
|
@ -491,7 +463,7 @@ void RatCAO::processMessage(const std::string &data)
|
|||
|
||||
void RatCAO::initialize(const std::string &data)
|
||||
{
|
||||
//dstream<<"RatCAO: Got init data"<<std::endl;
|
||||
//infostream<<"RatCAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
|
@ -601,22 +573,7 @@ void Oerkki1CAO::updateLight(u8 light_at_pos)
|
|||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 Oerkki1CAO::getLightPosition()
|
||||
|
@ -649,7 +606,7 @@ void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
|||
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||
|
||||
if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
|
||||
if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
|
||||
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
|
||||
{
|
||||
if(m_attack_interval.step(dtime, 0.5))
|
||||
|
@ -713,7 +670,7 @@ void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
|||
|
||||
void Oerkki1CAO::processMessage(const std::string &data)
|
||||
{
|
||||
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||
//infostream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
|
@ -728,14 +685,14 @@ void Oerkki1CAO::processMessage(const std::string &data)
|
|||
}
|
||||
else if(cmd == 1)
|
||||
{
|
||||
u16 damage = readU8(is);
|
||||
//u16 damage = readU8(is);
|
||||
m_damage_visual_timer = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
void Oerkki1CAO::initialize(const std::string &data)
|
||||
{
|
||||
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||
//infostream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
|
@ -752,6 +709,18 @@ void Oerkki1CAO::initialize(const std::string &data)
|
|||
updateNodePos();
|
||||
}
|
||||
|
||||
bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
|
||||
{
|
||||
m_damage_visual_timer = 1.0;
|
||||
|
||||
m_position += dir * BS;
|
||||
pos_translator.sharpen();
|
||||
pos_translator.update(m_position);
|
||||
updateNodePos();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
FireflyCAO
|
||||
*/
|
||||
|
@ -833,22 +802,7 @@ void FireflyCAO::updateLight(u8 light_at_pos)
|
|||
|
||||
u8 li = 255;
|
||||
video::SColor color(255,li,li,li);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 FireflyCAO::getLightPosition()
|
||||
|
@ -877,7 +831,7 @@ void FireflyCAO::step(float dtime, ClientEnvironment *env)
|
|||
|
||||
void FireflyCAO::processMessage(const std::string &data)
|
||||
{
|
||||
//dstream<<"FireflyCAO: Got message"<<std::endl;
|
||||
//infostream<<"FireflyCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
|
@ -894,7 +848,7 @@ void FireflyCAO::processMessage(const std::string &data)
|
|||
|
||||
void FireflyCAO::initialize(const std::string &data)
|
||||
{
|
||||
//dstream<<"FireflyCAO: Got init data"<<std::endl;
|
||||
//infostream<<"FireflyCAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
|
@ -910,3 +864,413 @@ void FireflyCAO::initialize(const std::string &data)
|
|||
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
/*
|
||||
MobV2CAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
MobV2CAO proto_MobV2CAO;
|
||||
|
||||
MobV2CAO::MobV2CAO():
|
||||
ClientActiveObject(0),
|
||||
m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
m_yaw(0),
|
||||
m_walking(false),
|
||||
m_walking_unset_timer(0),
|
||||
m_walk_timer(0),
|
||||
m_walk_frame(0),
|
||||
m_damage_visual_timer(0),
|
||||
m_last_light(0),
|
||||
m_shooting(0),
|
||||
m_shooting_unset_timer(0),
|
||||
m_sprite_size(BS,BS),
|
||||
m_sprite_y(0),
|
||||
m_bright_shooting(false),
|
||||
m_lock_full_brightness(false),
|
||||
m_player_hit_timer(0)
|
||||
{
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
|
||||
m_properties = new Settings;
|
||||
}
|
||||
|
||||
MobV2CAO::~MobV2CAO()
|
||||
{
|
||||
delete m_properties;
|
||||
}
|
||||
|
||||
ClientActiveObject* MobV2CAO::create()
|
||||
{
|
||||
return new MobV2CAO();
|
||||
}
|
||||
|
||||
void MobV2CAO::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
/*infostream<<"MobV2CAO::addToScene using texture_name="<<
|
||||
m_texture_name<<std::endl;*/
|
||||
std::string texture_string = "[makealpha2:128,0,0;128,128,0:";
|
||||
texture_string += m_texture_name;
|
||||
|
||||
scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
|
||||
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
||||
bill->setMaterialTexture(0, g_texturesource->getTextureRaw(texture_string));
|
||||
bill->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||
bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||
bill->setColor(video::SColor(255,0,0,0));
|
||||
bill->setVisible(false); /* Set visible when brightness is known */
|
||||
bill->setSize(m_sprite_size);
|
||||
if(m_sprite_type == "humanoid_1"){
|
||||
const float txp = 1./192;
|
||||
const float txs = txp*32;
|
||||
const float typ = 1./240;
|
||||
const float tys = typ*48;
|
||||
bill->setTCoords(0, v2f(txs*1, tys*1));
|
||||
bill->setTCoords(1, v2f(txs*1, tys*0));
|
||||
bill->setTCoords(2, v2f(txs*0, tys*0));
|
||||
bill->setTCoords(3, v2f(txs*0, tys*1));
|
||||
} else if(m_sprite_type == "simple"){
|
||||
const float txs = 1.0;
|
||||
const float tys = 1.0 / m_simple_anim_frames;
|
||||
bill->setTCoords(0, v2f(txs*1, tys*1));
|
||||
bill->setTCoords(1, v2f(txs*1, tys*0));
|
||||
bill->setTCoords(2, v2f(txs*0, tys*0));
|
||||
bill->setTCoords(3, v2f(txs*0, tys*1));
|
||||
} else {
|
||||
infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
m_node = bill;
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
void MobV2CAO::removeFromScene()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->drop();
|
||||
m_node->remove();
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
void MobV2CAO::updateLight(u8 light_at_pos)
|
||||
{
|
||||
if(m_lock_full_brightness)
|
||||
light_at_pos = 15;
|
||||
|
||||
m_last_light = light_at_pos;
|
||||
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
if(m_damage_visual_timer > 0)
|
||||
return;
|
||||
|
||||
if(m_shooting && m_bright_shooting)
|
||||
return;
|
||||
|
||||
/*if(light_at_pos <= 2){
|
||||
m_node->setVisible(false);
|
||||
return;
|
||||
}*/
|
||||
|
||||
m_node->setVisible(true);
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
m_node->setColor(color);
|
||||
}
|
||||
|
||||
v3s16 MobV2CAO::getLightPosition()
|
||||
{
|
||||
return floatToInt(m_position+v3f(0,0,0), BS);
|
||||
}
|
||||
|
||||
void MobV2CAO::updateNodePos()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
|
||||
}
|
||||
|
||||
void MobV2CAO::step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
scene::MyBillboardSceneNode *bill = m_node;
|
||||
|
||||
pos_translator.translate(dtime);
|
||||
|
||||
if(m_sprite_type == "humanoid_1"){
|
||||
scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
|
||||
v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
|
||||
cam_to_mob.normalize();
|
||||
int col = 0;
|
||||
if(cam_to_mob.Y > 0.75)
|
||||
col = 5;
|
||||
else if(cam_to_mob.Y < -0.75)
|
||||
col = 4;
|
||||
else{
|
||||
float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
|
||||
float dir = mob_dir - m_yaw;
|
||||
dir = wrapDegrees_180(dir);
|
||||
//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||
if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
|
||||
col = 2;
|
||||
else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
|
||||
col = 3;
|
||||
else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
|
||||
col = 0;
|
||||
else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
|
||||
col = 1;
|
||||
else
|
||||
col = 4;
|
||||
}
|
||||
|
||||
int row = 0;
|
||||
if(m_shooting){
|
||||
row = 3;
|
||||
} else if(m_walking){
|
||||
m_walk_timer += dtime;
|
||||
if(m_walk_timer >= 0.5){
|
||||
m_walk_frame = (m_walk_frame + 1) % 2;
|
||||
m_walk_timer = 0;
|
||||
}
|
||||
if(m_walk_frame == 0)
|
||||
row = 1;
|
||||
else
|
||||
row = 2;
|
||||
}
|
||||
|
||||
const float txp = 1./192;
|
||||
const float txs = txp*32;
|
||||
const float typ = 1./240;
|
||||
const float tys = typ*48;
|
||||
bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||
bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||
bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||
bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||
} else if(m_sprite_type == "simple"){
|
||||
m_walk_timer += dtime;
|
||||
if(m_walk_timer >= m_simple_anim_frametime){
|
||||
m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
|
||||
m_walk_timer = 0;
|
||||
}
|
||||
int col = 0;
|
||||
int row = m_walk_frame;
|
||||
const float txs = 1.0;
|
||||
const float tys = 1.0 / m_simple_anim_frames;
|
||||
bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||
bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||
bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||
bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||
} else {
|
||||
infostream<<"MobV2CAO::step(): Unknown sprite type \""
|
||||
<<m_sprite_type<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
updateNodePos();
|
||||
|
||||
/* Damage local player */
|
||||
if(m_player_hit_damage && m_player_hit_timer <= 0.0){
|
||||
LocalPlayer *player = env->getLocalPlayer();
|
||||
assert(player);
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||
|
||||
if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
|
||||
objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
|
||||
{
|
||||
env->damageLocalPlayer(m_player_hit_damage);
|
||||
m_player_hit_timer = m_player_hit_interval;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run timers */
|
||||
|
||||
m_player_hit_timer -= dtime;
|
||||
|
||||
if(m_damage_visual_timer >= 0){
|
||||
m_damage_visual_timer -= dtime;
|
||||
if(m_damage_visual_timer <= 0){
|
||||
infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_walking_unset_timer += dtime;
|
||||
if(m_walking_unset_timer >= 1.0){
|
||||
m_walking = false;
|
||||
}
|
||||
|
||||
m_shooting_unset_timer -= dtime;
|
||||
if(m_shooting_unset_timer <= 0.0){
|
||||
if(m_bright_shooting){
|
||||
u8 li = decode_light(m_last_light);
|
||||
video::SColor color(255,li,li,li);
|
||||
bill->setColor(color);
|
||||
m_bright_shooting = false;
|
||||
}
|
||||
m_shooting = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MobV2CAO::processMessage(const std::string &data)
|
||||
{
|
||||
//infostream<<"MobV2CAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
|
||||
// Move
|
||||
if(cmd == 0)
|
||||
{
|
||||
// pos
|
||||
m_position = readV3F1000(is);
|
||||
pos_translator.update(m_position);
|
||||
// yaw
|
||||
m_yaw = readF1000(is);
|
||||
|
||||
m_walking = true;
|
||||
m_walking_unset_timer = 0;
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
// Damage
|
||||
else if(cmd == 1)
|
||||
{
|
||||
//u16 damage = readU16(is);
|
||||
|
||||
/*u8 li = decode_light(m_last_light);
|
||||
if(li >= 100)
|
||||
li = 30;
|
||||
else
|
||||
li = 255;*/
|
||||
|
||||
/*video::SColor color(255,255,0,0);
|
||||
m_node->setColor(color);
|
||||
|
||||
m_damage_visual_timer = 0.2;*/
|
||||
}
|
||||
// Trigger shooting
|
||||
else if(cmd == 2)
|
||||
{
|
||||
// length
|
||||
m_shooting_unset_timer = readF1000(is);
|
||||
// bright?
|
||||
m_bright_shooting = readU8(is);
|
||||
if(m_bright_shooting){
|
||||
u8 li = 255;
|
||||
video::SColor color(255,li,li,li);
|
||||
m_node->setColor(color);
|
||||
}
|
||||
|
||||
m_shooting = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MobV2CAO::initialize(const std::string &data)
|
||||
{
|
||||
//infostream<<"MobV2CAO: Got init data"<<std::endl;
|
||||
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// version
|
||||
u8 version = readU8(is);
|
||||
// check version
|
||||
if(version != 0){
|
||||
infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
decompressZlib(is, tmp_os);
|
||||
std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
|
||||
m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
|
||||
|
||||
infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
|
||||
m_properties->writeLines(infostream);
|
||||
|
||||
m_properties->setDefault("looks", "dummy_default");
|
||||
m_properties->setDefault("yaw", "0");
|
||||
m_properties->setDefault("pos", "(0,0,0)");
|
||||
m_properties->setDefault("player_hit_damage", "0");
|
||||
m_properties->setDefault("player_hit_distance", "1.5");
|
||||
m_properties->setDefault("player_hit_interval", "1.5");
|
||||
|
||||
setLooks(m_properties->get("looks"));
|
||||
m_yaw = m_properties->getFloat("yaw");
|
||||
m_position = m_properties->getV3F("pos");
|
||||
m_player_hit_damage = m_properties->getS32("player_hit_damage");
|
||||
m_player_hit_distance = m_properties->getFloat("player_hit_distance");
|
||||
m_player_hit_interval = m_properties->getFloat("player_hit_interval");
|
||||
|
||||
pos_translator.init(m_position);
|
||||
}
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
|
||||
{
|
||||
video::SColor color(255,255,0,0);
|
||||
m_node->setColor(color);
|
||||
|
||||
m_damage_visual_timer = 0.05;
|
||||
|
||||
m_position += dir * BS;
|
||||
pos_translator.sharpen();
|
||||
pos_translator.update(m_position);
|
||||
updateNodePos();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MobV2CAO::setLooks(const std::string &looks)
|
||||
{
|
||||
v2f selection_size = v2f(0.4, 0.4) * BS;
|
||||
float selection_y = 0 * BS;
|
||||
|
||||
if(looks == "dungeon_master"){
|
||||
m_texture_name = "dungeon_master.png";
|
||||
m_sprite_type = "humanoid_1";
|
||||
m_sprite_size = v2f(2, 3) * BS;
|
||||
m_sprite_y = 0.85 * BS;
|
||||
selection_size = v2f(0.4, 2.6) * BS;
|
||||
selection_y = -0.4 * BS;
|
||||
}
|
||||
else if(looks == "fireball"){
|
||||
m_texture_name = "fireball.png";
|
||||
m_sprite_type = "simple";
|
||||
m_sprite_size = v2f(1, 1) * BS;
|
||||
m_simple_anim_frames = 3;
|
||||
m_simple_anim_frametime = 0.1;
|
||||
m_lock_full_brightness = true;
|
||||
}
|
||||
else{
|
||||
m_texture_name = "stone.png";
|
||||
m_sprite_type = "simple";
|
||||
m_sprite_size = v2f(1, 1) * BS;
|
||||
m_simple_anim_frames = 3;
|
||||
m_simple_anim_frametime = 0.333;
|
||||
selection_size = v2f(0.4, 0.4) * BS;
|
||||
selection_y = 0 * BS;
|
||||
}
|
||||
|
||||
m_selection_box = core::aabbox3d<f32>(
|
||||
-selection_size.X, selection_y, -selection_size.X,
|
||||
selection_size.X, selection_y+selection_size.Y,
|
||||
selection_size.X);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "clientobject.h"
|
||||
#include "content_object.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
class Settings;
|
||||
#include "MyBillboardSceneNode.h"
|
||||
|
||||
/*
|
||||
SmoothTranslator
|
||||
|
@ -31,19 +33,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
struct SmoothTranslator
|
||||
{
|
||||
v3f vect_old;
|
||||
v3f vect_show;
|
||||
v3f vect_aim;
|
||||
f32 anim_counter;
|
||||
f32 anim_time;
|
||||
f32 anim_time_counter;
|
||||
v3f vect_show;
|
||||
v3f vect_aim;
|
||||
|
||||
SmoothTranslator():
|
||||
vect_old(0,0,0),
|
||||
vect_show(0,0,0),
|
||||
vect_aim(0,0,0),
|
||||
anim_counter(0),
|
||||
anim_time(0),
|
||||
anim_time_counter(0),
|
||||
vect_show(0,0,0),
|
||||
vect_aim(0,0,0)
|
||||
anim_time_counter(0)
|
||||
{}
|
||||
|
||||
void init(v3f vect)
|
||||
|
@ -51,6 +53,14 @@ struct SmoothTranslator
|
|||
vect_old = vect;
|
||||
vect_show = vect;
|
||||
vect_aim = vect;
|
||||
anim_counter = 0;
|
||||
anim_time = 0;
|
||||
anim_time_counter = 0;
|
||||
}
|
||||
|
||||
void sharpen()
|
||||
{
|
||||
init(vect_show);
|
||||
}
|
||||
|
||||
void update(v3f vect_new)
|
||||
|
@ -74,11 +84,16 @@ struct SmoothTranslator
|
|||
if(anim_time > 0.001)
|
||||
moveratio = anim_time_counter / anim_time;
|
||||
// Move a bit less than should, to avoid oscillation
|
||||
moveratio = moveratio * 0.8;
|
||||
moveratio = moveratio * 0.5;
|
||||
if(moveratio > 1.5)
|
||||
moveratio = 1.5;
|
||||
vect_show = vect_old + vect_move * moveratio;
|
||||
}
|
||||
|
||||
bool is_moving()
|
||||
{
|
||||
return ((anim_time_counter / anim_time) < 1.4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -233,6 +248,9 @@ public:
|
|||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
|
@ -286,6 +304,78 @@ private:
|
|||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
MobV2CAO
|
||||
*/
|
||||
|
||||
class MobV2CAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
MobV2CAO();
|
||||
virtual ~MobV2CAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_MOBV2;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create();
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
bool doShowSelectionBox(){return false;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
void setLooks(const std::string &looks);
|
||||
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::MyBillboardSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_texture_name;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
bool m_walking;
|
||||
float m_walking_unset_timer;
|
||||
float m_walk_timer;
|
||||
int m_walk_frame;
|
||||
float m_damage_visual_timer;
|
||||
u8 m_last_light;
|
||||
bool m_shooting;
|
||||
float m_shooting_unset_timer;
|
||||
v2f m_sprite_size;
|
||||
float m_sprite_y;
|
||||
bool m_bright_shooting;
|
||||
std::string m_sprite_type;
|
||||
int m_simple_anim_frames;
|
||||
float m_simple_anim_frametime;
|
||||
bool m_lock_full_brightness;
|
||||
int m_player_hit_damage;
|
||||
float m_player_hit_distance;
|
||||
float m_player_hit_interval;
|
||||
float m_player_hit_timer;
|
||||
|
||||
Settings *m_properties;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -297,6 +297,24 @@ InventoryItem *craft_get_result(InventoryItem **items)
|
|||
}
|
||||
}
|
||||
|
||||
// Locking Chest
|
||||
{
|
||||
ItemSpec specs[9];
|
||||
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot");
|
||||
specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
if(checkItemCombination(items, specs))
|
||||
{
|
||||
return new MaterialItem(CONTENT_LOCKABLE_CHEST, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Furnace
|
||||
{
|
||||
ItemSpec specs[9];
|
||||
|
|
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "main.h" // For g_settings and g_texturesource
|
||||
#include "mineral.h"
|
||||
#include "mapblock_mesh.h" // For MapBlock_LightColor()
|
||||
#include "settings.h"
|
||||
|
||||
#ifndef SERVER
|
||||
// Create a cuboid.
|
||||
|
@ -128,10 +129,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
/*
|
||||
Some settings
|
||||
*/
|
||||
bool new_style_water = g_settings.getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||
//bool smooth_lighting = g_settings.getBool("smooth_lighting");
|
||||
bool invisible_stone = g_settings.getBool("invisible_stone");
|
||||
bool new_style_water = g_settings->getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings->getBool("new_style_leaves");
|
||||
//bool smooth_lighting = g_settings->getBool("smooth_lighting");
|
||||
bool invisible_stone = g_settings->getBool("invisible_stone");
|
||||
|
||||
float node_liquid_level = 1.0;
|
||||
if(new_style_water)
|
||||
|
@ -199,6 +200,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
g_texturesource->getTextureId("apple.png"));
|
||||
material_apple.setTexture(0, pa_apple.atlas);
|
||||
|
||||
|
||||
// Sapling material
|
||||
video::SMaterial material_sapling;
|
||||
material_sapling.setFlag(video::EMF_LIGHTING, false);
|
||||
material_sapling.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_sapling.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_sapling.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
AtlasPointer pa_sapling = g_texturesource->getTexture(
|
||||
g_texturesource->getTextureId("sapling.png"));
|
||||
material_sapling.setTexture(0, pa_sapling.atlas);
|
||||
|
||||
|
||||
// junglegrass material
|
||||
video::SMaterial material_junglegrass;
|
||||
material_junglegrass.setFlag(video::EMF_LIGHTING, false);
|
||||
|
@ -1318,6 +1331,55 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
collector.append(material_apple, vertices, 4, indices, 6);
|
||||
}
|
||||
}
|
||||
else if(n.getContent() == CONTENT_SAPLING) {
|
||||
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
for(u32 j=0; j<4; j++)
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
|
||||
pa_sapling.x0(), pa_sapling.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
|
||||
pa_sapling.x1(), pa_sapling.y1()),
|
||||
video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
|
||||
pa_sapling.x1(), pa_sapling.y0()),
|
||||
video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
|
||||
pa_sapling.x0(), pa_sapling.y0()),
|
||||
};
|
||||
|
||||
if(j == 0)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(45);
|
||||
}
|
||||
else if(j == 1)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(-45);
|
||||
}
|
||||
else if(j == 2)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(135);
|
||||
}
|
||||
else if(j == 3)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(-135);
|
||||
}
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material_sapling, vertices, 4, indices, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_mapnode.h"
|
||||
#include "mapnode.h"
|
||||
#include "content_nodemeta.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define WATER_ALPHA 160
|
||||
|
||||
|
@ -103,9 +104,9 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
|
|||
void content_mapnode_init()
|
||||
{
|
||||
// Read some settings
|
||||
bool new_style_water = g_settings.getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||
bool invisible_stone = g_settings.getBool("invisible_stone");
|
||||
bool new_style_water = g_settings->getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings->getBool("new_style_leaves");
|
||||
bool invisible_stone = g_settings->getBool("invisible_stone");
|
||||
|
||||
content_t i;
|
||||
ContentFeatures *f = NULL;
|
||||
|
@ -236,12 +237,16 @@ void content_mapnode_init()
|
|||
if(new_style_leaves)
|
||||
{
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->visual_solidness = 1;
|
||||
f->setAllTextures("leaves.png");
|
||||
f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
f->setAllTextures("[noalpha:leaves.png");
|
||||
}
|
||||
f->extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
|
||||
f->extra_dug_item_rarity = 20;
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
|
||||
|
||||
|
@ -287,6 +292,8 @@ void content_mapnode_init()
|
|||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->visual_solidness = 1;
|
||||
f->setAllTextures("glass.png");
|
||||
f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
|
||||
|
||||
|
@ -384,7 +391,9 @@ void content_mapnode_init()
|
|||
f->liquid_alternative_flowing = CONTENT_WATER;
|
||||
f->liquid_alternative_source = CONTENT_WATERSOURCE;
|
||||
f->liquid_viscosity = WATER_VISC;
|
||||
#ifndef SERVER
|
||||
f->vertex_alpha = WATER_ALPHA;
|
||||
f->post_effect_color = video::SColor(64, 100, 100, 200);
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// Flowing water material
|
||||
|
@ -399,6 +408,7 @@ void content_mapnode_init()
|
|||
f->special_material->setTexture(0, pa_water1->atlas);
|
||||
f->special_atlas = pa_water1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_WATERSOURCE;
|
||||
f = &content_features(i);
|
||||
|
@ -411,7 +421,7 @@ void content_mapnode_init()
|
|||
else // old style
|
||||
{
|
||||
f->solidness = 1;
|
||||
|
||||
#ifndef SERVER
|
||||
TileSpec t;
|
||||
if(g_texturesource)
|
||||
t.texture = g_texturesource->getTexture("water.png");
|
||||
|
@ -420,6 +430,7 @@ void content_mapnode_init()
|
|||
t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
f->setAllTiles(t);
|
||||
#endif
|
||||
}
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
|
@ -432,7 +443,9 @@ void content_mapnode_init()
|
|||
f->liquid_alternative_flowing = CONTENT_WATER;
|
||||
f->liquid_alternative_source = CONTENT_WATERSOURCE;
|
||||
f->liquid_viscosity = WATER_VISC;
|
||||
#ifndef SERVER
|
||||
f->vertex_alpha = WATER_ALPHA;
|
||||
f->post_effect_color = video::SColor(64, 100, 100, 200);
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// Flowing water material
|
||||
|
@ -447,6 +460,7 @@ void content_mapnode_init()
|
|||
f->special_material->setTexture(0, pa_water1->atlas);
|
||||
f->special_atlas = pa_water1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_LAVA;
|
||||
f = &content_features(i);
|
||||
|
@ -465,6 +479,8 @@ void content_mapnode_init()
|
|||
f->liquid_alternative_source = CONTENT_LAVASOURCE;
|
||||
f->liquid_viscosity = LAVA_VISC;
|
||||
f->damage_per_second = 4*2;
|
||||
#ifndef SERVER
|
||||
f->post_effect_color = video::SColor(192, 255, 64, 0);
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// Flowing lava material
|
||||
|
@ -480,6 +496,7 @@ void content_mapnode_init()
|
|||
f->special_material->setTexture(0, pa_lava1->atlas);
|
||||
f->special_atlas = pa_lava1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_LAVASOURCE;
|
||||
f = &content_features(i);
|
||||
|
@ -491,7 +508,7 @@ void content_mapnode_init()
|
|||
else // old style
|
||||
{
|
||||
f->solidness = 2;
|
||||
|
||||
#ifndef SERVER
|
||||
TileSpec t;
|
||||
if(g_texturesource)
|
||||
t.texture = g_texturesource->getTexture("lava.png");
|
||||
|
@ -500,6 +517,7 @@ void content_mapnode_init()
|
|||
//t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||
//t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
f->setAllTiles(t);
|
||||
#endif
|
||||
}
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = false;
|
||||
|
@ -514,6 +532,8 @@ void content_mapnode_init()
|
|||
f->liquid_alternative_source = CONTENT_LAVASOURCE;
|
||||
f->liquid_viscosity = LAVA_VISC;
|
||||
f->damage_per_second = 4*2;
|
||||
#ifndef SERVER
|
||||
f->post_effect_color = video::SColor(192, 255, 64, 0);
|
||||
if(f->special_material == NULL && g_texturesource)
|
||||
{
|
||||
// Flowing lava material
|
||||
|
@ -529,6 +549,7 @@ void content_mapnode_init()
|
|||
f->special_material->setTexture(0, pa_lava1->atlas);
|
||||
f->special_atlas = pa_lava1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = CONTENT_TORCH;
|
||||
f = &content_features(i);
|
||||
|
@ -573,6 +594,20 @@ void content_mapnode_init()
|
|||
f->initial_metadata = new ChestNodeMetadata();
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
|
||||
i = CONTENT_LOCKABLE_CHEST;
|
||||
f = &content_features(i);
|
||||
f->param_type = CPT_FACEDIR_SIMPLE;
|
||||
f->setAllTextures("chest_side.png");
|
||||
f->setTexture(0, "chest_top.png");
|
||||
f->setTexture(1, "chest_top.png");
|
||||
f->setTexture(5, "chest_lock.png"); // Z-
|
||||
f->setInventoryTexture("chest_lock.png");
|
||||
//f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
if(f->initial_metadata == NULL)
|
||||
f->initial_metadata = new LockingChestNodeMetadata();
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
|
||||
i = CONTENT_FURNACE;
|
||||
f = &content_features(i);
|
||||
f->param_type = CPT_FACEDIR_SIMPLE;
|
||||
|
@ -630,6 +665,18 @@ void content_mapnode_init()
|
|||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 3.0);
|
||||
|
||||
i = CONTENT_SAPLING;
|
||||
f = &content_features(i);
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->setAllTextures("sapling.png");
|
||||
f->setInventoryTexture("sapling.png");
|
||||
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f->light_propagates = true;
|
||||
f->air_equivalent = false;
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
f->walkable = false;
|
||||
f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
|
||||
|
||||
i = CONTENT_BORDERSTONE;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("borderstone.png");
|
||||
|
|
|
@ -48,6 +48,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
|
|||
#define CONTENT_SIGN_WALL 14
|
||||
#define CONTENT_CHEST 15
|
||||
#define CONTENT_FURNACE 16
|
||||
#define CONTENT_LOCKABLE_CHEST 17
|
||||
|
||||
#define CONTENT_FENCE 21
|
||||
|
||||
|
@ -87,7 +88,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
|
|||
#define CONTENT_NC_RB 0x818
|
||||
#define CONTENT_APPLE 0x819
|
||||
#define CONTENT_BORDERSTONE 0x81a
|
||||
|
||||
#define CONTENT_SAPLING 0x820
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_nodemeta.h"
|
||||
#include "inventory.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
SignNodeMetadata
|
||||
|
@ -117,6 +118,70 @@ std::string ChestNodeMetadata::getInventoryDrawSpecString()
|
|||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
|
||||
/*
|
||||
LockingChestNodeMetadata
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
LockingChestNodeMetadata proto_LockingChestNodeMetadata;
|
||||
|
||||
LockingChestNodeMetadata::LockingChestNodeMetadata()
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), create);
|
||||
|
||||
m_inventory = new Inventory();
|
||||
m_inventory->addList("0", 8*4);
|
||||
}
|
||||
LockingChestNodeMetadata::~LockingChestNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
u16 LockingChestNodeMetadata::typeId() const
|
||||
{
|
||||
return CONTENT_LOCKABLE_CHEST;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::create(std::istream &is)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata();
|
||||
d->setOwner(deSerializeString(is));
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::clone()
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata();
|
||||
*d->m_inventory = *m_inventory;
|
||||
return d;
|
||||
}
|
||||
void LockingChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
os<<serializeString(m_text);
|
||||
m_inventory->serialize(os);
|
||||
}
|
||||
std::string LockingChestNodeMetadata::infoText()
|
||||
{
|
||||
return "Locking Chest";
|
||||
}
|
||||
bool LockingChestNodeMetadata::nodeRemovalDisabled()
|
||||
{
|
||||
/*
|
||||
Disable removal if chest contains something
|
||||
*/
|
||||
InventoryList *list = m_inventory->getList("0");
|
||||
if(list == NULL)
|
||||
return false;
|
||||
if(list->getUsedSlots() == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
|
||||
{
|
||||
return
|
||||
"invsize[8,9;]"
|
||||
"list[current_name;0;0,0;8,4;]"
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
|
||||
/*
|
||||
FurnaceNodeMetadata
|
||||
*/
|
||||
|
@ -223,12 +288,12 @@ bool FurnaceNodeMetadata::nodeRemovalDisabled()
|
|||
}
|
||||
void FurnaceNodeMetadata::inventoryModified()
|
||||
{
|
||||
dstream<<"Furnace inventory modification callback"<<std::endl;
|
||||
infostream<<"Furnace inventory modification callback"<<std::endl;
|
||||
}
|
||||
bool FurnaceNodeMetadata::step(float dtime)
|
||||
{
|
||||
if(dtime > 60.0)
|
||||
dstream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
|
||||
infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
|
||||
// Update at a fixed frequency
|
||||
const float interval = 2.0;
|
||||
m_step_accumulator += dtime;
|
||||
|
@ -238,7 +303,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
|||
m_step_accumulator -= interval;
|
||||
dtime = interval;
|
||||
|
||||
//dstream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||
//infostream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||
|
||||
InventoryList *dst_list = m_inventory->getList("dst");
|
||||
assert(dst_list);
|
||||
|
@ -270,7 +335,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
|||
*/
|
||||
if(m_fuel_time < m_fuel_totaltime)
|
||||
{
|
||||
//dstream<<"Furnace is active"<<std::endl;
|
||||
//infostream<<"Furnace is active"<<std::endl;
|
||||
m_fuel_time += dtime;
|
||||
m_src_time += dtime;
|
||||
if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
|
||||
|
@ -305,7 +370,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
|||
break;
|
||||
}
|
||||
|
||||
//dstream<<"Furnace is out of fuel"<<std::endl;
|
||||
//infostream<<"Furnace is out of fuel"<<std::endl;
|
||||
|
||||
InventoryList *fuel_list = m_inventory->getList("fuel");
|
||||
assert(fuel_list);
|
||||
|
@ -390,7 +455,7 @@ bool FurnaceNodeMetadata::step(float dtime)
|
|||
}
|
||||
else
|
||||
{
|
||||
//dstream<<"No fuel found"<<std::endl;
|
||||
//infostream<<"No fuel found"<<std::endl;
|
||||
// No fuel, stop loop.
|
||||
m_step_accumulator = 0;
|
||||
break;
|
||||
|
|
|
@ -62,6 +62,29 @@ private:
|
|||
Inventory *m_inventory;
|
||||
};
|
||||
|
||||
class LockingChestNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
LockingChestNodeMetadata();
|
||||
~LockingChestNodeMetadata();
|
||||
|
||||
virtual u16 typeId() const;
|
||||
static NodeMetadata* create(std::istream &is);
|
||||
virtual NodeMetadata* clone();
|
||||
virtual void serializeBody(std::ostream &os);
|
||||
virtual std::string infoText();
|
||||
virtual Inventory* getInventory() {return m_inventory;}
|
||||
virtual bool nodeRemovalDisabled();
|
||||
virtual std::string getInventoryDrawSpecString();
|
||||
|
||||
virtual std::string getOwner(){ return m_text; }
|
||||
virtual void setOwner(std::string t){ m_text = t; }
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
std::string m_text;
|
||||
};
|
||||
|
||||
class FurnaceNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define ACTIVEOBJECT_TYPE_RAT 3
|
||||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
||||
#define ACTIVEOBJECT_TYPE_MOBV2 6
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -20,9 +20,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_sao.h"
|
||||
#include "collision.h"
|
||||
#include "environment.h"
|
||||
#include "settings.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
/* Some helper functions */
|
||||
|
||||
// Y is copied, X and Z change is limited
|
||||
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
||||
{
|
||||
v3f d_wanted = target_speed - speed;
|
||||
d_wanted.Y = 0;
|
||||
f32 dl_wanted = d_wanted.getLength();
|
||||
f32 dl = dl_wanted;
|
||||
if(dl > max_increase)
|
||||
dl = max_increase;
|
||||
|
||||
v3f d = d_wanted.normalize() * dl;
|
||||
|
||||
speed.X += d.X;
|
||||
speed.Z += d.Z;
|
||||
speed.Y = target_speed.Y;
|
||||
}
|
||||
|
||||
/*
|
||||
TestSAO
|
||||
*/
|
||||
|
@ -64,7 +84,6 @@ void TestSAO::step(float dtime, bool send_recommended)
|
|||
if(m_timer1 < 0.0)
|
||||
{
|
||||
m_timer1 += 0.125;
|
||||
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
|
||||
|
||||
std::string data;
|
||||
|
||||
|
@ -111,7 +130,7 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|||
if(version != 0)
|
||||
return NULL;
|
||||
std::string inventorystring = deSerializeString(is);
|
||||
dstream<<"ItemSAO::create(): Creating item \""
|
||||
infostream<<"ItemSAO::create(): Creating item \""
|
||||
<<inventorystring<<"\""<<std::endl;
|
||||
return new ItemSAO(env, id, pos, inventorystring);
|
||||
}
|
||||
|
@ -186,7 +205,7 @@ std::string ItemSAO::getClientInitializationData()
|
|||
|
||||
std::string ItemSAO::getStaticData()
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<std::endl;
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[1];
|
||||
// version
|
||||
|
@ -202,14 +221,14 @@ InventoryItem * ItemSAO::createInventoryItem()
|
|||
try{
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
return item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": serialization error: "
|
||||
infostream<<__FUNCTION_NAME<<": serialization error: "
|
||||
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -217,7 +236,7 @@ InventoryItem * ItemSAO::createInventoryItem()
|
|||
|
||||
void ItemSAO::rightClick(Player *player)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<std::endl;
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
InventoryItem *item = createInventoryItem();
|
||||
if(item == NULL)
|
||||
return;
|
||||
|
@ -404,7 +423,7 @@ std::string RatSAO::getClientInitializationData()
|
|||
|
||||
std::string RatSAO::getStaticData()
|
||||
{
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
|
@ -422,23 +441,6 @@ InventoryItem* RatSAO::createPickedUpItem()
|
|||
Oerkki1SAO
|
||||
*/
|
||||
|
||||
// Y is copied, X and Z change is limited
|
||||
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
||||
{
|
||||
v3f d_wanted = target_speed - speed;
|
||||
d_wanted.Y = 0;
|
||||
f32 dl_wanted = d_wanted.getLength();
|
||||
f32 dl = dl_wanted;
|
||||
if(dl > max_increase)
|
||||
dl = max_increase;
|
||||
|
||||
v3f d = d_wanted.normalize() * dl;
|
||||
|
||||
speed.X += d.X;
|
||||
speed.Z += d.Z;
|
||||
speed.Y = target_speed.Y;
|
||||
}
|
||||
|
||||
// Prototype
|
||||
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
||||
|
||||
|
@ -520,13 +522,14 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
|
|||
Player *player = *i;
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||
if(dist < BS*1.45)
|
||||
if(dist < BS*0.6)
|
||||
{
|
||||
m_removed = true;
|
||||
return;
|
||||
player_is_too_close = true;
|
||||
near_player_pos = playerpos;
|
||||
break;
|
||||
}
|
||||
else if(dist < BS*15.0)
|
||||
else if(dist < BS*15.0 && !player_is_too_close)
|
||||
{
|
||||
player_is_close = true;
|
||||
near_player_pos = playerpos;
|
||||
|
@ -617,7 +620,7 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
|
|||
m_touching_ground = moveresult.touching_ground;
|
||||
|
||||
// Do collision damage
|
||||
float tolerance = BS*12;
|
||||
float tolerance = BS*30;
|
||||
float factor = BS*0.5;
|
||||
v3f speed_diff = old_speed - m_speed_f;
|
||||
// Increase effect in X and Z
|
||||
|
@ -665,7 +668,7 @@ std::string Oerkki1SAO::getClientInitializationData()
|
|||
|
||||
std::string Oerkki1SAO::getStaticData()
|
||||
{
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
|
@ -678,14 +681,14 @@ u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir)
|
|||
{
|
||||
m_speed_f += dir*12*BS;
|
||||
|
||||
u16 amount = 5;
|
||||
u16 amount = 20;
|
||||
doDamage(amount);
|
||||
return 65536/100;
|
||||
}
|
||||
|
||||
void Oerkki1SAO::doDamage(u16 d)
|
||||
{
|
||||
dstream<<"oerkki damage: "<<d<<std::endl;
|
||||
infostream<<"oerkki damage: "<<d<<std::endl;
|
||||
|
||||
if(d < m_hp)
|
||||
{
|
||||
|
@ -873,7 +876,7 @@ std::string FireflySAO::getClientInitializationData()
|
|||
|
||||
std::string FireflySAO::getStaticData()
|
||||
{
|
||||
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
|
@ -886,3 +889,581 @@ InventoryItem* FireflySAO::createPickedUpItem()
|
|||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
MobV2SAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL);
|
||||
|
||||
MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||
Settings *init_properties):
|
||||
ServerActiveObject(env, id, pos),
|
||||
m_move_type("ground_nodes"),
|
||||
m_speed(0,0,0),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_oldpos(0,0,0),
|
||||
m_yaw(0),
|
||||
m_counter1(0),
|
||||
m_counter2(0),
|
||||
m_age(0),
|
||||
m_touching_ground(false),
|
||||
m_hp(10),
|
||||
m_walk_around(false),
|
||||
m_walk_around_timer(0),
|
||||
m_next_pos_exists(false),
|
||||
m_shoot_reload_timer(0),
|
||||
m_shooting(false),
|
||||
m_shooting_timer(0),
|
||||
m_falling(false),
|
||||
m_disturb_timer(100000),
|
||||
m_random_disturb_timer(0),
|
||||
m_shoot_y(0)
|
||||
{
|
||||
ServerActiveObject::registerType(getType(), create);
|
||||
|
||||
m_properties = new Settings();
|
||||
if(init_properties)
|
||||
m_properties->update(*init_properties);
|
||||
|
||||
m_properties->setV3F("pos", pos);
|
||||
|
||||
setPropertyDefaults();
|
||||
readProperties();
|
||||
}
|
||||
|
||||
MobV2SAO::~MobV2SAO()
|
||||
{
|
||||
delete m_properties;
|
||||
}
|
||||
|
||||
ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data)
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
Settings properties;
|
||||
properties.parseConfigLines(is, "MobArgsEnd");
|
||||
MobV2SAO *o = new MobV2SAO(env, id, pos, &properties);
|
||||
return o;
|
||||
}
|
||||
|
||||
std::string MobV2SAO::getStaticData()
|
||||
{
|
||||
updateProperties();
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
m_properties->writeLines(os);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string MobV2SAO::getClientInitializationData()
|
||||
{
|
||||
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||
|
||||
updateProperties();
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
|
||||
Settings client_properties;
|
||||
|
||||
/*client_properties.set("version", "0");
|
||||
client_properties.updateValue(*m_properties, "pos");
|
||||
client_properties.updateValue(*m_properties, "yaw");
|
||||
client_properties.updateValue(*m_properties, "hp");*/
|
||||
|
||||
// Just send everything for simplicity
|
||||
client_properties.update(*m_properties);
|
||||
|
||||
std::ostringstream os2(std::ios::binary);
|
||||
client_properties.writeLines(os2);
|
||||
compressZlib(os2.str(), os);
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bool checkFreePosition(Map *map, v3s16 p0, v3s16 size)
|
||||
{
|
||||
for(int dx=0; dx<size.X; dx++)
|
||||
for(int dy=0; dy<size.Y; dy++)
|
||||
for(int dz=0; dz<size.Z; dz++){
|
||||
v3s16 dp(dx, dy, dz);
|
||||
v3s16 p = p0 + dp;
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() != CONTENT_AIR)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkWalkablePosition(Map *map, v3s16 p0)
|
||||
{
|
||||
v3s16 p = p0 + v3s16(0,-1,0);
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() != CONTENT_AIR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size)
|
||||
{
|
||||
if(!checkFreePosition(map, p0, size))
|
||||
return false;
|
||||
if(!checkWalkablePosition(map, p0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void get_random_u32_array(u32 a[], u32 len)
|
||||
{
|
||||
u32 i, n;
|
||||
for(i=0; i<len; i++)
|
||||
a[i] = i;
|
||||
n = len;
|
||||
while(n > 1){
|
||||
u32 k = myrand() % n;
|
||||
n--;
|
||||
u32 temp = a[n];
|
||||
a[n] = a[k];
|
||||
a[k] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
static void explodeSquare(Map *map, v3s16 p0, v3s16 size)
|
||||
{
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
|
||||
for(int dx=0; dx<size.X; dx++)
|
||||
for(int dy=0; dy<size.Y; dy++)
|
||||
for(int dz=0; dz<size.Z; dz++){
|
||||
v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2);
|
||||
v3s16 p = p0 + dp;
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() == CONTENT_IGNORE)
|
||||
continue;
|
||||
//map->removeNodeWithEvent(p);
|
||||
map->removeNodeAndUpdate(p, modified_blocks);
|
||||
}
|
||||
|
||||
// Send a MEET_OTHER event
|
||||
MapEditEvent event;
|
||||
event.type = MEET_OTHER;
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
event.modified_blocks.insert(p, true);
|
||||
}
|
||||
map->dispatchEvent(&event);
|
||||
}
|
||||
|
||||
void MobV2SAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
assert(m_env);
|
||||
Map *map = &m_env->getMap();
|
||||
|
||||
m_age += dtime;
|
||||
|
||||
if(m_die_age >= 0.0 && m_age >= m_die_age){
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_random_disturb_timer += dtime;
|
||||
if(m_random_disturb_timer >= 5.0)
|
||||
{
|
||||
m_random_disturb_timer = 0;
|
||||
// Check connected players
|
||||
core::list<Player*> players = m_env->getPlayers(true);
|
||||
core::list<Player*>::Iterator i;
|
||||
for(i = players.begin();
|
||||
i != players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||
if(dist < BS*16)
|
||||
{
|
||||
if(myrand_range(0,3) == 0){
|
||||
actionstream<<"Mob id="<<m_id<<" at "
|
||||
<<PP(m_base_position/BS)
|
||||
<<" got randomly disturbed by "
|
||||
<<player->getName()<<std::endl;
|
||||
m_disturbing_player = player->getName();
|
||||
m_disturb_timer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player *disturbing_player =
|
||||
m_env->getPlayer(m_disturbing_player.c_str());
|
||||
v3f disturbing_player_off = v3f(0,1,0);
|
||||
v3f disturbing_player_norm = v3f(0,1,0);
|
||||
float disturbing_player_distance = 1000000;
|
||||
float disturbing_player_dir = 0;
|
||||
if(disturbing_player){
|
||||
disturbing_player_off =
|
||||
disturbing_player->getPosition() - m_base_position;
|
||||
disturbing_player_distance = disturbing_player_off.getLength();
|
||||
disturbing_player_norm = disturbing_player_off;
|
||||
disturbing_player_norm.normalize();
|
||||
disturbing_player_dir = 180./PI*atan2(disturbing_player_norm.Z,
|
||||
disturbing_player_norm.X);
|
||||
}
|
||||
|
||||
m_disturb_timer += dtime;
|
||||
|
||||
if(!m_falling)
|
||||
{
|
||||
m_shooting_timer -= dtime;
|
||||
if(m_shooting_timer <= 0.0 && m_shooting){
|
||||
m_shooting = false;
|
||||
|
||||
std::string shoot_type = m_properties->get("shoot_type");
|
||||
v3f shoot_pos(0,0,0);
|
||||
shoot_pos.Y += m_properties->getFloat("shoot_y") * BS;
|
||||
if(shoot_type == "fireball"){
|
||||
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||
dir.Y = m_shoot_y;
|
||||
dir.normalize();
|
||||
v3f speed = dir * BS * 10.0;
|
||||
v3f pos = m_base_position + shoot_pos;
|
||||
infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
|
||||
<<" shooting fireball from "<<PP(pos)
|
||||
<<" at speed "<<PP(speed)<<std::endl;
|
||||
Settings properties;
|
||||
properties.set("looks", "fireball");
|
||||
properties.setV3F("speed", speed);
|
||||
properties.setFloat("die_age", 5.0);
|
||||
properties.set("move_type", "constant_speed");
|
||||
properties.setFloat("hp", 1000);
|
||||
properties.set("lock_full_brightness", "true");
|
||||
properties.set("player_hit_damage", "9");
|
||||
properties.set("player_hit_distance", "2");
|
||||
properties.set("player_hit_interval", "1");
|
||||
ServerActiveObject *obj = new MobV2SAO(m_env, 0,
|
||||
pos, &properties);
|
||||
//m_env->addActiveObjectAsStatic(obj);
|
||||
m_env->addActiveObject(obj);
|
||||
} else {
|
||||
infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
|
||||
<<": Unknown shoot_type="<<shoot_type
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_shoot_reload_timer += dtime;
|
||||
|
||||
float reload_time = 15.0;
|
||||
if(m_disturb_timer <= 15.0)
|
||||
reload_time = 3.0;
|
||||
|
||||
bool shoot_without_player = false;
|
||||
if(m_properties->getBool("mindless_rage"))
|
||||
shoot_without_player = true;
|
||||
|
||||
if(!m_shooting && m_shoot_reload_timer >= reload_time &&
|
||||
!m_next_pos_exists &&
|
||||
(m_disturb_timer <= 60.0 || shoot_without_player))
|
||||
{
|
||||
m_shoot_y = 0;
|
||||
if(m_disturb_timer < 60.0 && disturbing_player &&
|
||||
disturbing_player_distance < 16*BS &&
|
||||
fabs(disturbing_player_norm.Y) < 0.8){
|
||||
m_yaw = disturbing_player_dir;
|
||||
sendPosition();
|
||||
m_shoot_y += disturbing_player_norm.Y;
|
||||
} else {
|
||||
m_shoot_y = 0.01 * myrand_range(-30,10);
|
||||
}
|
||||
m_shoot_reload_timer = 0.0;
|
||||
m_shooting = true;
|
||||
m_shooting_timer = 1.5;
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (2 = shooting)
|
||||
writeU8(os, 2);
|
||||
// time
|
||||
writeF1000(os, m_shooting_timer + 0.1);
|
||||
// bright?
|
||||
writeU8(os, true);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_move_type == "ground_nodes")
|
||||
{
|
||||
if(!m_shooting){
|
||||
m_walk_around_timer -= dtime;
|
||||
if(m_walk_around_timer <= 0.0){
|
||||
m_walk_around = !m_walk_around;
|
||||
if(m_walk_around)
|
||||
m_walk_around_timer = 0.1*myrand_range(10,50);
|
||||
else
|
||||
m_walk_around_timer = 0.1*myrand_range(30,70);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move */
|
||||
if(m_next_pos_exists){
|
||||
v3f pos_f = m_base_position;
|
||||
v3f next_pos_f = intToFloat(m_next_pos_i, BS);
|
||||
|
||||
v3f v = next_pos_f - pos_f;
|
||||
m_yaw = atan2(v.Z, v.X) / PI * 180;
|
||||
|
||||
v3f diff = next_pos_f - pos_f;
|
||||
v3f dir = diff;
|
||||
dir.normalize();
|
||||
float speed = BS * 0.5;
|
||||
if(m_falling)
|
||||
speed = BS * 3.0;
|
||||
dir *= dtime * speed;
|
||||
bool arrived = false;
|
||||
if(dir.getLength() > diff.getLength()){
|
||||
dir = diff;
|
||||
arrived = true;
|
||||
}
|
||||
pos_f += dir;
|
||||
m_base_position = pos_f;
|
||||
|
||||
if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
|
||||
verbosestream<<"Mob id="<<m_id<<": arrived to "
|
||||
<<PP(m_next_pos_i)<<std::endl;
|
||||
m_next_pos_exists = false;
|
||||
}
|
||||
}
|
||||
|
||||
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if(m_size.X >= 2.5){
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
|
||||
if(!m_next_pos_exists){
|
||||
/* Check whether to drop down */
|
||||
if(checkFreePosition(map,
|
||||
pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){
|
||||
m_next_pos_i = pos_i + v3s16(0,-1,0);
|
||||
m_next_pos_exists = true;
|
||||
m_falling = true;
|
||||
} else {
|
||||
m_falling = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_walk_around)
|
||||
{
|
||||
if(!m_next_pos_exists){
|
||||
/* Find some position where to go next */
|
||||
v3s16 dps[3*3*3];
|
||||
int num_dps = 0;
|
||||
for(int dx=-1; dx<=1; dx++)
|
||||
for(int dy=-1; dy<=1; dy++)
|
||||
for(int dz=-1; dz<=1; dz++){
|
||||
if(dx == 0 && dy == 0)
|
||||
continue;
|
||||
if(dx != 0 && dz != 0 && dy != 0)
|
||||
continue;
|
||||
dps[num_dps++] = v3s16(dx,dy,dz);
|
||||
}
|
||||
u32 order[3*3*3];
|
||||
get_random_u32_array(order, num_dps);
|
||||
for(int i=0; i<num_dps; i++){
|
||||
v3s16 p = dps[order[i]] + pos_i;
|
||||
bool is_free = checkFreeAndWalkablePosition(map,
|
||||
p + pos_size_off, size_blocks);
|
||||
if(!is_free)
|
||||
continue;
|
||||
m_next_pos_i = p;
|
||||
m_next_pos_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_move_type == "constant_speed")
|
||||
{
|
||||
m_base_position += m_speed * dtime;
|
||||
|
||||
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if(m_size.X >= 2.5){
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
|
||||
if(!free){
|
||||
explodeSquare(map, pos_i, v3s16(3,3,3));
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorstream<<"MobV2SAO::step(): id="<<m_id<<" unknown move_type=\""
|
||||
<<m_move_type<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
|
||||
if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||
{
|
||||
sendPosition();
|
||||
}
|
||||
}
|
||||
|
||||
u16 MobV2SAO::punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername)
|
||||
{
|
||||
assert(m_env);
|
||||
Map *map = &m_env->getMap();
|
||||
|
||||
actionstream<<playername<<" punches mob id="<<m_id
|
||||
<<" with a \""<<toolname<<"\" at "
|
||||
<<PP(m_base_position/BS)<<std::endl;
|
||||
|
||||
m_disturb_timer = 0;
|
||||
m_disturbing_player = playername;
|
||||
m_next_pos_exists = false; // Cancel moving immediately
|
||||
|
||||
m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.);
|
||||
v3f new_base_position = m_base_position + dir * BS;
|
||||
{
|
||||
v3s16 pos_i = floatToInt(new_base_position, BS);
|
||||
v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if(m_size.X >= 2.5){
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
|
||||
if(free)
|
||||
m_base_position = new_base_position;
|
||||
}
|
||||
sendPosition();
|
||||
|
||||
u16 amount = 2;
|
||||
/* See tool names in inventory.h */
|
||||
if(toolname == "WSword")
|
||||
amount = 4;
|
||||
if(toolname == "STSword")
|
||||
amount = 6;
|
||||
if(toolname == "SteelSword")
|
||||
amount = 8;
|
||||
if(toolname == "STAxe")
|
||||
amount = 3;
|
||||
if(toolname == "SteelAxe")
|
||||
amount = 4;
|
||||
if(toolname == "SteelPick")
|
||||
amount = 3;
|
||||
doDamage(amount);
|
||||
return 65536/100;
|
||||
}
|
||||
|
||||
bool MobV2SAO::isPeaceful()
|
||||
{
|
||||
return m_properties->getBool("is_peaceful");
|
||||
}
|
||||
|
||||
void MobV2SAO::sendPosition()
|
||||
{
|
||||
m_last_sent_position = m_base_position;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (0 = update position)
|
||||
writeU8(os, 0);
|
||||
// pos
|
||||
writeV3F1000(os, m_base_position);
|
||||
// yaw
|
||||
writeF1000(os, m_yaw);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
void MobV2SAO::setPropertyDefaults()
|
||||
{
|
||||
m_properties->setDefault("is_peaceful", "false");
|
||||
m_properties->setDefault("move_type", "ground_nodes");
|
||||
m_properties->setDefault("speed", "(0,0,0)");
|
||||
m_properties->setDefault("age", "0");
|
||||
m_properties->setDefault("yaw", "0");
|
||||
m_properties->setDefault("pos", "(0,0,0)");
|
||||
m_properties->setDefault("hp", "0");
|
||||
m_properties->setDefault("die_age", "-1");
|
||||
m_properties->setDefault("size", "(1,2)");
|
||||
m_properties->setDefault("shoot_type", "fireball");
|
||||
m_properties->setDefault("shoot_y", "0");
|
||||
m_properties->setDefault("mindless_rage", "false");
|
||||
}
|
||||
void MobV2SAO::readProperties()
|
||||
{
|
||||
m_move_type = m_properties->get("move_type");
|
||||
m_speed = m_properties->getV3F("speed");
|
||||
m_age = m_properties->getFloat("age");
|
||||
m_yaw = m_properties->getFloat("yaw");
|
||||
m_base_position = m_properties->getV3F("pos");
|
||||
m_hp = m_properties->getS32("hp");
|
||||
m_die_age = m_properties->getFloat("die_age");
|
||||
m_size = m_properties->getV2F("size");
|
||||
}
|
||||
void MobV2SAO::updateProperties()
|
||||
{
|
||||
m_properties->set("move_type", m_move_type);
|
||||
m_properties->setV3F("speed", m_speed);
|
||||
m_properties->setFloat("age", m_age);
|
||||
m_properties->setFloat("yaw", m_yaw);
|
||||
m_properties->setV3F("pos", m_base_position);
|
||||
m_properties->setS32("hp", m_hp);
|
||||
m_properties->setFloat("die_age", m_die_age);
|
||||
m_properties->setV2F("size", m_size);
|
||||
|
||||
m_properties->setS32("version", 0);
|
||||
}
|
||||
|
||||
void MobV2SAO::doDamage(u16 d)
|
||||
{
|
||||
infostream<<"MobV2 hp="<<m_hp<<" damage="<<d<<std::endl;
|
||||
|
||||
if(d < m_hp)
|
||||
{
|
||||
m_hp -= d;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionstream<<"A "<<(isPeaceful()?"peaceful":"non-peaceful")
|
||||
<<" mob id="<<m_id<<" dies at "<<PP(m_base_position)<<std::endl;
|
||||
// Die
|
||||
m_hp = 0;
|
||||
m_removed = true;
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (1 = damage)
|
||||
writeU8(os, 1);
|
||||
// amount
|
||||
writeU16(os, d);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
std::string getStaticData();
|
||||
InventoryItem* createPickedUpItem(){return NULL;}
|
||||
u16 punch(const std::string &toolname, v3f dir);
|
||||
bool isPeaceful(){return false;}
|
||||
private:
|
||||
void doDamage(u16 d);
|
||||
|
||||
|
@ -139,5 +140,59 @@ private:
|
|||
bool m_touching_ground;
|
||||
};
|
||||
|
||||
class Settings;
|
||||
|
||||
class MobV2SAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
|
||||
Settings *init_properties);
|
||||
virtual ~MobV2SAO();
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_MOBV2;}
|
||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data);
|
||||
std::string getStaticData();
|
||||
std::string getClientInitializationData();
|
||||
void step(float dtime, bool send_recommended);
|
||||
InventoryItem* createPickedUpItem(){return NULL;}
|
||||
u16 punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername);
|
||||
bool isPeaceful();
|
||||
private:
|
||||
void sendPosition();
|
||||
void setPropertyDefaults();
|
||||
void readProperties();
|
||||
void updateProperties();
|
||||
void doDamage(u16 d);
|
||||
|
||||
std::string m_move_type;
|
||||
v3f m_speed;
|
||||
v3f m_last_sent_position;
|
||||
v3f m_oldpos;
|
||||
float m_yaw;
|
||||
float m_counter1;
|
||||
float m_counter2;
|
||||
float m_age;
|
||||
bool m_touching_ground;
|
||||
int m_hp;
|
||||
bool m_walk_around;
|
||||
float m_walk_around_timer;
|
||||
bool m_next_pos_exists;
|
||||
v3s16 m_next_pos_i;
|
||||
float m_shoot_reload_timer;
|
||||
bool m_shooting;
|
||||
float m_shooting_timer;
|
||||
float m_die_age;
|
||||
v2f m_size;
|
||||
bool m_falling;
|
||||
float m_disturb_timer;
|
||||
std::string m_disturbing_player;
|
||||
float m_random_disturb_timer;
|
||||
float m_shoot_y;
|
||||
|
||||
Settings *m_properties;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
19
src/debug.h
|
@ -235,10 +235,9 @@ private:
|
|||
|
||||
#if CATCH_UNHANDLED_EXCEPTIONS == 1
|
||||
#define BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER try{
|
||||
#define END_PORTABLE_DEBUG_EXCEPTION_HANDLER\
|
||||
#define END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)\
|
||||
}catch(std::exception &e){\
|
||||
dstream<<std::endl<<DTIME\
|
||||
<<"ERROR: An unhandled exception occurred: "\
|
||||
logstream<<"ERROR: An unhandled exception occurred: "\
|
||||
<<e.what()<<std::endl;\
|
||||
assert(0);\
|
||||
}
|
||||
|
@ -257,24 +256,24 @@ public:
|
|||
BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER\
|
||||
_set_se_translator(se_trans_func);
|
||||
|
||||
#define END_DEBUG_EXCEPTION_HANDLER \
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream) \
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#else // Probably mingw
|
||||
#define BEGIN_DEBUG_EXCEPTION_HANDLER\
|
||||
BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream)\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#endif
|
||||
#else // Posix
|
||||
#define BEGIN_DEBUG_EXCEPTION_HANDLER\
|
||||
BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream)\
|
||||
END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#endif
|
||||
#else
|
||||
// Dummy ones
|
||||
#define BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER
|
||||
#define END_DEBUG_EXCEPTION_HANDLER(logstream)
|
||||
#endif
|
||||
|
||||
#endif // DEBUG_HEADER
|
||||
|
|
|
@ -17,89 +17,94 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
|
||||
extern Settings g_settings;
|
||||
|
||||
void set_default_settings()
|
||||
void set_default_settings(Settings *settings)
|
||||
{
|
||||
// Client and server
|
||||
|
||||
g_settings.setDefault("port", "");
|
||||
g_settings.setDefault("name", "");
|
||||
g_settings.setDefault("footprints", "false");
|
||||
settings->setDefault("port", "");
|
||||
settings->setDefault("name", "");
|
||||
settings->setDefault("footprints", "false");
|
||||
|
||||
// Client stuff
|
||||
|
||||
g_settings.setDefault("keymap_forward", "KEY_KEY_W");
|
||||
g_settings.setDefault("keymap_backward", "KEY_KEY_S");
|
||||
g_settings.setDefault("keymap_left", "KEY_KEY_A");
|
||||
g_settings.setDefault("keymap_right", "KEY_KEY_D");
|
||||
g_settings.setDefault("keymap_jump", "KEY_SPACE");
|
||||
g_settings.setDefault("keymap_sneak", "KEY_LSHIFT");
|
||||
g_settings.setDefault("keymap_inventory", "KEY_KEY_I");
|
||||
g_settings.setDefault("keymap_chat", "KEY_KEY_T");
|
||||
g_settings.setDefault("keymap_cmd", "/");
|
||||
g_settings.setDefault("keymap_rangeselect", "KEY_KEY_R");
|
||||
g_settings.setDefault("keymap_freemove", "KEY_KEY_K");
|
||||
g_settings.setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||
g_settings.setDefault("keymap_frametime_graph", "KEY_F1");
|
||||
g_settings.setDefault("keymap_screenshot", "KEY_F12");
|
||||
settings->setDefault("keymap_forward", "KEY_KEY_W");
|
||||
settings->setDefault("keymap_backward", "KEY_KEY_S");
|
||||
settings->setDefault("keymap_left", "KEY_KEY_A");
|
||||
settings->setDefault("keymap_right", "KEY_KEY_D");
|
||||
settings->setDefault("keymap_jump", "KEY_SPACE");
|
||||
settings->setDefault("keymap_sneak", "KEY_LSHIFT");
|
||||
settings->setDefault("keymap_inventory", "KEY_KEY_I");
|
||||
settings->setDefault("keymap_chat", "KEY_KEY_T");
|
||||
settings->setDefault("keymap_cmd", "/");
|
||||
settings->setDefault("keymap_rangeselect", "KEY_KEY_R");
|
||||
settings->setDefault("keymap_freemove", "KEY_KEY_K");
|
||||
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||
settings->setDefault("keymap_frametime_graph", "KEY_F1");
|
||||
settings->setDefault("keymap_screenshot", "KEY_F12");
|
||||
// Some (temporary) keys for debugging
|
||||
g_settings.setDefault("keymap_special1", "KEY_KEY_E");
|
||||
g_settings.setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||
settings->setDefault("keymap_special1", "KEY_KEY_E");
|
||||
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||
|
||||
g_settings.setDefault("wanted_fps", "30");
|
||||
g_settings.setDefault("fps_max", "60");
|
||||
g_settings.setDefault("viewing_range_nodes_max", "300");
|
||||
g_settings.setDefault("viewing_range_nodes_min", "15");
|
||||
g_settings.setDefault("screenW", "800");
|
||||
g_settings.setDefault("screenH", "600");
|
||||
g_settings.setDefault("address", "");
|
||||
g_settings.setDefault("random_input", "false");
|
||||
g_settings.setDefault("client_unload_unused_data_timeout", "600");
|
||||
g_settings.setDefault("enable_fog", "true");
|
||||
g_settings.setDefault("new_style_water", "false");
|
||||
g_settings.setDefault("new_style_leaves", "true");
|
||||
g_settings.setDefault("smooth_lighting", "true");
|
||||
g_settings.setDefault("frametime_graph", "false");
|
||||
g_settings.setDefault("enable_texture_atlas", "true");
|
||||
g_settings.setDefault("texture_path", "");
|
||||
g_settings.setDefault("video_driver", "opengl");
|
||||
g_settings.setDefault("free_move", "false");
|
||||
g_settings.setDefault("continuous_forward", "false");
|
||||
g_settings.setDefault("fast_move", "false");
|
||||
g_settings.setDefault("invert_mouse", "false");
|
||||
g_settings.setDefault("enable_farmesh", "false");
|
||||
g_settings.setDefault("enable_clouds", "true");
|
||||
g_settings.setDefault("invisible_stone", "false");
|
||||
g_settings.setDefault("screenshot_path", ".");
|
||||
settings->setDefault("wanted_fps", "30");
|
||||
settings->setDefault("fps_max", "60");
|
||||
settings->setDefault("viewing_range_nodes_max", "300");
|
||||
settings->setDefault("viewing_range_nodes_min", "15");
|
||||
settings->setDefault("screenW", "800");
|
||||
settings->setDefault("screenH", "600");
|
||||
settings->setDefault("address", "");
|
||||
settings->setDefault("random_input", "false");
|
||||
settings->setDefault("client_unload_unused_data_timeout", "600");
|
||||
settings->setDefault("enable_fog", "true");
|
||||
settings->setDefault("fov", "72");
|
||||
settings->setDefault("view_bobbing", "true");
|
||||
settings->setDefault("new_style_water", "false");
|
||||
settings->setDefault("new_style_leaves", "true");
|
||||
settings->setDefault("smooth_lighting", "true");
|
||||
settings->setDefault("frametime_graph", "false");
|
||||
settings->setDefault("enable_texture_atlas", "true");
|
||||
settings->setDefault("texture_path", "");
|
||||
settings->setDefault("video_driver", "opengl");
|
||||
settings->setDefault("free_move", "false");
|
||||
settings->setDefault("continuous_forward", "false");
|
||||
settings->setDefault("fast_move", "false");
|
||||
settings->setDefault("invert_mouse", "false");
|
||||
settings->setDefault("enable_farmesh", "false");
|
||||
settings->setDefault("enable_clouds", "true");
|
||||
settings->setDefault("invisible_stone", "false");
|
||||
settings->setDefault("screenshot_path", ".");
|
||||
settings->setDefault("view_bobbing_amount", "1.0");
|
||||
|
||||
// Server stuff
|
||||
g_settings.setDefault("motd", "");
|
||||
g_settings.setDefault("enable_experimental", "false");
|
||||
g_settings.setDefault("creative_mode", "false");
|
||||
g_settings.setDefault("enable_damage", "true");
|
||||
g_settings.setDefault("give_initial_stuff", "false");
|
||||
g_settings.setDefault("default_password", "");
|
||||
g_settings.setDefault("default_privs", "build, shout");
|
||||
g_settings.setDefault("profiler_print_interval", "0");
|
||||
g_settings.setDefault("enable_mapgen_debug_info", "false");
|
||||
g_settings.setDefault("fixed_map_seed", "");
|
||||
// "map-dir" doesn't exist by default.
|
||||
settings->setDefault("motd", "");
|
||||
settings->setDefault("max_users", "20");
|
||||
settings->setDefault("strict_protocol_version_checking", "true");
|
||||
settings->setDefault("creative_mode", "false");
|
||||
settings->setDefault("enable_damage", "true");
|
||||
settings->setDefault("only_peaceful_mobs", "false");
|
||||
settings->setDefault("fixed_map_seed", "");
|
||||
settings->setDefault("give_initial_stuff", "false");
|
||||
settings->setDefault("default_password", "");
|
||||
settings->setDefault("default_privs", "build, shout");
|
||||
|
||||
g_settings.setDefault("objectdata_interval", "0.2");
|
||||
g_settings.setDefault("active_object_range", "2");
|
||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
settings->setDefault("profiler_print_interval", "0");
|
||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||
settings->setDefault("objectdata_interval", "0.2");
|
||||
settings->setDefault("active_object_send_range_blocks", "3");
|
||||
settings->setDefault("active_block_range", "5");
|
||||
//settings->setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
// This causes frametime jitter on client side, or does it?
|
||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||
g_settings.setDefault("max_block_send_distance", "8");
|
||||
g_settings.setDefault("max_block_generate_distance", "8");
|
||||
g_settings.setDefault("time_send_interval", "20");
|
||||
g_settings.setDefault("time_speed", "96");
|
||||
g_settings.setDefault("server_unload_unused_data_timeout", "60");
|
||||
g_settings.setDefault("server_map_save_interval", "60");
|
||||
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
//g_settings.setDefault("dungeon_rarity", "0.025");
|
||||
settings->setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||
settings->setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||
settings->setDefault("max_block_send_distance", "8");
|
||||
settings->setDefault("max_block_generate_distance", "8");
|
||||
settings->setDefault("time_send_interval", "20");
|
||||
settings->setDefault("time_speed", "96");
|
||||
settings->setDefault("server_unload_unused_data_timeout", "60");
|
||||
settings->setDefault("server_map_save_interval", "10");
|
||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
settings->setDefault("enable_experimental", "false");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DEFAULTSETTINGS_HEADER
|
||||
#define DEFAULTSETTINGS_HEADER
|
||||
|
||||
class Settings;
|
||||
|
||||
void set_default_settings(Settings *settings);
|
||||
|
||||
#endif
|
||||
|
|
@ -25,6 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapblock.h"
|
||||
#include "serverobject.h"
|
||||
#include "content_sao.h"
|
||||
#include "mapgen.h"
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
#include "profiler.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
Environment::Environment():
|
||||
m_time_of_day(9000)
|
||||
|
@ -300,7 +306,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
// Full path to this file
|
||||
std::string path = players_path + "/" + player_files[i].name;
|
||||
|
||||
//dstream<<"Checking player file "<<path<<std::endl;
|
||||
//infostream<<"Checking player file "<<path<<std::endl;
|
||||
|
||||
// Load player to see what is its name
|
||||
ServerRemotePlayer testplayer;
|
||||
|
@ -309,24 +315,24 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"Failed to read "<<path<<std::endl;
|
||||
infostream<<"Failed to read "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
testplayer.deSerialize(is);
|
||||
}
|
||||
|
||||
//dstream<<"Loaded test player with name "<<testplayer.getName()<<std::endl;
|
||||
//infostream<<"Loaded test player with name "<<testplayer.getName()<<std::endl;
|
||||
|
||||
// Search for the player
|
||||
std::string playername = testplayer.getName();
|
||||
Player *player = getPlayer(playername.c_str());
|
||||
if(player == NULL)
|
||||
{
|
||||
dstream<<"Didn't find matching player, ignoring file "<<path<<std::endl;
|
||||
infostream<<"Didn't find matching player, ignoring file "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
//dstream<<"Found matching player, overwriting."<<std::endl;
|
||||
//infostream<<"Found matching player, overwriting."<<std::endl;
|
||||
|
||||
// OK, found. Save player there.
|
||||
{
|
||||
|
@ -334,7 +340,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
std::ofstream os(path.c_str(), std::ios_base::binary);
|
||||
if(os.good() == false)
|
||||
{
|
||||
dstream<<"Failed to overwrite "<<path<<std::endl;
|
||||
infostream<<"Failed to overwrite "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
player->serialize(os);
|
||||
|
@ -348,7 +354,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
Player *player = *i;
|
||||
if(saved_players.find(player) != NULL)
|
||||
{
|
||||
/*dstream<<"Player "<<player->getName()
|
||||
/*infostream<<"Player "<<player->getName()
|
||||
<<" was already saved."<<std::endl;*/
|
||||
continue;
|
||||
}
|
||||
|
@ -356,7 +362,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
// Don't save unnamed player
|
||||
if(playername == "")
|
||||
{
|
||||
//dstream<<"Not saving unnamed player."<<std::endl;
|
||||
//infostream<<"Not saving unnamed player."<<std::endl;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
|
@ -377,18 +383,18 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
}
|
||||
if(found == false)
|
||||
{
|
||||
dstream<<"WARNING: Didn't find free file for player"<<std::endl;
|
||||
infostream<<"Didn't find free file for player"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
/*dstream<<"Saving player "<<player->getName()<<" to "
|
||||
/*infostream<<"Saving player "<<player->getName()<<" to "
|
||||
<<path<<std::endl;*/
|
||||
// Open file and serialize
|
||||
std::ofstream os(path.c_str(), std::ios_base::binary);
|
||||
if(os.good() == false)
|
||||
{
|
||||
dstream<<"WARNING: Failed to overwrite "<<path<<std::endl;
|
||||
infostream<<"Failed to overwrite "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
player->serialize(os);
|
||||
|
@ -396,7 +402,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
|||
}
|
||||
}
|
||||
|
||||
//dstream<<"Saved "<<saved_players.size()<<" players."<<std::endl;
|
||||
//infostream<<"Saved "<<saved_players.size()<<" players."<<std::endl;
|
||||
}
|
||||
|
||||
void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
|
@ -414,7 +420,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
|||
// Full path to this file
|
||||
std::string path = players_path + "/" + player_files[i].name;
|
||||
|
||||
dstream<<"Checking player file "<<path<<std::endl;
|
||||
infostream<<"Checking player file "<<path<<std::endl;
|
||||
|
||||
// Load player to see what is its name
|
||||
ServerRemotePlayer testplayer;
|
||||
|
@ -423,7 +429,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
|||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"Failed to read "<<path<<std::endl;
|
||||
infostream<<"Failed to read "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
testplayer.deSerialize(is);
|
||||
|
@ -431,11 +437,11 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
|||
|
||||
if(!string_allowed(testplayer.getName(), PLAYERNAME_ALLOWED_CHARS))
|
||||
{
|
||||
dstream<<"Not loading player with invalid name: "
|
||||
infostream<<"Not loading player with invalid name: "
|
||||
<<testplayer.getName()<<std::endl;
|
||||
}
|
||||
|
||||
dstream<<"Loaded test player with name "<<testplayer.getName()
|
||||
infostream<<"Loaded test player with name "<<testplayer.getName()
|
||||
<<std::endl;
|
||||
|
||||
// Search for the player
|
||||
|
@ -444,20 +450,20 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
|||
bool newplayer = false;
|
||||
if(player == NULL)
|
||||
{
|
||||
dstream<<"Is a new player"<<std::endl;
|
||||
infostream<<"Is a new player"<<std::endl;
|
||||
player = new ServerRemotePlayer();
|
||||
newplayer = true;
|
||||
}
|
||||
|
||||
// Load player
|
||||
{
|
||||
dstream<<"Reading player "<<testplayer.getName()<<" from "
|
||||
infostream<<"Reading player "<<testplayer.getName()<<" from "
|
||||
<<path<<std::endl;
|
||||
// Open file and deserialize
|
||||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"Failed to read "<<path<<std::endl;
|
||||
infostream<<"Failed to read "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
player->deSerialize(is);
|
||||
|
@ -476,7 +482,7 @@ void ServerEnvironment::saveMeta(const std::string &savedir)
|
|||
std::ofstream os(path.c_str(), std::ios_base::binary);
|
||||
if(os.good() == false)
|
||||
{
|
||||
dstream<<"WARNING: ServerEnvironment::saveMeta(): Failed to open "
|
||||
infostream<<"ServerEnvironment::saveMeta(): Failed to open "
|
||||
<<path<<std::endl;
|
||||
throw SerializationError("Couldn't save env meta");
|
||||
}
|
||||
|
@ -497,7 +503,7 @@ void ServerEnvironment::loadMeta(const std::string &savedir)
|
|||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"WARNING: ServerEnvironment::loadMeta(): Failed to open "
|
||||
infostream<<"ServerEnvironment::loadMeta(): Failed to open "
|
||||
<<path<<std::endl;
|
||||
throw SerializationError("Couldn't load env meta");
|
||||
}
|
||||
|
@ -599,7 +605,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
|||
// Set current time as timestamp (and let it set ChangedFlag)
|
||||
block->setTimestamp(m_game_time);
|
||||
|
||||
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
||||
//infostream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
||||
|
||||
// Activate stored objects
|
||||
activateObjects(block);
|
||||
|
@ -647,6 +653,20 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
|||
}
|
||||
}
|
||||
|
||||
static void getMob_dungeon_master(Settings &properties)
|
||||
{
|
||||
properties.set("looks", "dungeon_master");
|
||||
properties.setFloat("yaw", 1.57);
|
||||
properties.setFloat("hp", 30);
|
||||
properties.setBool("bright_shooting", true);
|
||||
properties.set("shoot_type", "fireball");
|
||||
properties.set("shoot_y", "0.7");
|
||||
properties.set("player_hit_damage", "1");
|
||||
properties.set("player_hit_distance", "1.0");
|
||||
properties.set("player_hit_interval", "0.5");
|
||||
properties.setBool("mindless_rage", myrand_range(0,100)==0);
|
||||
}
|
||||
|
||||
void ServerEnvironment::step(float dtime)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
@ -654,7 +674,7 @@ void ServerEnvironment::step(float dtime)
|
|||
//TimeTaker timer("ServerEnv step");
|
||||
|
||||
// Get some settings
|
||||
bool footprints = g_settings.getBool("footprints");
|
||||
bool footprints = g_settings->getBool("footprints");
|
||||
|
||||
/*
|
||||
Increment game time
|
||||
|
@ -669,37 +689,40 @@ void ServerEnvironment::step(float dtime)
|
|||
/*
|
||||
Handle players
|
||||
*/
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
// Ignore disconnected players
|
||||
if(player->peer_id == 0)
|
||||
continue;
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
|
||||
// Move
|
||||
player->move(dtime, *m_map, 100*BS);
|
||||
|
||||
/*
|
||||
Add footsteps to grass
|
||||
*/
|
||||
if(footprints)
|
||||
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_LOWPASS);
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
// Get node that is at BS/4 under player
|
||||
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
|
||||
try{
|
||||
MapNode n = m_map->getNode(bottompos);
|
||||
if(n.getContent() == CONTENT_GRASS)
|
||||
{
|
||||
n.setContent(CONTENT_GRASS_FOOTSTEPS);
|
||||
m_map->setNode(bottompos, n);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
Player *player = *i;
|
||||
|
||||
// Ignore disconnected players
|
||||
if(player->peer_id == 0)
|
||||
continue;
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
|
||||
// Move
|
||||
player->move(dtime, *m_map, 100*BS);
|
||||
|
||||
/*
|
||||
Add footsteps to grass
|
||||
*/
|
||||
if(footprints)
|
||||
{
|
||||
// Get node that is at BS/4 under player
|
||||
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
|
||||
try{
|
||||
MapNode n = m_map->getNode(bottompos);
|
||||
if(n.getContent() == CONTENT_GRASS)
|
||||
{
|
||||
n.setContent(CONTENT_GRASS_FOOTSTEPS);
|
||||
m_map->setNode(bottompos, n);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -709,6 +732,7 @@ void ServerEnvironment::step(float dtime)
|
|||
*/
|
||||
if(m_active_blocks_management_interval.step(dtime, 2.0))
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg", SPT_LOWPASS);
|
||||
/*
|
||||
Get player block positions
|
||||
*/
|
||||
|
@ -729,7 +753,7 @@ void ServerEnvironment::step(float dtime)
|
|||
/*
|
||||
Update list of active blocks, collecting changes
|
||||
*/
|
||||
const s16 active_block_range = 5;
|
||||
const s16 active_block_range = g_settings->getS16("active_block_range");
|
||||
core::map<v3s16, bool> blocks_removed;
|
||||
core::map<v3s16, bool> blocks_added;
|
||||
m_active_blocks.update(players_blockpos, active_block_range,
|
||||
|
@ -748,7 +772,7 @@ void ServerEnvironment::step(float dtime)
|
|||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
/*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") became inactive"<<std::endl;*/
|
||||
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
|
@ -769,7 +793,7 @@ void ServerEnvironment::step(float dtime)
|
|||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
/*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") became active"<<std::endl;*/
|
||||
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
|
@ -785,6 +809,8 @@ void ServerEnvironment::step(float dtime)
|
|||
*/
|
||||
if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg", SPT_LOWPASS);
|
||||
|
||||
float dtime = 1.0;
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
|
@ -793,7 +819,7 @@ void ServerEnvironment::step(float dtime)
|
|||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
/*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") being handled"<<std::endl;*/
|
||||
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
|
@ -819,8 +845,10 @@ void ServerEnvironment::step(float dtime)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_active_blocks_test_interval.step(dtime, 10.0))
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg", SPT_LOWPASS);
|
||||
//float dtime = 10.0;
|
||||
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
|
@ -829,7 +857,7 @@ void ServerEnvironment::step(float dtime)
|
|||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
/*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
/*infostream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
|
||||
<<") being handled"<<std::endl;*/
|
||||
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
|
@ -854,7 +882,7 @@ void ServerEnvironment::step(float dtime)
|
|||
// TODO: Implement usage of ActiveBlockModifier
|
||||
|
||||
// Find out how many objects the block contains
|
||||
u32 active_object_count = block->m_static_objects.m_active.size();
|
||||
//u32 active_object_count = block->m_static_objects.m_active.size();
|
||||
// Find out how many objects this and all the neighbors contain
|
||||
u32 active_object_count_wider = 0;
|
||||
for(s16 x=-1; x<=1; x++)
|
||||
|
@ -928,7 +956,93 @@ void ServerEnvironment::step(float dtime)
|
|||
addActiveObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Fun things spawn in caves and dungeons
|
||||
*/
|
||||
if(n.getContent() == CONTENT_STONE ||
|
||||
n.getContent() == CONTENT_MOSSYCOBBLE)
|
||||
{
|
||||
if(myrand()%200 == 0 && active_object_count_wider == 0)
|
||||
{
|
||||
v3s16 p1 = p + v3s16(0,1,0);
|
||||
MapNode n1a = m_map->getNodeNoEx(p1+v3s16(0,0,0));
|
||||
if(n1a.getLightBlend(getDayNightRatio()) <= 3){
|
||||
MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,1,0));
|
||||
if(n1a.getContent() == CONTENT_AIR &&
|
||||
n1b.getContent() == CONTENT_AIR)
|
||||
{
|
||||
v3f pos = intToFloat(p1, BS);
|
||||
int i = myrand()%5;
|
||||
if(i == 0 || i == 1){
|
||||
actionstream<<"A dungeon master spawns at "
|
||||
<<PP(p1)<<std::endl;
|
||||
Settings properties;
|
||||
getMob_dungeon_master(properties);
|
||||
ServerActiveObject *obj = new MobV2SAO(
|
||||
this, 0, pos, &properties);
|
||||
addActiveObject(obj);
|
||||
} else if(i == 2 || i == 3){
|
||||
actionstream<<"Rats spawn at "
|
||||
<<PP(p1)<<std::endl;
|
||||
for(int j=0; j<3; j++){
|
||||
ServerActiveObject *obj = new RatSAO(
|
||||
this, 0, pos);
|
||||
addActiveObject(obj);
|
||||
}
|
||||
} else {
|
||||
actionstream<<"An oerkki spawns at "
|
||||
<<PP(p1)<<std::endl;
|
||||
ServerActiveObject *obj = new Oerkki1SAO(
|
||||
this, 0, pos);
|
||||
addActiveObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Make trees from saplings!
|
||||
*/
|
||||
if(n.getContent() == CONTENT_SAPLING)
|
||||
{
|
||||
if(myrand()%50 == 0)
|
||||
{
|
||||
actionstream<<"A sapling grows into a tree at "
|
||||
<<PP(p)<<std::endl;
|
||||
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
v3s16 tree_p = p;
|
||||
ManualMapVoxelManipulator vmanip(m_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;
|
||||
mapgen::make_tree(vmanip, tree_p, is_apple_tree);
|
||||
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());
|
||||
}
|
||||
m_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++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
event.modified_blocks.insert(p, true);
|
||||
}
|
||||
m_map->dispatchEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -937,12 +1051,13 @@ void ServerEnvironment::step(float dtime)
|
|||
Step active objects
|
||||
*/
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_LOWPASS);
|
||||
//TimeTaker timer("Step active objects");
|
||||
|
||||
// This helps the objects to send data at the same time
|
||||
bool send_recommended = false;
|
||||
m_send_recommended_timer += dtime;
|
||||
if(m_send_recommended_timer > 0.15)
|
||||
if(m_send_recommended_timer > 0.10)
|
||||
{
|
||||
m_send_recommended_timer = 0;
|
||||
send_recommended = true;
|
||||
|
@ -953,6 +1068,11 @@ void ServerEnvironment::step(float dtime)
|
|||
i.atEnd()==false; i++)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
// Remove non-peaceful mobs on peaceful mode
|
||||
if(g_settings->getBool("only_peaceful_mobs")){
|
||||
if(!obj->isPeaceful())
|
||||
obj->m_removed = true;
|
||||
}
|
||||
// Don't step if is to be removed or stored statically
|
||||
if(obj->m_removed || obj->m_pending_deactivation)
|
||||
continue;
|
||||
|
@ -972,19 +1092,20 @@ void ServerEnvironment::step(float dtime)
|
|||
*/
|
||||
if(m_object_management_interval.step(dtime, 0.5))
|
||||
{
|
||||
ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg", SPT_LOWPASS);
|
||||
/*
|
||||
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
||||
*/
|
||||
removeRemovedObjects();
|
||||
}
|
||||
|
||||
if(g_settings.getBool("enable_experimental"))
|
||||
if(g_settings->getBool("enable_experimental"))
|
||||
{
|
||||
|
||||
/*
|
||||
TEST CODE
|
||||
*/
|
||||
#if 1
|
||||
#if 0
|
||||
m_random_spawn_timer -= dtime;
|
||||
if(m_random_spawn_timer < 0)
|
||||
{
|
||||
|
@ -1006,7 +1127,7 @@ void ServerEnvironment::step(float dtime)
|
|||
pos = player->getPosition();
|
||||
pos += v3f(
|
||||
myrand_range(-3,3)*BS,
|
||||
0,
|
||||
5,
|
||||
myrand_range(-3,3)*BS
|
||||
);
|
||||
|
||||
|
@ -1018,7 +1139,14 @@ void ServerEnvironment::step(float dtime)
|
|||
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
||||
//ServerActiveObject *obj = new RatSAO(this, 0, pos);
|
||||
//ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
|
||||
ServerActiveObject *obj = new FireflySAO(this, 0, pos);
|
||||
//ServerActiveObject *obj = new FireflySAO(this, 0, pos);
|
||||
|
||||
infostream<<"Server: Spawning MobV2SAO at "
|
||||
<<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
|
||||
|
||||
Settings properties;
|
||||
getMob_dungeon_master(properties);
|
||||
ServerActiveObject *obj = new MobV2SAO(this, 0, pos, &properties);
|
||||
addActiveObject(obj);
|
||||
}
|
||||
#endif
|
||||
|
@ -1074,6 +1202,47 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
|||
return id;
|
||||
}
|
||||
|
||||
bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
|
||||
{
|
||||
assert(obj);
|
||||
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
|
||||
// The block in which the object resides in
|
||||
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
|
||||
/*
|
||||
Update the static data
|
||||
*/
|
||||
|
||||
// Create new static object
|
||||
std::string staticdata = obj->getStaticData();
|
||||
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
// Get or generate the block
|
||||
MapBlock *block = m_map->emergeBlock(blockpos);
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.insert(0, s_obj);
|
||||
block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD);
|
||||
succeeded = true;
|
||||
}
|
||||
else{
|
||||
infostream<<"ServerEnvironment::addActiveObjectAsStatic: "
|
||||
<<"Could not find or generate "
|
||||
<<"a block for storing static object"<<std::endl;
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
delete obj;
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
/*
|
||||
Finds out what new objects have been added to
|
||||
inside a radius around a position
|
||||
|
@ -1143,13 +1312,13 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
|||
ServerActiveObject *object = getActiveObject(id);
|
||||
if(object == NULL)
|
||||
{
|
||||
dstream<<"WARNING: ServerEnvironment::getRemovedActiveObjects():"
|
||||
infostream<<"ServerEnvironment::getRemovedActiveObjects():"
|
||||
<<" object in current_objects is NULL"<<std::endl;
|
||||
}
|
||||
else if(object->m_removed == false)
|
||||
{
|
||||
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||
/*dstream<<"removed == false"
|
||||
/*infostream<<"removed == false"
|
||||
<<"distance_f = "<<distance_f
|
||||
<<", radius_f = "<<radius_f<<std::endl;*/
|
||||
if(distance_f < radius_f)
|
||||
|
@ -1183,7 +1352,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
|||
u16 new_id = getFreeServerActiveObjectId(m_active_objects);
|
||||
if(new_id == 0)
|
||||
{
|
||||
dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): "
|
||||
infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"no free ids available"<<std::endl;
|
||||
delete object;
|
||||
return 0;
|
||||
|
@ -1192,12 +1361,12 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
|||
}
|
||||
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
||||
{
|
||||
dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): "
|
||||
infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||
delete object;
|
||||
return 0;
|
||||
}
|
||||
/*dstream<<"INFO: ServerEnvironment::addActiveObjectRaw(): "
|
||||
/*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"added (id="<<object->getId()<<")"<<std::endl;*/
|
||||
|
||||
m_active_objects.insert(object->getId(), object);
|
||||
|
@ -1219,7 +1388,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
|||
block->setChangedFlag();
|
||||
}
|
||||
else{
|
||||
dstream<<"WARNING: ServerEnv: Could not find a block for "
|
||||
infostream<<"ServerEnv: Could not find a block for "
|
||||
<<"storing newly added static active object"<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1410,7 @@ void ServerEnvironment::removeRemovedObjects()
|
|||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||
infostream<<"NULL object found in ServerEnvironment"
|
||||
<<" while finding removed objects. id="<<id<<std::endl;
|
||||
// Id to be removed from m_active_objects
|
||||
objects_to_remove.push_back(id);
|
||||
|
@ -1303,7 +1472,7 @@ void ServerEnvironment::activateObjects(MapBlock *block)
|
|||
i = block->m_static_objects.m_stored.begin();
|
||||
i != block->m_static_objects.m_stored.end(); i++)
|
||||
{
|
||||
/*dstream<<"INFO: Server: Creating an active object from "
|
||||
/*infostream<<"Server: Creating an active object from "
|
||||
<<"static data"<<std::endl;*/
|
||||
StaticObject &s_obj = *i;
|
||||
// Create an active object from the data
|
||||
|
@ -1351,21 +1520,22 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
|||
i.atEnd()==false; i++)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
u16 id = i.getNode()->getKey();
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||
infostream<<"NULL object found in ServerEnvironment"
|
||||
<<std::endl;
|
||||
assert(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
u16 id = i.getNode()->getKey();
|
||||
v3f objectpos = obj->getBasePosition();
|
||||
|
||||
// The block in which the object resides in
|
||||
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
|
||||
|
||||
// If block is active, don't remove
|
||||
if(m_active_blocks.contains(blockpos_o))
|
||||
continue;
|
||||
|
@ -1413,7 +1583,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
|||
obj->m_static_block = block->getPos();
|
||||
}
|
||||
else{
|
||||
dstream<<"WARNING: ServerEnv: Could not find or generate "
|
||||
infostream<<"ServerEnv: Could not find or generate "
|
||||
<<"a block for storing static object"<<std::endl;
|
||||
obj->m_static_exists = false;
|
||||
continue;
|
||||
|
@ -1431,7 +1601,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
|||
continue;
|
||||
}
|
||||
|
||||
/*dstream<<"INFO: Server: Stored static data. Deleting object."
|
||||
/*infostream<<"Server: Stored static data. Deleting object."
|
||||
<<std::endl;*/
|
||||
// Delete active object
|
||||
delete obj;
|
||||
|
@ -1505,8 +1675,8 @@ void ClientEnvironment::step(float dtime)
|
|||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
// Get some settings
|
||||
bool free_move = g_settings.getBool("free_move");
|
||||
bool footprints = g_settings.getBool("footprints");
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
bool footprints = g_settings->getBool("footprints");
|
||||
|
||||
// Get local player
|
||||
LocalPlayer *lplayer = getLocalPlayer();
|
||||
|
@ -1519,11 +1689,6 @@ void ClientEnvironment::step(float dtime)
|
|||
*/
|
||||
bool is_climbing = lplayer->is_climbing;
|
||||
|
||||
/*
|
||||
Check if the player is frozen (don't apply physics)
|
||||
*/
|
||||
bool is_frozen = lplayer->is_frozen;
|
||||
|
||||
f32 player_speed = 0.001; // just some small value
|
||||
player_speed = lplayer->getSpeed().getLength();
|
||||
|
||||
|
@ -1581,7 +1746,7 @@ void ClientEnvironment::step(float dtime)
|
|||
v3f lplayerpos = lplayer->getPosition();
|
||||
|
||||
// Apply physics
|
||||
if(free_move == false && is_climbing == false && is_frozen == false)
|
||||
if(free_move == false && is_climbing == false)
|
||||
{
|
||||
// Gravity
|
||||
v3f speed = lplayer->getSpeed();
|
||||
|
@ -1615,7 +1780,7 @@ void ClientEnvironment::step(float dtime)
|
|||
while(dtime_downcount > 0.001);
|
||||
|
||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||
|
||||
|
||||
for(core::list<CollisionInfo>::Iterator
|
||||
i = player_collisions.begin();
|
||||
i != player_collisions.end(); i++)
|
||||
|
@ -1692,18 +1857,19 @@ void ClientEnvironment::step(float dtime)
|
|||
// Move
|
||||
player->move(dtime, *m_map, 100*BS);
|
||||
|
||||
// Update lighting on remote players on client
|
||||
u8 light = LIGHT_MAX;
|
||||
try{
|
||||
// Get node at head
|
||||
v3s16 p = player->getLightPosition();
|
||||
MapNode n = m_map->getNode(p);
|
||||
light = n.getLightBlend(getDayNightRatio());
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
player->updateLight(light);
|
||||
}
|
||||
|
||||
// Update lighting on all players on client
|
||||
u8 light = LIGHT_MAX;
|
||||
try{
|
||||
// Get node at head
|
||||
v3s16 p = player->getLightPosition();
|
||||
MapNode n = m_map->getNode(p);
|
||||
light = n.getLightBlend(getDayNightRatio());
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
player->updateLight(light);
|
||||
|
||||
/*
|
||||
Add footsteps to grass
|
||||
*/
|
||||
|
@ -1821,7 +1987,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
|||
u16 new_id = getFreeClientActiveObjectId(m_active_objects);
|
||||
if(new_id == 0)
|
||||
{
|
||||
dstream<<"WARNING: ClientEnvironment::addActiveObject(): "
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"no free ids available"<<std::endl;
|
||||
delete object;
|
||||
return 0;
|
||||
|
@ -1830,12 +1996,12 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
|||
}
|
||||
if(isFreeClientActiveObjectId(object->getId(), m_active_objects) == false)
|
||||
{
|
||||
dstream<<"WARNING: ClientEnvironment::addActiveObject(): "
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||
delete object;
|
||||
return 0;
|
||||
}
|
||||
dstream<<"INFO: ClientEnvironment::addActiveObject(): "
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"added (id="<<object->getId()<<")"<<std::endl;
|
||||
m_active_objects.insert(object->getId(), object);
|
||||
object->addToScene(m_smgr);
|
||||
|
@ -1848,7 +2014,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
|||
ClientActiveObject* obj = ClientActiveObject::create(type);
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: ClientEnvironment::addActiveObject(): "
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"id="<<id<<" type="<<type<<": Couldn't create object"
|
||||
<<std::endl;
|
||||
return;
|
||||
|
@ -1856,19 +2022,19 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
|||
|
||||
obj->setId(id);
|
||||
|
||||
addActiveObject(obj);
|
||||
|
||||
obj->initialize(init_data);
|
||||
|
||||
addActiveObject(obj);
|
||||
}
|
||||
|
||||
void ClientEnvironment::removeActiveObject(u16 id)
|
||||
{
|
||||
dstream<<"ClientEnvironment::removeActiveObject(): "
|
||||
infostream<<"ClientEnvironment::removeActiveObject(): "
|
||||
<<"id="<<id<<std::endl;
|
||||
ClientActiveObject* obj = getActiveObject(id);
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: ClientEnvironment::removeActiveObject(): "
|
||||
infostream<<"ClientEnvironment::removeActiveObject(): "
|
||||
<<"id="<<id<<" not found"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
@ -1883,7 +2049,7 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
|
|||
ClientActiveObject* obj = getActiveObject(id);
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: ClientEnvironment::processActiveObjectMessage():"
|
||||
infostream<<"ClientEnvironment::processActiveObjectMessage():"
|
||||
<<" got message for id="<<id<<", which doesn't exist."
|
||||
<<std::endl;
|
||||
return;
|
||||
|
@ -1946,29 +2112,6 @@ ClientEnvEvent ClientEnvironment::getClientEvent()
|
|||
return m_client_event_queue.pop_front();
|
||||
}
|
||||
|
||||
void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos)
|
||||
{
|
||||
/*LocalPlayer *player = getLocalPlayer();
|
||||
assert(player);
|
||||
v3f pos_f = player->getPosition() + v3f(0,BS*1.625,0);*/
|
||||
v3f pos_f = camera_pos;
|
||||
v3s16 p_nodes = floatToInt(pos_f, BS);
|
||||
MapNode n = m_map->getNodeNoEx(p_nodes);
|
||||
if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE)
|
||||
{
|
||||
v2u32 ss = driver->getScreenSize();
|
||||
core::rect<s32> rect(0,0, ss.X, ss.Y);
|
||||
driver->draw2DRectangle(video::SColor(64, 100, 100, 200), rect);
|
||||
}
|
||||
else if(content_features(n).solidness == 2 &&
|
||||
g_settings.getBool("free_move") == false)
|
||||
{
|
||||
v2u32 ss = driver->getScreenSize();
|
||||
core::rect<s32> rect(0,0, ss.X, ss.Y);
|
||||
driver->draw2DRectangle(video::SColor(255, 0, 0, 0), rect);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef SERVER
|
||||
|
||||
|
||||
|
|
|
@ -182,6 +182,14 @@ public:
|
|||
*/
|
||||
u16 addActiveObject(ServerActiveObject *object);
|
||||
|
||||
/*
|
||||
Add an active object as a static object to the corresponding
|
||||
MapBlock.
|
||||
Caller allocates memory, ServerEnvironment frees memory.
|
||||
Return value: true if succeeded, false if failed.
|
||||
*/
|
||||
bool addActiveObjectAsStatic(ServerActiveObject *object);
|
||||
|
||||
/*
|
||||
Find out what new objects have been added to
|
||||
inside a radius around a position
|
||||
|
@ -413,9 +421,6 @@ public:
|
|||
|
||||
// Get event from queue. CEE_NONE is returned if queue is empty.
|
||||
ClientEnvEvent getClientEvent();
|
||||
|
||||
// Post effects
|
||||
void drawPostFx(video::IVideoDriver* driver, v3f camera_pos);
|
||||
|
||||
private:
|
||||
ClientMap *m_map;
|
||||
|
|
|
@ -279,7 +279,7 @@ bool RecursiveDeleteContent(std::string path)
|
|||
{
|
||||
if(trim(list[i].name) == "." || trim(list[i].name) == "..")
|
||||
continue;
|
||||
std::string childpath = path + "/" + list[i].name;
|
||||
std::string childpath = path + DIR_DELIM + list[i].name;
|
||||
bool r = RecursiveDelete(childpath);
|
||||
if(r == false)
|
||||
{
|
||||
|
@ -299,7 +299,7 @@ bool CreateAllDirs(std::string path)
|
|||
while(!PathExists(basepath))
|
||||
{
|
||||
tocreate.push_back(basepath);
|
||||
pos = basepath.rfind('/');
|
||||
pos = basepath.rfind(DIR_DELIM_C);
|
||||
if(pos == std::string::npos)
|
||||
return false;
|
||||
basepath = basepath.substr(0,pos);
|
||||
|
|
|
@ -24,6 +24,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <vector>
|
||||
#include "exceptions.h"
|
||||
|
||||
#ifdef _WIN32 // WINDOWS
|
||||
#define DIR_DELIM "\\"
|
||||
#define DIR_DELIM_C '\\'
|
||||
#else // POSIX
|
||||
#define DIR_DELIM "/"
|
||||
#define DIR_DELIM_C '/'
|
||||
#endif
|
||||
|
||||
namespace fs
|
||||
{
|
||||
|
||||
|
|
677
src/game.cpp
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "guiDeathScreen.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "gettext.h"
|
||||
#include "client.h"
|
||||
|
||||
GUIDeathScreen::GUIDeathScreen(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr, IRespawnInitiator *respawner
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_respawner(respawner),
|
||||
m_screensize(1,1)
|
||||
{
|
||||
}
|
||||
|
||||
GUIDeathScreen::~GUIDeathScreen()
|
||||
{
|
||||
removeChildren();
|
||||
delete m_respawner;
|
||||
}
|
||||
|
||||
void GUIDeathScreen::removeChildren()
|
||||
{
|
||||
const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for(core::list<gui::IGUIElement*>::ConstIterator
|
||||
i = children.begin(); i != children.end(); i++)
|
||||
{
|
||||
children_copy.push_back(*i);
|
||||
}
|
||||
for(core::list<gui::IGUIElement*>::Iterator
|
||||
i = children_copy.begin();
|
||||
i != children_copy.end(); i++)
|
||||
{
|
||||
(*i)->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIDeathScreen::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
m_screensize = screensize;
|
||||
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
core::rect<s32> rect(
|
||||
screensize.X/2 - 500/2,
|
||||
screensize.Y/2 - 200/2,
|
||||
screensize.X/2 + 500/2,
|
||||
screensize.Y/2 + 200/2
|
||||
);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = rect.getSize();
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
changeCtype("");
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 400, 50);
|
||||
rect = rect + v2s32(size.X/2-400/2, size.Y/2-50/2-25);
|
||||
Environment->addStaticText(wgettext("You died."), rect, false,
|
||||
true, this, 256);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, 30);
|
||||
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
|
||||
gui::IGUIElement *e =
|
||||
Environment->addButton(rect, this, 257,
|
||||
wgettext("Respawn"));
|
||||
Environment->setFocus(e);
|
||||
}
|
||||
changeCtype("C");
|
||||
}
|
||||
|
||||
void GUIDeathScreen::drawMenu()
|
||||
{
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
{
|
||||
video::SColor color(180,50,0,0);
|
||||
driver->draw2DRectangle(color,
|
||||
core::rect<s32>(0,0,m_screensize.X,m_screensize.Y), NULL);
|
||||
}
|
||||
{
|
||||
video::SColor bgcolor(50,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIDeathScreen::OnEvent(const SEvent& event)
|
||||
{
|
||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
||||
{
|
||||
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
|
||||
{
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
|
||||
{
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.EventType==EET_GUI_EVENT)
|
||||
{
|
||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
||||
&& isVisible())
|
||||
{
|
||||
if(!canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
dstream<<"GUIDeathScreen: Not allowing focus change."
|
||||
<<std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
||||
{
|
||||
switch(event.GUIEvent.Caller->getID())
|
||||
{
|
||||
case 257:
|
||||
respawn();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
void GUIDeathScreen::respawn()
|
||||
{
|
||||
m_respawner->respawn();
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GUIMESSAGEMENU_HEADER
|
||||
#define GUIMESSAGEMENU_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "modalMenu.h"
|
||||
#include "utility.h"
|
||||
#include <string>
|
||||
|
||||
class IRespawnInitiator
|
||||
{
|
||||
public:
|
||||
virtual void respawn() = 0;
|
||||
};
|
||||
|
||||
class GUIDeathScreen : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIDeathScreen(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr, IRespawnInitiator *respawner);
|
||||
~GUIDeathScreen();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent& event);
|
||||
|
||||
void respawn();
|
||||
|
||||
private:
|
||||
IRespawnInitiator *m_respawner;
|
||||
v2u32 m_screensize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -22,6 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "constants.h"
|
||||
#include "keycode.h"
|
||||
#include "strfnd.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
void drawInventoryItem(video::IVideoDriver *driver,
|
||||
gui::IGUIFont *font,
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
#include "serialization.h"
|
||||
#include "main.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "settings.h"
|
||||
|
||||
GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
|
||||
|
@ -340,20 +346,20 @@ void GUIKeyChangeMenu::drawMenu()
|
|||
|
||||
bool GUIKeyChangeMenu::acceptInput()
|
||||
{
|
||||
g_settings.set("keymap_forward", key_forward.sym());
|
||||
g_settings.set("keymap_backward", key_backward.sym());
|
||||
g_settings.set("keymap_left", key_left.sym());
|
||||
g_settings.set("keymap_right", key_right.sym());
|
||||
g_settings.set("keymap_jump", key_jump.sym());
|
||||
g_settings.set("keymap_sneak", key_sneak.sym());
|
||||
g_settings.set("keymap_inventory", key_inventory.sym());
|
||||
g_settings.set("keymap_chat", key_chat.sym());
|
||||
g_settings.set("keymap_cmd", key_cmd.sym());
|
||||
g_settings.set("keymap_rangeselect", key_range.sym());
|
||||
g_settings.set("keymap_freemove", key_fly.sym());
|
||||
g_settings.set("keymap_fastmove", key_fast.sym());
|
||||
g_settings.set("keymap_special1", key_use.sym());
|
||||
g_settings.set("keymap_print_debug_stacks", key_dump.sym());
|
||||
g_settings->set("keymap_forward", key_forward.sym());
|
||||
g_settings->set("keymap_backward", key_backward.sym());
|
||||
g_settings->set("keymap_left", key_left.sym());
|
||||
g_settings->set("keymap_right", key_right.sym());
|
||||
g_settings->set("keymap_jump", key_jump.sym());
|
||||
g_settings->set("keymap_sneak", key_sneak.sym());
|
||||
g_settings->set("keymap_inventory", key_inventory.sym());
|
||||
g_settings->set("keymap_chat", key_chat.sym());
|
||||
g_settings->set("keymap_cmd", key_cmd.sym());
|
||||
g_settings->set("keymap_rangeselect", key_range.sym());
|
||||
g_settings->set("keymap_freemove", key_fly.sym());
|
||||
g_settings->set("keymap_fastmove", key_fast.sym());
|
||||
g_settings->set("keymap_special1", key_use.sym());
|
||||
g_settings->set("keymap_print_debug_stacks", key_dump.sym());
|
||||
clearKeyCache();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
|
||||
#include "gettext.h"
|
||||
|
|
|
@ -21,6 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
|
|
@ -20,6 +20,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
|
|
@ -23,6 +23,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "porting.h"
|
||||
#include "config.h"
|
||||
#include "main.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
|
|
@ -21,6 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
|||
{
|
||||
std::string inventorystring;
|
||||
std::getline(is, inventorystring, '|');
|
||||
return new MapBlockObjectItem(inventorystring);
|
||||
throw SerializationError("MBOItem not supported anymore");
|
||||
}
|
||||
else if(name == "CraftItem")
|
||||
{
|
||||
|
@ -158,7 +158,7 @@ InventoryItem *MaterialItem::createCookResult() const
|
|||
*/
|
||||
|
||||
#ifndef SERVER
|
||||
video::ITexture * CraftItem::getImage()
|
||||
video::ITexture * CraftItem::getImage() const
|
||||
{
|
||||
if(g_texturesource == NULL)
|
||||
return NULL;
|
||||
|
@ -219,77 +219,6 @@ bool CraftItem::use(ServerEnvironment *env, Player *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
MapBlockObjectItem DEPRECATED
|
||||
TODO: Remove
|
||||
*/
|
||||
#ifndef SERVER
|
||||
video::ITexture * MapBlockObjectItem::getImage()
|
||||
{
|
||||
if(m_inventorystring.substr(0,3) == "Rat")
|
||||
return g_texturesource->getTextureRaw("rat.png");
|
||||
|
||||
if(m_inventorystring.substr(0,4) == "Sign")
|
||||
return g_texturesource->getTextureRaw("sign.png");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
std::string MapBlockObjectItem::getText()
|
||||
{
|
||||
if(m_inventorystring.substr(0,3) == "Rat")
|
||||
return "";
|
||||
|
||||
if(m_inventorystring.substr(0,4) == "Sign")
|
||||
return "";
|
||||
|
||||
return "obj";
|
||||
}
|
||||
|
||||
MapBlockObject * MapBlockObjectItem::createObject
|
||||
(v3f pos, f32 player_yaw, f32 player_pitch)
|
||||
{
|
||||
std::istringstream is(m_inventorystring);
|
||||
std::string name;
|
||||
std::getline(is, name, ' ');
|
||||
|
||||
if(name == "None")
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if(name == "Sign")
|
||||
{
|
||||
std::string text;
|
||||
std::getline(is, text, '|');
|
||||
SignObject *obj = new SignObject(NULL, -1, pos);
|
||||
obj->setText(text);
|
||||
obj->setYaw(-player_yaw);
|
||||
return obj;
|
||||
}
|
||||
else if(name == "Rat")
|
||||
{
|
||||
RatObject *obj = new RatObject(NULL, -1, pos);
|
||||
return obj;
|
||||
}
|
||||
else if(name == "ItemObj")
|
||||
{
|
||||
/*
|
||||
Now we are an inventory item containing the serialization
|
||||
string of an object that contains the serialization
|
||||
string of an inventory item. Fuck this.
|
||||
*/
|
||||
//assert(0);
|
||||
dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj "
|
||||
<<"because an item-object should never be inside "
|
||||
<<"an object-item."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Inventory
|
||||
*/
|
||||
|
|
135
src/inventory.h
|
@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <string>
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
#include "mapblockobject.h"
|
||||
#include "main.h" // For g_materials
|
||||
#include "mapnode.h" // For content_t
|
||||
|
||||
|
@ -53,8 +52,12 @@ public:
|
|||
// Shall make an exact clone of the item
|
||||
virtual InventoryItem* clone() = 0;
|
||||
#ifndef SERVER
|
||||
// Shall return an image to show in the GUI (or NULL)
|
||||
virtual video::ITexture * getImage() { return NULL; }
|
||||
// Return the name of the image for this item
|
||||
virtual std::string getBasename() const { return ""; }
|
||||
// Shall return an image of the item (or NULL)
|
||||
virtual video::ITexture * getImage() const { return NULL; }
|
||||
// Shall return an image of the item without embellishments (or NULL)
|
||||
virtual video::ITexture * getImageRaw() const { return getImage(); }
|
||||
#endif
|
||||
// Shall return a text to show in the GUI
|
||||
virtual std::string getText() { return ""; }
|
||||
|
@ -149,10 +152,9 @@ public:
|
|||
return new MaterialItem(m_content, m_count);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage()
|
||||
video::ITexture * getImage() const
|
||||
{
|
||||
return content_features(m_content).inventory_texture;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
std::string getText()
|
||||
|
@ -193,56 +195,6 @@ private:
|
|||
content_t m_content;
|
||||
};
|
||||
|
||||
//TODO: Remove
|
||||
class MapBlockObjectItem : public InventoryItem
|
||||
{
|
||||
public:
|
||||
MapBlockObjectItem(std::string inventorystring):
|
||||
InventoryItem(1)
|
||||
{
|
||||
m_inventorystring = inventorystring;
|
||||
}
|
||||
|
||||
/*
|
||||
Implementation interface
|
||||
*/
|
||||
virtual const char* getName() const
|
||||
{
|
||||
return "MBOItem";
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
std::string sane_string(m_inventorystring);
|
||||
str_replace_char(sane_string, '|', '?');
|
||||
os<<getName();
|
||||
os<<" ";
|
||||
os<<sane_string;
|
||||
os<<"|";
|
||||
}
|
||||
virtual InventoryItem* clone()
|
||||
{
|
||||
return new MapBlockObjectItem(m_inventorystring);
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage();
|
||||
#endif
|
||||
std::string getText();
|
||||
|
||||
/*
|
||||
Special methods
|
||||
*/
|
||||
std::string getInventoryString()
|
||||
{
|
||||
return m_inventorystring;
|
||||
}
|
||||
|
||||
MapBlockObject * createObject(v3f pos, f32 player_yaw, f32 player_pitch);
|
||||
|
||||
private:
|
||||
std::string m_inventorystring;
|
||||
};
|
||||
|
||||
/*
|
||||
An item that is used as a mid-product when crafting.
|
||||
Subnames:
|
||||
|
@ -276,7 +228,7 @@ public:
|
|||
return new CraftItem(m_subname, m_count);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage();
|
||||
video::ITexture * getImage() const;
|
||||
#endif
|
||||
std::string getText()
|
||||
{
|
||||
|
@ -353,40 +305,43 @@ public:
|
|||
return new ToolItem(m_toolname, m_wear);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage()
|
||||
std::string getBasename() const {
|
||||
if(m_toolname == "WPick")
|
||||
return "tool_woodpick.png";
|
||||
else if(m_toolname == "STPick")
|
||||
return "tool_stonepick.png";
|
||||
else if(m_toolname == "SteelPick")
|
||||
return "tool_steelpick.png";
|
||||
else if(m_toolname == "MesePick")
|
||||
return "tool_mesepick.png";
|
||||
else if(m_toolname == "WShovel")
|
||||
return "tool_woodshovel.png";
|
||||
else if(m_toolname == "STShovel")
|
||||
return "tool_stoneshovel.png";
|
||||
else if(m_toolname == "SteelShovel")
|
||||
return "tool_steelshovel.png";
|
||||
else if(m_toolname == "WAxe")
|
||||
return "tool_woodaxe.png";
|
||||
else if(m_toolname == "STAxe")
|
||||
return "tool_stoneaxe.png";
|
||||
else if(m_toolname == "SteelAxe")
|
||||
return "tool_steelaxe.png";
|
||||
else if(m_toolname == "WSword")
|
||||
return "tool_woodsword.png";
|
||||
else if(m_toolname == "STSword")
|
||||
return "tool_stonesword.png";
|
||||
else if(m_toolname == "SteelSword")
|
||||
return "tool_steelsword.png";
|
||||
else
|
||||
return "cloud.png";
|
||||
}
|
||||
|
||||
video::ITexture * getImage() const
|
||||
{
|
||||
if(g_texturesource == NULL)
|
||||
return NULL;
|
||||
|
||||
std::string basename;
|
||||
if(m_toolname == "WPick")
|
||||
basename = "tool_woodpick.png";
|
||||
else if(m_toolname == "STPick")
|
||||
basename = "tool_stonepick.png";
|
||||
else if(m_toolname == "SteelPick")
|
||||
basename = "tool_steelpick.png";
|
||||
else if(m_toolname == "MesePick")
|
||||
basename = "tool_mesepick.png";
|
||||
else if(m_toolname == "WShovel")
|
||||
basename = "tool_woodshovel.png";
|
||||
else if(m_toolname == "STShovel")
|
||||
basename = "tool_stoneshovel.png";
|
||||
else if(m_toolname == "SteelShovel")
|
||||
basename = "tool_steelshovel.png";
|
||||
else if(m_toolname == "WAxe")
|
||||
basename = "tool_woodaxe.png";
|
||||
else if(m_toolname == "STAxe")
|
||||
basename = "tool_stoneaxe.png";
|
||||
else if(m_toolname == "SteelAxe")
|
||||
basename = "tool_steelaxe.png";
|
||||
else if(m_toolname == "WSword")
|
||||
basename = "tool_woodsword.png";
|
||||
else if(m_toolname == "STSword")
|
||||
basename = "tool_stonesword.png";
|
||||
else if(m_toolname == "SteelSword")
|
||||
basename = "tool_steelsword.png";
|
||||
else
|
||||
basename = "cloud.png";
|
||||
std::string basename = getBasename();
|
||||
|
||||
/*
|
||||
Calculate a progress value with sane amount of
|
||||
|
@ -401,6 +356,14 @@ public:
|
|||
|
||||
return g_texturesource->getTextureRaw(os.str());
|
||||
}
|
||||
|
||||
video::ITexture * getImageRaw() const
|
||||
{
|
||||
if(g_texturesource == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_texturesource->getTextureRaw(getBasename());
|
||||
}
|
||||
#endif
|
||||
std::string getText()
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "keycode.h"
|
||||
#include "main.h" // For g_settings
|
||||
#include "exceptions.h"
|
||||
#include "settings.h"
|
||||
|
||||
class UnknownKeycode : public BaseException
|
||||
{
|
||||
|
@ -334,7 +335,7 @@ KeyPress getKeySetting(const char *settingname)
|
|||
if(n)
|
||||
return n->getValue();
|
||||
g_key_setting_cache.insert(settingname,
|
||||
g_settings.get(settingname).c_str());
|
||||
g_settings->get(settingname).c_str());
|
||||
return g_key_setting_cache.find(settingname)->getValue();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include "threads.h"
|
||||
#include "debug.h"
|
||||
#include "gettime.h"
|
||||
|
||||
std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
|
||||
std::map<threadid_t, std::string> log_threadnames;
|
||||
|
||||
void log_add_output(ILogOutput *out, enum LogMessageLevel lev)
|
||||
{
|
||||
log_outputs[lev].push_back(out);
|
||||
}
|
||||
|
||||
void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev)
|
||||
{
|
||||
for(int i=0; i<=lev; i++)
|
||||
log_outputs[i].push_back(out);
|
||||
}
|
||||
|
||||
void log_add_output_all_levs(ILogOutput *out)
|
||||
{
|
||||
for(int i=0; i<LMT_NUM_VALUES; i++)
|
||||
log_outputs[i].push_back(out);
|
||||
}
|
||||
|
||||
void log_register_thread(const std::string &name)
|
||||
{
|
||||
threadid_t id = get_current_thread_id();
|
||||
log_threadnames[id] = name;
|
||||
}
|
||||
|
||||
static std::string get_lev_string(enum LogMessageLevel lev)
|
||||
{
|
||||
switch(lev){
|
||||
case LMT_ERROR:
|
||||
return "ERROR";
|
||||
case LMT_ACTION:
|
||||
return "ACTION";
|
||||
case LMT_INFO:
|
||||
return "INFO";
|
||||
case LMT_VERBOSE:
|
||||
return "VERBOSE";
|
||||
case LMT_NUM_VALUES:
|
||||
break;
|
||||
}
|
||||
return "(unknown level)";
|
||||
}
|
||||
|
||||
void log_printline(enum LogMessageLevel lev, const std::string &text)
|
||||
{
|
||||
std::string threadname = "(unknown thread)";
|
||||
std::map<threadid_t, std::string>::const_iterator i;
|
||||
i = log_threadnames.find(get_current_thread_id());
|
||||
if(i != log_threadnames.end())
|
||||
threadname = i->second;
|
||||
std::string levelname = get_lev_string(lev);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
os<<getTimestamp()<<": "<<levelname<<"["<<threadname<<"]: "<<text;
|
||||
for(std::list<ILogOutput*>::iterator i = log_outputs[lev].begin();
|
||||
i != log_outputs[lev].end(); i++){
|
||||
ILogOutput *out = *i;
|
||||
out->printLog(os.str());
|
||||
out->printLog(lev, text);
|
||||
}
|
||||
}
|
||||
|
||||
class Logbuf : public std::streambuf
|
||||
{
|
||||
public:
|
||||
Logbuf(enum LogMessageLevel lev):
|
||||
m_lev(lev)
|
||||
{
|
||||
}
|
||||
|
||||
~Logbuf()
|
||||
{
|
||||
}
|
||||
|
||||
int overflow(int c)
|
||||
{
|
||||
bufchar(c);
|
||||
return c;
|
||||
}
|
||||
std::streamsize xsputn(const char *s, std::streamsize n)
|
||||
{
|
||||
for(int i=0; i<n; i++)
|
||||
bufchar(s[i]);
|
||||
return n;
|
||||
}
|
||||
|
||||
void printbuf()
|
||||
{
|
||||
log_printline(m_lev, m_buf);
|
||||
}
|
||||
|
||||
void bufchar(char c)
|
||||
{
|
||||
if(c == '\n' || c == '\r'){
|
||||
if(m_buf != "")
|
||||
printbuf();
|
||||
m_buf = "";
|
||||
return;
|
||||
}
|
||||
m_buf += c;
|
||||
}
|
||||
|
||||
private:
|
||||
enum LogMessageLevel m_lev;
|
||||
std::string m_buf;
|
||||
};
|
||||
|
||||
Logbuf errorbuf(LMT_ERROR);
|
||||
Logbuf actionbuf(LMT_ACTION);
|
||||
Logbuf infobuf(LMT_INFO);
|
||||
Logbuf verbosebuf(LMT_VERBOSE);
|
||||
std::ostream errorstream(&errorbuf);
|
||||
std::ostream actionstream(&actionbuf);
|
||||
std::ostream infostream(&infobuf);
|
||||
std::ostream verbosestream(&verbosebuf);
|
||||
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef LOG_HEADER
|
||||
#define LOG_HEADER
|
||||
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
Use this for logging everything.
|
||||
|
||||
If you need to explicitly print something, use dstream or cout or cerr.
|
||||
*/
|
||||
|
||||
enum LogMessageLevel {
|
||||
LMT_ERROR, /* Something failed ("invalid map data on disk, block (2,2,1)") */
|
||||
LMT_ACTION, /* In-game actions ("celeron55 placed block at (12,4,-5)") */
|
||||
LMT_INFO, /* More deep info ("saving map on disk (only_modified=true)") */
|
||||
LMT_VERBOSE, /* Flood-style ("loaded block (2,2,2) from disk") */
|
||||
LMT_NUM_VALUES,
|
||||
};
|
||||
|
||||
class ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
virtual void printLog(const std::string &line){};
|
||||
/* line: Only actual printed text */
|
||||
virtual void printLog(enum LogMessageLevel lev, const std::string &line){};
|
||||
};
|
||||
|
||||
void log_add_output(ILogOutput *out, enum LogMessageLevel lev);
|
||||
void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev);
|
||||
void log_add_output_all_levs(ILogOutput *out);
|
||||
|
||||
void log_register_thread(const std::string &name);
|
||||
|
||||
void log_printline(enum LogMessageLevel lev, const std::string &text);
|
||||
|
||||
#define LOGLINEF(lev, ...)\
|
||||
{\
|
||||
char buf[10000];\
|
||||
snprintf(buf, 10000, __VA_ARGS__);\
|
||||
log_printline(lev, buf);\
|
||||
}
|
||||
|
||||
extern std::ostream errorstream;
|
||||
extern std::ostream actionstream;
|
||||
extern std::ostream infostream;
|
||||
extern std::ostream verbosestream;
|
||||
|
||||
#endif
|
||||
|
157
src/main.cpp
|
@ -411,10 +411,13 @@ Doing currently:
|
|||
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
|
||||
#endif
|
||||
|
||||
#include "irrlicht.h" // createDevice
|
||||
|
||||
#include "main.h"
|
||||
#include "mainmenumanager.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <locale.h>
|
||||
#include "main.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
#include "test.h"
|
||||
|
@ -431,8 +434,11 @@ Doing currently:
|
|||
#include "game.h"
|
||||
#include "keycode.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include "defaultsettings.h"
|
||||
#include "gettext.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
|
||||
// This makes textures
|
||||
ITextureSource *g_texturesource = NULL;
|
||||
|
@ -441,25 +447,23 @@ ITextureSource *g_texturesource = NULL;
|
|||
Settings.
|
||||
These are loaded from the config file.
|
||||
*/
|
||||
|
||||
Settings g_settings;
|
||||
// This is located in defaultsettings.cpp
|
||||
extern void set_default_settings();
|
||||
Settings main_settings;
|
||||
Settings *g_settings = &main_settings;
|
||||
|
||||
// Global profiler
|
||||
Profiler g_profiler;
|
||||
Profiler main_profiler;
|
||||
Profiler *g_profiler = &main_profiler;
|
||||
|
||||
/*
|
||||
Random stuff
|
||||
*/
|
||||
|
||||
/*
|
||||
GUI Stuff
|
||||
mainmenumanager.h
|
||||
*/
|
||||
|
||||
gui::IGUIEnvironment* guienv = NULL;
|
||||
gui::IGUIStaticText *guiroot = NULL;
|
||||
|
||||
MainMenuManager g_menumgr;
|
||||
|
||||
bool noMenuActive()
|
||||
|
@ -468,7 +472,6 @@ bool noMenuActive()
|
|||
}
|
||||
|
||||
// Passed to menus to allow disconnecting and exiting
|
||||
|
||||
MainGameCallback *g_gamecallback = NULL;
|
||||
|
||||
/*
|
||||
|
@ -477,19 +480,15 @@ MainGameCallback *g_gamecallback = NULL;
|
|||
|
||||
// Connection
|
||||
std::ostream *dout_con_ptr = &dummyout;
|
||||
std::ostream *derr_con_ptr = &dstream_no_stderr;
|
||||
//std::ostream *dout_con_ptr = &dstream_no_stderr;
|
||||
//std::ostream *derr_con_ptr = &dstream_no_stderr;
|
||||
//std::ostream *dout_con_ptr = &dstream;
|
||||
//std::ostream *derr_con_ptr = &dstream;
|
||||
std::ostream *derr_con_ptr = &verbosestream;
|
||||
|
||||
// Server
|
||||
std::ostream *dout_server_ptr = &dstream;
|
||||
std::ostream *derr_server_ptr = &dstream;
|
||||
std::ostream *dout_server_ptr = &infostream;
|
||||
std::ostream *derr_server_ptr = &errorstream;
|
||||
|
||||
// Client
|
||||
std::ostream *dout_client_ptr = &dstream;
|
||||
std::ostream *derr_client_ptr = &dstream;
|
||||
std::ostream *dout_client_ptr = &infostream;
|
||||
std::ostream *derr_client_ptr = &errorstream;
|
||||
|
||||
/*
|
||||
gettime.h implementation
|
||||
|
@ -581,7 +580,6 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
//dstream<<"MyEventReceiver: mouse input"<<std::endl;
|
||||
left_active = event.MouseInput.isLeftPressed();
|
||||
middle_active = event.MouseInput.isMiddlePressed();
|
||||
right_active = event.MouseInput.isRightPressed();
|
||||
|
@ -1024,7 +1022,7 @@ void SpeedTests()
|
|||
|
||||
u32 dtime = timer.stop();
|
||||
u32 per_ms = n / dtime;
|
||||
std::cout<<"Done. "<<dtime<<"ms, "
|
||||
dstream<<"Done. "<<dtime<<"ms, "
|
||||
<<per_ms<<"/ms"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1076,12 +1074,37 @@ void drawMenuBackground(video::IVideoDriver* driver)
|
|||
}
|
||||
}
|
||||
|
||||
class DstreamLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
dstream<<line<<std::endl;
|
||||
}
|
||||
} main_dstream_log_out;
|
||||
|
||||
class DstreamNoStderrLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
dstream_no_stderr<<line<<std::endl;
|
||||
}
|
||||
} main_dstream_no_stderr_log_out;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/*
|
||||
Initialization
|
||||
*/
|
||||
|
||||
log_add_output_maxlev(&main_dstream_log_out, LMT_ACTION);
|
||||
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
||||
|
||||
log_register_thread("main");
|
||||
|
||||
// Set locale. This is for forcing '.' as the decimal point.
|
||||
std::locale::global(std::locale("C"));
|
||||
// This enables printing all characters in bitmap font
|
||||
|
@ -1108,6 +1131,7 @@ int main(int argc, char *argv[])
|
|||
allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG));
|
||||
#endif
|
||||
allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG));
|
||||
allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG));
|
||||
|
||||
Settings cmd_args;
|
||||
|
||||
|
@ -1149,6 +1173,9 @@ int main(int argc, char *argv[])
|
|||
if(cmd_args.getFlag("dstream-on-stderr") == false)
|
||||
disable_stderr = true;
|
||||
#endif
|
||||
|
||||
if(cmd_args.getFlag("info-on-stderr"))
|
||||
log_add_output(&main_dstream_log_out, LMT_INFO);
|
||||
|
||||
porting::signal_handler_init();
|
||||
bool &kill = *porting::signal_handler_killstatus();
|
||||
|
@ -1159,13 +1186,13 @@ int main(int argc, char *argv[])
|
|||
// Create user data directory
|
||||
fs::CreateDir(porting::path_userdata);
|
||||
|
||||
init_gettext((porting::path_data+"/../locale").c_str());
|
||||
init_gettext((porting::path_data+DIR_DELIM+".."+DIR_DELIM+"locale").c_str());
|
||||
|
||||
// Initialize debug streams
|
||||
#ifdef RUN_IN_PLACE
|
||||
std::string debugfile = DEBUGFILE;
|
||||
#else
|
||||
std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;
|
||||
std::string debugfile = porting::path_userdata+DIR_DELIM+DEBUGFILE;
|
||||
#endif
|
||||
debugstreams_init(disable_stderr, debugfile.c_str());
|
||||
// Initialize debug stacks
|
||||
|
@ -1180,7 +1207,7 @@ int main(int argc, char *argv[])
|
|||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
// Print startup message
|
||||
dstream<<DTIME<<PROJECT_NAME
|
||||
actionstream<<PROJECT_NAME<<
|
||||
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
|
||||
<<", "<<BUILD_INFO
|
||||
<<std::endl;
|
||||
|
@ -1190,7 +1217,7 @@ int main(int argc, char *argv[])
|
|||
*/
|
||||
|
||||
// Initialize default settings
|
||||
set_default_settings();
|
||||
set_default_settings(g_settings);
|
||||
|
||||
// Initialize sockets
|
||||
sockets_init();
|
||||
|
@ -1205,10 +1232,10 @@ int main(int argc, char *argv[])
|
|||
|
||||
if(cmd_args.exists("config"))
|
||||
{
|
||||
bool r = g_settings.readConfigFile(cmd_args.get("config").c_str());
|
||||
bool r = g_settings->readConfigFile(cmd_args.get("config").c_str());
|
||||
if(r == false)
|
||||
{
|
||||
dstream<<"Could not read configuration from \""
|
||||
errorstream<<"Could not read configuration from \""
|
||||
<<cmd_args.get("config")<<"\""<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1217,14 +1244,16 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
{
|
||||
core::array<std::string> filenames;
|
||||
filenames.push_back(porting::path_userdata + "/minetest.conf");
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + "minetest.conf");
|
||||
#ifdef RUN_IN_PLACE
|
||||
filenames.push_back(porting::path_userdata + "/../minetest.conf");
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + ".." + DIR_DELIM + "minetest.conf");
|
||||
#endif
|
||||
|
||||
for(u32 i=0; i<filenames.size(); i++)
|
||||
{
|
||||
bool r = g_settings.readConfigFile(filenames[i].c_str());
|
||||
bool r = g_settings->readConfigFile(filenames[i].c_str());
|
||||
if(r)
|
||||
{
|
||||
configpath = filenames[i];
|
||||
|
@ -1275,17 +1304,17 @@ int main(int argc, char *argv[])
|
|||
u16 port = 30000;
|
||||
if(cmd_args.exists("port"))
|
||||
port = cmd_args.getU16("port");
|
||||
else if(g_settings.exists("port"))
|
||||
port = g_settings.getU16("port");
|
||||
else if(g_settings->exists("port"))
|
||||
port = g_settings->getU16("port");
|
||||
if(port == 0)
|
||||
port = 30000;
|
||||
|
||||
// Map directory
|
||||
std::string map_dir = porting::path_userdata+"/world";
|
||||
std::string map_dir = porting::path_userdata+DIR_DELIM+"world";
|
||||
if(cmd_args.exists("map-dir"))
|
||||
map_dir = cmd_args.get("map-dir");
|
||||
else if(g_settings.exists("map-dir"))
|
||||
map_dir = g_settings.get("map-dir");
|
||||
else if(g_settings->exists("map-dir"))
|
||||
map_dir = g_settings->get("map-dir");
|
||||
|
||||
// Run dedicated server if asked to
|
||||
if(cmd_args.getFlag("server"))
|
||||
|
@ -1319,10 +1348,10 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
address = g_settings.get("address");
|
||||
address = g_settings->get("address");
|
||||
}
|
||||
|
||||
std::string playername = g_settings.get("name");
|
||||
std::string playername = g_settings->get("name");
|
||||
|
||||
/*
|
||||
Device initialization
|
||||
|
@ -1331,14 +1360,14 @@ int main(int argc, char *argv[])
|
|||
// Resolution selection
|
||||
|
||||
bool fullscreen = false;
|
||||
u16 screenW = g_settings.getU16("screenW");
|
||||
u16 screenH = g_settings.getU16("screenH");
|
||||
u16 screenW = g_settings->getU16("screenW");
|
||||
u16 screenH = g_settings->getU16("screenH");
|
||||
|
||||
// Determine driver
|
||||
|
||||
video::E_DRIVER_TYPE driverType;
|
||||
|
||||
std::string driverstring = g_settings.get("video_driver");
|
||||
std::string driverstring = g_settings->get("video_driver");
|
||||
|
||||
if(driverstring == "null")
|
||||
driverType = video::EDT_NULL;
|
||||
|
@ -1354,7 +1383,7 @@ int main(int argc, char *argv[])
|
|||
driverType = video::EDT_OPENGL;
|
||||
else
|
||||
{
|
||||
dstream<<"WARNING: Invalid video_driver specified; defaulting "
|
||||
errorstream<<"WARNING: Invalid video_driver specified; defaulting "
|
||||
"to opengl"<<std::endl;
|
||||
driverType = video::EDT_OPENGL;
|
||||
}
|
||||
|
@ -1397,7 +1426,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
device->setResizable(true);
|
||||
|
||||
bool random_input = g_settings.getBool("random_input")
|
||||
bool random_input = g_settings->getBool("random_input")
|
||||
|| cmd_args.getFlag("random-input");
|
||||
InputHandler *input = NULL;
|
||||
if(random_input)
|
||||
|
@ -1425,14 +1454,14 @@ int main(int argc, char *argv[])
|
|||
if(font)
|
||||
skin->setFont(font);
|
||||
else
|
||||
dstream<<"WARNING: Font file was not found."
|
||||
errorstream<<"WARNING: Font file was not found."
|
||||
" Using default font."<<std::endl;
|
||||
// If font was not found, this will get us one
|
||||
font = skin->getFont();
|
||||
assert(font);
|
||||
|
||||
u32 text_height = font->getDimension(L"Hello, world!").Height;
|
||||
dstream<<"text_height="<<text_height<<std::endl;
|
||||
infostream<<"text_height="<<text_height<<std::endl;
|
||||
|
||||
//skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0));
|
||||
skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255));
|
||||
|
@ -1508,10 +1537,10 @@ int main(int argc, char *argv[])
|
|||
menudata.address = narrow_to_wide(address);
|
||||
menudata.name = narrow_to_wide(playername);
|
||||
menudata.port = narrow_to_wide(itos(port));
|
||||
menudata.fancy_trees = g_settings.getBool("new_style_leaves");
|
||||
menudata.smooth_lighting = g_settings.getBool("smooth_lighting");
|
||||
menudata.creative_mode = g_settings.getBool("creative_mode");
|
||||
menudata.enable_damage = g_settings.getBool("enable_damage");
|
||||
menudata.fancy_trees = g_settings->getBool("new_style_leaves");
|
||||
menudata.smooth_lighting = g_settings->getBool("smooth_lighting");
|
||||
menudata.creative_mode = g_settings->getBool("creative_mode");
|
||||
menudata.enable_damage = g_settings->getBool("enable_damage");
|
||||
|
||||
GUIMainMenu *menu =
|
||||
new GUIMainMenu(guienv, guiroot, -1,
|
||||
|
@ -1520,7 +1549,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if(error_message != L"")
|
||||
{
|
||||
dstream<<"WARNING: error_message = "
|
||||
errorstream<<"error_message = "
|
||||
<<wide_to_narrow(error_message)<<std::endl;
|
||||
|
||||
GUIMessageMenu *menu2 =
|
||||
|
@ -1532,7 +1561,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
|
||||
dstream<<"Created main menu"<<std::endl;
|
||||
infostream<<"Created main menu"<<std::endl;
|
||||
|
||||
while(device->run() && kill == false)
|
||||
{
|
||||
|
@ -1557,7 +1586,7 @@ int main(int argc, char *argv[])
|
|||
if(device->run() == false || kill == true)
|
||||
break;
|
||||
|
||||
dstream<<"Dropping main menu"<<std::endl;
|
||||
infostream<<"Dropping main menu"<<std::endl;
|
||||
|
||||
menu->drop();
|
||||
|
||||
|
@ -1574,16 +1603,16 @@ int main(int argc, char *argv[])
|
|||
|
||||
password = translatePassword(playername, menudata.password);
|
||||
|
||||
//dstream<<"Main: password hash: '"<<password<<"'"<<std::endl;
|
||||
//infostream<<"Main: password hash: '"<<password<<"'"<<std::endl;
|
||||
|
||||
address = wide_to_narrow(menudata.address);
|
||||
int newport = stoi(wide_to_narrow(menudata.port));
|
||||
if(newport != 0)
|
||||
port = newport;
|
||||
g_settings.set("new_style_leaves", itos(menudata.fancy_trees));
|
||||
g_settings.set("smooth_lighting", itos(menudata.smooth_lighting));
|
||||
g_settings.set("creative_mode", itos(menudata.creative_mode));
|
||||
g_settings.set("enable_damage", itos(menudata.enable_damage));
|
||||
g_settings->set("new_style_leaves", itos(menudata.fancy_trees));
|
||||
g_settings->set("smooth_lighting", itos(menudata.smooth_lighting));
|
||||
g_settings->set("creative_mode", itos(menudata.creative_mode));
|
||||
g_settings->set("enable_damage", itos(menudata.enable_damage));
|
||||
|
||||
// NOTE: These are now checked server side; no need to do it
|
||||
// here, so let's not do it here.
|
||||
|
@ -1602,12 +1631,12 @@ int main(int argc, char *argv[])
|
|||
}*/
|
||||
|
||||
// Save settings
|
||||
g_settings.set("name", playername);
|
||||
g_settings.set("address", address);
|
||||
g_settings.set("port", itos(port));
|
||||
g_settings->set("name", playername);
|
||||
g_settings->set("address", address);
|
||||
g_settings->set("port", itos(port));
|
||||
// Update configuration file
|
||||
if(configpath != "")
|
||||
g_settings.updateConfigFile(configpath.c_str());
|
||||
g_settings->updateConfigFile(configpath.c_str());
|
||||
|
||||
// Continue to game
|
||||
break;
|
||||
|
@ -1641,12 +1670,12 @@ int main(int argc, char *argv[])
|
|||
} //try
|
||||
catch(con::PeerNotFoundException &e)
|
||||
{
|
||||
dstream<<DTIME<<"Connection error (timed out?)"<<std::endl;
|
||||
errorstream<<"Connection error (timed out?)"<<std::endl;
|
||||
error_message = L"Connection error (timed out?)";
|
||||
}
|
||||
catch(SocketException &e)
|
||||
{
|
||||
dstream<<DTIME<<"Socket error (port already in use?)"<<std::endl;
|
||||
errorstream<<"Socket error (port already in use?)"<<std::endl;
|
||||
error_message = L"Socket error (port already in use?)";
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
|
@ -1655,7 +1684,7 @@ int main(int argc, char *argv[])
|
|||
std::string narrow_message = "Some exception, what()=\"";
|
||||
narrow_message += e.what();
|
||||
narrow_message += "\"";
|
||||
dstream<<DTIME<<narrow_message<<std::endl;
|
||||
errorstream<<narrow_message<<std::endl;
|
||||
error_message = narrow_to_wide(narrow_message);
|
||||
}
|
||||
#endif
|
||||
|
@ -1669,7 +1698,7 @@ int main(int argc, char *argv[])
|
|||
*/
|
||||
device->drop();
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
|
||||
debugstreams_deinit();
|
||||
|
||||
|
|
108
src/main.h
|
@ -21,16 +21,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MAIN_HEADER
|
||||
|
||||
// Settings
|
||||
#include "utility.h"
|
||||
extern Settings g_settings;
|
||||
class Settings;
|
||||
extern Settings *g_settings;
|
||||
|
||||
// This makes and maps textures
|
||||
class ITextureSource;
|
||||
extern ITextureSource *g_texturesource;
|
||||
|
||||
// Global profiler
|
||||
#include "profiler.h"
|
||||
extern Profiler g_profiler;
|
||||
class Profiler;
|
||||
extern Profiler *g_profiler;
|
||||
|
||||
// Debug streams
|
||||
|
||||
|
@ -50,105 +50,5 @@ extern std::ostream *derr_server_ptr;
|
|||
#define dout_server (*dout_server_ptr)
|
||||
#define derr_server (*derr_server_ptr)
|
||||
|
||||
/*
|
||||
All kinds of stuff that needs to be exposed from main.cpp
|
||||
*/
|
||||
|
||||
#include "modalMenu.h"
|
||||
#include "guiPauseMenu.h" //For IGameCallback
|
||||
|
||||
extern gui::IGUIEnvironment* guienv;
|
||||
extern gui::IGUIStaticText *guiroot;
|
||||
|
||||
// Handler for the modal menus
|
||||
|
||||
class MainMenuManager : public IMenuManager
|
||||
{
|
||||
public:
|
||||
virtual void createdMenu(GUIModalMenu *menu)
|
||||
{
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
assert(*i != menu);
|
||||
}
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(false);
|
||||
m_stack.push_back(menu);
|
||||
}
|
||||
|
||||
virtual void deletingMenu(GUIModalMenu *menu)
|
||||
{
|
||||
// Remove all entries if there are duplicates
|
||||
bool removed_entry;
|
||||
do{
|
||||
removed_entry = false;
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
if(*i == menu)
|
||||
{
|
||||
m_stack.erase(i);
|
||||
removed_entry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(removed_entry);
|
||||
|
||||
/*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast();
|
||||
assert(*i == menu);
|
||||
m_stack.erase(i);*/
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(true);
|
||||
}
|
||||
|
||||
u32 menuCount()
|
||||
{
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
core::list<GUIModalMenu*> m_stack;
|
||||
};
|
||||
|
||||
extern MainMenuManager g_menumgr;
|
||||
|
||||
extern bool noMenuActive();
|
||||
|
||||
class MainGameCallback : public IGameCallback
|
||||
{
|
||||
public:
|
||||
MainGameCallback(IrrlichtDevice *a_device):
|
||||
disconnect_requested(false),
|
||||
changepassword_requested(false),
|
||||
device(a_device)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void exitToOS()
|
||||
{
|
||||
device->closeDevice();
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
disconnect_requested = true;
|
||||
}
|
||||
|
||||
virtual void changePassword()
|
||||
{
|
||||
changepassword_requested = true;
|
||||
}
|
||||
|
||||
bool disconnect_requested;
|
||||
bool changepassword_requested;
|
||||
IrrlichtDevice *device;
|
||||
};
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MAINMENUMANAGER_HEADER
|
||||
#define MAINMENUMANAGER_HEADER
|
||||
|
||||
/*
|
||||
All kinds of stuff that needs to be exposed from main.cpp
|
||||
*/
|
||||
#include "debug.h" // assert
|
||||
#include "modalMenu.h"
|
||||
#include "guiPauseMenu.h" //For IGameCallback
|
||||
|
||||
extern gui::IGUIEnvironment* guienv;
|
||||
extern gui::IGUIStaticText *guiroot;
|
||||
|
||||
// Handler for the modal menus
|
||||
|
||||
class MainMenuManager : public IMenuManager
|
||||
{
|
||||
public:
|
||||
virtual void createdMenu(GUIModalMenu *menu)
|
||||
{
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
assert(*i != menu);
|
||||
}
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(false);
|
||||
m_stack.push_back(menu);
|
||||
}
|
||||
|
||||
virtual void deletingMenu(GUIModalMenu *menu)
|
||||
{
|
||||
// Remove all entries if there are duplicates
|
||||
bool removed_entry;
|
||||
do{
|
||||
removed_entry = false;
|
||||
for(core::list<GUIModalMenu*>::Iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); i++)
|
||||
{
|
||||
if(*i == menu)
|
||||
{
|
||||
m_stack.erase(i);
|
||||
removed_entry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(removed_entry);
|
||||
|
||||
/*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast();
|
||||
assert(*i == menu);
|
||||
m_stack.erase(i);*/
|
||||
|
||||
if(m_stack.size() != 0)
|
||||
(*m_stack.getLast())->setVisible(true);
|
||||
}
|
||||
|
||||
u32 menuCount()
|
||||
{
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
core::list<GUIModalMenu*> m_stack;
|
||||
};
|
||||
|
||||
extern MainMenuManager g_menumgr;
|
||||
|
||||
extern bool noMenuActive();
|
||||
|
||||
class MainGameCallback : public IGameCallback
|
||||
{
|
||||
public:
|
||||
MainGameCallback(IrrlichtDevice *a_device):
|
||||
disconnect_requested(false),
|
||||
changepassword_requested(false),
|
||||
device(a_device)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void exitToOS()
|
||||
{
|
||||
device->closeDevice();
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
disconnect_requested = true;
|
||||
}
|
||||
|
||||
virtual void changePassword()
|
||||
{
|
||||
changepassword_requested = true;
|
||||
}
|
||||
|
||||
bool disconnect_requested;
|
||||
bool changepassword_requested;
|
||||
IrrlichtDevice *device;
|
||||
};
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
||||
|
||||
#endif
|
||||
|
277
src/map.cpp
|
@ -29,6 +29,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapgen.h"
|
||||
#include "nodemetadata.h"
|
||||
#include "content_mapnode.h"
|
||||
#ifndef SERVER
|
||||
#include <IMaterialRenderer.h>
|
||||
#endif
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
SQLite format specification:
|
||||
|
@ -342,7 +347,7 @@ void Map::unspreadLight(enum LightBank bank,
|
|||
*/
|
||||
/*if(light_sources.find(n2pos))
|
||||
{
|
||||
std::cout<<"Removed from light_sources"<<std::endl;
|
||||
infostream<<"Removed from light_sources"<<std::endl;
|
||||
light_sources.remove(n2pos);
|
||||
}*/
|
||||
}
|
||||
|
@ -373,7 +378,7 @@ void Map::unspreadLight(enum LightBank bank,
|
|||
}
|
||||
}
|
||||
|
||||
/*dstream<<"unspreadLight(): Changed block "
|
||||
/*infostream<<"unspreadLight(): Changed block "
|
||||
<<blockchangecount<<" times"
|
||||
<<" for "<<from_nodes.size()<<" nodes"
|
||||
<<std::endl;*/
|
||||
|
@ -435,7 +440,7 @@ void Map::spreadLight(enum LightBank bank,
|
|||
{
|
||||
v3s16 pos = j.getNode()->getKey();
|
||||
//v3s16 pos = *j;
|
||||
//dstream<<"pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
|
||||
//infostream<<"pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
|
||||
v3s16 blockpos = getNodeBlockPos(pos);
|
||||
|
||||
// Only fetch a new block if the block position has changed
|
||||
|
@ -540,7 +545,7 @@ void Map::spreadLight(enum LightBank bank,
|
|||
}
|
||||
}
|
||||
|
||||
/*dstream<<"spreadLight(): Changed block "
|
||||
/*infostream<<"spreadLight(): Changed block "
|
||||
<<blockchangecount<<" times"
|
||||
<<" for "<<from_nodes.size()<<" nodes"
|
||||
<<std::endl;*/
|
||||
|
@ -724,7 +729,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||
dummy block.
|
||||
*/
|
||||
//assert(0);
|
||||
dstream<<"updateLighting(): InvalidPositionException"
|
||||
infostream<<"updateLighting(): InvalidPositionException"
|
||||
<<std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -748,7 +753,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||
assert(0);
|
||||
}
|
||||
|
||||
/*dstream<<"Bottom for sunlight-propagated block ("
|
||||
/*infostream<<"Bottom for sunlight-propagated block ("
|
||||
<<pos.X<<","<<pos.Y<<","<<pos.Z<<") not valid"
|
||||
<<std::endl;*/
|
||||
|
||||
|
@ -771,7 +776,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||
generation for testing or whatever
|
||||
*/
|
||||
#if 0
|
||||
//if(g_settings.get(""))
|
||||
//if(g_settings->get(""))
|
||||
{
|
||||
core::map<v3s16, MapBlock*>::Iterator i;
|
||||
i = blocks_to_update.getIterator();
|
||||
|
@ -795,7 +800,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||
{
|
||||
u32 diff = modified_blocks.size() - count_was;
|
||||
count_was = modified_blocks.size();
|
||||
dstream<<"unspreadLight modified "<<diff<<std::endl;
|
||||
infostream<<"unspreadLight modified "<<diff<<std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -807,7 +812,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||
{
|
||||
u32 diff = modified_blocks.size() - count_was;
|
||||
count_was = modified_blocks.size();
|
||||
dstream<<"spreadLight modified "<<diff<<std::endl;
|
||||
infostream<<"spreadLight modified "<<diff<<std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -863,7 +868,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||
//TimeTaker timer("blitBack");
|
||||
vmanip.blitBack(modified_blocks);
|
||||
}
|
||||
/*dstream<<"emerge_time="<<emerge_time<<std::endl;
|
||||
/*infostream<<"emerge_time="<<emerge_time<<std::endl;
|
||||
emerge_time = 0;*/
|
||||
}
|
||||
|
||||
|
@ -891,7 +896,7 @@ void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
|
|||
/*
|
||||
*/
|
||||
void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks)
|
||||
core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name)
|
||||
{
|
||||
/*PrintInfo(m_dout);
|
||||
m_dout<<DTIME<<"Map::addNodeAndUpdate(): p=("
|
||||
|
@ -1024,6 +1029,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||
if(meta_proto)
|
||||
{
|
||||
NodeMetadata *meta = meta_proto->clone();
|
||||
meta->setOwner(player_name);
|
||||
setNodeMetadata(p, meta);
|
||||
}
|
||||
|
||||
|
@ -1305,7 +1311,8 @@ bool Map::addNodeWithEvent(v3s16 p, MapNode n)
|
|||
bool succeeded = true;
|
||||
try{
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
addNodeAndUpdate(p, n, modified_blocks);
|
||||
std::string st = std::string("");
|
||||
addNodeAndUpdate(p, n, modified_blocks, st);
|
||||
|
||||
// Copy modified_blocks to event
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
|
@ -1479,12 +1486,12 @@ void Map::timerUpdate(float dtime, float unload_timeout,
|
|||
|
||||
if(deleted_blocks_count != 0)
|
||||
{
|
||||
PrintInfo(dstream); // ServerMap/ClientMap:
|
||||
dstream<<"Unloaded "<<deleted_blocks_count
|
||||
PrintInfo(infostream); // ServerMap/ClientMap:
|
||||
infostream<<"Unloaded "<<deleted_blocks_count
|
||||
<<" blocks from memory";
|
||||
if(save_before_unloading)
|
||||
dstream<<", of which "<<saved_blocks_count<<" were written";
|
||||
dstream<<"."<<std::endl;
|
||||
infostream<<", of which "<<saved_blocks_count<<" were written";
|
||||
infostream<<"."<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1551,7 +1558,7 @@ void Map::unloadUnusedData(float timeout,
|
|||
|
||||
deleteSectors(sector_deletion_queue);
|
||||
|
||||
dstream<<"Map: Unloaded "<<deleted_blocks_count<<" blocks from memory"
|
||||
infostream<<"Map: Unloaded "<<deleted_blocks_count<<" blocks from memory"
|
||||
<<", of which "<<saved_blocks_count<<" were wr."
|
||||
<<std::endl;
|
||||
|
||||
|
@ -1587,7 +1594,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||
u32 initial_size = m_transforming_liquid.size();
|
||||
|
||||
/*if(initial_size != 0)
|
||||
dstream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
|
||||
infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
|
||||
|
||||
// list of nodes that due to viscosity have not reached their max level height
|
||||
UniqueQueue<v3s16> must_reflow;
|
||||
|
@ -1815,7 +1822,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||
break;
|
||||
}
|
||||
}
|
||||
//dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
|
||||
//infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
|
||||
while (must_reflow.size() > 0)
|
||||
m_transforming_liquid.push_back(must_reflow.pop_front());
|
||||
updateLighting(lighting_modified_blocks, modified_blocks);
|
||||
|
@ -1828,7 +1835,7 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p)
|
|||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||
if(block == NULL)
|
||||
{
|
||||
dstream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
||||
infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
||||
<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1843,7 +1850,7 @@ void Map::setNodeMetadata(v3s16 p, NodeMetadata *meta)
|
|||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||
if(block == NULL)
|
||||
{
|
||||
dstream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
||||
infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
@ -1857,7 +1864,7 @@ void Map::removeNodeMetadata(v3s16 p)
|
|||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||
if(block == NULL)
|
||||
{
|
||||
dstream<<"WARNING: Map::removeNodeMetadata(): Block not found"
|
||||
infostream<<"WARNING: Map::removeNodeMetadata(): Block not found"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
@ -1905,11 +1912,11 @@ ServerMap::ServerMap(std::string savedir):
|
|||
m_database_read(NULL),
|
||||
m_database_write(NULL)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<std::endl;
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
|
||||
//m_chunksize = 8; // Takes a few seconds
|
||||
|
||||
if (g_settings.get("fixed_map_seed").empty())
|
||||
if (g_settings->get("fixed_map_seed").empty())
|
||||
{
|
||||
m_seed = (((u64)(myrand()%0xffff)<<0)
|
||||
+ ((u64)(myrand()%0xffff)<<16)
|
||||
|
@ -1918,7 +1925,7 @@ ServerMap::ServerMap(std::string savedir):
|
|||
}
|
||||
else
|
||||
{
|
||||
m_seed = g_settings.getU64("fixed_map_seed");
|
||||
m_seed = g_settings->getU64("fixed_map_seed");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1943,7 +1950,7 @@ ServerMap::ServerMap(std::string savedir):
|
|||
// If directory is empty, it is safe to save into it.
|
||||
if(fs::GetDirListing(m_savedir).size() == 0)
|
||||
{
|
||||
dstream<<DTIME<<"Server: Empty save directory is valid."
|
||||
infostream<<"Server: Empty save directory is valid."
|
||||
<<std::endl;
|
||||
m_map_saving_enabled = true;
|
||||
}
|
||||
|
@ -1954,7 +1961,7 @@ ServerMap::ServerMap(std::string savedir):
|
|||
loadMapMeta();
|
||||
}
|
||||
catch(FileNotGoodException &e){
|
||||
dstream<<DTIME<<"WARNING: Could not load map metadata"
|
||||
infostream<<"WARNING: Could not load map metadata"
|
||||
//<<" Disabling chunk-based generator."
|
||||
<<std::endl;
|
||||
//m_chunksize = 0;
|
||||
|
@ -1965,18 +1972,18 @@ ServerMap::ServerMap(std::string savedir):
|
|||
loadChunkMeta();
|
||||
}
|
||||
catch(FileNotGoodException &e){
|
||||
dstream<<DTIME<<"WARNING: Could not load chunk metadata."
|
||||
infostream<<"WARNING: Could not load chunk metadata."
|
||||
<<" Disabling chunk-based generator."
|
||||
<<std::endl;
|
||||
m_chunksize = 0;
|
||||
}*/
|
||||
|
||||
/*dstream<<DTIME<<"Server: Successfully loaded chunk "
|
||||
/*infostream<<"Server: Successfully loaded chunk "
|
||||
"metadata and sector (0,0) from "<<savedir<<
|
||||
", assuming valid save directory."
|
||||
<<std::endl;*/
|
||||
|
||||
dstream<<DTIME<<"INFO: Server: Successfully loaded map "
|
||||
infostream<<"Server: Successfully loaded map "
|
||||
<<"and chunk metadata from "<<savedir
|
||||
<<", assuming valid save directory."
|
||||
<<std::endl;
|
||||
|
@ -1993,13 +2000,13 @@ ServerMap::ServerMap(std::string savedir):
|
|||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
dstream<<DTIME<<"WARNING: Server: Failed to load map from "<<savedir
|
||||
infostream<<"WARNING: Server: Failed to load map from "<<savedir
|
||||
<<", exception: "<<e.what()<<std::endl;
|
||||
dstream<<"Please remove the map or fix it."<<std::endl;
|
||||
dstream<<"WARNING: Map saving will be disabled."<<std::endl;
|
||||
infostream<<"Please remove the map or fix it."<<std::endl;
|
||||
infostream<<"WARNING: Map saving will be disabled."<<std::endl;
|
||||
}
|
||||
|
||||
dstream<<DTIME<<"INFO: Initializing new map."<<std::endl;
|
||||
infostream<<"Initializing new map."<<std::endl;
|
||||
|
||||
// Create zero sector
|
||||
emergeSector(v2s16(0,0));
|
||||
|
@ -2010,7 +2017,7 @@ ServerMap::ServerMap(std::string savedir):
|
|||
|
||||
ServerMap::~ServerMap()
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<std::endl;
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -2018,16 +2025,16 @@ ServerMap::~ServerMap()
|
|||
{
|
||||
// Save only changed parts
|
||||
save(true);
|
||||
dstream<<DTIME<<"Server: saved map to "<<m_savedir<<std::endl;
|
||||
infostream<<"Server: saved map to "<<m_savedir<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstream<<DTIME<<"Server: map not saved"<<std::endl;
|
||||
infostream<<"Server: map not saved"<<std::endl;
|
||||
}
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
dstream<<DTIME<<"Server: Failed to save map to "<<m_savedir
|
||||
infostream<<"Server: Failed to save map to "<<m_savedir
|
||||
<<", exception: "<<e.what()<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -2056,9 +2063,9 @@ ServerMap::~ServerMap()
|
|||
|
||||
void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
|
||||
{
|
||||
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
|
||||
if(enable_mapgen_debug_info)
|
||||
dstream<<"initBlockMake(): ("<<blockpos.X<<","<<blockpos.Y<<","
|
||||
infostream<<"initBlockMake(): ("<<blockpos.X<<","<<blockpos.Y<<","
|
||||
<<blockpos.Z<<")"<<std::endl;
|
||||
|
||||
// Do nothing if not inside limits (+-1 because of neighbors)
|
||||
|
@ -2142,19 +2149,19 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
core::map<v3s16, MapBlock*> &changed_blocks)
|
||||
{
|
||||
v3s16 blockpos = data->blockpos;
|
||||
/*dstream<<"finishBlockMake(): ("<<blockpos.X<<","<<blockpos.Y<<","
|
||||
/*infostream<<"finishBlockMake(): ("<<blockpos.X<<","<<blockpos.Y<<","
|
||||
<<blockpos.Z<<")"<<std::endl;*/
|
||||
|
||||
if(data->no_op)
|
||||
{
|
||||
//dstream<<"finishBlockMake(): no-op"<<std::endl;
|
||||
//infostream<<"finishBlockMake(): no-op"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
|
||||
|
||||
/*dstream<<"Resulting vmanip:"<<std::endl;
|
||||
data->vmanip.print(dstream);*/
|
||||
/*infostream<<"Resulting vmanip:"<<std::endl;
|
||||
data->vmanip.print(infostream);*/
|
||||
|
||||
/*
|
||||
Blit generated stuff to map
|
||||
|
@ -2167,7 +2174,7 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
}
|
||||
|
||||
if(enable_mapgen_debug_info)
|
||||
dstream<<"finishBlockMake: changed_blocks.size()="
|
||||
infostream<<"finishBlockMake: changed_blocks.size()="
|
||||
<<changed_blocks.size()<<std::endl;
|
||||
|
||||
/*
|
||||
|
@ -2308,7 +2315,7 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
*/
|
||||
//save(true);
|
||||
|
||||
/*dstream<<"finishBlockMake() done for ("<<blockpos.X<<","<<blockpos.Y<<","
|
||||
/*infostream<<"finishBlockMake() done for ("<<blockpos.X<<","<<blockpos.Y<<","
|
||||
<<blockpos.Z<<")"<<std::endl;*/
|
||||
#if 0
|
||||
if(enable_mapgen_debug_info)
|
||||
|
@ -2324,7 +2331,7 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
|||
MapBlock *block = getBlockNoCreateNoEx(p);
|
||||
char spos[20];
|
||||
snprintf(spos, 20, "(%2d,%2d,%2d)", x, y, z);
|
||||
dstream<<"Generated "<<spos<<": "
|
||||
infostream<<"Generated "<<spos<<": "
|
||||
<<analyze_block(block)<<std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -2360,7 +2367,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
|
|||
ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d);
|
||||
if(sector == NULL)
|
||||
{
|
||||
dstream<<"ServerMap::createSector(): loadSectorFull didn't make a sector"<<std::endl;
|
||||
infostream<<"ServerMap::createSector(): loadSectorFull didn't make a sector"<<std::endl;
|
||||
throw InvalidPositionException("");
|
||||
}
|
||||
return sector;
|
||||
|
@ -2402,11 +2409,11 @@ MapBlock * ServerMap::generateBlock(
|
|||
{
|
||||
DSTACKF("%s: p=(%d,%d,%d)", __FUNCTION_NAME, p.X, p.Y, p.Z);
|
||||
|
||||
/*dstream<<"generateBlock(): "
|
||||
/*infostream<<"generateBlock(): "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
|
||||
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
|
||||
|
||||
TimeTaker timer("generateBlock");
|
||||
|
||||
|
@ -2420,7 +2427,7 @@ MapBlock * ServerMap::generateBlock(
|
|||
*/
|
||||
if(blockpos_over_limit(p))
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Block position over limit"<<std::endl;
|
||||
infostream<<__FUNCTION_NAME<<": Block position over limit"<<std::endl;
|
||||
throw InvalidPositionException("generateBlock(): pos. over limit");
|
||||
}
|
||||
|
||||
|
@ -2466,7 +2473,7 @@ MapBlock * ServerMap::generateBlock(
|
|||
MapNode n = block->getNode(p);
|
||||
if(n.getContent() == CONTENT_IGNORE)
|
||||
{
|
||||
dstream<<"CONTENT_IGNORE at "
|
||||
infostream<<"CONTENT_IGNORE at "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;
|
||||
erroneus_content = true;
|
||||
|
@ -2540,7 +2547,7 @@ MapBlock * ServerMap::createBlock(v3s16 p)
|
|||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
dstream<<"createBlock: createSector() failed"<<std::endl;
|
||||
infostream<<"createBlock: createSector() failed"<<std::endl;
|
||||
throw e;
|
||||
}
|
||||
/*
|
||||
|
@ -2550,7 +2557,7 @@ MapBlock * ServerMap::createBlock(v3s16 p)
|
|||
*/
|
||||
/*catch(std::exception &e)
|
||||
{
|
||||
dstream<<"createBlock: createSector() failed: "
|
||||
infostream<<"createBlock: createSector() failed: "
|
||||
<<e.what()<<std::endl;
|
||||
throw e;
|
||||
}*/
|
||||
|
@ -2642,18 +2649,18 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
|||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
dstream<<"emergeBlock: createSector() failed: "
|
||||
infostream<<"emergeBlock: createSector() failed: "
|
||||
<<e.what()<<std::endl;
|
||||
dstream<<"Path to failed sector: "<<getSectorDir(p2d)
|
||||
infostream<<"Path to failed sector: "<<getSectorDir(p2d)
|
||||
<<std::endl
|
||||
<<"You could try to delete it."<<std::endl;
|
||||
throw e;
|
||||
}
|
||||
catch(VersionMismatchException &e)
|
||||
{
|
||||
dstream<<"emergeBlock: createSector() failed: "
|
||||
infostream<<"emergeBlock: createSector() failed: "
|
||||
<<e.what()<<std::endl;
|
||||
dstream<<"Path to failed sector: "<<getSectorDir(p2d)
|
||||
infostream<<"Path to failed sector: "<<getSectorDir(p2d)
|
||||
<<std::endl
|
||||
<<"You could try to delete it."<<std::endl;
|
||||
throw e;
|
||||
|
@ -2689,7 +2696,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
|||
else
|
||||
{
|
||||
// Valid block
|
||||
//dstream<<"emergeBlock(): Returning already valid block"<<std::endl;
|
||||
//infostream<<"emergeBlock(): Returning already valid block"<<std::endl;
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -2699,7 +2706,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
|||
*/
|
||||
if(only_from_disk && (does_not_exist || lighting_expired))
|
||||
{
|
||||
//dstream<<"emergeBlock(): Was not on disk but not generating"<<std::endl;
|
||||
//infostream<<"emergeBlock(): Was not on disk but not generating"<<std::endl;
|
||||
|
||||
if(block == NULL)
|
||||
{
|
||||
|
@ -2713,11 +2720,11 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
|||
return block;
|
||||
}
|
||||
|
||||
//dstream<<"Not found on disk, generating."<<std::endl;
|
||||
//infostream<<"Not found on disk, generating."<<std::endl;
|
||||
// 0ms
|
||||
//TimeTaker("emergeBlock() generate");
|
||||
|
||||
//dstream<<"emergeBlock(): Didn't find valid block -> making one"<<std::endl;
|
||||
//infostream<<"emergeBlock(): Didn't find valid block -> making one"<<std::endl;
|
||||
|
||||
/*
|
||||
If the block doesn't exist, generate the block.
|
||||
|
@ -2819,7 +2826,7 @@ void ServerMap::createDatabase() {
|
|||
if(e == SQLITE_ABORT)
|
||||
throw FileNotGoodException("Could not create database structure");
|
||||
else
|
||||
dstream<<"Server: Database structure was created";
|
||||
infostream<<"Server: Database structure was created";
|
||||
}
|
||||
|
||||
void ServerMap::verifyDatabase() {
|
||||
|
@ -2827,7 +2834,7 @@ void ServerMap::verifyDatabase() {
|
|||
return;
|
||||
|
||||
{
|
||||
std::string dbp = m_savedir + "/map.sqlite";
|
||||
std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
|
||||
bool needs_create = false;
|
||||
int d;
|
||||
|
||||
|
@ -2842,7 +2849,7 @@ void ServerMap::verifyDatabase() {
|
|||
|
||||
d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
if(d != SQLITE_OK) {
|
||||
dstream<<"WARNING: Database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
infostream<<"WARNING: Database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
throw FileNotGoodException("Cannot open database file");
|
||||
}
|
||||
|
||||
|
@ -2851,22 +2858,22 @@ void ServerMap::verifyDatabase() {
|
|||
|
||||
d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
|
||||
if(d != SQLITE_OK) {
|
||||
dstream<<"WARNING: Database read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
infostream<<"WARNING: Database read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
throw FileNotGoodException("Cannot prepare read statement");
|
||||
}
|
||||
|
||||
d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?)", -1, &m_database_write, NULL);
|
||||
if(d != SQLITE_OK) {
|
||||
dstream<<"WARNING: Database write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
infostream<<"WARNING: Database write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
throw FileNotGoodException("Cannot prepare write statement");
|
||||
}
|
||||
|
||||
dstream<<"Server: Database opened"<<std::endl;
|
||||
infostream<<"Server: Database opened"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerMap::loadFromFolders() {
|
||||
if(!m_database && !fs::PathExists(m_savedir + "/map.sqlite"))
|
||||
if(!m_database && !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -2896,13 +2903,13 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout)
|
|||
(unsigned int)pos.X&0xffff,
|
||||
(unsigned int)pos.Y&0xffff);
|
||||
|
||||
return m_savedir + "/sectors/" + cc;
|
||||
return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc;
|
||||
case 2:
|
||||
snprintf(cc, 9, "%.3x/%.3x",
|
||||
snprintf(cc, 9, "%.3x" DIR_DELIM "%.3x",
|
||||
(unsigned int)pos.X&0xfff,
|
||||
(unsigned int)pos.Y&0xfff);
|
||||
|
||||
return m_savedir + "/sectors2/" + cc;
|
||||
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
@ -2912,7 +2919,7 @@ v2s16 ServerMap::getSectorPos(std::string dirname)
|
|||
{
|
||||
unsigned int x, y;
|
||||
int r;
|
||||
size_t spos = dirname.rfind('/') + 1;
|
||||
size_t spos = dirname.rfind(DIR_DELIM_C) + 1;
|
||||
assert(spos != std::string::npos);
|
||||
if(dirname.size() - spos == 8)
|
||||
{
|
||||
|
@ -2922,7 +2929,7 @@ v2s16 ServerMap::getSectorPos(std::string dirname)
|
|||
else if(dirname.size() - spos == 3)
|
||||
{
|
||||
// New layout
|
||||
r = sscanf(dirname.substr(spos-4).c_str(), "%3x/%3x", &x, &y);
|
||||
r = sscanf(dirname.substr(spos-4).c_str(), "%3x" DIR_DELIM "%3x", &x, &y);
|
||||
// Sign-extend the 12 bit values up to 16 bits...
|
||||
if(x&0x800) x|=0xF000;
|
||||
if(y&0x800) y|=0xF000;
|
||||
|
@ -2962,12 +2969,12 @@ void ServerMap::save(bool only_changed)
|
|||
DSTACK(__FUNCTION_NAME);
|
||||
if(m_map_saving_enabled == false)
|
||||
{
|
||||
dstream<<DTIME<<"WARNING: Not saving map, saving disabled."<<std::endl;
|
||||
infostream<<"WARNING: Not saving map, saving disabled."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(only_changed == false)
|
||||
dstream<<DTIME<<"ServerMap: Saving whole map, this can take time."
|
||||
infostream<<"ServerMap: Saving whole map, this can take time."
|
||||
<<std::endl;
|
||||
|
||||
if(only_changed == false || m_map_metadata_changed)
|
||||
|
@ -3008,7 +3015,7 @@ void ServerMap::save(bool only_changed)
|
|||
saveBlock(block);
|
||||
block_count++;
|
||||
|
||||
/*dstream<<"ServerMap: Written block ("
|
||||
/*infostream<<"ServerMap: Written block ("
|
||||
<<block->getPos().X<<","
|
||||
<<block->getPos().Y<<","
|
||||
<<block->getPos().Z<<")"
|
||||
|
@ -3025,7 +3032,7 @@ void ServerMap::save(bool only_changed)
|
|||
if(only_changed == false || sector_meta_count != 0
|
||||
|| block_count != 0)
|
||||
{
|
||||
dstream<<DTIME<<"ServerMap: Written: "
|
||||
infostream<<"ServerMap: Written: "
|
||||
<<sector_meta_count<<" sector metadata files, "
|
||||
<<block_count<<" block files"
|
||||
<<", "<<block_count_all<<" blocks in memory."
|
||||
|
@ -3037,17 +3044,17 @@ void ServerMap::saveMapMeta()
|
|||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
dstream<<"INFO: ServerMap::saveMapMeta(): "
|
||||
infostream<<"ServerMap::saveMapMeta(): "
|
||||
<<"seed="<<m_seed
|
||||
<<std::endl;
|
||||
|
||||
createDirs(m_savedir);
|
||||
|
||||
std::string fullpath = m_savedir + "/map_meta.txt";
|
||||
std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
|
||||
std::ofstream os(fullpath.c_str(), std::ios_base::binary);
|
||||
if(os.good() == false)
|
||||
{
|
||||
dstream<<"ERROR: ServerMap::saveMapMeta(): "
|
||||
infostream<<"ERROR: ServerMap::saveMapMeta(): "
|
||||
<<"could not open"<<fullpath<<std::endl;
|
||||
throw FileNotGoodException("Cannot open chunk metadata");
|
||||
}
|
||||
|
@ -3066,14 +3073,14 @@ void ServerMap::loadMapMeta()
|
|||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
dstream<<"INFO: ServerMap::loadMapMeta(): Loading map metadata"
|
||||
infostream<<"ServerMap::loadMapMeta(): Loading map metadata"
|
||||
<<std::endl;
|
||||
|
||||
std::string fullpath = m_savedir + "/map_meta.txt";
|
||||
std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
|
||||
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"ERROR: ServerMap::loadMapMeta(): "
|
||||
infostream<<"ERROR: ServerMap::loadMapMeta(): "
|
||||
<<"could not open"<<fullpath<<std::endl;
|
||||
throw FileNotGoodException("Cannot open map metadata");
|
||||
}
|
||||
|
@ -3095,9 +3102,7 @@ void ServerMap::loadMapMeta()
|
|||
|
||||
m_seed = params.getU64("seed");
|
||||
|
||||
dstream<<"INFO: ServerMap::loadMapMeta(): "
|
||||
<<"seed="<<m_seed
|
||||
<<std::endl;
|
||||
infostream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
|
||||
}
|
||||
|
||||
void ServerMap::saveSectorMeta(ServerMapSector *sector)
|
||||
|
@ -3110,7 +3115,7 @@ void ServerMap::saveSectorMeta(ServerMapSector *sector)
|
|||
std::string dir = getSectorDir(pos);
|
||||
createDirs(dir);
|
||||
|
||||
std::string fullpath = dir + "/meta";
|
||||
std::string fullpath = dir + DIR_DELIM + "meta";
|
||||
std::ofstream o(fullpath.c_str(), std::ios_base::binary);
|
||||
if(o.good() == false)
|
||||
throw FileNotGoodException("Cannot open sector metafile");
|
||||
|
@ -3128,7 +3133,7 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load
|
|||
|
||||
ServerMapSector *sector = NULL;
|
||||
|
||||
std::string fullpath = sectordir + "/meta";
|
||||
std::string fullpath = sectordir + DIR_DELIM + "meta";
|
||||
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
|
||||
if(is.good() == false)
|
||||
{
|
||||
|
@ -3136,7 +3141,7 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load
|
|||
// format. Just go ahead and create the sector.
|
||||
if(fs::PathExists(sectordir))
|
||||
{
|
||||
/*dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
|
||||
/*infostream<<"ServerMap::loadSectorMeta(): Sector metafile "
|
||||
<<fullpath<<" doesn't exist but directory does."
|
||||
<<" Continuing with a sector with no metadata."
|
||||
<<std::endl;*/
|
||||
|
@ -3267,7 +3272,7 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
|
|||
|
||||
if(loadlayout != 2)
|
||||
{
|
||||
dstream<<"Sector converted to new layout - deleting "<<
|
||||
infostream<<"Sector converted to new layout - deleting "<<
|
||||
sectordir1<<std::endl;
|
||||
fs::RecursiveDelete(sectordir1);
|
||||
}
|
||||
|
@ -3279,13 +3284,13 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
|
|||
void ServerMap::beginSave() {
|
||||
verifyDatabase();
|
||||
if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK)
|
||||
dstream<<"WARNING: beginSave() failed, saving might be slow.";
|
||||
infostream<<"WARNING: beginSave() failed, saving might be slow.";
|
||||
}
|
||||
|
||||
void ServerMap::endSave() {
|
||||
verifyDatabase();
|
||||
if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK)
|
||||
dstream<<"WARNING: endSave() failed, map might not have saved.";
|
||||
infostream<<"WARNING: endSave() failed, map might not have saved.";
|
||||
}
|
||||
|
||||
void ServerMap::saveBlock(MapBlock *block)
|
||||
|
@ -3297,7 +3302,7 @@ void ServerMap::saveBlock(MapBlock *block)
|
|||
if(block->isDummy())
|
||||
{
|
||||
/*v3s16 p = block->getPos();
|
||||
dstream<<"ServerMap::saveBlock(): WARNING: Not writing dummy block "
|
||||
infostream<<"ServerMap::saveBlock(): WARNING: Not writing dummy block "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
|
||||
return;
|
||||
}
|
||||
|
@ -3314,7 +3319,7 @@ void ServerMap::saveBlock(MapBlock *block)
|
|||
|
||||
createDirs(sectordir);
|
||||
|
||||
std::string fullpath = sectordir+"/"+getBlockFilename(p3d);
|
||||
std::string fullpath = sectordir+DIR_DELIM+getBlockFilename(p3d);
|
||||
std::ofstream o(fullpath.c_str(), std::ios_base::binary);
|
||||
if(o.good() == false)
|
||||
throw FileNotGoodException("Cannot open block data");
|
||||
|
@ -3342,12 +3347,12 @@ void ServerMap::saveBlock(MapBlock *block)
|
|||
const char *bytes = tmp.c_str();
|
||||
|
||||
if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK)
|
||||
dstream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
infostream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) // TODO this mught not be the right length
|
||||
dstream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
infostream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
int written = sqlite3_step(m_database_write);
|
||||
if(written != SQLITE_DONE)
|
||||
dstream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
|
||||
infostream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
|
||||
<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
// Make ready for later reuse
|
||||
sqlite3_reset(m_database_write);
|
||||
|
@ -3360,7 +3365,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
|
|||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
std::string fullpath = sectordir+"/"+blockfile;
|
||||
std::string fullpath = sectordir+DIR_DELIM+blockfile;
|
||||
try{
|
||||
|
||||
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
|
||||
|
@ -3423,7 +3428,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
|
|||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<"WARNING: Invalid block data on disk "
|
||||
infostream<<"WARNING: Invalid block data on disk "
|
||||
<<"fullpath="<<fullpath
|
||||
<<" (SerializationError). "
|
||||
<<"what()="<<e.what()
|
||||
|
@ -3490,7 +3495,7 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
|
|||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<"WARNING: Invalid block data in database "
|
||||
infostream<<"WARNING: Invalid block data in database "
|
||||
<<" (SerializationError). "
|
||||
<<"what()="<<e.what()
|
||||
<<std::endl;
|
||||
|
@ -3511,7 +3516,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
|||
verifyDatabase();
|
||||
|
||||
if(sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK)
|
||||
dstream<<"WARNING: Could not bind block position for load: "
|
||||
infostream<<"WARNING: Could not bind block position for load: "
|
||||
<<sqlite3_errmsg(m_database)<<std::endl;
|
||||
if(sqlite3_step(m_database_read) == SQLITE_ROW) {
|
||||
/*
|
||||
|
@ -3586,7 +3591,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
|||
*/
|
||||
|
||||
std::string blockfilename = getBlockFilename(blockpos);
|
||||
if(fs::PathExists(sectordir+"/"+blockfilename) == false)
|
||||
if(fs::PathExists(sectordir+DIR_DELIM+blockfilename) == false)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
@ -3619,7 +3624,8 @@ ClientMap::ClientMap(
|
|||
m_client(client),
|
||||
m_control(control),
|
||||
m_camera_position(0,0,0),
|
||||
m_camera_direction(0,0,1)
|
||||
m_camera_direction(0,0,1),
|
||||
m_camera_fov(PI)
|
||||
{
|
||||
m_camera_mutex.Init();
|
||||
assert(m_camera_mutex.IsInitialized());
|
||||
|
@ -3728,6 +3734,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||
m_camera_mutex.Lock();
|
||||
v3f camera_position = m_camera_position;
|
||||
v3f camera_direction = m_camera_direction;
|
||||
f32 camera_fov = m_camera_fov;
|
||||
m_camera_mutex.Unlock();
|
||||
|
||||
/*
|
||||
|
@ -3775,7 +3782,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||
int time2 = time(0);
|
||||
if(time2 > time1 + 4)
|
||||
{
|
||||
dstream<<"ClientMap::renderMap(): "
|
||||
infostream<<"ClientMap::renderMap(): "
|
||||
"Rendering takes ages, returning."
|
||||
<<std::endl;
|
||||
return;
|
||||
|
@ -3820,7 +3827,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||
|
||||
float d = 0.0;
|
||||
if(isBlockInSight(block->getPos(), camera_position,
|
||||
camera_direction, range, &d) == false)
|
||||
camera_direction, camera_fov,
|
||||
range, &d) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -3936,10 +3944,39 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||
m_control.blocks_drawn = blocks_drawn;
|
||||
m_control.blocks_would_have_drawn = blocks_would_have_drawn;
|
||||
|
||||
/*dstream<<"renderMap(): is_transparent_pass="<<is_transparent_pass
|
||||
/*infostream<<"renderMap(): is_transparent_pass="<<is_transparent_pass
|
||||
<<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
|
||||
}
|
||||
|
||||
void ClientMap::renderPostFx()
|
||||
{
|
||||
// Sadly ISceneManager has no "post effects" render pass, in that case we
|
||||
// could just register for that and handle it in renderMap().
|
||||
|
||||
m_camera_mutex.Lock();
|
||||
v3f camera_position = m_camera_position;
|
||||
m_camera_mutex.Unlock();
|
||||
|
||||
MapNode n = getNodeNoEx(floatToInt(camera_position, BS));
|
||||
|
||||
// - If the player is in a solid node, make everything black.
|
||||
// - If the player is in liquid, draw a semi-transparent overlay.
|
||||
ContentFeatures& features = content_features(n);
|
||||
video::SColor post_effect_color = features.post_effect_color;
|
||||
if(features.solidness == 2 && g_settings->getBool("free_move") == false)
|
||||
{
|
||||
post_effect_color = video::SColor(255, 0, 0, 0);
|
||||
}
|
||||
if (post_effect_color.getAlpha() != 0)
|
||||
{
|
||||
// Draw a full-screen rectangle
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
v2u32 ss = driver->getScreenSize();
|
||||
core::rect<s32> rect(0,0, ss.X, ss.Y);
|
||||
driver->draw2DRectangle(post_effect_color, rect);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientMap::setTempMod(v3s16 p, NodeMod mod,
|
||||
core::map<v3s16, MapBlock*> *affected_blocks)
|
||||
{
|
||||
|
@ -4157,7 +4194,7 @@ MapVoxelManipulator::MapVoxelManipulator(Map *map)
|
|||
|
||||
MapVoxelManipulator::~MapVoxelManipulator()
|
||||
{
|
||||
/*dstream<<"MapVoxelManipulator: blocks: "<<m_loaded_blocks.size()
|
||||
/*infostream<<"MapVoxelManipulator: blocks: "<<m_loaded_blocks.size()
|
||||
<<std::endl;*/
|
||||
}
|
||||
|
||||
|
@ -4189,11 +4226,11 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
|
|||
{
|
||||
TimeTaker timer1("emerge load", &emerge_load_time);
|
||||
|
||||
/*dstream<<"Loading block (caller_id="<<caller_id<<")"
|
||||
/*infostream<<"Loading block (caller_id="<<caller_id<<")"
|
||||
<<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<" wanted area: ";
|
||||
a.print(dstream);
|
||||
dstream<<std::endl;*/
|
||||
a.print(infostream);
|
||||
infostream<<std::endl;*/
|
||||
|
||||
MapBlock *block = m_map->getBlockNoCreate(p);
|
||||
if(block->isDummy())
|
||||
|
@ -4221,7 +4258,7 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
|
|||
m_loaded_blocks.insert(p, !block_data_inexistent);
|
||||
}
|
||||
|
||||
//dstream<<"emerge done"<<std::endl;
|
||||
//infostream<<"emerge done"<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4237,7 +4274,7 @@ void MapVoxelManipulator::blitBack
|
|||
|
||||
//TimeTaker timer1("blitBack");
|
||||
|
||||
/*dstream<<"blitBack(): m_loaded_blocks.size()="
|
||||
/*infostream<<"blitBack(): m_loaded_blocks.size()="
|
||||
<<m_loaded_blocks.size()<<std::endl;*/
|
||||
|
||||
/*
|
||||
|
@ -4326,10 +4363,10 @@ void ManualMapVoxelManipulator::initialEmerge(
|
|||
u32 size_MB = block_area_nodes.getVolume()*4/1000000;
|
||||
if(size_MB >= 1)
|
||||
{
|
||||
dstream<<"initialEmerge: area: ";
|
||||
block_area_nodes.print(dstream);
|
||||
dstream<<" ("<<size_MB<<"MB)";
|
||||
dstream<<std::endl;
|
||||
infostream<<"initialEmerge: area: ";
|
||||
block_area_nodes.print(infostream);
|
||||
infostream<<" ("<<size_MB<<"MB)";
|
||||
infostream<<std::endl;
|
||||
}
|
||||
|
||||
addArea(block_area_nodes);
|
||||
|
@ -4397,7 +4434,7 @@ void ManualMapVoxelManipulator::blitBackAll(
|
|||
if(existed == false)
|
||||
{
|
||||
// The Great Bug was found using this
|
||||
/*dstream<<"ManualMapVoxelManipulator::blitBackAll: "
|
||||
/*infostream<<"ManualMapVoxelManipulator::blitBackAll: "
|
||||
<<"Inexistent ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
continue;
|
||||
|
@ -4405,7 +4442,7 @@ void ManualMapVoxelManipulator::blitBackAll(
|
|||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
if(block == NULL)
|
||||
{
|
||||
dstream<<"WARNING: "<<__FUNCTION_NAME
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": got NULL block "
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;
|
||||
|
|
|
@ -205,7 +205,7 @@ public:
|
|||
These handle lighting but not faces.
|
||||
*/
|
||||
void addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name);
|
||||
void removeNodeAndUpdate(v3s16 p,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
|
||||
|
@ -518,11 +518,12 @@ public:
|
|||
ISceneNode::drop();
|
||||
}
|
||||
|
||||
void updateCamera(v3f pos, v3f dir)
|
||||
void updateCamera(v3f pos, v3f dir, f32 fov)
|
||||
{
|
||||
JMutexAutoLock lock(m_camera_mutex);
|
||||
m_camera_position = pos;
|
||||
m_camera_direction = dir;
|
||||
m_camera_fov = fov;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -552,6 +553,8 @@ public:
|
|||
|
||||
void renderMap(video::IVideoDriver* driver, s32 pass);
|
||||
|
||||
void renderPostFx();
|
||||
|
||||
/*
|
||||
Methods for setting temporary modifications to nodes for
|
||||
drawing.
|
||||
|
@ -601,6 +604,7 @@ private:
|
|||
|
||||
v3f m_camera_position;
|
||||
v3f m_camera_direction;
|
||||
f32 m_camera_fov;
|
||||
JMutex m_camera_mutex;
|
||||
|
||||
core::map<v2s16, bool> m_last_drawn_sectors;
|
||||
|
|
|
@ -36,7 +36,6 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
|||
m_lighting_expired(true),
|
||||
m_day_night_differs(false),
|
||||
m_generated(false),
|
||||
m_objects(this),
|
||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||
m_usage_timer(0),
|
||||
m_owner(0) //j
|
||||
|
@ -435,17 +434,6 @@ void MapBlock::copyFrom(VoxelManipulator &dst)
|
|||
getPosRelative(), data_size);
|
||||
}
|
||||
|
||||
void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
||||
{
|
||||
/*
|
||||
Step objects
|
||||
*/
|
||||
m_objects.step(dtime, server, daynight_ratio);
|
||||
|
||||
setChangedFlag();
|
||||
}
|
||||
|
||||
|
||||
void MapBlock::updateDayNightDiff()
|
||||
{
|
||||
if(data == NULL)
|
||||
|
@ -826,10 +814,9 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||
|
||||
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||
{
|
||||
// Versions up from 9 have block objects.
|
||||
// Versions up from 9 have block objects. (DEPRECATED)
|
||||
if(version >= 9)
|
||||
{
|
||||
//serializeObjects(os, version); // DEPRECATED
|
||||
// count=0
|
||||
writeU16(os, 0);
|
||||
}
|
||||
|
@ -850,11 +837,17 @@ void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
|||
void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
|
||||
{
|
||||
/*
|
||||
Versions up from 9 have block objects.
|
||||
Versions up from 9 have block objects. (DEPRECATED)
|
||||
*/
|
||||
if(version >= 9)
|
||||
{
|
||||
updateObjects(is, version, NULL, 0);
|
||||
u16 count = readU16(is);
|
||||
// Not supported and length not known if count is not 0
|
||||
if(count != 0){
|
||||
dstream<<"WARNING: MapBlock::deSerializeDiskExtra(): "
|
||||
<<"Ignoring stuff coming at and after MBOs"<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "exceptions.h"
|
||||
#include "serialization.h"
|
||||
#include "constants.h"
|
||||
#include "mapblockobject.h"
|
||||
#include "voxel.h"
|
||||
#include "nodemetadata.h"
|
||||
#include "staticobject.h"
|
||||
|
@ -226,8 +225,10 @@ public:
|
|||
|
||||
void setLightingExpired(bool expired)
|
||||
{
|
||||
m_lighting_expired = expired;
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
if(expired != m_lighting_expired){
|
||||
m_lighting_expired = expired;
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
}
|
||||
bool getLightingExpired()
|
||||
{
|
||||
|
@ -240,8 +241,10 @@ public:
|
|||
}
|
||||
void setGenerated(bool b)
|
||||
{
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
m_generated = b;
|
||||
if(b != m_generated){
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
m_generated = b;
|
||||
}
|
||||
}
|
||||
|
||||
bool isValid()
|
||||
|
@ -420,68 +423,6 @@ public:
|
|||
// Copies data from VoxelManipulator getPosRelative()
|
||||
void copyFrom(VoxelManipulator &dst);
|
||||
|
||||
/*
|
||||
MapBlockObject stuff
|
||||
DEPRECATED
|
||||
*/
|
||||
|
||||
/*void serializeObjects(std::ostream &os, u8 version)
|
||||
{
|
||||
m_objects.serialize(os, version);
|
||||
}*/
|
||||
// If smgr!=NULL, new objects are added to the scene
|
||||
void updateObjects(std::istream &is, u8 version,
|
||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
||||
{
|
||||
m_objects.update(is, version, smgr, daynight_ratio);
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void clearObjects()
|
||||
{
|
||||
m_objects.clear();
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void addObject(MapBlockObject *object)
|
||||
throw(ContainerFullException, AlreadyExistsException)
|
||||
{
|
||||
m_objects.add(object);
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void removeObject(s16 id)
|
||||
{
|
||||
m_objects.remove(id);
|
||||
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
MapBlockObject * getObject(s16 id)
|
||||
{
|
||||
return m_objects.get(id);
|
||||
}
|
||||
JMutexAutoLock * getObjectLock()
|
||||
{
|
||||
return m_objects.getLock();
|
||||
}
|
||||
|
||||
/*
|
||||
Moves objects, deletes objects and spawns new objects
|
||||
*/
|
||||
void stepObjects(float dtime, bool server, u32 daynight_ratio);
|
||||
|
||||
// origin is relative to block
|
||||
void getObjects(v3f origin, f32 max_d,
|
||||
core::array<DistanceSortedObject> &dest)
|
||||
{
|
||||
m_objects.getObjects(origin, max_d, dest);
|
||||
}
|
||||
|
||||
s32 getObjectCount()
|
||||
{
|
||||
return m_objects.getCount();
|
||||
}
|
||||
|
||||
#ifndef SERVER // Only on client
|
||||
/*
|
||||
Methods for setting temporary modifications to nodes for
|
||||
|
@ -702,9 +643,6 @@ private:
|
|||
|
||||
bool m_generated;
|
||||
|
||||
// DEPRECATED
|
||||
MapBlockObjectList m_objects;
|
||||
|
||||
#ifndef SERVER // Only on client
|
||||
/*
|
||||
Set to true if the mesh has been ordered to be updated
|
||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "map.h"
|
||||
#include "main.h" // For g_settings and g_texturesource
|
||||
#include "content_mapblock.h"
|
||||
#include "settings.h"
|
||||
|
||||
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
||||
{
|
||||
|
@ -491,10 +492,10 @@ void updateFastFaceRow(
|
|||
|
||||
u16 continuous_tiles_count = 0;
|
||||
|
||||
bool makes_face;
|
||||
bool makes_face = false;
|
||||
v3s16 p_corrected;
|
||||
v3s16 face_dir_corrected;
|
||||
u8 lights[4];
|
||||
u8 lights[4] = {0,0,0,0};
|
||||
TileSpec tile;
|
||||
getTileInfo(blockpos_nodes, p, face_dir, daynight_ratio,
|
||||
vmanip, temp_mods, smooth_lighting,
|
||||
|
@ -619,9 +620,9 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
|
|||
/*
|
||||
Some settings
|
||||
*/
|
||||
//bool new_style_water = g_settings.getBool("new_style_water");
|
||||
//bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||
bool smooth_lighting = g_settings.getBool("smooth_lighting");
|
||||
//bool new_style_water = g_settings->getBool("new_style_water");
|
||||
//bool new_style_leaves = g_settings->getBool("new_style_leaves");
|
||||
bool smooth_lighting = g_settings->getBool("smooth_lighting");
|
||||
|
||||
/*
|
||||
We are including the faces of the trailing edges of the block.
|
||||
|
|
|
@ -1,939 +0,0 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// This file contains the DEPRECATED MapBlockObject system
|
||||
|
||||
#include "mapblockobject.h"
|
||||
#include "mapblock.h"
|
||||
// For object wrapping
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
#include "utility.h"
|
||||
#include "mapblock.h"
|
||||
|
||||
/*
|
||||
MapBlockObject
|
||||
*/
|
||||
|
||||
// This is here because it uses the MapBlock
|
||||
v3f MapBlockObject::getAbsolutePos()
|
||||
{
|
||||
if(m_block == NULL)
|
||||
return m_pos;
|
||||
|
||||
// getPosRelative gets nodepos relative to map origin
|
||||
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
||||
return blockpos + m_pos;
|
||||
}
|
||||
|
||||
void MapBlockObject::setBlockChanged()
|
||||
{
|
||||
if(m_block)
|
||||
m_block->setChangedFlag();
|
||||
}
|
||||
|
||||
/*
|
||||
MovingObject
|
||||
*/
|
||||
|
||||
v3f MovingObject::getAbsoluteShowPos()
|
||||
{
|
||||
if(m_block == NULL)
|
||||
return m_pos;
|
||||
|
||||
// getPosRelative gets nodepos relative to map origin
|
||||
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
||||
return blockpos + m_showpos;
|
||||
}
|
||||
|
||||
void MovingObject::move(float dtime, v3f acceleration)
|
||||
{
|
||||
DSTACKF("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
|
||||
", dtime=%f, acc=(%f,%f,%f)",
|
||||
__FUNCTION_NAME,
|
||||
getTypeId(),
|
||||
m_pos.X, m_pos.Y, m_pos.Z,
|
||||
m_speed.X, m_speed.Y, m_speed.Z,
|
||||
dtime,
|
||||
acceleration.X, acceleration.Y, acceleration.Z
|
||||
);
|
||||
|
||||
v3s16 oldpos_i = floatToInt(m_pos, BS);
|
||||
|
||||
if(m_block->isValidPosition(oldpos_i) == false)
|
||||
{
|
||||
// Should have wrapped, cancelling further movement.
|
||||
return;
|
||||
}
|
||||
|
||||
// No collisions if there is no collision box
|
||||
if(m_collision_box == NULL)
|
||||
{
|
||||
m_speed += dtime * acceleration;
|
||||
m_pos += m_speed * dtime;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set insane speed to zero
|
||||
// Otherwise there will be divides by zero and other silly stuff
|
||||
if(m_speed.getLength() > 1000.0*BS)
|
||||
m_speed = v3f(0,0,0);
|
||||
|
||||
// Limit speed to a reasonable value
|
||||
float speed_limit = 20.0*BS;
|
||||
if(m_speed.getLength() > speed_limit)
|
||||
m_speed = m_speed * (speed_limit / m_speed.getLength());
|
||||
|
||||
v3f position = m_pos;
|
||||
v3f oldpos = position;
|
||||
|
||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// Allow 0.1 blocks per increment
|
||||
// time = distance / speed
|
||||
// NOTE: In the loop below collisions are detected at 0.15*BS radius
|
||||
float speedlength = m_speed.getLength();
|
||||
f32 dtime_max_increment;
|
||||
if(fabs(speedlength) > 0.001)
|
||||
dtime_max_increment = 0.05*BS / speedlength;
|
||||
else
|
||||
dtime_max_increment = 0.5;
|
||||
|
||||
m_touching_ground = false;
|
||||
|
||||
u32 loopcount = 0;
|
||||
do
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
f32 dtime_part;
|
||||
if(dtime > dtime_max_increment)
|
||||
dtime_part = dtime_max_increment;
|
||||
else
|
||||
dtime_part = dtime;
|
||||
dtime -= dtime_part;
|
||||
|
||||
// Begin of dtime limited code
|
||||
|
||||
m_speed += acceleration * dtime_part;
|
||||
position += m_speed * dtime_part;
|
||||
|
||||
/*
|
||||
Collision detection
|
||||
*/
|
||||
|
||||
v3s16 pos_i = floatToInt(position, BS);
|
||||
|
||||
// The loop length is limited to the object moving a distance
|
||||
f32 d = (float)BS * 0.15;
|
||||
|
||||
core::aabbox3d<f32> objectbox(
|
||||
m_collision_box->MinEdge + position,
|
||||
m_collision_box->MaxEdge + position
|
||||
);
|
||||
|
||||
core::aabbox3d<f32> objectbox_old(
|
||||
m_collision_box->MinEdge + oldpos,
|
||||
m_collision_box->MaxEdge + oldpos
|
||||
);
|
||||
|
||||
//TODO: Get these ranges from somewhere
|
||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
try{
|
||||
MapNode n = m_block->getNodeParent(v3s16(x,y,z));
|
||||
if(content_features(n).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Doing nothing here will block the object from
|
||||
// walking over map borders
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
// See if the object is touching ground
|
||||
if(
|
||||
fabs(nodebox.MaxEdge.Y-objectbox.MinEdge.Y) < d
|
||||
&& nodebox.MaxEdge.X-d > objectbox.MinEdge.X
|
||||
&& nodebox.MinEdge.X+d < objectbox.MaxEdge.X
|
||||
&& nodebox.MaxEdge.Z-d > objectbox.MinEdge.Z
|
||||
&& nodebox.MinEdge.Z+d < objectbox.MaxEdge.Z
|
||||
){
|
||||
m_touching_ground = true;
|
||||
}
|
||||
|
||||
if(objectbox.intersectsWithBox(nodebox))
|
||||
{
|
||||
|
||||
v3f dirs[3] = {
|
||||
v3f(0,0,1), // back
|
||||
v3f(0,1,0), // top
|
||||
v3f(1,0,0), // right
|
||||
};
|
||||
for(u16 i=0; i<3; i++)
|
||||
{
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax = objectbox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin = objectbox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax_old = objectbox_old.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin_old = objectbox_old.MinEdge.dotProduct(dirs[i]);
|
||||
|
||||
bool main_edge_collides =
|
||||
((nodemax > playermin && nodemax <= playermin_old + d
|
||||
&& m_speed.dotProduct(dirs[i]) < 0)
|
||||
||
|
||||
(nodemin < playermax && nodemin >= playermax_old - d
|
||||
&& m_speed.dotProduct(dirs[i]) > 0));
|
||||
|
||||
bool other_edges_collide = true;
|
||||
for(u16 j=0; j<3; j++)
|
||||
{
|
||||
if(j == i)
|
||||
continue;
|
||||
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
||||
f32 playermax = objectbox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 playermin = objectbox.MinEdge.dotProduct(dirs[j]);
|
||||
if(!(nodemax - d > playermin && nodemin + d < playermax))
|
||||
{
|
||||
other_edges_collide = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(main_edge_collides && other_edges_collide)
|
||||
{
|
||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // if(objectbox.intersectsWithBox(nodebox))
|
||||
} // for y
|
||||
|
||||
} // End of dtime limited loop
|
||||
while(dtime > 0.001);
|
||||
|
||||
m_pos = position;
|
||||
}
|
||||
|
||||
void MovingObject::simpleMove(float dtime)
|
||||
{
|
||||
m_pos_animation_time_counter += dtime;
|
||||
m_pos_animation_counter += dtime;
|
||||
v3f movevector = m_pos - m_oldpos;
|
||||
f32 moveratio;
|
||||
if(m_pos_animation_time < 0.001)
|
||||
moveratio = 1.0;
|
||||
else
|
||||
moveratio = m_pos_animation_counter / m_pos_animation_time;
|
||||
if(moveratio > 1.5)
|
||||
moveratio = 1.5;
|
||||
m_showpos = m_oldpos + movevector * moveratio;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
/*
|
||||
RatObject
|
||||
*/
|
||||
void RatObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture
|
||||
(0, driver->getTexture(getTexturePath("rat.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
updateNodePos();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
ItemObject
|
||||
*/
|
||||
#ifndef SERVER
|
||||
void ItemObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
// Get image of item for showing
|
||||
video::ITexture *texture = getItemImage();
|
||||
|
||||
/*
|
||||
Create a mesh
|
||||
*/
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, texture);
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
// Set it to use the materials of the meshbuffers directly.
|
||||
// This is needed for changing the texture in the future
|
||||
((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
|
||||
mesh->drop();
|
||||
|
||||
updateSceneNode();
|
||||
}
|
||||
|
||||
video::ITexture * ItemObject::getItemImage()
|
||||
{
|
||||
/*
|
||||
Create an inventory item to see what is its image
|
||||
*/
|
||||
video::ITexture *texture = NULL;
|
||||
InventoryItem *item = createInventoryItem();
|
||||
if(item)
|
||||
texture = item->getImage();
|
||||
if(item)
|
||||
delete item;
|
||||
return texture;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
InventoryItem * ItemObject::createInventoryItem()
|
||||
{
|
||||
try{
|
||||
std::istringstream is(m_itemstring, std::ios_base::binary);
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
dstream<<__FUNCTION_NAME<<": m_itemstring=\""
|
||||
<<m_itemstring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
return item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": serialization error: "
|
||||
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PlayerObject
|
||||
*/
|
||||
#ifndef SERVER
|
||||
void PlayerObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
|
||||
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
// Attach a simple mesh to the player for showing an image
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
{ // Front
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
{ // Back
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
updateNodePos();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
MapBlockObjectList
|
||||
*/
|
||||
|
||||
MapBlockObjectList::MapBlockObjectList(MapBlock *block):
|
||||
m_block(block)
|
||||
{
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
MapBlockObjectList::~MapBlockObjectList()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
/*
|
||||
The serialization format:
|
||||
[0] u16 number of entries
|
||||
[2] entries (id, typeId, parameters)
|
||||
*/
|
||||
|
||||
void MapBlockObjectList::serialize(std::ostream &os, u8 version)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
u8 buf[2];
|
||||
writeU16(buf, m_objects.size());
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
i.getNode()->getValue()->serialize(os, version);
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlockObjectList::update(std::istream &is, u8 version,
|
||||
scene::ISceneManager *smgr, u32 daynight_ratio)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
/*
|
||||
Collect all existing ids to a set.
|
||||
|
||||
As things are updated, they are removed from this.
|
||||
|
||||
All remaining ones are deleted.
|
||||
*/
|
||||
core::map<s16, bool> ids_to_delete;
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
ids_to_delete.insert(i.getNode()->getKey(), true);
|
||||
}
|
||||
|
||||
u8 buf[6];
|
||||
|
||||
is.read((char*)buf, 2);
|
||||
u16 count = readU16(buf);
|
||||
|
||||
for(u16 i=0; i<count; i++)
|
||||
{
|
||||
// Read id
|
||||
is.read((char*)buf, 2);
|
||||
s16 id = readS16(buf);
|
||||
|
||||
// Read position
|
||||
// stored as x1000/BS v3s16
|
||||
is.read((char*)buf, 6);
|
||||
v3s16 pos_i = readV3S16(buf);
|
||||
v3f pos((f32)pos_i.X/1000*BS,
|
||||
(f32)pos_i.Y/1000*BS,
|
||||
(f32)pos_i.Z/1000*BS);
|
||||
|
||||
// Read typeId
|
||||
is.read((char*)buf, 2);
|
||||
u16 type_id = readU16(buf);
|
||||
|
||||
bool create_new = false;
|
||||
|
||||
// Find an object with the id
|
||||
core::map<s16, MapBlockObject*>::Node *n;
|
||||
n = m_objects.find(id);
|
||||
// If no entry is found for id
|
||||
if(n == NULL)
|
||||
{
|
||||
// Insert dummy pointer node
|
||||
m_objects.insert(id, NULL);
|
||||
// Get node
|
||||
n = m_objects.find(id);
|
||||
// A new object will be created at this node
|
||||
create_new = true;
|
||||
}
|
||||
// If type_id differs
|
||||
else if(n->getValue()->getTypeId() != type_id)
|
||||
{
|
||||
// Delete old object
|
||||
delete n->getValue();
|
||||
// A new object will be created at this node
|
||||
create_new = true;
|
||||
}
|
||||
|
||||
MapBlockObject *obj = NULL;
|
||||
|
||||
if(create_new)
|
||||
{
|
||||
/*dstream<<"MapBlockObjectList adding new object"
|
||||
" id="<<id
|
||||
<<std::endl;*/
|
||||
|
||||
if(type_id == MAPBLOCKOBJECT_TYPE_SIGN)
|
||||
{
|
||||
obj = new SignObject(m_block, id, pos);
|
||||
}
|
||||
else if(type_id == MAPBLOCKOBJECT_TYPE_RAT)
|
||||
{
|
||||
obj = new RatObject(m_block, id, pos);
|
||||
}
|
||||
else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
|
||||
{
|
||||
obj = new ItemObject(m_block, id, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is fatal because we cannot know the length
|
||||
// of the object's data
|
||||
throw SerializationError
|
||||
("MapBlockObjectList::update(): Unknown MapBlockObject type");
|
||||
}
|
||||
|
||||
if(smgr != NULL)
|
||||
//obj->addToScene(smgr, daynight_ratio);
|
||||
obj->addToScene(smgr);
|
||||
|
||||
n->setValue(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = n->getValue();
|
||||
obj->updatePos(pos);
|
||||
/*if(daynight_ratio != m_last_update_daynight_ratio)
|
||||
{
|
||||
obj->removeFromScene();
|
||||
obj->addToScene(smgr, daynight_ratio);
|
||||
}*/
|
||||
}
|
||||
|
||||
// Now there is an object in obj.
|
||||
// Update it.
|
||||
|
||||
obj->update(is, version);
|
||||
|
||||
/*
|
||||
Update light on client
|
||||
*/
|
||||
if(smgr != NULL)
|
||||
{
|
||||
u8 light = LIGHT_MAX;
|
||||
try{
|
||||
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
||||
MapNode n = m_block->getNodeParent(relpos_i);
|
||||
light = n.getLightBlend(daynight_ratio);
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
obj->updateLight(light);
|
||||
}
|
||||
|
||||
// Remove from deletion list
|
||||
if(ids_to_delete.find(id) != NULL)
|
||||
ids_to_delete.remove(id);
|
||||
}
|
||||
|
||||
// Delete all objects whose ids_to_delete remain in ids_to_delete
|
||||
for(core::map<s16, bool>::Iterator
|
||||
i = ids_to_delete.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
s16 id = i.getNode()->getKey();
|
||||
|
||||
/*dstream<<"MapBlockObjectList deleting object"
|
||||
" id="<<id
|
||||
<<std::endl;*/
|
||||
|
||||
MapBlockObject *obj = m_objects[id];
|
||||
obj->removeFromScene();
|
||||
delete obj;
|
||||
m_objects.remove(id);
|
||||
}
|
||||
|
||||
m_last_update_daynight_ratio = daynight_ratio;
|
||||
}
|
||||
|
||||
s16 MapBlockObjectList::getFreeId() throw(ContainerFullException)
|
||||
{
|
||||
s16 id = 0;
|
||||
for(;;)
|
||||
{
|
||||
if(m_objects.find(id) == NULL)
|
||||
return id;
|
||||
if(id == 32767)
|
||||
throw ContainerFullException
|
||||
("MapBlockObjectList doesn't fit more objects");
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlockObjectList::add(MapBlockObject *object)
|
||||
throw(ContainerFullException, AlreadyExistsException)
|
||||
{
|
||||
if(object == NULL)
|
||||
{
|
||||
dstream<<"MapBlockObjectList::add(): NULL object"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Create unique id if id==-1
|
||||
if(object->m_id == -1)
|
||||
{
|
||||
object->m_id = getFreeId();
|
||||
}
|
||||
|
||||
if(m_objects.find(object->m_id) != NULL)
|
||||
{
|
||||
dstream<<"MapBlockObjectList::add(): "
|
||||
"object with same id already exists"<<std::endl;
|
||||
throw AlreadyExistsException
|
||||
("MapBlockObjectList already has given id");
|
||||
}
|
||||
|
||||
object->m_block = m_block;
|
||||
|
||||
/*v3f p = object->m_pos;
|
||||
dstream<<"MapBlockObjectList::add(): "
|
||||
<<"m_block->getPos()=("
|
||||
<<m_block->getPos().X<<","
|
||||
<<m_block->getPos().Y<<","
|
||||
<<m_block->getPos().Z<<")"
|
||||
<<" inserting object with id="<<object->m_id
|
||||
<<" pos="
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||
<<std::endl;*/
|
||||
|
||||
m_objects.insert(object->m_id, object);
|
||||
}
|
||||
|
||||
void MapBlockObjectList::clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
//FIXME: This really shouldn't be NULL at any time,
|
||||
// but this condition was added because it was.
|
||||
if(obj != NULL)
|
||||
{
|
||||
obj->removeFromScene();
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
m_objects.clear();
|
||||
}
|
||||
|
||||
void MapBlockObjectList::remove(s16 id)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<s16, MapBlockObject*>::Node *n;
|
||||
n = m_objects.find(id);
|
||||
if(n == NULL)
|
||||
return;
|
||||
|
||||
n->getValue()->removeFromScene();
|
||||
delete n->getValue();
|
||||
m_objects.remove(id);
|
||||
}
|
||||
|
||||
MapBlockObject * MapBlockObjectList::get(s16 id)
|
||||
{
|
||||
core::map<s16, MapBlockObject*>::Node *n;
|
||||
n = m_objects.find(id);
|
||||
if(n == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<s16, bool> ids_to_delete;
|
||||
|
||||
{
|
||||
DSTACKF("%s: stepping objects", __FUNCTION_NAME);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
|
||||
DSTACKF("%s: stepping object type %i", __FUNCTION_NAME,
|
||||
obj->getTypeId());
|
||||
|
||||
if(server)
|
||||
{
|
||||
// Update light
|
||||
u8 light = LIGHT_MAX;
|
||||
try{
|
||||
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
||||
MapNode n = m_block->getNodeParent(relpos_i);
|
||||
light = n.getLightBlend(daynight_ratio);
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
obj->updateLight(light);
|
||||
|
||||
bool to_delete = obj->serverStep(dtime, daynight_ratio);
|
||||
|
||||
if(to_delete)
|
||||
ids_to_delete.insert(obj->m_id, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->clientStep(dtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
DSTACKF("%s: deleting objects", __FUNCTION_NAME);
|
||||
|
||||
// Delete objects in delete queue
|
||||
for(core::map<s16, bool>::Iterator
|
||||
i = ids_to_delete.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
s16 id = i.getNode()->getKey();
|
||||
|
||||
MapBlockObject *obj = m_objects[id];
|
||||
obj->removeFromScene();
|
||||
delete obj;
|
||||
m_objects.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Wrap objects on server
|
||||
*/
|
||||
|
||||
if(server == false)
|
||||
return;
|
||||
|
||||
{
|
||||
DSTACKF("%s: object wrap loop", __FUNCTION_NAME);
|
||||
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
|
||||
v3s16 pos_i = floatToInt(obj->m_pos, BS);
|
||||
|
||||
if(m_block->isValidPosition(pos_i))
|
||||
{
|
||||
// No wrap
|
||||
continue;
|
||||
}
|
||||
|
||||
bool impossible = wrapObject(obj);
|
||||
|
||||
if(impossible)
|
||||
{
|
||||
// No wrap
|
||||
continue;
|
||||
}
|
||||
|
||||
// Restart find
|
||||
i = m_objects.getIterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
// No lock here; this is called so that the lock is already locked.
|
||||
//JMutexAutoLock lock(m_mutex);
|
||||
|
||||
assert(object->m_block == m_block);
|
||||
assert(m_objects.find(object->m_id) != NULL);
|
||||
assert(m_objects[object->m_id] == object);
|
||||
|
||||
Map *map = m_block->getParent();
|
||||
|
||||
// Calculate blockpos on map
|
||||
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
||||
v3f pos_f_on_oldblock = object->m_pos;
|
||||
v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock, BS);
|
||||
v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
|
||||
v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
|
||||
|
||||
// Get new block
|
||||
MapBlock *newblock;
|
||||
try{
|
||||
newblock = map->getBlockNoCreate(pos_blocks_on_map);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Couldn't find block -> not wrapping
|
||||
/*dstream<<"WARNING: Wrapping object not possible: "
|
||||
<<"could not find new block"
|
||||
<<"("<<pos_blocks_on_map.X
|
||||
<<","<<pos_blocks_on_map.Y
|
||||
<<","<<pos_blocks_on_map.Z
|
||||
<<")"<<std::endl;*/
|
||||
/*dstream<<"pos_f_on_oldblock=("
|
||||
<<pos_f_on_oldblock.X<<","
|
||||
<<pos_f_on_oldblock.Y<<","
|
||||
<<pos_f_on_oldblock.Z<<")"
|
||||
<<std::endl;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if(newblock == m_block)
|
||||
{
|
||||
dstream<<"WARNING: Wrapping object not possible: "
|
||||
"newblock == oldblock"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate position on new block
|
||||
v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map, BS);
|
||||
v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
|
||||
v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map, BS);
|
||||
v3f pos_f_on_newblock = pos_f_on_oldblock
|
||||
- newblock_pos_f_on_map + oldblock_pos_f_on_map;
|
||||
|
||||
// Remove object from this block
|
||||
m_objects.remove(object->m_id);
|
||||
|
||||
// Add object to new block
|
||||
object->m_pos = pos_f_on_newblock;
|
||||
object->m_id = -1;
|
||||
object->m_block = NULL;
|
||||
newblock->addObject(object);
|
||||
|
||||
//dstream<<"NOTE: Wrapped object"<<std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MapBlockObjectList::getObjects(v3f origin, f32 max_d,
|
||||
core::array<DistanceSortedObject> &dest)
|
||||
{
|
||||
for(core::map<s16, MapBlockObject*>::Iterator
|
||||
i = m_objects.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlockObject *obj = i.getNode()->getValue();
|
||||
|
||||
f32 d = (obj->getRelativeShowPos() - origin).getLength();
|
||||
|
||||
if(d > max_d)
|
||||
continue;
|
||||
|
||||
DistanceSortedObject dso(obj, d);
|
||||
|
||||
dest.push_back(dso);
|
||||
}
|
||||
}
|
||||
|
||||
//END
|
1116
src/mapblockobject.h
|
@ -80,7 +80,7 @@ static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void make_tree(VoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree)
|
||||
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree)
|
||||
{
|
||||
MapNode treenode(CONTENT_TREE);
|
||||
MapNode leavesnode(CONTENT_LEAVES);
|
||||
|
@ -1405,6 +1405,7 @@ bool get_have_sand(u64 seed, v2s16 p2d)
|
|||
*/
|
||||
void add_random_objects(MapBlock *block)
|
||||
{
|
||||
#if 0
|
||||
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||
{
|
||||
|
@ -1465,6 +1466,7 @@ void add_random_objects(MapBlock *block)
|
|||
}
|
||||
}
|
||||
block->setChangedFlag();
|
||||
#endif
|
||||
}
|
||||
|
||||
void make_block(BlockMakeData *data)
|
||||
|
|
|
@ -40,6 +40,9 @@ namespace mapgen
|
|||
|
||||
// Add objects according to block content
|
||||
void add_random_objects(MapBlock *block);
|
||||
|
||||
// Add a tree
|
||||
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree);
|
||||
|
||||
/*
|
||||
These are used by FarMesh
|
||||
|
|
|
@ -19,7 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#include "common_irrlicht.h"
|
||||
#include "mapnode.h"
|
||||
#ifndef SERVER
|
||||
#include "tile.h"
|
||||
#endif
|
||||
#include "porting.h"
|
||||
#include <string>
|
||||
#include "mineral.h"
|
||||
|
@ -31,10 +33,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
ContentFeatures::~ContentFeatures()
|
||||
{
|
||||
delete initial_metadata;
|
||||
#ifndef SERVER
|
||||
delete special_material;
|
||||
delete special_atlas;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
|
||||
{
|
||||
if(g_texturesource)
|
||||
|
@ -85,6 +90,7 @@ void ContentFeatures::setInventoryTextureCube(std::string top,
|
|||
imgname_full += right;
|
||||
inventory_texture = g_texturesource->getTextureRaw(imgname_full);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ContentFeatures g_content_features[MAX_CONTENT+1];
|
||||
|
||||
|
@ -122,7 +128,8 @@ void init_mapnode()
|
|||
/*
|
||||
Initialize content feature table
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SERVER
|
||||
/*
|
||||
Set initial material type to same in all tiles, so that the
|
||||
same material can be used in more stuff.
|
||||
|
@ -144,6 +151,7 @@ void init_mapnode()
|
|||
for(u16 j=0; j<6; j++)
|
||||
f->tiles[j].material_type = initial_material_type;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Initially set every block to be shown as an unknown block.
|
||||
|
@ -188,6 +196,7 @@ v3s16 facedir_rotate(u8 facedir, v3s16 dir)
|
|||
return newdir;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
TileSpec MapNode::getTile(v3s16 dir)
|
||||
{
|
||||
if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
|
||||
|
@ -239,6 +248,7 @@ TileSpec MapNode::getTile(v3s16 dir)
|
|||
|
||||
return spec;
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 MapNode::getMineral()
|
||||
{
|
||||
|
|
|
@ -23,11 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <iostream>
|
||||
#include "common_irrlicht.h"
|
||||
#include "light.h"
|
||||
#include "utility.h"
|
||||
#include "exceptions.h"
|
||||
#include "serialization.h"
|
||||
#include "tile.h"
|
||||
#include "materials.h"
|
||||
#ifndef SERVER
|
||||
#include "tile.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
Naming scheme:
|
||||
|
@ -101,9 +102,7 @@ class NodeMetadata;
|
|||
|
||||
struct ContentFeatures
|
||||
{
|
||||
// Type of MapNode::param1
|
||||
ContentParamType param_type;
|
||||
|
||||
#ifndef SERVER
|
||||
/*
|
||||
0: up
|
||||
1: down
|
||||
|
@ -115,7 +114,18 @@ struct ContentFeatures
|
|||
TileSpec tiles[6];
|
||||
|
||||
video::ITexture *inventory_texture;
|
||||
|
||||
|
||||
// Used currently for flowing liquids
|
||||
u8 vertex_alpha;
|
||||
// Post effect color, drawn when the camera is inside the node.
|
||||
video::SColor post_effect_color;
|
||||
// Special irrlicht material, used sometimes
|
||||
video::SMaterial *special_material;
|
||||
AtlasPointer *special_atlas;
|
||||
#endif
|
||||
|
||||
// Type of MapNode::param1
|
||||
ContentParamType param_type;
|
||||
// True for all ground-like things like stone and mud, false for eg. trees
|
||||
bool is_ground_content;
|
||||
bool light_propagates;
|
||||
|
@ -145,7 +155,11 @@ struct ContentFeatures
|
|||
// Inventory item string as which the node appears in inventory when dug.
|
||||
// Mineral overrides this.
|
||||
std::string dug_item;
|
||||
|
||||
|
||||
// Extra dug item and its rarity
|
||||
std::string extra_dug_item;
|
||||
s32 extra_dug_item_rarity;
|
||||
|
||||
// Initial metadata is cloned from this
|
||||
NodeMetadata *initial_metadata;
|
||||
|
||||
|
@ -158,11 +172,6 @@ struct ContentFeatures
|
|||
// 1 giving almost instantaneous propagation and 7 being
|
||||
// the slowest possible
|
||||
u8 liquid_viscosity;
|
||||
// Used currently for flowing liquids
|
||||
u8 vertex_alpha;
|
||||
// Special irrlicht material, used sometimes
|
||||
video::SMaterial *special_material;
|
||||
AtlasPointer *special_atlas;
|
||||
|
||||
// Amount of light the node emits
|
||||
u8 light_source;
|
||||
|
@ -176,8 +185,15 @@ struct ContentFeatures
|
|||
|
||||
void reset()
|
||||
{
|
||||
param_type = CPT_NONE;
|
||||
#ifndef SERVER
|
||||
inventory_texture = NULL;
|
||||
|
||||
vertex_alpha = 255;
|
||||
post_effect_color = video::SColor(0, 0, 0, 0);
|
||||
special_material = NULL;
|
||||
special_atlas = NULL;
|
||||
#endif
|
||||
param_type = CPT_NONE;
|
||||
is_ground_content = false;
|
||||
light_propagates = false;
|
||||
sunlight_propagates = false;
|
||||
|
@ -196,9 +212,6 @@ struct ContentFeatures
|
|||
liquid_alternative_flowing = CONTENT_IGNORE;
|
||||
liquid_alternative_source = CONTENT_IGNORE;
|
||||
liquid_viscosity = 0;
|
||||
vertex_alpha = 255;
|
||||
special_material = NULL;
|
||||
special_atlas = NULL;
|
||||
light_source = 0;
|
||||
digging_properties.clear();
|
||||
damage_per_second = 0;
|
||||
|
@ -215,6 +228,12 @@ struct ContentFeatures
|
|||
Quickhands for simple materials
|
||||
*/
|
||||
|
||||
#ifdef SERVER
|
||||
void setTexture(u16 i, std::string name, u8 alpha=255)
|
||||
{}
|
||||
void setAllTextures(std::string name, u8 alpha=255)
|
||||
{}
|
||||
#else
|
||||
void setTexture(u16 i, std::string name, u8 alpha=255);
|
||||
|
||||
void setAllTextures(std::string name, u8 alpha=255)
|
||||
|
@ -226,7 +245,9 @@ struct ContentFeatures
|
|||
// Force inventory texture too
|
||||
setInventoryTexture(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERVER
|
||||
void setTile(u16 i, const TileSpec &tile)
|
||||
{
|
||||
tiles[i] = tile;
|
||||
|
@ -238,11 +259,20 @@ struct ContentFeatures
|
|||
setTile(i, tile);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SERVER
|
||||
void setInventoryTexture(std::string imgname)
|
||||
{}
|
||||
void setInventoryTextureCube(std::string top,
|
||||
std::string left, std::string right)
|
||||
{}
|
||||
#else
|
||||
void setInventoryTexture(std::string imgname);
|
||||
|
||||
void setInventoryTextureCube(std::string top,
|
||||
std::string left, std::string right);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -625,6 +655,7 @@ struct MapNode
|
|||
}
|
||||
|
||||
// In mapnode.cpp
|
||||
#ifndef SERVER
|
||||
/*
|
||||
Get tile of a face of the node.
|
||||
dir: direction of face
|
||||
|
@ -632,6 +663,7 @@ struct MapNode
|
|||
which must be obeyed so that the texture atlas can be used.
|
||||
*/
|
||||
TileSpec getTile(v3s16 dir);
|
||||
#endif
|
||||
|
||||
/*
|
||||
Gets mineral content of node, if there is any.
|
||||
|
|
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "inventory.h"
|
||||
#include <sstream>
|
||||
#include "content_mapnode.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
NodeMetadata
|
||||
|
@ -55,7 +56,7 @@ NodeMetadata* NodeMetadata::deSerialize(std::istream &is)
|
|||
if(n == NULL)
|
||||
{
|
||||
// If factory is not found, just return.
|
||||
dstream<<"WARNING: NodeMetadata: No factory for typeId="
|
||||
infostream<<"WARNING: NodeMetadata: No factory for typeId="
|
||||
<<id<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ NodeMetadata* NodeMetadata::deSerialize(std::istream &is)
|
|||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
dstream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
|
||||
infostream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +139,7 @@ void NodeMetadataList::deSerialize(std::istream &is)
|
|||
|
||||
if(version > 1)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
|
||||
infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
|
||||
<<std::endl;
|
||||
throw SerializationError("NodeMetadataList::deSerialize");
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ void NodeMetadataList::deSerialize(std::istream &is)
|
|||
|
||||
if(m_data.find(p))
|
||||
{
|
||||
dstream<<"WARNING: NodeMetadataList::deSerialize(): "
|
||||
infostream<<"WARNING: NodeMetadataList::deSerialize(): "
|
||||
<<"already set data at position"
|
||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
|
||||
<<std::endl;
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
// Used to make custom inventory menus.
|
||||
// See format in guiInventoryMenu.cpp.
|
||||
virtual std::string getInventoryDrawSpecString(){return "";}
|
||||
// primarily used for locking chests, but others can play too
|
||||
virtual std::string getOwner(){ return std::string(""); }
|
||||
virtual void setOwner(std::string t){ }
|
||||
|
||||
protected:
|
||||
static void registerType(u16 id, Factory f);
|
||||
|
|
|
@ -22,6 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "connection.h"
|
||||
#include "constants.h"
|
||||
#include "utility.h"
|
||||
#ifndef SERVER
|
||||
#include <ITextSceneNode.h>
|
||||
#endif
|
||||
#include "settings.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
@ -30,6 +34,7 @@ Player::Player():
|
|||
touching_ground(false),
|
||||
in_water(false),
|
||||
in_water_stable(false),
|
||||
is_climbing(false),
|
||||
swimming_up(false),
|
||||
inventory_backup(NULL),
|
||||
craftresult_is_preview(true),
|
||||
|
@ -380,21 +385,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
/*
|
||||
Calculate new position
|
||||
*/
|
||||
if(is_frozen) {
|
||||
// Still move very slowly so as not to feel all completely stuck
|
||||
position += m_speed * dtime * 0.001;
|
||||
}
|
||||
else {
|
||||
position += m_speed * dtime;
|
||||
}
|
||||
|
||||
/*
|
||||
If the player enters an unloaded chunk this is set to true.
|
||||
*/
|
||||
is_frozen = false;
|
||||
|
||||
// Skip collision detection if a special movement mode is used
|
||||
bool free_move = g_settings.getBool("free_move");
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
if(free_move)
|
||||
{
|
||||
setPosition(position);
|
||||
|
@ -550,6 +544,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
|
||||
<<"):"<<std::endl;*/
|
||||
|
||||
bool standing_on_unloaded = false;
|
||||
|
||||
/*
|
||||
Go through every node around the player
|
||||
*/
|
||||
|
@ -557,6 +553,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||
{
|
||||
bool is_unloaded = false;
|
||||
try{
|
||||
// Player collides into walkable nodes
|
||||
if(content_walkable(map.getNode(v3s16(x,y,z)).getContent()) == false)
|
||||
|
@ -564,12 +561,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
if(!is_frozen) {
|
||||
// freeze when entering unloaded areas
|
||||
is_frozen = true;
|
||||
is_unloaded = true;
|
||||
// Doing nothing here will block the player from
|
||||
// walking over map borders
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
|
@ -591,6 +586,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
&& nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z
|
||||
){
|
||||
touching_ground = true;
|
||||
if(is_unloaded)
|
||||
standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
// If player doesn't intersect with node, ignore node.
|
||||
|
@ -772,7 +769,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
if(old_speed.Y < m_speed.Y - 0.1 && !standing_on_unloaded)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
|
@ -804,9 +801,9 @@ void LocalPlayer::applyControl(float dtime)
|
|||
|
||||
v3f speed = v3f(0,0,0);
|
||||
|
||||
bool free_move = g_settings.getBool("free_move");
|
||||
bool fast_move = g_settings.getBool("fast_move");
|
||||
bool continuous_forward = g_settings.getBool("continuous_forward");
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
bool fast_move = g_settings->getBool("fast_move");
|
||||
bool continuous_forward = g_settings->getBool("continuous_forward");
|
||||
|
||||
if(free_move || is_climbing)
|
||||
{
|
||||
|
|
38
src/player.h
|
@ -71,12 +71,17 @@ public:
|
|||
return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
|
||||
}
|
||||
|
||||
v3f getEyePosition()
|
||||
v3f getEyeOffset()
|
||||
{
|
||||
// This is at the height of the eyes of the current figure
|
||||
// return m_position + v3f(0, BS+BS/2, 0);
|
||||
// return v3f(0, BS+BS/2, 0);
|
||||
// This is more like in minecraft
|
||||
return m_position + v3f(0,BS+(5*BS)/8,0);
|
||||
return v3f(0,BS+(5*BS)/8,0);
|
||||
}
|
||||
|
||||
v3f getEyePosition()
|
||||
{
|
||||
return m_position + getEyeOffset();
|
||||
}
|
||||
|
||||
virtual void setPosition(const v3f &position)
|
||||
|
@ -125,7 +130,10 @@ public:
|
|||
|
||||
virtual bool isLocal() const = 0;
|
||||
|
||||
virtual void updateLight(u8 light_at_pos) {};
|
||||
virtual void updateLight(u8 light_at_pos)
|
||||
{
|
||||
light = light_at_pos;
|
||||
}
|
||||
|
||||
// NOTE: Use peer_id == 0 for disconnected
|
||||
/*virtual bool isClientConnected() { return false; }
|
||||
|
@ -146,8 +154,9 @@ public:
|
|||
bool in_water_stable;
|
||||
bool is_climbing;
|
||||
bool swimming_up;
|
||||
bool is_frozen;
|
||||
|
||||
u8 light;
|
||||
|
||||
Inventory inventory;
|
||||
// Actual inventory is backed up here when creative mode is used
|
||||
Inventory *inventory_backup;
|
||||
|
@ -270,25 +279,14 @@ public:
|
|||
|
||||
virtual void updateLight(u8 light_at_pos)
|
||||
{
|
||||
Player::updateLight(light_at_pos);
|
||||
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||
|
@ -365,7 +363,7 @@ public:
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
core::list<CollisionInfo> *collision_info);
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||
|
|
|
@ -87,8 +87,8 @@ void signal_handler_init(void)
|
|||
Path mangler
|
||||
*/
|
||||
|
||||
std::string path_data = "../data";
|
||||
std::string path_userdata = "../";
|
||||
std::string path_data = ".." DIR_DELIM "data";
|
||||
std::string path_userdata = "..";
|
||||
|
||||
void pathRemoveFile(char *path, char delim)
|
||||
{
|
||||
|
@ -127,10 +127,10 @@ void initializePaths()
|
|||
pathRemoveFile(buf, '\\');
|
||||
|
||||
// Use "./bin/../data"
|
||||
path_data = std::string(buf) + "/../data";
|
||||
path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data";
|
||||
|
||||
// Use "./bin/../"
|
||||
path_userdata = std::string(buf) + "/../";
|
||||
path_userdata = std::string(buf) + DIR_DELIM ".." DIR_DELIM;
|
||||
|
||||
/*
|
||||
Linux
|
||||
|
@ -188,13 +188,13 @@ void initializePaths()
|
|||
pathRemoveFile(buf, '\\');
|
||||
|
||||
// Use "./bin/../data"
|
||||
path_data = std::string(buf) + "/../data";
|
||||
path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data";
|
||||
//path_data = std::string(buf) + "/../share/" + PROJECT_NAME;
|
||||
|
||||
// Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
|
||||
len = GetEnvironmentVariable("APPDATA", buf, buflen);
|
||||
assert(len < buflen);
|
||||
path_userdata = std::string(buf) + "/" + PROJECT_NAME;
|
||||
path_userdata = std::string(buf) + DIR_DELIM + PROJECT_NAME;
|
||||
|
||||
/*
|
||||
Linux
|
||||
|
|
|
@ -38,24 +38,38 @@ public:
|
|||
m_mutex.Init();
|
||||
}
|
||||
|
||||
void add(const std::string &name, u32 duration)
|
||||
void add(const std::string &name, float value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
core::map<std::string, u32>::Node *n = m_data.find(name);
|
||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
m_data[name] = duration;
|
||||
m_data[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->setValue(n->getValue()+duration);
|
||||
n->setValue(n->getValue() + value);
|
||||
}
|
||||
}
|
||||
|
||||
void lowpass(const std::string &name, float value, float factor)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
core::map<std::string, float>::Node *n = m_data.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
m_data[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->setValue(n->getValue() * (1.0 - 1.0/factor) + value / factor);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
for(core::map<std::string, u32>::Iterator
|
||||
for(core::map<std::string, float>::Iterator
|
||||
i = m_data.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
|
@ -66,14 +80,14 @@ public:
|
|||
void print(std::ostream &o)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
for(core::map<std::string, u32>::Iterator
|
||||
for(core::map<std::string, float>::Iterator
|
||||
i = m_data.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
o<<name<<": ";
|
||||
o<<" "<<name<<": ";
|
||||
s32 clampsize = 40;
|
||||
s32 space = clampsize-name.size();
|
||||
s32 space = clampsize - name.size();
|
||||
for(s32 j=0; j<space; j++)
|
||||
{
|
||||
if(j%2 == 0 && j < space - 1)
|
||||
|
@ -88,25 +102,34 @@ public:
|
|||
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
core::map<std::string, u32> m_data;
|
||||
core::map<std::string, float> m_data;
|
||||
};
|
||||
|
||||
enum ScopeProfilerType{
|
||||
SPT_ADD,
|
||||
SPT_LOWPASS
|
||||
};
|
||||
|
||||
class ScopeProfiler
|
||||
{
|
||||
public:
|
||||
ScopeProfiler(Profiler *profiler, const std::string &name):
|
||||
ScopeProfiler(Profiler *profiler, const std::string &name,
|
||||
enum ScopeProfilerType type = SPT_ADD):
|
||||
m_profiler(profiler),
|
||||
m_name(name),
|
||||
m_timer(NULL)
|
||||
m_timer(NULL),
|
||||
m_type(type)
|
||||
{
|
||||
if(m_profiler)
|
||||
m_timer = new TimeTaker(m_name.c_str());
|
||||
}
|
||||
// name is copied
|
||||
ScopeProfiler(Profiler *profiler, const char *name):
|
||||
ScopeProfiler(Profiler *profiler, const char *name,
|
||||
enum ScopeProfilerType type = SPT_ADD):
|
||||
m_profiler(profiler),
|
||||
m_name(name),
|
||||
m_timer(NULL)
|
||||
m_timer(NULL),
|
||||
m_type(type)
|
||||
{
|
||||
if(m_profiler)
|
||||
m_timer = new TimeTaker(m_name.c_str());
|
||||
|
@ -116,8 +139,16 @@ public:
|
|||
if(m_timer)
|
||||
{
|
||||
u32 duration = m_timer->stop(true);
|
||||
if(m_profiler)
|
||||
m_profiler->add(m_name, duration);
|
||||
if(m_profiler){
|
||||
switch(m_type){
|
||||
case SPT_ADD:
|
||||
m_profiler->add(m_name, duration);
|
||||
break;
|
||||
case SPT_LOWPASS:
|
||||
m_profiler->lowpass(m_name, duration, 20.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete m_timer;
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +156,7 @@ private:
|
|||
Profiler *m_profiler;
|
||||
std::string m_name;
|
||||
TimeTaker *m_timer;
|
||||
enum ScopeProfilerType m_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
1018
src/server.cpp
15
src/server.h
|
@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "environment.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
#include "utility.h"
|
||||
#include "porting.h"
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
|
@ -458,11 +457,7 @@ public:
|
|||
}
|
||||
|
||||
// Saves g_settings to configpath given at initialization
|
||||
void saveConfig()
|
||||
{
|
||||
if(m_configpath != "")
|
||||
g_settings.updateConfigFile(m_configpath.c_str());
|
||||
}
|
||||
void saveConfig();
|
||||
|
||||
void setIpBanned(const std::string &ip, const std::string &name)
|
||||
{
|
||||
|
@ -485,6 +480,9 @@ public:
|
|||
{
|
||||
return m_con.GetPeerNoEx(peer_id);
|
||||
}
|
||||
|
||||
// Envlock and conlock should be locked when calling this
|
||||
void notifyPlayer(const char *name, const std::wstring msg);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -501,6 +499,8 @@ private:
|
|||
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
|
||||
static void SendAccessDenied(con::Connection &con, u16 peer_id,
|
||||
const std::wstring &reason);
|
||||
static void SendDeathscreen(con::Connection &con, u16 peer_id,
|
||||
bool set_camera_point_target, v3f camera_point_target);
|
||||
|
||||
/*
|
||||
Non-static send methods
|
||||
|
@ -537,6 +537,9 @@ private:
|
|||
Something random
|
||||
*/
|
||||
|
||||
void HandlePlayerHP(Player *player, s16 damage);
|
||||
void RespawnPlayer(Player *player);
|
||||
|
||||
void UpdateCrafting(u16 peer_id);
|
||||
|
||||
// When called, connection mutex should be locked
|
||||
|
|
|
@ -18,6 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include "servercommand.h"
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
void cmd_status(std::wostringstream &os,
|
||||
ServerCommandContext *ctx)
|
||||
|
@ -93,10 +96,31 @@ void cmd_grantrevoke(std::wostringstream &os,
|
|||
std::string playername = wide_to_narrow(ctx->parms[1]);
|
||||
u64 privs = ctx->server->getPlayerAuthPrivs(playername);
|
||||
|
||||
if(ctx->parms[0] == L"grant")
|
||||
if(ctx->parms[0] == L"grant"){
|
||||
privs |= newprivs;
|
||||
else
|
||||
actionstream<<ctx->player->getName()<<" grants "
|
||||
<<wide_to_narrow(ctx->parms[2])<<" to "
|
||||
<<playername<<std::endl;
|
||||
|
||||
std::wstring msg;
|
||||
msg += narrow_to_wide(ctx->player->getName());
|
||||
msg += L" granted you the privilege \"";
|
||||
msg += ctx->parms[2];
|
||||
msg += L"\"";
|
||||
ctx->server->notifyPlayer(playername.c_str(), msg);
|
||||
} else {
|
||||
privs &= ~newprivs;
|
||||
actionstream<<ctx->player->getName()<<" revokes "
|
||||
<<wide_to_narrow(ctx->parms[2])<<" from "
|
||||
<<playername<<std::endl;
|
||||
|
||||
std::wstring msg;
|
||||
msg += narrow_to_wide(ctx->player->getName());
|
||||
msg += L" revoked from you the privilege \"";
|
||||
msg += ctx->parms[2];
|
||||
msg += L"\"";
|
||||
ctx->server->notifyPlayer(playername.c_str(), msg);
|
||||
}
|
||||
|
||||
ctx->server->setPlayerAuthPrivs(playername, privs);
|
||||
|
||||
|
@ -122,6 +146,9 @@ void cmd_time(std::wostringstream &os,
|
|||
u32 time = stoi(wide_to_narrow(ctx->parms[1]));
|
||||
ctx->server->setTimeOfDay(time);
|
||||
os<<L"-!- time_of_day changed.";
|
||||
|
||||
actionstream<<ctx->player->getName()<<" sets time "
|
||||
<<time<<std::endl;
|
||||
}
|
||||
|
||||
void cmd_shutdown(std::wostringstream &os,
|
||||
|
@ -133,8 +160,9 @@ void cmd_shutdown(std::wostringstream &os,
|
|||
return;
|
||||
}
|
||||
|
||||
dstream<<DTIME<<" Server: Operator requested shutdown."
|
||||
<<std::endl;
|
||||
actionstream<<ctx->player->getName()
|
||||
<<" shuts down server"<<std::endl;
|
||||
|
||||
ctx->server->requestShutdown();
|
||||
|
||||
os<<L"*** Server shutting down (operator request)";
|
||||
|
@ -155,7 +183,10 @@ void cmd_setting(std::wostringstream &os,
|
|||
|
||||
std::string confline = wide_to_narrow(ctx->paramstring);
|
||||
|
||||
g_settings.parseConfigLine(confline);
|
||||
actionstream<<ctx->player->getName()
|
||||
<<" sets: "<<confline<<std::endl;
|
||||
|
||||
g_settings->parseConfigLine(confline);
|
||||
|
||||
ctx->server->saveConfig();
|
||||
|
||||
|
@ -185,6 +216,11 @@ void cmd_teleport(std::wostringstream &os,
|
|||
}
|
||||
|
||||
v3f dest(stoi(coords[0])*10, stoi(coords[1])*10, stoi(coords[2])*10);
|
||||
|
||||
actionstream<<ctx->player->getName()<<" teleports from "
|
||||
<<PP(ctx->player->getPosition()/BS)<<" to "
|
||||
<<PP(dest/BS)<<std::endl;
|
||||
|
||||
ctx->player->setPosition(dest);
|
||||
ctx->server->SendMovePlayer(ctx->player);
|
||||
|
||||
|
@ -225,6 +261,9 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
|||
ctx->server->setIpBanned(ip_string, player->getName());
|
||||
os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
|
||||
<<narrow_to_wide(player->getName());
|
||||
|
||||
actionstream<<ctx->player->getName()<<" bans "
|
||||
<<player->getName()<<" / "<<ip_string<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -232,6 +271,9 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
|||
std::string desc = ctx->server->getBanDescription(ip_or_name);
|
||||
ctx->server->unsetIpBanned(ip_or_name);
|
||||
os<<L"-!- Unbanned "<<narrow_to_wide(desc);
|
||||
|
||||
actionstream<<ctx->player->getName()<<" unbans "
|
||||
<<ip_or_name<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,18 +70,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "config.h"
|
||||
#include "mineral.h"
|
||||
#include "filesys.h"
|
||||
#include "defaultsettings.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
Settings.
|
||||
These are loaded from the config file.
|
||||
*/
|
||||
|
||||
Settings g_settings;
|
||||
|
||||
extern void set_default_settings();
|
||||
Settings main_settings;
|
||||
Settings *g_settings = &main_settings;
|
||||
|
||||
// Global profiler
|
||||
Profiler g_profiler;
|
||||
Profiler main_profiler;
|
||||
Profiler *g_profiler = &main_profiler;
|
||||
|
||||
// A dummy thing
|
||||
ITextureSource *g_texturesource = NULL;
|
||||
|
@ -92,15 +95,15 @@ ITextureSource *g_texturesource = NULL;
|
|||
|
||||
// Connection
|
||||
std::ostream *dout_con_ptr = &dummyout;
|
||||
std::ostream *derr_con_ptr = &dstream_no_stderr;
|
||||
std::ostream *derr_con_ptr = &verbosestream;
|
||||
|
||||
// Server
|
||||
std::ostream *dout_server_ptr = &dstream;
|
||||
std::ostream *derr_server_ptr = &dstream;
|
||||
std::ostream *dout_server_ptr = &infostream;
|
||||
std::ostream *derr_server_ptr = &errorstream;
|
||||
|
||||
// Client
|
||||
std::ostream *dout_client_ptr = &dstream;
|
||||
std::ostream *derr_client_ptr = &dstream;
|
||||
std::ostream *dout_client_ptr = &infostream;
|
||||
std::ostream *derr_client_ptr = &errorstream;
|
||||
|
||||
/*
|
||||
gettime.h implementation
|
||||
|
@ -114,12 +117,37 @@ u32 getTimeMs()
|
|||
return porting::getTimeMs();
|
||||
}
|
||||
|
||||
class DstreamLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
dstream<<line<<std::endl;
|
||||
}
|
||||
} main_dstream_log_out;
|
||||
|
||||
class DstreamNoStderrLogOutput: public ILogOutput
|
||||
{
|
||||
public:
|
||||
/* line: Full line with timestamp, level and thread */
|
||||
void printLog(const std::string &line)
|
||||
{
|
||||
dstream_no_stderr<<line<<std::endl;
|
||||
}
|
||||
} main_dstream_no_stderr_log_out;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/*
|
||||
Initialization
|
||||
*/
|
||||
|
||||
log_add_output_maxlev(&main_dstream_log_out, LMT_ACTION);
|
||||
log_add_output_all_levs(&main_dstream_no_stderr_log_out);
|
||||
|
||||
log_register_thread("main");
|
||||
|
||||
// Set locale. This is for forcing '.' as the decimal point.
|
||||
std::locale::global(std::locale("C"));
|
||||
// This enables printing all characters in bitmap font
|
||||
|
@ -147,7 +175,7 @@ int main(int argc, char *argv[])
|
|||
#ifdef RUN_IN_PLACE
|
||||
std::string debugfile = DEBUGFILE;
|
||||
#else
|
||||
std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;
|
||||
std::string debugfile = porting::path_userdata+DIR_DELIM+DEBUGFILE;
|
||||
#endif
|
||||
debugstreams_init(disable_stderr, debugfile.c_str());
|
||||
// Initialize debug stacks
|
||||
|
@ -162,7 +190,7 @@ int main(int argc, char *argv[])
|
|||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
// Print startup message
|
||||
dstream<<DTIME<<PROJECT_NAME <<
|
||||
actionstream<<PROJECT_NAME<<
|
||||
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
|
||||
<<", "<<BUILD_INFO
|
||||
<<std::endl;
|
||||
|
@ -183,6 +211,7 @@ int main(int argc, char *argv[])
|
|||
allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG));
|
||||
allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG));
|
||||
allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING));
|
||||
allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG));
|
||||
|
||||
Settings cmd_args;
|
||||
|
||||
|
@ -215,13 +244,15 @@ int main(int argc, char *argv[])
|
|||
return cmd_args.getFlag("help") ? 0 : 1;
|
||||
}
|
||||
|
||||
if(cmd_args.getFlag("info-on-stderr"))
|
||||
log_add_output(&main_dstream_log_out, LMT_INFO);
|
||||
|
||||
/*
|
||||
Basic initialization
|
||||
*/
|
||||
|
||||
// Initialize default settings
|
||||
set_default_settings();
|
||||
set_default_settings(g_settings);
|
||||
|
||||
// Initialize sockets
|
||||
sockets_init();
|
||||
|
@ -236,10 +267,10 @@ int main(int argc, char *argv[])
|
|||
|
||||
if(cmd_args.exists("config"))
|
||||
{
|
||||
bool r = g_settings.readConfigFile(cmd_args.get("config").c_str());
|
||||
bool r = g_settings->readConfigFile(cmd_args.get("config").c_str());
|
||||
if(r == false)
|
||||
{
|
||||
dstream<<"Could not read configuration from \""
|
||||
errorstream<<"Could not read configuration from \""
|
||||
<<cmd_args.get("config")<<"\""<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
@ -248,14 +279,16 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
{
|
||||
core::array<std::string> filenames;
|
||||
filenames.push_back(porting::path_userdata + "/minetest.conf");
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + "minetest.conf");
|
||||
#ifdef RUN_IN_PLACE
|
||||
filenames.push_back(porting::path_userdata + "/../minetest.conf");
|
||||
filenames.push_back(porting::path_userdata +
|
||||
DIR_DELIM + ".." + DIR_DELIM + "minetest.conf");
|
||||
#endif
|
||||
|
||||
for(u32 i=0; i<filenames.size(); i++)
|
||||
{
|
||||
bool r = g_settings.readConfigFile(filenames[i].c_str());
|
||||
bool r = g_settings->readConfigFile(filenames[i].c_str());
|
||||
if(r)
|
||||
{
|
||||
configpath = filenames[i];
|
||||
|
@ -305,9 +338,9 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
port = cmd_args.getU16("port");
|
||||
}
|
||||
else if(g_settings.exists("port") && g_settings.getU16("port") != 0)
|
||||
else if(g_settings->exists("port") && g_settings->getU16("port") != 0)
|
||||
{
|
||||
port = g_settings.getU16("port");
|
||||
port = g_settings->getU16("port");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -316,11 +349,11 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
// Figure out path to map
|
||||
std::string map_dir = porting::path_userdata+"/world";
|
||||
std::string map_dir = porting::path_userdata+DIR_DELIM+"world";
|
||||
if(cmd_args.exists("map-dir"))
|
||||
map_dir = cmd_args.get("map-dir");
|
||||
else if(g_settings.exists("map-dir"))
|
||||
map_dir = g_settings.get("map-dir");
|
||||
else if(g_settings->exists("map-dir"))
|
||||
map_dir = g_settings->get("map-dir");
|
||||
|
||||
// Create server
|
||||
Server server(map_dir.c_str(), configpath);
|
||||
|
@ -332,10 +365,10 @@ int main(int argc, char *argv[])
|
|||
} //try
|
||||
catch(con::PeerNotFoundException &e)
|
||||
{
|
||||
dstream<<DTIME<<"Connection timed out."<<std::endl;
|
||||
errorstream<<"Connection timed out."<<std::endl;
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
|
||||
debugstreams_deinit();
|
||||
|
||||
|
|
|
@ -104,12 +104,15 @@ public:
|
|||
If the object doesn't return an item, this will be called.
|
||||
Return value is tool wear.
|
||||
*/
|
||||
virtual u16 punch(const std::string &toolname, v3f dir)
|
||||
virtual u16 punch(const std::string &toolname, v3f dir,
|
||||
const std::string &playername)
|
||||
{return 0;}
|
||||
|
||||
/*
|
||||
*/
|
||||
virtual void rightClick(Player *player){}
|
||||
|
||||
virtual bool isPeaceful(){return true;}
|
||||
|
||||
/*
|
||||
Number of players which know about this object. Object won't be
|
||||
|
|
|
@ -0,0 +1,658 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef SETTINGS_HEADER
|
||||
#define SETTINGS_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include "strfnd.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "debug.h"
|
||||
#include "utility.h"
|
||||
#include "log.h"
|
||||
|
||||
enum ValueType
|
||||
{
|
||||
VALUETYPE_STRING,
|
||||
VALUETYPE_FLAG // Doesn't take any arguments
|
||||
};
|
||||
|
||||
struct ValueSpec
|
||||
{
|
||||
ValueSpec(ValueType a_type, const char *a_help=NULL)
|
||||
{
|
||||
type = a_type;
|
||||
help = a_help;
|
||||
}
|
||||
ValueType type;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings()
|
||||
{
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
void writeLines(std::ostream &os)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseConfigLine(const std::string &line)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
return true;
|
||||
|
||||
//infostream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
return true;
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
/*infostream<<"Config name=\""<<name<<"\" value=\""
|
||||
<<value<<"\""<<std::endl;*/
|
||||
|
||||
m_settings[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void parseConfigLines(std::istream &is, const std::string &endstring)
|
||||
{
|
||||
for(;;){
|
||||
if(is.eof())
|
||||
break;
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
std::string trimmedline = trim(line);
|
||||
if(endstring != ""){
|
||||
if(trimmedline == endstring)
|
||||
break;
|
||||
}
|
||||
parseConfigLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns false on EOF
|
||||
bool parseConfigObject(std::istream &is)
|
||||
{
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
/*
|
||||
NOTE: This function might be expanded to allow multi-line
|
||||
settings.
|
||||
*/
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
//infostream<<"got line: \""<<line<<"\""<<std::endl;
|
||||
|
||||
return parseConfigLine(line);
|
||||
}
|
||||
|
||||
/*
|
||||
Read configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool readConfigFile(const char *filename)
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
errorstream<<"Error opening configuration file \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
infostream<<"Parsing configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
while(parseConfigObject(is));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Reads a configuration object from stream (usually a single line)
|
||||
and adds it to dst.
|
||||
|
||||
Preserves comments and empty lines.
|
||||
|
||||
Settings that were added to dst are also added to updated.
|
||||
key of updated is setting name, value of updated is dummy.
|
||||
|
||||
Returns false on EOF
|
||||
*/
|
||||
bool getUpdatedConfigObject(std::istream &is,
|
||||
core::list<std::string> &dst,
|
||||
core::map<std::string, bool> &updated)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
// NOTE: This function will be expanded to allow multi-line settings
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
std::string line_end = "";
|
||||
if(is.eof() == false)
|
||||
line_end = "\n";
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
if(m_settings.find(name))
|
||||
{
|
||||
std::string newvalue = m_settings[name];
|
||||
|
||||
if(newvalue != value)
|
||||
{
|
||||
infostream<<"Changing value of \""<<name<<"\" = \""
|
||||
<<value<<"\" -> \""<<newvalue<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
dst.push_back(name + " = " + newvalue + line_end);
|
||||
|
||||
updated[name] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Updates configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool updateConfigFile(const char *filename)
|
||||
{
|
||||
infostream<<"Updating configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
core::list<std::string> objects;
|
||||
core::map<std::string, bool> updated;
|
||||
|
||||
// Read and modify stuff
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
infostream<<"updateConfigFile():"
|
||||
" Error opening configuration file"
|
||||
" for reading: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(getUpdatedConfigObject(is, objects, updated));
|
||||
}
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Write stuff back
|
||||
{
|
||||
std::ofstream os(filename);
|
||||
if(os.good() == false)
|
||||
{
|
||||
errorstream<<"Error opening configuration file"
|
||||
" for writing: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Write updated stuff
|
||||
*/
|
||||
for(core::list<std::string>::Iterator
|
||||
i = objects.begin();
|
||||
i != objects.end(); i++)
|
||||
{
|
||||
os<<(*i);
|
||||
}
|
||||
|
||||
/*
|
||||
Write stuff that was not already in the file
|
||||
*/
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
if(updated.find(i.getNode()->getKey()))
|
||||
continue;
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: Types of allowed_options are ignored
|
||||
|
||||
returns true on success
|
||||
*/
|
||||
bool parseCommandLine(int argc, char *argv[],
|
||||
core::map<std::string, ValueSpec> &allowed_options)
|
||||
{
|
||||
int i=1;
|
||||
for(;;)
|
||||
{
|
||||
if(i >= argc)
|
||||
break;
|
||||
std::string argname = argv[i];
|
||||
if(argname.substr(0, 2) != "--")
|
||||
{
|
||||
errorstream<<"Invalid command-line parameter \""
|
||||
<<argname<<"\": --<option> expected."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
|
||||
std::string name = argname.substr(2);
|
||||
|
||||
core::map<std::string, ValueSpec>::Node *n;
|
||||
n = allowed_options.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
errorstream<<"Unknown command-line parameter \""
|
||||
<<argname<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueType type = n->getValue().type;
|
||||
|
||||
std::string value = "";
|
||||
|
||||
if(type == VALUETYPE_FLAG)
|
||||
{
|
||||
value = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i >= argc)
|
||||
{
|
||||
errorstream<<"Invalid command-line parameter \""
|
||||
<<name<<"\": missing value"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
value = argv[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
infostream<<"Valid command-line parameter: \""
|
||||
<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
set(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
void set(std::string name, const char *value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
void setDefault(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_defaults[name] = value;
|
||||
}
|
||||
|
||||
bool exists(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
return (m_settings.find(name) || m_defaults.find(name));
|
||||
}
|
||||
|
||||
std::string get(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, std::string>::Node *n;
|
||||
n = m_settings.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
n = m_defaults.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
infostream<<"Settings: Setting not found: \""
|
||||
<<name<<"\""<<std::endl;
|
||||
throw SettingNotFoundException("Setting not found");
|
||||
}
|
||||
}
|
||||
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
bool getBool(std::string name)
|
||||
{
|
||||
return is_yes(get(name));
|
||||
}
|
||||
|
||||
bool getFlag(std::string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getBool(name);
|
||||
}
|
||||
catch(SettingNotFoundException &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Asks if empty
|
||||
bool getBoolAsk(std::string name, std::string question, bool def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getBool(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" [y/N]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return is_yes(s);
|
||||
}
|
||||
|
||||
float getFloat(std::string name)
|
||||
{
|
||||
return stof(get(name));
|
||||
}
|
||||
|
||||
u16 getU16(std::string name)
|
||||
{
|
||||
return stoi(get(name), 0, 65535);
|
||||
}
|
||||
|
||||
u16 getU16Ask(std::string name, std::string question, u16 def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getU16(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" ["<<def<<"]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return stoi(s, 0, 65535);
|
||||
}
|
||||
|
||||
s16 getS16(std::string name)
|
||||
{
|
||||
return stoi(get(name), -32768, 32767);
|
||||
}
|
||||
|
||||
s32 getS32(std::string name)
|
||||
{
|
||||
return stoi(get(name));
|
||||
}
|
||||
|
||||
v3f getV3F(std::string name)
|
||||
{
|
||||
v3f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(","));
|
||||
value.Z = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
v2f getV2F(std::string name)
|
||||
{
|
||||
v2f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
u64 getU64(std::string name)
|
||||
{
|
||||
u64 value = 0;
|
||||
std::string s = get(name);
|
||||
std::istringstream ss(s);
|
||||
ss>>value;
|
||||
return value;
|
||||
}
|
||||
|
||||
void setBool(std::string name, bool value)
|
||||
{
|
||||
if(value)
|
||||
set(name, "true");
|
||||
else
|
||||
set(name, "false");
|
||||
}
|
||||
|
||||
void setS32(std::string name, s32 value)
|
||||
{
|
||||
set(name, itos(value));
|
||||
}
|
||||
|
||||
void setFloat(std::string name, float value)
|
||||
{
|
||||
set(name, ftos(value));
|
||||
}
|
||||
|
||||
void setV3F(std::string name, v3f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setV2F(std::string name, v2f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setU64(std::string name, u64 value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<value;
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings.clear();
|
||||
m_defaults.clear();
|
||||
}
|
||||
|
||||
void updateValue(Settings &other, const std::string &name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return;
|
||||
|
||||
try{
|
||||
std::string val = other.get(name);
|
||||
m_settings[name] = val;
|
||||
} catch(SettingNotFoundException &e){
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void update(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return;
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_settings[i.getNode()->getKey()] = i.getNode()->getValue();
|
||||
}
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_defaults.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_defaults[i.getNode()->getKey()] = i.getNode()->getValue();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Settings & operator+=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_settings.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_defaults.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_defaults.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
Settings & operator=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
(*this) += other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
core::map<std::string, std::string> m_settings;
|
||||
core::map<std::string, std::string> m_defaults;
|
||||
// All methods that access m_settings/m_defaults directly should lock this.
|
||||
JMutex m_mutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
140
src/test.cpp
|
@ -32,6 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "porting.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "mapsector.h"
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
Asserts that the exception occurs
|
||||
|
@ -48,9 +50,9 @@ struct TestUtilities
|
|||
{
|
||||
void Run()
|
||||
{
|
||||
/*dstream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
|
||||
dstream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
|
||||
dstream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
|
||||
/*infostream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
|
||||
infostream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
|
||||
infostream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
|
||||
assert(fabs(wrapDegrees(100.0) - 100.0) < 0.001);
|
||||
assert(fabs(wrapDegrees(720.5) - 0.5) < 0.001);
|
||||
assert(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
|
||||
|
@ -111,13 +113,13 @@ struct TestCompress
|
|||
|
||||
std::string str_out = os.str();
|
||||
|
||||
dstream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
dstream<<"TestCompress: 1,5,5,1 -> ";
|
||||
infostream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
infostream<<"TestCompress: 1,5,5,1 -> ";
|
||||
for(u32 i=0; i<str_out.size(); i++)
|
||||
{
|
||||
dstream<<(u32)str_out[i]<<",";
|
||||
infostream<<(u32)str_out[i]<<",";
|
||||
}
|
||||
dstream<<std::endl;
|
||||
infostream<<std::endl;
|
||||
|
||||
assert(str_out.size() == 10);
|
||||
|
||||
|
@ -138,12 +140,12 @@ struct TestCompress
|
|||
decompress(is, os2, 0);
|
||||
std::string str_out2 = os2.str();
|
||||
|
||||
dstream<<"decompress: ";
|
||||
infostream<<"decompress: ";
|
||||
for(u32 i=0; i<str_out2.size(); i++)
|
||||
{
|
||||
dstream<<(u32)str_out2[i]<<",";
|
||||
infostream<<(u32)str_out2[i]<<",";
|
||||
}
|
||||
dstream<<std::endl;
|
||||
infostream<<std::endl;
|
||||
|
||||
assert(str_out2.size() == fromdata.getSize());
|
||||
|
||||
|
@ -167,13 +169,13 @@ struct TestCompress
|
|||
|
||||
std::string str_out = os.str();
|
||||
|
||||
dstream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
dstream<<"TestCompress: 1,5,5,1 -> ";
|
||||
infostream<<"str_out.size()="<<str_out.size()<<std::endl;
|
||||
infostream<<"TestCompress: 1,5,5,1 -> ";
|
||||
for(u32 i=0; i<str_out.size(); i++)
|
||||
{
|
||||
dstream<<(u32)str_out[i]<<",";
|
||||
infostream<<(u32)str_out[i]<<",";
|
||||
}
|
||||
dstream<<std::endl;
|
||||
infostream<<std::endl;
|
||||
|
||||
/*assert(str_out.size() == 10);
|
||||
|
||||
|
@ -194,12 +196,12 @@ struct TestCompress
|
|||
decompress(is, os2, SER_FMT_VER_HIGHEST);
|
||||
std::string str_out2 = os2.str();
|
||||
|
||||
dstream<<"decompress: ";
|
||||
infostream<<"decompress: ";
|
||||
for(u32 i=0; i<str_out2.size(); i++)
|
||||
{
|
||||
dstream<<(u32)str_out2[i]<<",";
|
||||
infostream<<(u32)str_out2[i]<<",";
|
||||
}
|
||||
dstream<<std::endl;
|
||||
infostream<<std::endl;
|
||||
|
||||
assert(str_out2.size() == fromdata.getSize());
|
||||
|
||||
|
@ -257,12 +259,12 @@ struct TestVoxelManipulator
|
|||
|
||||
assert(aa.size() == results.size());
|
||||
|
||||
dstream<<"Result of diff:"<<std::endl;
|
||||
infostream<<"Result of diff:"<<std::endl;
|
||||
for(core::list<VoxelArea>::Iterator
|
||||
i = aa.begin(); i != aa.end(); i++)
|
||||
{
|
||||
i->print(dstream);
|
||||
dstream<<std::endl;
|
||||
i->print(infostream);
|
||||
infostream<<std::endl;
|
||||
|
||||
s32 j = results.linear_search(*i);
|
||||
assert(j != -1);
|
||||
|
@ -276,27 +278,27 @@ struct TestVoxelManipulator
|
|||
|
||||
VoxelManipulator v;
|
||||
|
||||
v.print(dstream);
|
||||
v.print(infostream);
|
||||
|
||||
dstream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
|
||||
infostream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
|
||||
|
||||
v.setNodeNoRef(v3s16(-1,0,-1), MapNode(2));
|
||||
|
||||
v.print(dstream);
|
||||
v.print(infostream);
|
||||
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
|
||||
|
||||
dstream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
|
||||
infostream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
|
||||
|
||||
EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,0,-1)));
|
||||
|
||||
v.print(dstream);
|
||||
v.print(infostream);
|
||||
|
||||
dstream<<"*** Adding area ***"<<std::endl;
|
||||
infostream<<"*** Adding area ***"<<std::endl;
|
||||
|
||||
v.addArea(a);
|
||||
|
||||
v.print(dstream);
|
||||
v.print(infostream);
|
||||
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
|
||||
EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1)));
|
||||
|
@ -342,12 +344,12 @@ struct TestVoxelManipulator
|
|||
p++;
|
||||
}
|
||||
|
||||
v.print(dstream, VOXELPRINT_WATERPRESSURE);
|
||||
v.print(infostream, VOXELPRINT_WATERPRESSURE);
|
||||
|
||||
core::map<v3s16, u8> active_nodes;
|
||||
v.updateAreaWaterPressure(area, active_nodes);
|
||||
|
||||
v.print(dstream, VOXELPRINT_WATERPRESSURE);
|
||||
v.print(infostream, VOXELPRINT_WATERPRESSURE);
|
||||
|
||||
//s16 highest_y = -32768;
|
||||
/*
|
||||
|
@ -364,8 +366,8 @@ struct TestVoxelManipulator
|
|||
//v.flowWater(active_nodes, 0, true, 1000);
|
||||
v.flowWater(active_nodes, 0, false, 1000);
|
||||
|
||||
dstream<<"Final result of flowWater:"<<std::endl;
|
||||
v.print(dstream, VOXELPRINT_WATERPRESSURE);
|
||||
infostream<<"Final result of flowWater:"<<std::endl;
|
||||
v.print(infostream, VOXELPRINT_WATERPRESSURE);
|
||||
#endif
|
||||
|
||||
//assert(0);
|
||||
|
@ -764,15 +766,15 @@ struct TestConnection
|
|||
assert(readU8(&p1.data[6]) == channel);
|
||||
assert(readU8(&p1.data[7]) == data1[0]);
|
||||
|
||||
//dstream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
|
||||
//infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
|
||||
|
||||
SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
|
||||
|
||||
/*dstream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
|
||||
/*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
|
||||
<<data1.getSize()<<std::endl;
|
||||
dstream<<"readU8(&p2[3])="<<readU8(&p2[3])
|
||||
infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
|
||||
<<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
|
||||
dstream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
|
||||
infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
|
||||
|
||||
assert(p2.getSize() == 3 + data1.getSize());
|
||||
assert(readU8(&p2[0]) == TYPE_RELIABLE);
|
||||
|
@ -790,14 +792,14 @@ struct TestConnection
|
|||
}
|
||||
void peerAdded(con::Peer *peer)
|
||||
{
|
||||
dstream<<"Handler("<<name<<")::peerAdded(): "
|
||||
infostream<<"Handler("<<name<<")::peerAdded(): "
|
||||
"id="<<peer->id<<std::endl;
|
||||
last_id = peer->id;
|
||||
count++;
|
||||
}
|
||||
void deletingPeer(con::Peer *peer, bool timeout)
|
||||
{
|
||||
dstream<<"Handler("<<name<<")::deletingPeer(): "
|
||||
infostream<<"Handler("<<name<<")::deletingPeer(): "
|
||||
"id="<<peer->id
|
||||
<<", timeout="<<timeout<<std::endl;
|
||||
last_id = peer->id;
|
||||
|
@ -823,11 +825,11 @@ struct TestConnection
|
|||
Handler hand_server("server");
|
||||
Handler hand_client("client");
|
||||
|
||||
dstream<<"** Creating server Connection"<<std::endl;
|
||||
infostream<<"** Creating server Connection"<<std::endl;
|
||||
con::Connection server(proto_id, 512, 5.0, &hand_server);
|
||||
server.Serve(30001);
|
||||
|
||||
dstream<<"** Creating client Connection"<<std::endl;
|
||||
infostream<<"** Creating client Connection"<<std::endl;
|
||||
con::Connection client(proto_id, 512, 5.0, &hand_client);
|
||||
|
||||
assert(hand_server.count == 0);
|
||||
|
@ -836,7 +838,7 @@ struct TestConnection
|
|||
sleep_ms(50);
|
||||
|
||||
Address server_address(127,0,0,1, 30001);
|
||||
dstream<<"** running client.Connect()"<<std::endl;
|
||||
infostream<<"** running client.Connect()"<<std::endl;
|
||||
client.Connect(server_address);
|
||||
|
||||
sleep_ms(50);
|
||||
|
@ -851,9 +853,9 @@ struct TestConnection
|
|||
{
|
||||
u16 peer_id;
|
||||
u8 data[100];
|
||||
dstream<<"** running server.Receive()"<<std::endl;
|
||||
infostream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, data, 100);
|
||||
dstream<<"** Server received: peer_id="<<peer_id
|
||||
infostream<<"** Server received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -878,9 +880,9 @@ struct TestConnection
|
|||
{
|
||||
u16 peer_id;
|
||||
u8 data[100];
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
u32 size = client.Receive(peer_id, data, 100);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -896,9 +898,9 @@ struct TestConnection
|
|||
{
|
||||
u16 peer_id;
|
||||
u8 data[100];
|
||||
dstream<<"** running server.Receive()"<<std::endl;
|
||||
infostream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, data, 100);
|
||||
dstream<<"** Server received: peer_id="<<peer_id
|
||||
infostream<<"** Server received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -911,16 +913,16 @@ struct TestConnection
|
|||
u32 datasize = sizeof(data);*/
|
||||
SharedBuffer<u8> data = SharedBufferFromString("Hello World!");
|
||||
|
||||
dstream<<"** running client.Send()"<<std::endl;
|
||||
infostream<<"** running client.Send()"<<std::endl;
|
||||
client.Send(PEER_ID_SERVER, 0, data, true);
|
||||
|
||||
sleep_ms(50);
|
||||
|
||||
u16 peer_id;
|
||||
u8 recvdata[100];
|
||||
dstream<<"** running server.Receive()"<<std::endl;
|
||||
infostream<<"** running server.Receive()"<<std::endl;
|
||||
u32 size = server.Receive(peer_id, recvdata, 100);
|
||||
dstream<<"** Server received: peer_id="<<peer_id
|
||||
infostream<<"** Server received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<*data
|
||||
<<std::endl;
|
||||
|
@ -941,7 +943,7 @@ struct TestConnection
|
|||
Address client_address =
|
||||
server.GetPeer(peer_id_client)->address;
|
||||
|
||||
dstream<<"*** Sending packets in wrong order (2,1,2)"
|
||||
infostream<<"*** Sending packets in wrong order (2,1,2)"
|
||||
<<std::endl;
|
||||
|
||||
u8 chn = 0;
|
||||
|
@ -956,16 +958,16 @@ struct TestConnection
|
|||
|
||||
sleep_ms(50);
|
||||
|
||||
dstream<<"*** Receiving the packets"<<std::endl;
|
||||
infostream<<"*** Receiving the packets"<<std::endl;
|
||||
|
||||
u16 peer_id;
|
||||
u8 recvdata[20];
|
||||
u32 size;
|
||||
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
peer_id = 132;
|
||||
size = client.Receive(peer_id, recvdata, 20);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<recvdata
|
||||
<<std::endl;
|
||||
|
@ -973,10 +975,10 @@ struct TestConnection
|
|||
assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
|
||||
assert(peer_id == PEER_ID_SERVER);
|
||||
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
peer_id = 132;
|
||||
size = client.Receive(peer_id, recvdata, 20);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<recvdata
|
||||
<<std::endl;
|
||||
|
@ -987,17 +989,17 @@ struct TestConnection
|
|||
bool got_exception = false;
|
||||
try
|
||||
{
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
peer_id = 132;
|
||||
size = client.Receive(peer_id, recvdata, 20);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<", data="<<recvdata
|
||||
<<std::endl;
|
||||
}
|
||||
catch(con::NoIncomingDataException &e)
|
||||
{
|
||||
dstream<<"** No incoming data for client"<<std::endl;
|
||||
infostream<<"** No incoming data for client"<<std::endl;
|
||||
got_exception = true;
|
||||
}
|
||||
assert(got_exception);
|
||||
|
@ -1009,35 +1011,35 @@ struct TestConnection
|
|||
data1[i] = i/4;
|
||||
}
|
||||
|
||||
dstream<<"Sending data (size="<<datasize<<"):";
|
||||
infostream<<"Sending data (size="<<datasize<<"):";
|
||||
for(int i=0; i<datasize && i<20; i++){
|
||||
if(i%2==0) DEBUGPRINT(" ");
|
||||
DEBUGPRINT("%.2X", ((int)((const char*)*data1)[i])&0xff);
|
||||
}
|
||||
if(datasize>20)
|
||||
dstream<<"...";
|
||||
dstream<<std::endl;
|
||||
infostream<<"...";
|
||||
infostream<<std::endl;
|
||||
|
||||
server.Send(peer_id_client, 0, data1, true);
|
||||
|
||||
sleep_ms(50);
|
||||
|
||||
u8 recvdata[datasize + 1000];
|
||||
dstream<<"** running client.Receive()"<<std::endl;
|
||||
infostream<<"** running client.Receive()"<<std::endl;
|
||||
u16 peer_id = 132;
|
||||
u16 size = client.Receive(peer_id, recvdata, datasize + 1000);
|
||||
dstream<<"** Client received: peer_id="<<peer_id
|
||||
infostream<<"** Client received: peer_id="<<peer_id
|
||||
<<", size="<<size
|
||||
<<std::endl;
|
||||
|
||||
dstream<<"Received data (size="<<size<<"):";
|
||||
infostream<<"Received data (size="<<size<<"):";
|
||||
for(int i=0; i<size && i<20; i++){
|
||||
if(i%2==0) DEBUGPRINT(" ");
|
||||
DEBUGPRINT("%.2X", ((int)((const char*)recvdata)[i])&0xff);
|
||||
}
|
||||
if(size>20)
|
||||
dstream<<"...";
|
||||
dstream<<std::endl;
|
||||
infostream<<"...";
|
||||
infostream<<std::endl;
|
||||
|
||||
assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
|
||||
assert(peer_id == PEER_ID_SERVER);
|
||||
|
@ -1056,7 +1058,7 @@ struct TestConnection
|
|||
#define TEST(X)\
|
||||
{\
|
||||
X x;\
|
||||
dstream<<"Running " #X <<std::endl;\
|
||||
infostream<<"Running " #X <<std::endl;\
|
||||
x.Run();\
|
||||
}
|
||||
|
||||
|
@ -1064,7 +1066,7 @@ void run_tests()
|
|||
{
|
||||
return; //j
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
dstream<<"run_tests() started"<<std::endl;
|
||||
infostream<<"run_tests() started"<<std::endl;
|
||||
TEST(TestUtilities);
|
||||
TEST(TestSettings);
|
||||
TEST(TestCompress);
|
||||
|
@ -1078,6 +1080,6 @@ void run_tests()
|
|||
TEST(TestConnection);
|
||||
dout_con<<"=== END RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
|
||||
}
|
||||
dstream<<"run_tests() passed"<<std::endl;
|
||||
infostream<<"run_tests() passed"<<std::endl;
|
||||
}
|
||||
|
||||
|
|
227
src/tile.cpp
|
@ -22,6 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "main.h" // for g_settings
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
A cache from texture name to texture path
|
||||
|
@ -112,10 +115,10 @@ std::string getTexturePath(const std::string &filename)
|
|||
/*
|
||||
Check from texture_path
|
||||
*/
|
||||
std::string texture_path = g_settings.get("texture_path");
|
||||
std::string texture_path = g_settings->get("texture_path");
|
||||
if(texture_path != "")
|
||||
{
|
||||
std::string testpath = texture_path + '/' + filename;
|
||||
std::string testpath = texture_path + DIR_DELIM + filename;
|
||||
// Check all filename extensions. Returns "" if not found.
|
||||
fullpath = getImagePath(testpath);
|
||||
}
|
||||
|
@ -157,10 +160,10 @@ TextureSource::TextureSource(IrrlichtDevice *device):
|
|||
m_name_to_id[""] = 0;
|
||||
|
||||
// Build main texture atlas
|
||||
if(g_settings.getBool("enable_texture_atlas"))
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
buildMainAtlas();
|
||||
else
|
||||
dstream<<"INFO: Not building texture atlas."<<std::endl;
|
||||
infostream<<"Not building texture atlas."<<std::endl;
|
||||
}
|
||||
|
||||
TextureSource::~TextureSource()
|
||||
|
@ -177,7 +180,7 @@ void TextureSource::processQueue()
|
|||
GetRequest<std::string, u32, u8, u8>
|
||||
request = m_get_texture_queue.pop();
|
||||
|
||||
dstream<<"INFO: TextureSource::processQueue(): "
|
||||
infostream<<"TextureSource::processQueue(): "
|
||||
<<"got texture request with "
|
||||
<<"name=\""<<request.key<<"\""
|
||||
<<std::endl;
|
||||
|
@ -194,7 +197,7 @@ void TextureSource::processQueue()
|
|||
|
||||
u32 TextureSource::getTextureId(const std::string &name)
|
||||
{
|
||||
//dstream<<"INFO: getTextureId(): \""<<name<<"\""<<std::endl;
|
||||
//infostream<<"getTextureId(): \""<<name<<"\""<<std::endl;
|
||||
|
||||
{
|
||||
/*
|
||||
|
@ -218,7 +221,7 @@ u32 TextureSource::getTextureId(const std::string &name)
|
|||
}
|
||||
else
|
||||
{
|
||||
dstream<<"INFO: getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
|
||||
infostream<<"getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
|
||||
|
||||
// We're gonna ask the result to be put into here
|
||||
ResultQueue<std::string, u32, u8, u8> result_queue;
|
||||
|
@ -226,7 +229,7 @@ u32 TextureSource::getTextureId(const std::string &name)
|
|||
// Throw a request in
|
||||
m_get_texture_queue.add(name, 0, 0, &result_queue);
|
||||
|
||||
dstream<<"INFO: Waiting for texture from main thread, name=\""
|
||||
infostream<<"Waiting for texture from main thread, name=\""
|
||||
<<name<<"\""<<std::endl;
|
||||
|
||||
try
|
||||
|
@ -242,12 +245,12 @@ u32 TextureSource::getTextureId(const std::string &name)
|
|||
}
|
||||
catch(ItemNotFoundException &e)
|
||||
{
|
||||
dstream<<"WARNING: Waiting for texture timed out."<<std::endl;
|
||||
infostream<<"Waiting for texture timed out."<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dstream<<"WARNING: getTextureId(): Failed"<<std::endl;
|
||||
infostream<<"getTextureId(): Failed"<<std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -276,12 +279,12 @@ video::IImage* generate_image_from_scratch(std::string name,
|
|||
*/
|
||||
u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||
{
|
||||
//dstream<<"INFO: getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
|
||||
//infostream<<"getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
|
||||
|
||||
// Empty name means texture 0
|
||||
if(name == "")
|
||||
{
|
||||
dstream<<"INFO: getTextureIdDirect(): name is empty"<<std::endl;
|
||||
infostream<<"getTextureIdDirect(): name is empty"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -290,7 +293,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
*/
|
||||
if(get_current_thread_id() != m_main_thread)
|
||||
{
|
||||
dstream<<"ERROR: TextureSource::getTextureIdDirect() "
|
||||
errorstream<<"TextureSource::getTextureIdDirect() "
|
||||
"called not from main thread"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -305,13 +308,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
n = m_name_to_id.find(name);
|
||||
if(n != NULL)
|
||||
{
|
||||
dstream<<"INFO: getTextureIdDirect(): \""<<name
|
||||
infostream<<"getTextureIdDirect(): \""<<name
|
||||
<<"\" found in cache"<<std::endl;
|
||||
return n->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
dstream<<"INFO: getTextureIdDirect(): \""<<name
|
||||
infostream<<"getTextureIdDirect(): \""<<name
|
||||
<<"\" NOT found in cache. Creating it."<<std::endl;
|
||||
|
||||
/*
|
||||
|
@ -346,13 +349,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
{
|
||||
// Construct base name
|
||||
base_image_name = name.substr(0, last_separator_position);
|
||||
/*dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
|
||||
/*infostream<<"getTextureIdDirect(): Calling itself recursively"
|
||||
" to get base image of \""<<name<<"\" = \""
|
||||
<<base_image_name<<"\""<<std::endl;*/
|
||||
base_image_id = getTextureIdDirect(base_image_name);
|
||||
}
|
||||
|
||||
//dstream<<"base_image_id="<<base_image_id<<std::endl;
|
||||
//infostream<<"base_image_id="<<base_image_id<<std::endl;
|
||||
|
||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||
assert(driver);
|
||||
|
@ -375,7 +378,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
|
||||
if(image == NULL)
|
||||
{
|
||||
dstream<<"WARNING: getTextureIdDirect(): NULL image in "
|
||||
infostream<<"getTextureIdDirect(): NULL image in "
|
||||
<<"cache: \""<<base_image_name<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -394,7 +397,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
core::rect<s32>(pos_from, dim) // from
|
||||
);
|
||||
|
||||
/*dstream<<"INFO: getTextureIdDirect(): Loaded \""
|
||||
/*infostream<<"getTextureIdDirect(): Loaded \""
|
||||
<<base_image_name<<"\" from image cache"
|
||||
<<std::endl;*/
|
||||
}
|
||||
|
@ -406,12 +409,12 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
*/
|
||||
|
||||
std::string last_part_of_name = name.substr(last_separator_position+1);
|
||||
//dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
//infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
|
||||
// Generate image according to part of name
|
||||
if(generate_image(last_part_of_name, baseimg, m_device) == false)
|
||||
{
|
||||
dstream<<"INFO: getTextureIdDirect(): "
|
||||
infostream<<"getTextureIdDirect(): "
|
||||
"failed to generate \""<<last_part_of_name<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
@ -419,7 +422,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
// If no resulting image, print a warning
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
dstream<<"WARNING: getTextureIdDirect(): baseimg is NULL (attempted to"
|
||||
infostream<<"getTextureIdDirect(): baseimg is NULL (attempted to"
|
||||
" create texture \""<<name<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -448,7 +451,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||
m_atlaspointer_cache.push_back(nap);
|
||||
m_name_to_id.insert(name, id);
|
||||
|
||||
/*dstream<<"INFO: getTextureIdDirect(): "
|
||||
/*infostream<<"getTextureIdDirect(): "
|
||||
<<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/
|
||||
|
||||
return id;
|
||||
|
@ -460,7 +463,7 @@ std::string TextureSource::getTextureName(u32 id)
|
|||
|
||||
if(id >= m_atlaspointer_cache.size())
|
||||
{
|
||||
dstream<<"WARNING: TextureSource::getTextureName(): id="<<id
|
||||
infostream<<"TextureSource::getTextureName(): id="<<id
|
||||
<<" >= m_atlaspointer_cache.size()="
|
||||
<<m_atlaspointer_cache.size()<<std::endl;
|
||||
return "";
|
||||
|
@ -482,7 +485,7 @@ AtlasPointer TextureSource::getTexture(u32 id)
|
|||
|
||||
void TextureSource::buildMainAtlas()
|
||||
{
|
||||
dstream<<"TextureSource::buildMainAtlas()"<<std::endl;
|
||||
infostream<<"TextureSource::buildMainAtlas()"<<std::endl;
|
||||
|
||||
//return; // Disable (for testing)
|
||||
|
||||
|
@ -498,7 +501,7 @@ void TextureSource::buildMainAtlas()
|
|||
//assert(atlas_img);
|
||||
if(atlas_img == NULL)
|
||||
{
|
||||
dstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
|
||||
errorstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
|
||||
"image; not building texture atlas."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
@ -567,7 +570,7 @@ void TextureSource::buildMainAtlas()
|
|||
video::IImage *img2 = generate_image_from_scratch(name, m_device);
|
||||
if(img2 == NULL)
|
||||
{
|
||||
dstream<<"WARNING: TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
|
||||
infostream<<"TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -578,7 +581,7 @@ void TextureSource::buildMainAtlas()
|
|||
if(dim.Width > max_size_in_atlas.Width
|
||||
|| dim.Height > max_size_in_atlas.Height)
|
||||
{
|
||||
dstream<<"INFO: TextureSource::buildMainAtlas(): Not adding "
|
||||
infostream<<"TextureSource::buildMainAtlas(): Not adding "
|
||||
<<"\""<<name<<"\" because image is large"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
@ -586,13 +589,13 @@ void TextureSource::buildMainAtlas()
|
|||
// Stop making atlas if atlas is full
|
||||
if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
|
||||
{
|
||||
dstream<<"WARNING: TextureSource::buildMainAtlas(): "
|
||||
infostream<<"TextureSource::buildMainAtlas(): "
|
||||
<<"Atlas is full, not adding more textures."
|
||||
<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
dstream<<"INFO: TextureSource::buildMainAtlas(): Adding \""<<name
|
||||
infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
|
||||
<<"\" to texture atlas"<<std::endl;
|
||||
|
||||
// Tile it a few times in the X direction
|
||||
|
@ -671,7 +674,7 @@ void TextureSource::buildMainAtlas()
|
|||
if(m_name_to_id.find(name) == NULL)
|
||||
continue;
|
||||
u32 id = m_name_to_id[name];
|
||||
//dstream<<"id of name "<<name<<" is "<<id<<std::endl;
|
||||
//infostream<<"id of name "<<name<<" is "<<id<<std::endl;
|
||||
m_atlaspointer_cache[id].a.atlas = t;
|
||||
}
|
||||
|
||||
|
@ -685,7 +688,7 @@ void TextureSource::buildMainAtlas()
|
|||
video::IImage* generate_image_from_scratch(std::string name,
|
||||
IrrlichtDevice *device)
|
||||
{
|
||||
/*dstream<<"INFO: generate_image_from_scratch(): "
|
||||
/*infostream<<"generate_image_from_scratch(): "
|
||||
"\""<<name<<"\""<<std::endl;*/
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
|
@ -710,7 +713,7 @@ video::IImage* generate_image_from_scratch(std::string name,
|
|||
}
|
||||
}
|
||||
|
||||
/*dstream<<"INFO: generate_image_from_scratch(): "
|
||||
/*infostream<<"generate_image_from_scratch(): "
|
||||
<<"last_separator_position="<<last_separator_position
|
||||
<<std::endl;*/
|
||||
|
||||
|
@ -723,7 +726,7 @@ video::IImage* generate_image_from_scratch(std::string name,
|
|||
{
|
||||
// Construct base name
|
||||
base_image_name = name.substr(0, last_separator_position);
|
||||
/*dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
|
||||
/*infostream<<"generate_image_from_scratch(): Calling itself recursively"
|
||||
" to get base image of \""<<name<<"\" = \""
|
||||
<<base_image_name<<"\""<<std::endl;*/
|
||||
baseimg = generate_image_from_scratch(base_image_name, device);
|
||||
|
@ -735,12 +738,12 @@ video::IImage* generate_image_from_scratch(std::string name,
|
|||
*/
|
||||
|
||||
std::string last_part_of_name = name.substr(last_separator_position+1);
|
||||
//dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
//infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
|
||||
|
||||
// Generate image according to part of name
|
||||
if(generate_image(last_part_of_name, baseimg, device) == false)
|
||||
{
|
||||
dstream<<"INFO: generate_image_from_scratch(): "
|
||||
infostream<<"generate_image_from_scratch(): "
|
||||
"failed to generate \""<<last_part_of_name<<"\""
|
||||
<<std::endl;
|
||||
return NULL;
|
||||
|
@ -760,20 +763,20 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
{
|
||||
// A normal texture; load it from a file
|
||||
std::string path = getTexturePath(part_of_name.c_str());
|
||||
/*dstream<<"INFO: generate_image(): Loading path \""<<path
|
||||
/*infostream<<"generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;*/
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): Could not load image \""
|
||||
infostream<<"generate_image(): Could not load image \""
|
||||
<<part_of_name<<"\" from path \""<<path<<"\""
|
||||
<<" while building texture"<<std::endl;
|
||||
|
||||
//return false;
|
||||
|
||||
dstream<<"WARNING: generate_image(): Creating a dummy"
|
||||
infostream<<"generate_image(): Creating a dummy"
|
||||
<<" image for \""<<part_of_name<<"\""<<std::endl;
|
||||
|
||||
// Just create a dummy image
|
||||
|
@ -798,7 +801,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
// If base image is NULL, load as base.
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
//dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
|
||||
//infostream<<"Setting "<<part_of_name<<" as base"<<std::endl;
|
||||
/*
|
||||
Copy it this way to get an alpha channel.
|
||||
Otherwise images with alpha cannot be blitted on
|
||||
|
@ -812,7 +815,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
// Else blit on base.
|
||||
else
|
||||
{
|
||||
//dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||
//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||
// Size of the copied area
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
//core::dimension2d<u32> dim(16,16);
|
||||
|
@ -833,7 +836,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
{
|
||||
// A special texture modification
|
||||
|
||||
dstream<<"INFO: generate_image(): generating special "
|
||||
infostream<<"generate_image(): generating special "
|
||||
<<"modification \""<<part_of_name<<"\""
|
||||
<<std::endl;
|
||||
|
||||
|
@ -856,7 +859,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
{
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): baseimg==NULL "
|
||||
infostream<<"generate_image(): baseimg==NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
|
@ -950,7 +953,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
sf.next(":");
|
||||
u32 w0 = stoi(sf.next("x"));
|
||||
u32 h0 = stoi(sf.next(":"));
|
||||
dstream<<"INFO: combined w="<<w0<<" h="<<h0<<std::endl;
|
||||
infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
|
||||
core::dimension2d<u32> dim(w0,h0);
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
while(sf.atend() == false)
|
||||
|
@ -958,7 +961,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
u32 x = stoi(sf.next(","));
|
||||
u32 y = stoi(sf.next("="));
|
||||
std::string filename = sf.next(":");
|
||||
dstream<<"INFO: Adding \""<<filename
|
||||
infostream<<"Adding \""<<filename
|
||||
<<"\" to combined ("<<x<<","<<y<<")"
|
||||
<<std::endl;
|
||||
video::IImage *img = driver->createImageFromFile(
|
||||
|
@ -966,7 +969,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
if(img)
|
||||
{
|
||||
core::dimension2d<u32> dim = img->getDimension();
|
||||
dstream<<"INFO: Size "<<dim.Width
|
||||
infostream<<"Size "<<dim.Width
|
||||
<<"x"<<dim.Height<<std::endl;
|
||||
core::position2d<s32> pos_base(x, y);
|
||||
video::IImage *img2 =
|
||||
|
@ -981,7 +984,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
}
|
||||
else
|
||||
{
|
||||
dstream<<"WARNING: img==NULL"<<std::endl;
|
||||
infostream<<"img==NULL"<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -993,7 +996,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
{
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): baseimg==NULL "
|
||||
infostream<<"generate_image(): baseimg==NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
|
@ -1013,7 +1016,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): baseimg!=NULL "
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
|
@ -1023,14 +1026,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
|
||||
std::string path = getTexturePath(filename.c_str());
|
||||
|
||||
dstream<<"INFO: generate_image(): Loading path \""<<path
|
||||
infostream<<"generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): Loading path \""
|
||||
infostream<<"generate_image(): Loading path \""
|
||||
<<path<<"\" failed"<<std::endl;
|
||||
}
|
||||
else
|
||||
|
@ -1052,6 +1055,120 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
image->drop();
|
||||
}
|
||||
}
|
||||
/*
|
||||
"[makealpha:R,G,B:filename.png"
|
||||
Use an image with converting one color to transparent.
|
||||
*/
|
||||
else if(part_of_name.substr(0,11) == "[makealpha:")
|
||||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Strfnd sf(part_of_name.substr(11));
|
||||
u32 r1 = stoi(sf.next(","));
|
||||
u32 g1 = stoi(sf.next(","));
|
||||
u32 b1 = stoi(sf.next(":"));
|
||||
std::string filename = sf.next("");
|
||||
|
||||
std::string path = getTexturePath(filename.c_str());
|
||||
|
||||
infostream<<"generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): Loading path \""
|
||||
<<path<<"\" failed"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
|
||||
for(u32 y=0; y<dim.Height; y++)
|
||||
for(u32 x=0; x<dim.Width; x++)
|
||||
{
|
||||
video::SColor c = image->getPixel(x,y);
|
||||
u32 r = c.getRed();
|
||||
u32 g = c.getGreen();
|
||||
u32 b = c.getBlue();
|
||||
if(!(r == r1 && g == g1 && b == b1))
|
||||
continue;
|
||||
c.setAlpha(0);
|
||||
image->setPixel(x,y,c);
|
||||
}
|
||||
// Blit
|
||||
image->copyTo(baseimg);
|
||||
|
||||
image->drop();
|
||||
}
|
||||
}
|
||||
/*
|
||||
"[makealpha2:R,G,B;R2,G2,B2:filename.png"
|
||||
Use an image with converting two colors to transparent.
|
||||
*/
|
||||
else if(part_of_name.substr(0,12) == "[makealpha2:")
|
||||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Strfnd sf(part_of_name.substr(12));
|
||||
u32 r1 = stoi(sf.next(","));
|
||||
u32 g1 = stoi(sf.next(","));
|
||||
u32 b1 = stoi(sf.next(";"));
|
||||
u32 r2 = stoi(sf.next(","));
|
||||
u32 g2 = stoi(sf.next(","));
|
||||
u32 b2 = stoi(sf.next(":"));
|
||||
std::string filename = sf.next("");
|
||||
|
||||
std::string path = getTexturePath(filename.c_str());
|
||||
|
||||
infostream<<"generate_image(): Loading path \""<<path
|
||||
<<"\""<<std::endl;
|
||||
|
||||
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||
|
||||
if(image == NULL)
|
||||
{
|
||||
infostream<<"generate_image(): Loading path \""
|
||||
<<path<<"\" failed"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
|
||||
for(u32 y=0; y<dim.Height; y++)
|
||||
for(u32 x=0; x<dim.Width; x++)
|
||||
{
|
||||
video::SColor c = image->getPixel(x,y);
|
||||
u32 r = c.getRed();
|
||||
u32 g = c.getGreen();
|
||||
u32 b = c.getBlue();
|
||||
if(!(r == r1 && g == g1 && b == b1) &&
|
||||
!(r == r2 && g == g2 && b == b2))
|
||||
continue;
|
||||
c.setAlpha(0);
|
||||
image->setPixel(x,y,c);
|
||||
}
|
||||
// Blit
|
||||
image->copyTo(baseimg);
|
||||
|
||||
image->drop();
|
||||
}
|
||||
}
|
||||
/*
|
||||
[inventorycube{topimage{leftimage{rightimage
|
||||
In every subimage, replace ^ with &.
|
||||
|
@ -1064,7 +1181,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
{
|
||||
if(baseimg != NULL)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): baseimg!=NULL "
|
||||
infostream<<"generate_image(): baseimg!=NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
|
@ -1082,7 +1199,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
|
||||
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): EVDF_RENDER_TO_TARGET"
|
||||
infostream<<"generate_image(): EVDF_RENDER_TO_TARGET"
|
||||
" not supported. Creating fallback image"<<std::endl;
|
||||
baseimg = generate_image_from_scratch(
|
||||
imagename_top, device);
|
||||
|
@ -1091,7 +1208,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
|
||||
u32 w0 = 64;
|
||||
u32 h0 = 64;
|
||||
//dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl;
|
||||
//infostream<<"inventorycube w="<<w0<<" h="<<h0<<std::endl;
|
||||
core::dimension2d<u32> dim(w0,h0);
|
||||
|
||||
// Generate images for the faces of the cube
|
||||
|
@ -1193,7 +1310,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||
}
|
||||
else
|
||||
{
|
||||
dstream<<"WARNING: generate_image(): Invalid "
|
||||
infostream<<"generate_image(): Invalid "
|
||||
" modification: \""<<part_of_name<<"\""<<std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ struct TileSpec
|
|||
}
|
||||
|
||||
// Sets everything else except the texture in the material
|
||||
void applyMaterialOptions(video::SMaterial &material)
|
||||
void applyMaterialOptions(video::SMaterial &material) const
|
||||
{
|
||||
if(alpha != 255 && material_type != MATERIAL_ALPHA_VERTEX)
|
||||
dstream<<"WARNING: TileSpec: alpha != 255 "
|
||||
|
|
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "gettime.h"
|
||||
#include "sha1.h"
|
||||
#include "base64.h"
|
||||
#include "log.h"
|
||||
|
||||
TimeTaker::TimeTaker(const char *name, u32 *result)
|
||||
{
|
||||
|
@ -47,7 +48,7 @@ u32 TimeTaker::stop(bool quiet)
|
|||
else
|
||||
{
|
||||
if(quiet == false)
|
||||
std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
|
||||
infostream<<m_name<<" took "<<dtime<<"ms"<<std::endl;
|
||||
}
|
||||
m_running = false;
|
||||
return dtime;
|
||||
|
@ -156,14 +157,50 @@ void mysrand(unsigned seed)
|
|||
next = seed;
|
||||
}
|
||||
|
||||
int myrand_range(int min, int max)
|
||||
{
|
||||
if(max-min > MYRAND_MAX)
|
||||
{
|
||||
errorstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
|
||||
assert(0);
|
||||
}
|
||||
if(min > max)
|
||||
{
|
||||
assert(0);
|
||||
return max;
|
||||
}
|
||||
return (myrand()%(max-min+1))+min;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
// Sets the color of all vertices in the mesh
|
||||
void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color)
|
||||
{
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
blockpos: position of block in block coordinates
|
||||
camera_pos: position of camera in nodes
|
||||
camera_dir: an unit vector pointing to camera direction
|
||||
range: viewing range
|
||||
*/
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
|
||||
f32 *distance_ptr)
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
f32 camera_fov, f32 range, f32 *distance_ptr)
|
||||
{
|
||||
v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
|
||||
|
||||
|
@ -211,8 +248,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
|
|||
cosangle += block_max_radius / dforward;
|
||||
|
||||
// If block is not in the field of view, skip it
|
||||
//if(cosangle < cos(FOV_ANGLE/2))
|
||||
if(cosangle < cos(FOV_ANGLE/2. * 4./3.))
|
||||
if(cosangle < cos(camera_fov / 2))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
605
src/utility.h
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <jthread.h>
|
||||
#include <jmutex.h>
|
||||
#include <jmutexautolock.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
|
@ -553,6 +554,11 @@ private:
|
|||
u32 *m_result;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
// Sets the color of all vertices in the mesh
|
||||
void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
|
||||
#endif
|
||||
|
||||
// Calculates the borders of a "d-radius" cube
|
||||
inline void getFacePositions(core::list<v3s16> &list, u16 d)
|
||||
{
|
||||
|
@ -804,6 +810,35 @@ inline float wrapDegrees(float f)
|
|||
return f;
|
||||
}
|
||||
|
||||
/* Wrap to 0...360 */
|
||||
inline float wrapDegrees_0_360(float f)
|
||||
{
|
||||
// Take examples of f=10, f=720.5, f=-0.5, f=-360.5
|
||||
// This results in
|
||||
// 10, 720, -1, -361
|
||||
int i = floor(f);
|
||||
// 0, 2, 0, -1
|
||||
int l = i / 360;
|
||||
// Wrap to 0...360
|
||||
// 0, 2, -1, -2
|
||||
if(i < 0)
|
||||
l -= 1;
|
||||
// 0, 720, 0, -360
|
||||
int k = l * 360;
|
||||
// 10, 0.5, -0.5, -0.5
|
||||
f -= float(k);
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Wrap to -180...180 */
|
||||
inline float wrapDegrees_180(float f)
|
||||
{
|
||||
f += 180;
|
||||
f = wrapDegrees_0_360(f);
|
||||
f -= 180;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline std::string lowercase(const std::string &s)
|
||||
{
|
||||
std::string s2;
|
||||
|
@ -935,557 +970,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Config stuff
|
||||
*/
|
||||
|
||||
enum ValueType
|
||||
{
|
||||
VALUETYPE_STRING,
|
||||
VALUETYPE_FLAG // Doesn't take any arguments
|
||||
};
|
||||
|
||||
struct ValueSpec
|
||||
{
|
||||
ValueSpec(ValueType a_type, const char *a_help=NULL)
|
||||
{
|
||||
type = a_type;
|
||||
help = a_help;
|
||||
}
|
||||
ValueType type;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings()
|
||||
{
|
||||
m_mutex.Init();
|
||||
}
|
||||
|
||||
void writeLines(std::ostream &os)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseConfigLine(const std::string &line)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
return true;
|
||||
|
||||
//dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
return true;
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
/*dstream<<"Config name=\""<<name<<"\" value=\""
|
||||
<<value<<"\""<<std::endl;*/
|
||||
|
||||
m_settings[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns false on EOF
|
||||
bool parseConfigObject(std::istream &is)
|
||||
{
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
/*
|
||||
NOTE: This function might be expanded to allow multi-line
|
||||
settings.
|
||||
*/
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
//dstream<<"got line: \""<<line<<"\""<<std::endl;
|
||||
|
||||
return parseConfigLine(line);
|
||||
}
|
||||
|
||||
/*
|
||||
Read configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool readConfigFile(const char *filename)
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"Error opening configuration file \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
dstream<<"Parsing configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
while(parseConfigObject(is));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Reads a configuration object from stream (usually a single line)
|
||||
and adds it to dst.
|
||||
|
||||
Preserves comments and empty lines.
|
||||
|
||||
Settings that were added to dst are also added to updated.
|
||||
key of updated is setting name, value of updated is dummy.
|
||||
|
||||
Returns false on EOF
|
||||
*/
|
||||
bool getUpdatedConfigObject(std::istream &is,
|
||||
core::list<std::string> &dst,
|
||||
core::map<std::string, bool> &updated)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
// NOTE: This function will be expanded to allow multi-line settings
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
std::string line_end = "";
|
||||
if(is.eof() == false)
|
||||
line_end = "\n";
|
||||
|
||||
// Ignore comments
|
||||
if(trimmedline[0] == '#')
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
if(m_settings.find(name))
|
||||
{
|
||||
std::string newvalue = m_settings[name];
|
||||
|
||||
if(newvalue != value)
|
||||
{
|
||||
dstream<<"Changing value of \""<<name<<"\" = \""
|
||||
<<value<<"\" -> \""<<newvalue<<"\""
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
dst.push_back(name + " = " + newvalue + line_end);
|
||||
|
||||
updated[name] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Updates configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool updateConfigFile(const char *filename)
|
||||
{
|
||||
dstream<<"Updating configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
core::list<std::string> objects;
|
||||
core::map<std::string, bool> updated;
|
||||
|
||||
// Read and modify stuff
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
dstream<<"INFO: updateConfigFile():"
|
||||
" Error opening configuration file"
|
||||
" for reading: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(getUpdatedConfigObject(is, objects, updated));
|
||||
}
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// Write stuff back
|
||||
{
|
||||
std::ofstream os(filename);
|
||||
if(os.good() == false)
|
||||
{
|
||||
dstream<<"Error opening configuration file"
|
||||
" for writing: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Write updated stuff
|
||||
*/
|
||||
for(core::list<std::string>::Iterator
|
||||
i = objects.begin();
|
||||
i != objects.end(); i++)
|
||||
{
|
||||
os<<(*i);
|
||||
}
|
||||
|
||||
/*
|
||||
Write stuff that was not already in the file
|
||||
*/
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
if(updated.find(i.getNode()->getKey()))
|
||||
continue;
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: Types of allowed_options are ignored
|
||||
|
||||
returns true on success
|
||||
*/
|
||||
bool parseCommandLine(int argc, char *argv[],
|
||||
core::map<std::string, ValueSpec> &allowed_options)
|
||||
{
|
||||
int i=1;
|
||||
for(;;)
|
||||
{
|
||||
if(i >= argc)
|
||||
break;
|
||||
std::string argname = argv[i];
|
||||
if(argname.substr(0, 2) != "--")
|
||||
{
|
||||
dstream<<"Invalid command-line parameter \""
|
||||
<<argname<<"\": --<option> expected."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
|
||||
std::string name = argname.substr(2);
|
||||
|
||||
core::map<std::string, ValueSpec>::Node *n;
|
||||
n = allowed_options.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
dstream<<"Unknown command-line parameter \""
|
||||
<<argname<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueType type = n->getValue().type;
|
||||
|
||||
std::string value = "";
|
||||
|
||||
if(type == VALUETYPE_FLAG)
|
||||
{
|
||||
value = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i >= argc)
|
||||
{
|
||||
dstream<<"Invalid command-line parameter \""
|
||||
<<name<<"\": missing value"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
value = argv[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
dstream<<"Valid command-line parameter: \""
|
||||
<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
set(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
void set(std::string name, const char *value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
void setDefault(std::string name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_defaults[name] = value;
|
||||
}
|
||||
|
||||
bool exists(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
return (m_settings.find(name) || m_defaults.find(name));
|
||||
}
|
||||
|
||||
std::string get(std::string name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
core::map<std::string, std::string>::Node *n;
|
||||
n = m_settings.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
n = m_defaults.find(name);
|
||||
if(n == NULL)
|
||||
{
|
||||
dstream<<"INFO: Settings: Setting not found: \""
|
||||
<<name<<"\""<<std::endl;
|
||||
throw SettingNotFoundException("Setting not found");
|
||||
}
|
||||
}
|
||||
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
bool getBool(std::string name)
|
||||
{
|
||||
return is_yes(get(name));
|
||||
}
|
||||
|
||||
bool getFlag(std::string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getBool(name);
|
||||
}
|
||||
catch(SettingNotFoundException &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Asks if empty
|
||||
bool getBoolAsk(std::string name, std::string question, bool def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getBool(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" [y/N]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return is_yes(s);
|
||||
}
|
||||
|
||||
float getFloat(std::string name)
|
||||
{
|
||||
return stof(get(name));
|
||||
}
|
||||
|
||||
u16 getU16(std::string name)
|
||||
{
|
||||
return stoi(get(name), 0, 65535);
|
||||
}
|
||||
|
||||
u16 getU16Ask(std::string name, std::string question, u16 def)
|
||||
{
|
||||
// If it is in settings
|
||||
if(exists(name))
|
||||
return getU16(name);
|
||||
|
||||
std::string s;
|
||||
char templine[10];
|
||||
std::cout<<question<<" ["<<def<<"]: ";
|
||||
std::cin.getline(templine, 10);
|
||||
s = templine;
|
||||
|
||||
if(s == "")
|
||||
return def;
|
||||
|
||||
return stoi(s, 0, 65535);
|
||||
}
|
||||
|
||||
s16 getS16(std::string name)
|
||||
{
|
||||
return stoi(get(name), -32768, 32767);
|
||||
}
|
||||
|
||||
s32 getS32(std::string name)
|
||||
{
|
||||
return stoi(get(name));
|
||||
}
|
||||
|
||||
v3f getV3F(std::string name)
|
||||
{
|
||||
v3f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(","));
|
||||
value.Z = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
u64 getU64(std::string name)
|
||||
{
|
||||
u64 value = 0;
|
||||
std::string s = get(name);
|
||||
std::istringstream ss(s);
|
||||
ss>>value;
|
||||
return value;
|
||||
}
|
||||
|
||||
void setBool(std::string name, bool value)
|
||||
{
|
||||
if(value)
|
||||
set(name, "true");
|
||||
else
|
||||
set(name, "false");
|
||||
}
|
||||
|
||||
void setS32(std::string name, s32 value)
|
||||
{
|
||||
set(name, itos(value));
|
||||
}
|
||||
|
||||
void setFloat(std::string name, float value)
|
||||
{
|
||||
set(name, ftos(value));
|
||||
}
|
||||
|
||||
void setV3F(std::string name, v3f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setU64(std::string name, u64 value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<value;
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings.clear();
|
||||
m_defaults.clear();
|
||||
}
|
||||
|
||||
Settings & operator+=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_settings.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = other.m_defaults.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
m_defaults.insert(i.getNode()->getKey(),
|
||||
i.getNode()->getValue());
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
Settings & operator=(Settings &other)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
if(&other == this)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
(*this) += other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
core::map<std::string, std::string> m_settings;
|
||||
core::map<std::string, std::string> m_defaults;
|
||||
// All methods that access m_settings/m_defaults directly should lock this.
|
||||
JMutex m_mutex;
|
||||
};
|
||||
|
||||
/*
|
||||
FIFO queue (well, actually a FILO also)
|
||||
*/
|
||||
|
@ -1746,27 +1230,14 @@ int myrand(void);
|
|||
void mysrand(unsigned seed);
|
||||
#define MYRAND_MAX 32767
|
||||
|
||||
inline int myrand_range(int min, int max)
|
||||
{
|
||||
if(max-min > MYRAND_MAX)
|
||||
{
|
||||
dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
|
||||
assert(0);
|
||||
}
|
||||
if(min > max)
|
||||
{
|
||||
assert(0);
|
||||
return max;
|
||||
}
|
||||
return (myrand()%(max-min+1))+min;
|
||||
}
|
||||
int myrand_range(int min, int max);
|
||||
|
||||
/*
|
||||
Miscellaneous functions
|
||||
*/
|
||||
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
|
||||
f32 *distance_ptr=NULL);
|
||||
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
|
||||
|
||||
/*
|
||||
Queue with unique values with fast checking of value existence
|
||||
|
|
|
@ -24,7 +24,7 @@ f 128 79 0 # CONTENT_CHEST
|
|||
80d 219 202 178 # CONTENT_MOSSYCOBBLE
|
||||
80e 78 154 6 # CONTENT_GRAVEL
|
||||
80f 204 0 0 # CONTENT_SANDSTONE
|
||||
810 211 215 207 # CONTENT_CACTUS
|
||||
810 0 215 0 # CONTENT_CACTUS
|
||||
811 170 50 25 # CONTENT_BRICK
|
||||
812 104 78 42 # CONTENT_CLAY
|
||||
813 58 105 18 # CONTENT_PAPYRUS
|
||||
|
@ -33,3 +33,4 @@ f 128 79 0 # CONTENT_CHEST
|
|||
816 62 101 25 # CONTENT_JUNGLEGRASS
|
||||
817 255 153 255 # CONTENT_NC
|
||||
818 102 50 255 # CONTENT_NC_RB
|
||||
819 200 0 0 # CONTENT_APPLE
|
||||
|
|
|
@ -29,10 +29,9 @@ import time
|
|||
import getopt
|
||||
import sys
|
||||
import array
|
||||
import cStringIO
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageColor
|
||||
|
||||
CONTENT_WATER = [2, 9]
|
||||
|
||||
TRANSLATION_TABLE = {
|
||||
1: 0x800, # CONTENT_GRASS
|
||||
4: 0x801, # CONTENT_TREE
|
||||
|
@ -88,9 +87,19 @@ def int_to_hex4(i):
|
|||
def getBlockAsInteger(p):
|
||||
return p[2]*16777216 + p[1]*4096 + p[0]
|
||||
|
||||
def getIntegerAsBlock(i):
|
||||
return i%4096, int(i/4096)%4096, int(i/16777216)%4096
|
||||
def unsignedToSigned(i, max_positive):
|
||||
if i < max_positive:
|
||||
return i
|
||||
else:
|
||||
return i - 2*max_positive
|
||||
|
||||
def getIntegerAsBlock(i):
|
||||
x = unsignedToSigned(i % 4096, 2048)
|
||||
i = int((i - x) / 4096)
|
||||
y = unsignedToSigned(i % 4096, 2048)
|
||||
i = int((i - y) / 4096)
|
||||
z = unsignedToSigned(i % 4096, 2048)
|
||||
return x,y,z
|
||||
|
||||
def limit(i, l, h):
|
||||
if(i > h):
|
||||
|
@ -101,14 +110,15 @@ def limit(i, l, h):
|
|||
|
||||
|
||||
def usage():
|
||||
print "TODO: Help"
|
||||
print("TODO: Help")
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hi:o:", ["help", "input=",
|
||||
"output=", "bgcolor=", "scalecolor=", "origincolor=",
|
||||
"playercolor=", "draworigin", "drawplayers", "drawscale"])
|
||||
except getopt.GetoptError, err:
|
||||
"playercolor=", "draworigin", "drawplayers", "drawscale",
|
||||
"drawunderground"])
|
||||
except getopt.GetoptError as err:
|
||||
# print help information and exit:
|
||||
print str(err) # will print something like "option -a not recognized"
|
||||
print(str(err)) # will print something like "option -a not recognized"
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
|
@ -122,6 +132,7 @@ playercolor = "red"
|
|||
drawscale = False
|
||||
drawplayers = False
|
||||
draworigin = False
|
||||
drawunderground = False
|
||||
|
||||
sector_xmin = -1500 / 16
|
||||
sector_xmax = 1500 / 16
|
||||
|
@ -151,6 +162,8 @@ for o, a in opts:
|
|||
drawplayers = True
|
||||
elif o == "--draworigin":
|
||||
draworigin = True
|
||||
elif o == "--drawunderground":
|
||||
drawunderground = True
|
||||
else:
|
||||
assert False, "unhandled option"
|
||||
|
||||
|
@ -160,9 +173,9 @@ if path[-1:] != "/" and path[-1:] != "\\":
|
|||
# Load color information for the blocks.
|
||||
colors = {}
|
||||
try:
|
||||
f = file("colors.txt")
|
||||
f = file("colors.txt")
|
||||
except IOError:
|
||||
f = file(os.path.join(os.path.dirname(__file__), "colors.txt"))
|
||||
f = file(os.path.join(os.path.dirname(__file__), "colors.txt"))
|
||||
for line in f:
|
||||
values = string.split(line)
|
||||
colors[int(values[0], 16)] = (
|
||||
|
@ -190,7 +203,7 @@ if os.path.exists(path + "map.sqlite"):
|
|||
if not r:
|
||||
break
|
||||
|
||||
x, y, z = getIntegerAsBlock (r[0])
|
||||
x, y, z = getIntegerAsBlock(r[0])
|
||||
|
||||
if x < sector_xmin or x > sector_xmax:
|
||||
continue
|
||||
|
@ -223,6 +236,9 @@ if os.path.exists(path + "sectors"):
|
|||
xlist.append(x)
|
||||
zlist.append(z)
|
||||
|
||||
# Get rid of doubles
|
||||
xlist, zlist = zip(*sorted(set(zip(xlist, zlist))))
|
||||
|
||||
minx = min(xlist)
|
||||
minz = min(zlist)
|
||||
maxx = max(xlist)
|
||||
|
@ -231,7 +247,7 @@ maxz = max(zlist)
|
|||
w = (maxx - minx) * 16 + 16
|
||||
h = (maxz - minz) * 16 + 16
|
||||
|
||||
print "w=" + str(w) + " h=" + str(h)
|
||||
print("w=" + str(w) + " h=" + str(h))
|
||||
|
||||
im = Image.new("RGB", (w + border, h + border), bgcolor)
|
||||
draw = ImageDraw.Draw(im)
|
||||
|
@ -241,12 +257,15 @@ stuff = {}
|
|||
|
||||
starttime = time.time()
|
||||
|
||||
CONTENT_WATER = 2
|
||||
|
||||
def data_is_air(d):
|
||||
def content_is_water(d):
|
||||
return d in [2, 9]
|
||||
|
||||
def content_is_air(d):
|
||||
return d in [126, 127, 254]
|
||||
|
||||
|
||||
def read_blocknum(mapdata, version, datapos):
|
||||
def read_content(mapdata, version, datapos):
|
||||
if version == 20:
|
||||
if mapdata[datapos] < 0x80:
|
||||
return mapdata[datapos]
|
||||
|
@ -258,7 +277,7 @@ def read_blocknum(mapdata, version, datapos):
|
|||
raise Exception("Unsupported map format: " + str(version))
|
||||
|
||||
|
||||
def read_mapdata(f, version, pixellist, water):
|
||||
def read_mapdata(f, version, pixellist, water, day_night_differs):
|
||||
global stuff # oh my :-)
|
||||
|
||||
dec_o = zlib.decompressobj()
|
||||
|
@ -270,34 +289,35 @@ def read_mapdata(f, version, pixellist, water):
|
|||
f.close()
|
||||
|
||||
if(len(mapdata) < 4096):
|
||||
print "bad: " + xhex + "/" + zhex + "/" + yhex + " " + \
|
||||
str(len(mapdata))
|
||||
print("bad: " + xhex + "/" + zhex + "/" + yhex + " " + \
|
||||
str(len(mapdata)))
|
||||
else:
|
||||
chunkxpos = xpos * 16
|
||||
chunkypos = ypos * 16
|
||||
chunkzpos = zpos * 16
|
||||
blocknum = 0
|
||||
content = 0
|
||||
datapos = 0
|
||||
for (x, z) in reversed(pixellist):
|
||||
for y in reversed(range(16)):
|
||||
datapos = x + y * 16 + z * 256
|
||||
blocknum = read_blocknum(mapdata, version, datapos)
|
||||
if not data_is_air(blocknum) and blocknum in colors:
|
||||
if blocknum in CONTENT_WATER:
|
||||
water[(x, z)] += 1
|
||||
# Add dummy stuff for drawing sea without seabed
|
||||
stuff[(chunkxpos + x, chunkzpos + z)] = (
|
||||
chunkypos + y, blocknum, water[(x, z)])
|
||||
else:
|
||||
pixellist.remove((x, z))
|
||||
# Memorize information on the type and height of
|
||||
# the block and for drawing the picture.
|
||||
stuff[(chunkxpos + x, chunkzpos + z)] = (
|
||||
chunkypos + y, blocknum, water[(x, z)])
|
||||
break
|
||||
elif not data_is_air(blocknum) and blocknum not in colors:
|
||||
print "strange block: %s/%s/%s x: %d y: %d z: %d \
|
||||
block id: %x" % (xhex, zhex, yhex, x, y, z, blocknum)
|
||||
content = read_content(mapdata, version, datapos)
|
||||
if content_is_air(content):
|
||||
pass
|
||||
elif content_is_water(content):
|
||||
water[(x, z)] += 1
|
||||
# Add dummy stuff for drawing sea without seabed
|
||||
stuff[(chunkxpos + x, chunkzpos + z)] = (
|
||||
chunkypos + y, content, water[(x, z)], day_night_differs)
|
||||
elif content in colors:
|
||||
# Memorize information on the type and height of
|
||||
# the block and for drawing the picture.
|
||||
stuff[(chunkxpos + x, chunkzpos + z)] = (
|
||||
chunkypos + y, content, water[(x, z)], day_night_differs)
|
||||
pixellist.remove((x, z))
|
||||
break
|
||||
else:
|
||||
print("strange block: %s/%s/%s x: %d y: %d z: %d \
|
||||
block id: %x" % (xhex, zhex, yhex, x, y, z, content))
|
||||
|
||||
# Go through all sectors.
|
||||
for n in range(len(xlist)):
|
||||
|
@ -337,8 +357,9 @@ for n in range(len(xlist)):
|
|||
sectortype = ""
|
||||
|
||||
if cur:
|
||||
ps = getBlockAsInteger((xpos, 0, zpos))
|
||||
cur.execute("SELECT `pos` FROM `blocks` WHERE `pos`>=? AND `pos`<?", (ps, ps + 4096))
|
||||
psmin = getBlockAsInteger((xpos, -2048, zpos))
|
||||
psmax = getBlockAsInteger((xpos, 2047, zpos))
|
||||
cur.execute("SELECT `pos` FROM `blocks` WHERE `pos`>=? AND `pos`<=? AND (`pos` - ?) % 4096 = 0", (psmin, psmax, psmin))
|
||||
while True:
|
||||
r = cur.fetchone()
|
||||
if not r:
|
||||
|
@ -383,72 +404,39 @@ for n in range(len(xlist)):
|
|||
water[(x, z)] = 0
|
||||
|
||||
# Go through the Y axis from top to bottom.
|
||||
ylist2 = []
|
||||
for ypos in reversed(ylist):
|
||||
|
||||
yhex = int_to_hex4(ypos)
|
||||
|
||||
filename = ""
|
||||
if sectortype == "sqlite":
|
||||
ps = getBlockAsInteger((xpos, ypos, zpos))
|
||||
cur.execute("SELECT `data` FROM `blocks` WHERE `pos`==? LIMIT 1", (ps,))
|
||||
r = cur.fetchone()
|
||||
if not r:
|
||||
continue
|
||||
filename = "mtm_tmp"
|
||||
f = file(filename, 'wb')
|
||||
f.write(r[0])
|
||||
f.close()
|
||||
f = cStringIO.StringIO(r[0])
|
||||
else:
|
||||
if sectortype == "old":
|
||||
filename = path + "sectors/" + sector1 + "/" + yhex.lower()
|
||||
else:
|
||||
filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
|
||||
|
||||
f = file(filename, "rb")
|
||||
f = file(filename, "rb")
|
||||
|
||||
# Let's just memorize these even though it's not really necessary.
|
||||
version = ord(f.read(1))
|
||||
flags = f.read(1)
|
||||
|
||||
# Checking day and night differs -flag
|
||||
if not ord(flags) & 2:
|
||||
ylist2.append((ypos, filename))
|
||||
f.close()
|
||||
continue
|
||||
day_night_differs = ((ord(flags) & 2) != 0)
|
||||
|
||||
read_mapdata(f, version, pixellist, water)
|
||||
read_mapdata(f, version, pixellist, water, day_night_differs)
|
||||
|
||||
# After finding all the pixels in the sector, we can move on to
|
||||
# the next sector without having to continue the Y axis.
|
||||
if(len(pixellist) == 0):
|
||||
break
|
||||
|
||||
if len(pixellist) > 0:
|
||||
for (ypos, filename) in ylist2:
|
||||
ps = getBlockAsInteger((xpos, ypos, zpos))
|
||||
cur.execute("SELECT `data` FROM `blocks` WHERE `pos`==? LIMIT 1", (ps,))
|
||||
r = cur.fetchone()
|
||||
if not r:
|
||||
continue
|
||||
filename = "mtm_tmp"
|
||||
f = file(filename, 'wb')
|
||||
f.write(r[0])
|
||||
f.close()
|
||||
|
||||
f = file(filename, "rb")
|
||||
|
||||
version = ord(f.read(1))
|
||||
flags = f.read(1)
|
||||
|
||||
read_mapdata(f, version, pixellist, water)
|
||||
|
||||
# After finding all the pixels in the sector, we can move on
|
||||
# to the next sector without having to continue the Y axis.
|
||||
if(len(pixellist) == 0):
|
||||
break
|
||||
|
||||
print "Drawing image"
|
||||
print("Drawing image")
|
||||
# Drawing the picture
|
||||
starttime = time.time()
|
||||
n = 0
|
||||
|
@ -474,18 +462,29 @@ for (x, z) in stuff.iterkeys():
|
|||
n += 1
|
||||
|
||||
(r, g, b) = colors[stuff[(x, z)][1]]
|
||||
|
||||
dnd = stuff[(x, z)][3] # day/night differs?
|
||||
if not dnd and not drawunderground:
|
||||
if stuff[(x, z)][2] > 0: # water
|
||||
(r, g, b) = colors[CONTENT_WATER]
|
||||
else:
|
||||
continue
|
||||
|
||||
# Comparing heights of a couple of adjacent blocks and changing
|
||||
# brightness accordingly.
|
||||
try:
|
||||
c = stuff[(x, z)][1]
|
||||
c1 = stuff[(x - 1, z)][1]
|
||||
c2 = stuff[(x, z + 1)][1]
|
||||
c = stuff[(x, z)][1]
|
||||
if c1 not in CONTENT_WATER and c2 not in CONTENT_WATER and \
|
||||
c not in CONTENT_WATER:
|
||||
y1 = stuff[(x - 1, z)][0]
|
||||
y2 = stuff[(x, z + 1)][0]
|
||||
dnd1 = stuff[(x - 1, z)][3]
|
||||
dnd2 = stuff[(x, z + 1)][3]
|
||||
if not dnd:
|
||||
d = -69
|
||||
elif not content_is_water(c1) and not content_is_water(c2) and \
|
||||
not content_is_water(c):
|
||||
y = stuff[(x, z)][0]
|
||||
|
||||
y1 = stuff[(x - 1, z)][0] if dnd1 else y
|
||||
y2 = stuff[(x, z + 1)][0] if dnd2 else y
|
||||
d = ((y - y1) + (y - y2)) * 12
|
||||
else:
|
||||
d = 0
|
||||
|
@ -542,10 +541,10 @@ if drawplayers:
|
|||
p = string.split(line)
|
||||
if p[0] == "name":
|
||||
name = p[2]
|
||||
print filename + ": name = " + name
|
||||
print(filename + ": name = " + name)
|
||||
if p[0] == "position":
|
||||
position = string.split(p[2][1:-1], ",")
|
||||
print filename + ": position = " + p[2]
|
||||
print(filename + ": position = " + p[2])
|
||||
if len(name) > 0 and len(position) == 3:
|
||||
x = (int(float(position[0]) / 10 - minx * 16))
|
||||
z = int(h - (float(position[2]) / 10 - minz * 16))
|
||||
|
@ -557,8 +556,5 @@ if drawplayers:
|
|||
except OSError:
|
||||
pass
|
||||
|
||||
if os.path.isfile("mtm_tmp"):
|
||||
os.remove("mtm_tmp")
|
||||
|
||||
print "Saving"
|
||||
print("Saving")
|
||||
im.save(output)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Loads block files from sectors folders into map.sqlite database.
|
||||
# The sectors folder should be safe to remove after this prints "Finished."
|
||||
|
||||
import time, os
|
||||
import time, os, sys
|
||||
|
||||
try:
|
||||
import sqlite3
|
||||
|
@ -23,10 +23,14 @@ if os.path.isdir(path + 'sectors/'):
|
|||
if not paths:
|
||||
exit('Could not find sectors folder at ' + path + 'sectors2/ or ' + path + 'sectors/')
|
||||
|
||||
def uint(u):
|
||||
def parseSigned12bit(u):
|
||||
u = int('0x'+u, 16)
|
||||
return (u if u < 2**11 else u - 2**12)
|
||||
|
||||
def parseSigned16bit(u):
|
||||
u = int('0x'+u, 16)
|
||||
return (u if u < 2**15 else u - 2**16)
|
||||
|
||||
def int64(u):
|
||||
while u >= 2**63:
|
||||
u -= 2**64
|
||||
|
@ -38,12 +42,12 @@ def int64(u):
|
|||
def getSectorPos(dirname):
|
||||
if len(dirname) == 8:
|
||||
# Old layout
|
||||
x = uint(dirname[:4])
|
||||
z = uint(dirname[4:])
|
||||
x = parseSigned16bit(dirname[:4])
|
||||
z = parseSigned16bit(dirname[4:])
|
||||
elif len(dirname) == 7:
|
||||
# New layout
|
||||
x = uint(dirname[:3])
|
||||
z = uint(dirname[4:])
|
||||
x = parseSigned12bit(dirname[:3])
|
||||
z = parseSigned12bit(dirname[4:])
|
||||
else:
|
||||
print('Terrible sector at ' + dirname)
|
||||
return
|
||||
|
@ -60,7 +64,7 @@ def getBlockPos(sectordir, blockfile):
|
|||
if len(blockfile) != 4:
|
||||
print("Invalid block filename: " + blockfile)
|
||||
|
||||
y = uint(blockfile)
|
||||
y = parseSigned16bit(blockfile)
|
||||
|
||||
return p2d[0], y, p2d[1]
|
||||
|
||||
|
@ -110,8 +114,13 @@ for base in paths:
|
|||
continue
|
||||
|
||||
f = open(root+'/'+block, 'rb')
|
||||
cur.execute('INSERT OR IGNORE INTO `blocks` VALUES(?, ?)', (pos, f.read()))
|
||||
blob = f.read()
|
||||
f.close()
|
||||
if sys.version_info.major == 2:
|
||||
blob = buffer(blob)
|
||||
else:
|
||||
blob = memoryview(blob)
|
||||
cur.execute('INSERT OR IGNORE INTO `blocks` VALUES(?, ?)', (pos, blob))
|
||||
count += 1
|
||||
|
||||
if(time.time() - t > 3):
|
||||
|
|