added dedicated server build without irrlicht

This commit is contained in:
Perttu Ahola 2010-12-19 19:11:05 +02:00
parent 0ca9423b8b
commit ab7477c4c3
19 changed files with 669 additions and 125 deletions

@ -4,25 +4,28 @@
TARGET = test
SOURCE_FILES = guiPauseMenu.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp
SOURCES = $(addprefix src/, $(SOURCE_FILES))
OBJECTS = $(SOURCES:.cpp=.o)
FASTTARGET = fasttest
BUILD_DIR = build
OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))
#OBJECTS = $(SOURCES:.cpp=.o)
FAST_TARGET = fasttest
SERVER_TARGET = server
SERVER_SOURCE_FILES = mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp
SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))
SERVER_BUILD_DIR = serverbuild
SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))
#SERVER_OBJECTS = $(SERVER_SOURCES:.cpp=.o)
IRRLICHTPATH = ../irrlicht/irrlicht-1.7.1
JTHREADPATH = ../jthread/jthread-1.2.1
CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src
#CXXFLAGS = -O2 -ffast-math -Wall -fomit-frame-pointer -pipe
CXXFLAGS = -O2 -ffast-math -Wall -g -pipe
#CXXFLAGS = -O1 -ffast-math -Wall -g
#CXXFLAGS = -Wall -g -O0
#CXXFLAGS = -O3 -ffast-math -Wall
#CXXFLAGS = -O3 -ffast-math -Wall -g
#CXXFLAGS = -O2 -ffast-math -Wall -g
FASTCXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686
#FASTCXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686 -fwhole-program
#FAST_CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686
#Default target
@ -35,8 +38,13 @@ endif
# Target specific settings
all_linux fast_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L$(IRRLICHTPATH)/lib/Linux -L$(JTHREADPATH)/src/.libs -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -ljthread -lz
all_linux fast_linux: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src
fast_linux server_linux: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686
server_linux: LDFLAGS = -L$(JTHREADPATH)/src/.libs -ljthread -lz -lpthread
server_linux: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DSERVER
all_linux fast_linux clean_linux: SYSTEM=Linux
# These are out of date
all_win32: LDFLAGS = -L$(IRRLICHTPATH)/lib/Win32-gcc -L$(JTHREADPATH)/Debug -lIrrlicht -lopengl32 -lm -ljthread
all_win32 clean_win32: SYSTEM=Win32-gcc
all_win32 clean_win32: SUF=.exe
@ -44,31 +52,44 @@ all_win32 clean_win32: SUF=.exe
# Name of the binary - only valid for targets which set SYSTEM
DESTPATH = bin/$(TARGET)$(SUF)
FASTDESTPATH = bin/$(FASTTARGET)$(SUF)
FAST_DESTPATH = bin/$(FAST_TARGET)$(SUF)
SERVER_DESTPATH = bin/$(SERVER_TARGET)$(SUF)
# Build commands
all_linux all_win32: $(DESTPATH)
all_linux all_win32: make_build_dir $(DESTPATH)
fast_linux: make_build_dir $(FAST_DESTPATH)
server_linux: make_server_build_dir $(SERVER_DESTPATH)
fast_linux: $(FASTDESTPATH)
$(FASTDESTPATH): $(SOURCES)
$(CXX) -o $(FASTDESTPATH) $(SOURCES) $(CPPFLAGS) $(FASTCXXFLAGS) $(LDFLAGS) -DUNITTEST_DISABLE
@# Errno doesn't work ("error: __errno_location was not declared in this scope")
@#cat $(SOURCES) | $(CXX) -o $(FASTDESTPATH) -x c++ - -Isrc/ $(CPPFLAGS) $(FASTCXXFLAGS) $(LDFLAGS) -DUNITTEST_DISABLE -DDISABLE_ERRNO
make_build_dir:
mkdir -p $(BUILD_DIR)
make_server_build_dir:
mkdir -p $(SERVER_BUILD_DIR)
$(DESTPATH): $(OBJECTS)
$(CXX) -o $@ $(OBJECTS) $(LDFLAGS)
.cpp.o:
$(FAST_DESTPATH): $(SOURCES)
$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE
$(SERVER_DESTPATH): $(SERVER_OBJECTS)
$(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) -DSERVER -DUNITTEST_DISABLE
$(BUILD_DIR)/%.o: src/%.cpp
$(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)
clean: clean_linux clean_win32 clean_fast_linux
$(SERVER_BUILD_DIR)/%.o: src/%.cpp
$(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)
clean: clean_linux clean_win32 clean_fast_linux clean_server_linux
clean_linux clean_win32:
@$(RM) $(OBJECTS) $(DESTPATH)
clean_fast_linux:
@$(RM) $(FASTDESTPATH)
@$(RM) $(OBJECTS) $(FAST_DESTPATH)
.PHONY: all all_win32 clean clean_linux clean_win32
clean_server_linux:
@$(RM) $(SERVER_OBJECTS) $(SERVER_DESTPATH)
.PHONY: all all_win32 clean clean_linux clean_win32 clean_fast_linux clean_server_linux

