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.cpp
master
jachoo 2011-10-16 22:59:11 +02:00
commit d828688383
93 changed files with 6682 additions and 5175 deletions

View File

@ -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)

BIN
data/chest_lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

BIN
data/dungeon_master.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
data/fireball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

BIN
data/sapling.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

After

Width:  |  Height:  |  Size: 927 B

View File

@ -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
-----------------------

View File

@ -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

View File

@ -85,5 +85,10 @@ Furnace metadata:
Chest metadata:
TBD
Locking Chest metadata:
u16 string_len
u8[string_len] string
TBD
// END

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

901
src/camera.cpp Normal file
View File

@ -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;
}

233
src/camera.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;
}*/

View File

@ -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;

View File

@ -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;
}

View File

@ -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)();

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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];

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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");
}

28
src/defaultsettings.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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
{

File diff suppressed because it is too large Load Diff

179
src/guiDeathScreen.cpp Normal file
View File

@ -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();
}

60
src/guiDeathScreen.h Normal file
View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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
*/

View File

@ -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()
{

View File

@ -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();
}

144
src/log.cpp Normal file
View File

@ -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);

69
src/log.h Normal file
View File

@ -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

View File

@ -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();

View File

@ -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

124
src/mainmenumanager.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
/*

View File

@ -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

View File

@ -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.

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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

View File

@ -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()
{

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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

658
src/settings.h Normal file
View File

@ -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

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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 "

View File

@ -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;
}

View File

@ -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

View File

@ -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

172
util/minetestmapper.py Executable file → Normal file
View File

@ -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)

View File

@ -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):