diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client.cpp | 11 | ||||
-rw-r--r-- | src/client.h | 15 | ||||
-rw-r--r-- | src/environment.cpp | 9 | ||||
-rw-r--r-- | src/environment.h | 4 | ||||
-rw-r--r-- | src/inventory.h | 2 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/main.h | 16 | ||||
-rw-r--r-- | src/map.cpp | 20 | ||||
-rw-r--r-- | src/map.h | 17 | ||||
-rw-r--r-- | src/mapblock.cpp | 111 | ||||
-rw-r--r-- | src/mapblock.h | 40 | ||||
-rw-r--r-- | src/mapblockobject.h | 19 | ||||
-rw-r--r-- | src/mapsector.cpp | 2 | ||||
-rw-r--r-- | src/mapsector.h | 2 | ||||
-rw-r--r-- | src/player.cpp | 9 | ||||
-rw-r--r-- | src/player.h | 24 | ||||
-rw-r--r-- | src/server.cpp | 2 | ||||
-rw-r--r-- | src/servermain.cpp | 421 |
18 files changed, 626 insertions, 103 deletions
diff --git a/src/client.cpp b/src/client.cpp index b4871ff61..37482ba91 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -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), diff --git a/src/client.h b/src/client.h index 18aa619c6..4720bd720 100644 --- a/src/client.h +++ b/src/client.h @@ -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 diff --git a/src/environment.cpp b/src/environment.cpp index bb2d168ed..386eb124d 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -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) { diff --git a/src/environment.h b/src/environment.h index 4b18d6b73..f6ee2ceee 100644 --- a/src/environment.h +++ b/src/environment.h @@ -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(); diff --git a/src/inventory.h b/src/inventory.h index 50f3247c3..cb5b54851 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -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; diff --git a/src/main.cpp b/src/main.cpp index 6d470f73d..b747da66a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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{
diff --git a/src/main.h b/src/main.h index 6a4b5a090..98af41249 100644 --- a/src/main.h +++ b/src/main.h @@ -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; diff --git a/src/map.cpp b/src/map.cpp index 671e74edd..db9d4120e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -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: diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 7e23d295b..9372c8fb1 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -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) @@ -230,50 +267,6 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f 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; - } -} - -/* 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. diff --git a/src/mapblock.h b/src/mapblock.h index 2743d8397..304794dd4 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -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); @@ -388,7 +385,8 @@ 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) diff --git a/src/mapblockobject.h b/src/mapblockobject.h index 8518d6b11..1a403bfe1 100644 --- a/src/mapblockobject.h +++ b/src/mapblockobject.h @@ -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) diff --git a/src/mapsector.cpp b/src/mapsector.cpp index f83679314..8a3728c8f 100644 --- a/src/mapsector.cpp +++ b/src/mapsector.cpp @@ -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 diff --git a/src/mapsector.h b/src/mapsector.h index d5ffa7f1d..b57688115 100644 --- a/src/mapsector.h +++ b/src/mapsector.h @@ -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 diff --git a/src/player.cpp b/src/player.cpp index ef2a3bdfb..2c04f1f76 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -228,6 +228,8 @@ void Player::accelerate(v3f target_speed, f32 max_increase) RemotePlayer */ +#ifndef SERVER + RemotePlayer::RemotePlayer( scene::ISceneNode* parent, IrrlichtDevice *device, @@ -236,7 +238,7 @@ RemotePlayer::RemotePlayer( m_text(NULL) { m_box = core::aabbox3d<f32>(-BS/2,0,-BS/2,BS/2,BS*2,BS/2); - + if(parent != NULL && device != NULL) { // ISceneNode stores a member called SceneManager @@ -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 diff --git a/src/player.h b/src/player.h index 91ad99911..7337eb6db 100644 --- a/src/player.h +++ b/src/player.h @@ -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 diff --git a/src/server.cpp b/src/server.cpp index acb4003da..a2dfc8269 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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; /* diff --git a/src/servermain.cpp b/src/servermain.cpp new file mode 100644 index 000000000..e8d7c471d --- /dev/null +++ b/src/servermain.cpp @@ -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 |