@ -70,10 +70,17 @@ void * ClientUpdateThread::Thread()
return NULL;
}
Client::Client(IrrlichtDevice *device,
const char *playername):
Client::Client(
IrrlichtDevice *device,
const char *playername,
JMutex &range_mutex,
s16 &viewing_range_nodes,
bool &viewing_range_all):
m_thread(this),
m_env(new ClientMap(this,
range_mutex,
viewing_range_nodes,
viewing_range_all,
device->getSceneManager()->getRootSceneNode(),
device->getSceneManager(), 666),
dout_client),

@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef CLIENT_HEADER
#define CLIENT_HEADER
#ifndef SERVER
#include "connection.h"
#include "environment.h"
#include "common_irrlicht.h"
@ -137,7 +139,14 @@ public:
/*
NOTE: Every public method should be thread-safe
*/
Client(IrrlichtDevice *device, const char *playername);
Client(
IrrlichtDevice *device,
const char *playername,
JMutex &range_mutex,
s16 &viewing_range_nodes,
bool &viewing_range_all
);
~Client();
/*
The name of the local player should already be set when
@ -290,5 +299,7 @@ private:
//u32 m_daynight_ratio;
};
#endif
#endif // !SERVER
#endif // !CLIENT_HEADER

@ -149,7 +149,7 @@ void Environment::step(float dtime)
{
n.d = CONTENT_GRASS_FOOTSTEPS;
m_map->setNode(bottompos, n);
#ifndef SERVER
// Update mesh on client
if(m_map->mapType() == MAPTYPE_CLIENT)
{
@ -157,6 +157,7 @@ void Environment::step(float dtime)
MapBlock *b = m_map->getBlockNoCreate(p_blocks);
b->updateMesh(m_daynight_ratio);
}
#endif
}
}
catch(InvalidPositionException &e)
@ -179,7 +180,9 @@ void Environment::addPlayer(Player *player)
{
DSTACK(__FUNCTION_NAME);
//Check that only one local player exists and peer_ids are unique
#ifndef SERVER
assert(player->isLocal() == false || getLocalPlayer() == NULL);
#endif
assert(getPlayer(player->peer_id) == NULL);
m_players.push_back(player);
}
@ -203,6 +206,7 @@ re_search:
}
}
#ifndef SERVER
LocalPlayer * Environment::getLocalPlayer()
{
for(core::list<Player*>::Iterator i = m_players.begin();
@ -214,6 +218,7 @@ LocalPlayer * Environment::getLocalPlayer()
}
return NULL;
}
#endif
Player * Environment::getPlayer(u16 peer_id)
{
@ -243,6 +248,7 @@ void Environment::printPlayers(std::ostream &o)
}
}
#ifndef SERVER
void Environment::updateMeshes(v3s16 blockpos)
{
m_map->updateMeshes(blockpos, m_daynight_ratio);
@ -252,6 +258,7 @@ void Environment::expireMeshes(bool only_daynight_diffed)
{
m_map->expireMeshes(only_daynight_diffed);
}
#endif
void Environment::setDayNightRatio(u32 r)
{

@ -55,13 +55,17 @@ public:
*/
void addPlayer(Player *player);
void removePlayer(u16 peer_id);
#ifndef SERVER
LocalPlayer * getLocalPlayer();
#endif
Player * getPlayer(u16 peer_id);
core::list<Player*> getPlayers();
void printPlayers(std::ostream &o);
#ifndef SERVER
void updateMeshes(v3s16 blockpos);
void expireMeshes(bool only_daynight_diffed);
#endif
void setDayNightRatio(u32 r);
u32 getDayNightRatio();

@ -84,6 +84,7 @@ public:
{
return new MaterialItem(m_content, m_count);
}
#ifndef SERVER
video::ITexture * getImage()
{
/*if(m_content == CONTENT_TORCH)
@ -97,6 +98,7 @@ public:
return g_texturecache.get(g_content_inventory_textures[m_content]);
}
#endif
std::string getText()
{
std::ostringstream os;

@ -1509,7 +1509,10 @@ int main(int argc, char *argv[])
Create client
*/
Client client(device, playername);
Client client(device, playername,
g_range_mutex,
g_viewing_range_nodes,
g_viewing_range_all);
Address connect_address(0,0,0,0, port);
try{

@ -26,11 +26,6 @@ extern std::string getTimestamp();
#include <jmutex.h>
extern JMutex g_range_mutex;
extern s16 g_viewing_range_nodes;
//extern s16 g_actual_viewing_range_nodes;
extern bool g_viewing_range_all;
// Settings
extern Settings g_settings;
@ -51,13 +46,10 @@ extern std::ostream *derr_server_ptr;
#define dout_server (*dout_server_ptr)
#define derr_server (*derr_server_ptr)
// TODO: Move somewhere else? materials.h?
// This header is only for MATERIALS_COUNT
//#include "mapnode.h"
//extern video::SMaterial g_materials[MATERIALS_COUNT];
#include "utility.h"
extern TextureCache g_texturecache;
#ifndef SERVER
#include "utility.h"
extern TextureCache g_texturecache;
#endif
extern IrrlichtDevice *g_device;

@ -1062,6 +1062,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
}
}
#ifndef SERVER
void Map::expireMeshes(bool only_daynight_diffed)
{
TimeTaker timer("expireMeshes()", g_device);
@ -1128,6 +1129,8 @@ void Map::updateMeshes(v3s16 blockpos, u32 daynight_ratio)
catch(InvalidPositionException &e){}
}
#endif
bool Map::dayNightDiffed(v3s16 blockpos)
{
try{
@ -2678,12 +2681,17 @@ void ServerMap::PrintInfo(std::ostream &out)
out<<"ServerMap: ";
}
#ifndef SERVER
/*
ClientMap
*/
ClientMap::ClientMap(
Client *client,
JMutex &range_mutex,
s16 &viewing_range_nodes,
bool &viewing_range_all,
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id
@ -2691,7 +2699,10 @@ ClientMap::ClientMap(
Map(dout_client),
scene::ISceneNode(parent, mgr, id),
m_client(client),
mesh(NULL)
mesh(NULL),
m_range_mutex(range_mutex),
m_viewing_range_nodes(viewing_range_nodes),
m_viewing_range_all(viewing_range_all)
{
mesh_mutex.Init();
@ -2805,9 +2816,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
s16 viewing_range_nodes;
bool viewing_range_all;
{
JMutexAutoLock lock(g_range_mutex);
viewing_range_nodes = g_viewing_range_nodes;
viewing_range_all = g_viewing_range_all;
JMutexAutoLock lock(m_range_mutex);
viewing_range_nodes = m_viewing_range_nodes;
viewing_range_all = m_viewing_range_all;
}
m_camera_mutex.Lock();
@ -3042,6 +3053,7 @@ void ClientMap::PrintInfo(std::ostream &out)
out<<"ClientMap: ";
}
#endif // !SERVER
/*
MapVoxelManipulator

@ -376,13 +376,15 @@ public:
void removeNodeAndUpdate(v3s16 p,
core::map<v3s16, MapBlock*> &modified_blocks);
#ifndef SERVER
void expireMeshes(bool only_daynight_diffed);
/*
Updates the faces of the given block and blocks on the
leading edge.
*/
void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
void expireMeshes(bool only_daynight_diffed);
#endif
/*
Takes the blocks at the trailing edges into account
@ -535,6 +537,8 @@ private:
bool m_map_saving_enabled;
};
#ifndef SERVER
class Client;
class ClientMap : public Map, public scene::ISceneNode
@ -542,6 +546,9 @@ class ClientMap : public Map, public scene::ISceneNode
public:
ClientMap(
Client *client,
JMutex &range_mutex,
s16 &viewing_range_nodes,
bool &viewing_range_all,
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id
@ -600,8 +607,14 @@ private:
// This is the master heightmap mesh
scene::SMesh *mesh;
JMutex mesh_mutex;
JMutex &m_range_mutex;
s16 &m_viewing_range_nodes;
bool &m_viewing_range_all;
};
#endif
class MapVoxelManipulator : public VoxelManipulator
{
public:

@ -34,7 +34,6 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
m_pos(pos),
changed(true),
is_underground(false),
m_mesh_expired(false),
m_day_night_differs(false),
m_objects(this)
{
@ -42,17 +41,16 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
if(dummy == false)
reallocate();
#ifndef SERVER
m_mesh_expired = false;
mesh_mutex.Init();
mesh = NULL;
/*for(s32 i=0; i<DAYNIGHT_CACHE_COUNT; i++)
{
mesh[i] = NULL;
}*/
#endif
}
MapBlock::~MapBlock()
{
#ifndef SERVER
{
JMutexAutoLock lock(mesh_mutex);
@ -61,15 +59,8 @@ MapBlock::~MapBlock()
mesh->drop();
mesh = NULL;
}
/*for(s32 i=0; i<DAYNIGHT_CACHE_COUNT; i++)
{
if(mesh[i] != NULL)
{
mesh[i]->drop();
mesh[i] = NULL;
}
}*/
}
#endif
if(data)
delete[] data;
@ -136,6 +127,52 @@ MapNode MapBlock::getNodeParentNoEx(v3s16 p)
}
}
/*
Parameters must consist of air and !air.
Order doesn't matter.
If either of the nodes doesn't exist, light is 0.
parameters:
daynight_ratio: 0...1000
n: getNodeParent(p)
n2: getNodeParent(p + face_dir)
face_dir: axis oriented unit vector from p to p2
*/
u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
v3s16 face_dir)
{
try{
u8 light;
u8 l1 = n.getLightBlend(daynight_ratio);
u8 l2 = n2.getLightBlend(daynight_ratio);
if(l1 > l2)
light = l1;
else
light = l2;
// Make some nice difference to different sides
/*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
light = diminish_light(diminish_light(light));
else if(face_dir.X == -1 || face_dir.Z == -1)
light = diminish_light(light);*/
if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
light = diminish_light(diminish_light(light));
else if(face_dir.Z == 1 || face_dir.Z == -1)
light = diminish_light(light);
return light;
}
catch(InvalidPositionException &e)
{
return 0;
}
}
#ifndef SERVER
void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
v3s16 dir, v3f scale, v3f posRelative_f,
core::array<FastFace> &dest)
@ -229,50 +266,6 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
//return f;
}
/*
Parameters must consist of air and !air.
Order doesn't matter.
If either of the nodes doesn't exist, light is 0.
parameters:
daynight_ratio: 0...1000
n: getNodeParent(p)
n2: getNodeParent(p + face_dir)
face_dir: axis oriented unit vector from p to p2
*/
u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
v3s16 face_dir)
{
try{
u8 light;
u8 l1 = n.getLightBlend(daynight_ratio);
u8 l2 = n2.getLightBlend(daynight_ratio);
if(l1 > l2)
light = l1;
else
light = l2;
// Make some nice difference to different sides
/*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
light = diminish_light(diminish_light(light));
else if(face_dir.X == -1 || face_dir.Z == -1)
light = diminish_light(light);*/
if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
light = diminish_light(diminish_light(light));
else if(face_dir.Z == 1 || face_dir.Z == -1)
light = diminish_light(light);
return light;
}
catch(InvalidPositionException &e)
{
return 0;
}
}
/*
Gets node tile from any place relative to block.
Returns TILE_NODE if doesn't exist or should not be drawn.
@ -844,6 +837,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
}
}*/
#endif // !SERVER
/*
Propagates sunlight down through the block.
Doesn't modify nodes that are not affected by sunlight.

@ -88,11 +88,6 @@ public:
class MapBlock : public NodeContainer
{
public:
//scene::SMesh *mesh[DAYNIGHT_CACHE_COUNT];
scene::SMesh *mesh;
JMutex mesh_mutex;
MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false);
~MapBlock();
@ -131,7 +126,7 @@ public:
{
changed = true;
}
#ifndef SERVER
void setMeshExpired(bool expired)
{
m_mesh_expired = expired;
@ -141,7 +136,7 @@ public:
{
return m_mesh_expired;
}
#endif
v3s16 getPos()
{
return m_pos;
@ -273,10 +268,6 @@ public:
setNode(x0+x, y0+y, z0+z, node);
}
static void makeFastFace(TileSpec tile, u8 light, v3f p,
v3s16 dir, v3f scale, v3f posRelative_f,
core::array<FastFace> &dest);
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
v3s16 face_dir);
@ -288,6 +279,11 @@ public:
face_dir);
}
#ifndef SERVER
static void makeFastFace(TileSpec tile, u8 light, v3f p,
v3s16 dir, v3f scale, v3f posRelative_f,
core::array<FastFace> &dest);
TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir);
u8 getNodeContent(v3s16 p, MapNode mn);
@ -311,6 +307,7 @@ public:
/*void updateMesh(s32 daynight_i);
// Updates all DAYNIGHT_CACHE_COUNT meshes
void updateMeshes(s32 first_i=0);*/
#endif // !SERVER
bool propagateSunlight(core::map<v3s16, bool> & light_sources);
@ -389,6 +386,7 @@ public:
return m_objects.getCount();
}
#ifndef SERVER
/*
Methods for setting temporary modifications to nodes for
drawing
@ -406,6 +404,7 @@ public:
{
m_temp_mods.clear();
}
#endif
/*
Day-night lighting difference
@ -431,6 +430,16 @@ public:
void deSerialize(std::istream &is, u8 version);
/*
Public member variables
*/
#ifndef SERVER
//scene::SMesh *mesh[DAYNIGHT_CACHE_COUNT];
scene::SMesh *mesh;
JMutex mesh_mutex;
#endif
private:
/*
@ -468,19 +477,22 @@ private:
/*
Used for some initial lighting stuff.
At least /has been/ used. 8)
It's probably useless now.
*/
bool is_underground;
bool m_mesh_expired;
// Whether day and night lighting differs
bool m_day_night_differs;
MapBlockObjectList m_objects;
#ifndef SERVER
bool m_mesh_expired;
// Temporary modifications to nodes
// These are only used when drawing
core::map<v3s16, NodeMod> m_temp_mods;
#endif
};
inline bool blockpos_over_limit(v3s16 p)

@ -135,6 +135,12 @@ public:
// A return value of true requests deletion of the object by the caller.
// NOTE: Only server calls this.
virtual bool serverStep(float dtime) { return false; };
#ifdef SERVER
void clientStep(float dtime) {};
void addToScene(void *smgr) {};
void removeFromScene() {};
#else
// This should do slight animations only or so
virtual void clientStep(float dtime) {};
@ -147,6 +153,7 @@ public:
// Should return silently if there is nothing to remove
// NOTE: This has to be called before calling destructor
virtual void removeFromScene() {};
#endif
virtual std::string infoText() { return ""; }
@ -270,8 +277,8 @@ public:
virtual bool serverStep(float dtime) { return false; };
virtual void clientStep(float dtime) {};
virtual void addToScene(scene::ISceneManager *smgr) = 0;
virtual void removeFromScene() = 0;
/*virtual void addToScene(scene::ISceneManager *smgr) = 0;
virtual void removeFromScene() = 0;*/
/*
Special methods
@ -375,7 +382,7 @@ public:
return false;
}
#ifndef SERVER
virtual void clientStep(float dtime)
{
m_pos += m_speed * dtime;
@ -424,6 +431,7 @@ public:
m_node = NULL;
}
}
#endif
virtual std::string getInventoryString()
{
@ -520,6 +528,7 @@ public:
{
return false;
}
#ifndef SERVER
virtual void addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
@ -587,6 +596,7 @@ public:
m_node = NULL;
}
}
#endif
virtual std::string infoText()
{
@ -601,14 +611,15 @@ public:
/*
Special methods
*/
void updateSceneNode()
{
#ifndef SERVER
if(m_node != NULL)
{
m_node->setPosition(getAbsolutePos());
m_node->setRotation(v3f(0, m_yaw, 0));
}
#endif
}
void setText(std::string text)

@ -607,6 +607,7 @@ ServerMapSector* ServerMapSector::deSerialize(
return sector;
}
#ifndef SERVER
/*
ClientMapSector
*/
@ -667,5 +668,6 @@ void ClientMapSector::deSerialize(std::istream &is)
m_corners[2] = c2;
m_corners[3] = c3;
}
#endif // !SERVER
//END

@ -309,6 +309,7 @@ private:
core::map<v3s16, u8> *m_objects;
};
#ifndef SERVER
class ClientMapSector : public MapSector
{
public:
@ -331,6 +332,7 @@ private:
// The ground height of the corners is stored in here
s16 m_corners[4];
};
#endif
#endif

@ -228,6 +228,8 @@ void Player::accelerate(v3f target_speed, f32 max_increase)
RemotePlayer
*/
#ifndef SERVER
RemotePlayer::RemotePlayer(
scene::ISceneNode* parent,
IrrlichtDevice *device,
@ -320,6 +322,9 @@ void RemotePlayer::updateName(const char *name)
}
}
#endif
#ifndef SERVER
/*
LocalPlayer
*/
@ -399,5 +404,5 @@ void LocalPlayer::applyControl(float dtime)
// Accelerate to target speed with maximum increment
accelerate(speed, inc);
}
#endif

@ -109,6 +109,26 @@ protected:
v3f m_position;
};
class ServerRemotePlayer : public Player
{
public:
ServerRemotePlayer()
{
}
virtual ~ServerRemotePlayer()
{
}
bool isLocal() const
{
return false;
}
private:
};
#ifndef SERVER
class RemotePlayer : public Player, public scene::ISceneNode
{
public:
@ -165,6 +185,9 @@ private:
core::aabbox3d<f32> m_box;
};
#endif
#ifndef SERVER
struct PlayerControl
{
PlayerControl()
@ -225,6 +248,7 @@ public:
private:
};
#endif // !SERVER
#endif

@ -2082,7 +2082,7 @@ void Server::peerAdded(con::Peer *peer)
// The player shouldn't already exist
assert(player == NULL);
player = new RemotePlayer();
player = new ServerRemotePlayer();
player->peer_id = peer->id;
/*

421
src/servermain.cpp Normal file

@ -0,0 +1,421 @@
/*
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.
*/
/*
=============================== NOTES ==============================
TODO: Move the default settings into some separate file
*/
#ifndef SERVER
#ifdef _WIN32
#else
#error "For a server build, SERVER must be defined globally"
#endif
#endif
#ifdef UNITTEST_DISABLE
#ifdef _WIN32
#pragma message ("Disabling unit tests")
#else
#warning "Disabling unit tests"
#endif
// Disable unit tests
#define ENABLE_TESTS 0
#else
// Enable unit tests
#define ENABLE_TESTS 1
#endif
#ifdef _MSC_VER
#pragma comment(lib, "jthread.lib")
#pragma comment(lib, "zlibwapi.lib")
#endif
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define sleep_ms(x) Sleep(x)
#else
#include <unistd.h>
#define sleep_ms(x) usleep(x*1000)
#endif
#include <iostream>
#include <fstream>
#include <time.h>
#include <jmutexautolock.h>
#include <locale.h>
#include "common_irrlicht.h"
#include "debug.h"
#include "map.h"
#include "player.h"
#include "main.h"
#include "test.h"
#include "environment.h"
#include "server.h"
#include "serialization.h"
#include "constants.h"
#include "strfnd.h"
#include "porting.h"
// Dummy variable
IrrlichtDevice *g_device = NULL;
/*
Settings.
These are loaded from the config file.
*/
Settings g_settings;
// Sets default settings
void set_default_settings()
{
// Client stuff
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", "35");
g_settings.setDefault("screenW", "");
g_settings.setDefault("screenH", "");
g_settings.setDefault("host_game", "");
g_settings.setDefault("port", "");
g_settings.setDefault("address", "");
g_settings.setDefault("name", "");
g_settings.setDefault("random_input", "false");
g_settings.setDefault("client_delete_unused_sectors_timeout", "1200");
g_settings.setDefault("enable_fog", "true");
// Server stuff
g_settings.setDefault("creative_mode", "false");
g_settings.setDefault("heightmap_blocksize", "32");
g_settings.setDefault("height_randmax", "constant 50.0");
g_settings.setDefault("height_randfactor", "constant 0.6");
g_settings.setDefault("height_base", "linear 0 0 0");
g_settings.setDefault("plants_amount", "1.0");
g_settings.setDefault("ravines_amount", "1.0");
g_settings.setDefault("objectdata_interval", "0.2");
g_settings.setDefault("active_object_range", "2");
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
g_settings.setDefault("disable_water_climb", "true");
g_settings.setDefault("endless_water", "true");
g_settings.setDefault("max_block_send_distance", "5");
g_settings.setDefault("max_block_generate_distance", "4");
}
/*
Debug streams
*/
// Connection
std::ostream *dout_con_ptr = &dummyout;
std::ostream *derr_con_ptr = &dstream_no_stderr;
// Server
std::ostream *dout_server_ptr = &dstream;
std::ostream *derr_server_ptr = &dstream;
// Client
std::ostream *dout_client_ptr = &dstream;
std::ostream *derr_client_ptr = &dstream;
/*
Timestamp stuff
*/
JMutex g_timestamp_mutex;
std::string getTimestamp()
{
if(g_timestamp_mutex.IsInitialized()==false)
return "";
JMutexAutoLock lock(g_timestamp_mutex);
time_t t = time(NULL);
struct tm *tm = localtime(&t);
char cs[20];
strftime(cs, 20, "%H:%M:%S", tm);
return cs;
}
int main(int argc, char *argv[])
{
/*
Low-level initialization
*/
bool disable_stderr = false;
#ifdef _WIN32
disable_stderr = true;
#endif
// Initialize debug streams
debugstreams_init(disable_stderr, DEBUGFILE);
// Initialize debug stacks
debug_stacks_init();
DSTACK(__FUNCTION_NAME);
try
{
/*
Parse command line
*/
// List all allowed options
core::map<std::string, ValueSpec> allowed_options;
allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG));
allowed_options.insert("config", ValueSpec(VALUETYPE_STRING,
"Load configuration from specified file"));
allowed_options.insert("port", ValueSpec(VALUETYPE_STRING));
allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG));
allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG));
Settings cmd_args;
bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options);
if(ret == false || cmd_args.getFlag("help"))
{
dstream<<"Allowed options:"<<std::endl;
for(core::map<std::string, ValueSpec>::Iterator
i = allowed_options.getIterator();
i.atEnd() == false; i++)
{
dstream<<" --"<<i.getNode()->getKey();
if(i.getNode()->getValue().type == VALUETYPE_FLAG)
{
}
else
{
dstream<<" <value>";
}
dstream<<std::endl;
if(i.getNode()->getValue().help != NULL)
{
dstream<<" "<<i.getNode()->getValue().help
<<std::endl;
}
}
return cmd_args.getFlag("help") ? 0 : 1;
}
/*
Basic initialization
*/
// Initialize default settings
set_default_settings();
// Print startup message
dstream<<DTIME<<"minetest-c55 server"
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
<<", ENABLE_TESTS="<<ENABLE_TESTS
<<std::endl;
// Set locale. This is for forcing '.' as the decimal point.
std::locale::global(std::locale("C"));
// This enables printing all characters in bitmap font
setlocale(LC_CTYPE, "en_US");
// Initialize sockets
sockets_init();
atexit(sockets_cleanup);
// Initialize timestamp mutex
g_timestamp_mutex.Init();
/*
Initialization
*/
/*
Read config file
*/
// Path of configuration file in use
std::string configpath = "";
if(cmd_args.exists("config"))
{
bool r = g_settings.readConfigFile(cmd_args.get("config").c_str());
if(r == false)
{
dstream<<"Could not read configuration from \""
<<cmd_args.get("config")<<"\""<<std::endl;
return 1;
}
configpath = cmd_args.get("config");
}
else
{
const char *filenames[2] =
{
"../minetest.conf",
"../../minetest.conf"
};
for(u32 i=0; i<2; i++)
{
bool r = g_settings.readConfigFile(filenames[i]);
if(r)
{
configpath = filenames[i];
break;
}
}
}
// Initialize random seed
srand(time(0));
/*
Run unit tests
*/
if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
|| cmd_args.getFlag("enable-unittests") == true)
{
run_tests();
}
// Read map parameters from settings
HMParams hm_params;
hm_params.blocksize = g_settings.getU16("heightmap_blocksize");
hm_params.randmax = g_settings.get("height_randmax");
hm_params.randfactor = g_settings.get("height_randfactor");
hm_params.base = g_settings.get("height_base");
MapParams map_params;
map_params.plants_amount = g_settings.getFloat("plants_amount");
map_params.ravines_amount = g_settings.getFloat("ravines_amount");
/*
Check parameters
*/
std::cout<<std::endl<<std::endl;
std::cout
<<" .__ __ __ "<<std::endl
<<" _____ |__| ____ _____/ |_ ____ _______/ |_ "<<std::endl
<<" / \\| |/ \\_/ __ \\ __\\/ __ \\ / ___/\\ __\\"<<std::endl
<<"| Y Y \\ | | \\ ___/| | \\ ___/ \\___ \\ | | "<<std::endl
<<"|__|_| /__|___| /\\___ >__| \\___ >____ > |__| "<<std::endl
<<" \\/ \\/ \\/ \\/ \\/ "<<std::endl
<<std::endl
<<"Now with more waterish water!"
<<std::endl;
std::cout<<std::endl;
// Port?
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
{
dstream<<"Please specify port (in config or on command line)"
<<std::endl;
}
DSTACK("Dedicated server branch");
std::cout<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<"Running dedicated server"<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<std::endl;
Server server("../map", hm_params, map_params);
server.start(port);
for(;;)
{
// This is kind of a hack but can be done like this
// because server.step() is very light
sleep_ms(30);
server.step(0.030);
static int counter = 0;
counter--;
if(counter <= 0)
{
counter = 10;
core::list<PlayerInfo> list = server.getPlayerInfo();
core::list<PlayerInfo>::Iterator i;
static u32 sum_old = 0;
u32 sum = PIChecksum(list);
if(sum != sum_old)
{
std::cout<<DTIME<<"Player info:"<<std::endl;
for(i=list.begin(); i!=list.end(); i++)
{
i->PrintLine(&std::cout);
}
}
sum_old = sum;
}
}
/*
Update configuration file
*/
if(configpath != "")
{
g_settings.updateConfigFile(configpath.c_str());
}
} //try
catch(con::PeerNotFoundException &e)
{
dstream<<DTIME<<"Connection timed out."<<std::endl;
}
#if CATCH_UNHANDLED_EXCEPTIONS
/*
This is what has to be done in every thread to get suitable debug info
*/
catch(std::exception &e)
{
dstream<<std::endl<<DTIME<<"An unhandled exception occurred: "
<<e.what()<<std::endl;
assert(0);
}
#endif
debugstreams_deinit();
return 0;
}
//END