X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fserver.h;h=86d5513d8b2b68fe6ba64c714380d194d562d7c0;hb=42eb8c8e3be2c8183c12c30d4a0bbc660b2a9e59;hp=b88369ddf735a1d712653a4a54b77685c85fadc7;hpb=f2c26e20147cf586b5b4ffa761303b670689ab40;p=oweals%2Fminetest.git diff --git a/src/server.h b/src/server.h index b88369ddf..86d5513d8 100644 --- a/src/server.h +++ b/src/server.h @@ -3,16 +3,16 @@ Minetest-c55 Copyright (C) 2010-2011 celeron55, Perttu Ahola 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 +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -22,13 +22,48 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "connection.h" #include "environment.h" -#include "common_irrlicht.h" +#include "irrlichttypes_bloated.h" #include -#include "utility.h" #include "porting.h" #include "map.h" #include "inventory.h" -#include "auth.h" +#include "ban.h" +#include "gamedef.h" +#include "serialization.h" // For SER_FMT_VER_INVALID +#include "mods.h" +#include "inventorymanager.h" +#include "subgame.h" +#include "sound.h" +#include "util/thread.h" +#include "util/string.h" +#include "rollback_interface.h" // Needed for rollbackRevertActions() +#include // Needed for rollbackRevertActions() + +struct LuaState; +typedef struct lua_State lua_State; +class IWritableItemDefManager; +class IWritableNodeDefManager; +class IWritableCraftDefManager; +class EventManager; +class PlayerSAO; +class IRollbackManager; + +class ServerError : public std::exception +{ +public: + ServerError(const std::string &s) + { + m_s = "ServerError: "; + m_s += s; + } + virtual ~ServerError() throw() + {} + virtual const char * what() const throw() + { + return m_s.c_str(); + } + std::string m_s; +}; /* Some random functions @@ -68,14 +103,14 @@ public: delete q; } } - + /* peer_id=0 adds with nobody to send to */ void addBlock(u16 peer_id, v3s16 pos, u8 flags) { DSTACK(__FUNCTION_NAME); - + JMutexAutoLock lock(m_mutex); if(peer_id != 0) @@ -95,7 +130,7 @@ public: } } } - + /* Add the block */ @@ -125,7 +160,7 @@ public: JMutexAutoLock lock(m_mutex); return m_queue.size(); } - + u32 peerItemCount(u16 peer_id) { JMutexAutoLock lock(m_mutex); @@ -201,11 +236,9 @@ struct PlayerInfo void PrintLine(std::ostream *s); }; -u32 PIChecksum(core::list &l); - /* Used for queueing and sorting block transfers in containers - + Lower priority number means higher priority. */ struct PrioritySortedBlockTransfer @@ -225,6 +258,61 @@ struct PrioritySortedBlockTransfer u16 peer_id; }; +struct MediaRequest +{ + std::string name; + + MediaRequest(const std::string &name_=""): + name(name_) + {} +}; + +struct MediaInfo +{ + std::string path; + std::string sha1_digest; + + MediaInfo(const std::string path_="", + const std::string sha1_digest_=""): + path(path_), + sha1_digest(sha1_digest_) + { + } +}; + +struct ServerSoundParams +{ + float gain; + std::string to_player; + enum Type{ + SSP_LOCAL=0, + SSP_POSITIONAL=1, + SSP_OBJECT=2 + } type; + v3f pos; + u16 object; + float max_hear_distance; + bool loop; + + ServerSoundParams(): + gain(1.0), + to_player(""), + type(SSP_LOCAL), + pos(0,0,0), + object(0), + max_hear_distance(32*BS), + loop(false) + {} + + v3f getPos(ServerEnvironment *env, bool *pos_exists) const; +}; + +struct ServerPlayingSound +{ + ServerSoundParams params; + std::set clients; // peer ids +}; + class RemoteClient { public: @@ -235,16 +323,22 @@ public: u16 peer_id; // The serialization version to use with the client u8 serialization_version; + // + u16 net_proto_version; // Version is stored in here after INIT before INIT2 u8 pending_serialization_version; + bool definitions_sent; + RemoteClient(): m_time_from_building(9999), m_excess_gotblocks(0) { peer_id = 0; serialization_version = SER_FMT_VER_INVALID; + net_proto_version = 0; pending_serialization_version = SER_FMT_VER_INVALID; + definitions_sent = false; m_nearest_unsent_d = 0; m_nearest_unsent_reset_timer = 0.0; m_nothing_to_send_counter = 0; @@ -253,7 +347,7 @@ public: ~RemoteClient() { } - + /* Finds block that should be sent next to the client. Environment should be locked when this is called. @@ -262,17 +356,6 @@ public: void GetNextBlocks(Server *server, float dtime, core::array &dest); - /* - Connection and environment should be locked when this is called. - steps() objects of blocks not found in active_blocks, then - adds those blocks to active_blocks - */ - void SendObjectData( - Server *server, - float dtime, - core::map &stepped_blocks - ); - void GotBlock(v3s16 p); void SentBlock(v3s16 p); @@ -284,7 +367,7 @@ public: { return m_blocks_sending.size(); } - + // Increments timeouts and removes timed-out blocks from list // NOTE: This doesn't fix the server-not-sending-block bug // because it is related to emerging, not sending. @@ -303,13 +386,13 @@ public: // Time from last placing or removing blocks float m_time_from_building; - + /*JMutex m_dig_mutex; float m_dig_time_remaining; // -1 = not digging s16 m_dig_tool_item; v3s16 m_dig_position;*/ - + /* List of active objects that the client knows of. Value is dummy. @@ -322,7 +405,7 @@ private: - These don't have to be sent again. - A block is cleared from here when client says it has deleted it from it's memory - + Key is position, value is dummy. No MapBlock* is stored here because the blocks can get deleted. */ @@ -330,7 +413,7 @@ private: s16 m_nearest_unsent_d; v3s16 m_last_center; float m_nearest_unsent_reset_timer; - + /* Blocks that are currently on the line. This is used for throttling the sending of blocks. @@ -349,14 +432,15 @@ private: This is resetted by PrintInfo() */ u32 m_excess_gotblocks; - + // CPU usage optimization u32 m_nothing_to_send_counter; float m_nothing_to_send_pause_timer; }; class Server : public con::PeerHandler, public MapEventReceiver, - public InventoryManager + public InventoryManager, public IGameDef, + public IBackgroundBlockEmerger { public: /* @@ -364,7 +448,10 @@ public: */ Server( - std::string mapsavedir + const std::string &path_world, + const std::string &path_config, + const SubgameSpec &gamespec, + bool simple_singleplayer_mode ); ~Server(); void start(unsigned short port); @@ -379,15 +466,10 @@ public: core::list getPlayerInfo(); - /*u32 getDayNightRatio() - { - return time_to_daynight_ratio(m_time_of_day.get()); - }*/ - // Environment must be locked when called void setTimeOfDay(u32 time) { - m_env.setTimeOfDay(time); + m_env->setTimeOfDay(time); m_time_of_day_send_timer = 0; } @@ -395,7 +477,7 @@ public: { return m_shutdown_requested; } - + /* Shall be called with the environment locked. This is accessed by the map, which is inside the environment, @@ -406,8 +488,8 @@ public: /* Shall be called with the environment and the connection locked. */ - Inventory* getInventory(InventoryContext *c, std::string id); - void inventoryModified(InventoryContext *c, std::string id); + Inventory* getInventory(const InventoryLocation &loc); + void setInventoryModified(const InventoryLocation &loc); // Connection must be locked when called std::wstring getStatusString(); @@ -417,33 +499,97 @@ public: m_shutdown_requested = true; } + // Returns -1 if failed, sound handle on success + // Envlock + conlock + s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms); + void stopSound(s32 handle); - // Envlock and conlock should be locked when calling this - void SendMovePlayer(Player *player); - - u64 getPlayerAuthPrivs(const std::string &name) + // Envlock + conlock + std::set getPlayerEffectivePrivs(const std::string &name); + bool checkPriv(const std::string &name, const std::string &priv); + void reportPrivsModified(const std::string &name=""); // ""=all + void reportInventoryFormspecModified(const std::string &name); + + // Saves g_settings to configpath given at initialization + void saveConfig(); + + void setIpBanned(const std::string &ip, const std::string &name) { - try{ - return m_authmanager.getPrivs(name); - } - catch(AuthNotFoundException &e) - { - dstream<<"WARNING: Auth not found for "< &actions, + std::list *log); + + // IGameDef interface + // Under envlock + virtual IItemDefManager* getItemDefManager(); + virtual INodeDefManager* getNodeDefManager(); + virtual ICraftDefManager* getCraftDefManager(); + virtual ITextureSource* getTextureSource(); + virtual IShaderSource* getShaderSource(); + virtual u16 allocateUnknownNodeId(const std::string &name); + virtual ISoundManager* getSoundManager(); + virtual MtEventManager* getEventManager(); + virtual IRollbackReportSink* getRollbackReportSink(); + + IWritableItemDefManager* getWritableItemDefManager(); + IWritableNodeDefManager* getWritableNodeDefManager(); + IWritableCraftDefManager* getWritableCraftDefManager(); + + const ModSpec* getModSpec(const std::string &modname); + void getModNames(core::list &modlist); + std::string getBuiltinLuaPath(); + + std::string getWorldPath(){ return m_path_world; } + + bool isSingleplayer(){ return m_simple_singleplayer_mode; } + + void setAsyncFatalError(const std::string &error) + { + m_async_fatal_error.set(error); + } + + bool showFormspec(const char *name, const std::string &formspec, const std::string &formname); private: // con::PeerHandler implementation. @@ -451,26 +597,37 @@ private: // As of now, these create and remove clients and players. void peerAdded(con::Peer *peer); void deletingPeer(con::Peer *peer, bool timeout); - + /* Static send methods */ - + 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); + static void SendItemDef(con::Connection &con, u16 peer_id, + IItemDefManager *itemdef); + static void SendNodeDef(con::Connection &con, u16 peer_id, + INodeDefManager *nodedef, u16 protocol_version); + /* - Non-static send methods + Non-static send methods. + Conlock should be always used. + Envlock usage is documented badly but it's easy to figure out + which ones access the environment. */ // Envlock and conlock should be locked when calling these - void SendObjectData(float dtime); - void SendPlayerInfos(); void SendInventory(u16 peer_id); void SendChatMessage(u16 peer_id, const std::wstring &message); void BroadcastChatMessage(const std::wstring &message); - void SendPlayerHP(Player *player); + void SendPlayerHP(u16 peer_id); + void SendMovePlayer(u16 peer_id); + void SendPlayerPrivileges(u16 peer_id); + void SendPlayerInventoryFormspec(u16 peer_id); + void SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname); /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than @@ -482,79 +639,141 @@ private: void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0, core::list *far_players=NULL, float far_d_nodes=100); void setBlockNotSent(v3s16 p); - + // Environment and Connection must be locked when called void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver); - + // Sends blocks to clients (locks env and con on its own) void SendBlocks(float dtime); + void fillMediaCache(); + void sendMediaAnnouncement(u16 peer_id); + void sendRequestedMedia(u16 peer_id, + const core::list &tosend); + + void sendDetachedInventory(const std::string &name, u16 peer_id); + void sendDetachedInventoryToAll(const std::string &name); + void sendDetachedInventories(u16 peer_id); + /* Something random */ - + + void DiePlayer(u16 peer_id); + void RespawnPlayer(u16 peer_id); + void UpdateCrafting(u16 peer_id); - + // When called, connection mutex should be locked RemoteClient* getClient(u16 peer_id); - + // When called, environment mutex should be locked std::string getPlayerName(u16 peer_id) { - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); if(player == NULL) - return "[id="+itos(peer_id); + return "[id="+itos(peer_id)+"]"; return player->getName(); } + // When called, environment mutex should be locked + PlayerSAO* getPlayerSAO(u16 peer_id) + { + Player *player = m_env->getPlayer(peer_id); + if(player == NULL) + return NULL; + return player->getPlayerSAO(); + } + /* Get a player from memory or creates one. If player is already connected, return NULL - The password is not checked here - it is only used to - set the password if a new player is created. + Does not verify/modify auth info and password. Call with env and con locked. */ - Player *emergePlayer(const char *name, const char *password, u16 peer_id); - + PlayerSAO *emergePlayer(const char *name, u16 peer_id); + // Locks environment and connection by its own struct PeerChange; void handlePeerChange(PeerChange &c); void handlePeerChanges(); - u64 getPlayerPrivs(Player *player); - /* Variables */ - + + // World directory + std::string m_path_world; + // Path to user's configuration file ("" = no configuration file) + std::string m_path_config; + // Subgame specification + SubgameSpec m_gamespec; + // If true, do not allow multiple players and hide some multiplayer + // functionality + bool m_simple_singleplayer_mode; + + // Thread can set; step() will throw as ServerError + MutexedVariable m_async_fatal_error; + // Some timers float m_liquid_transform_timer; float m_print_info_timer; float m_objectdata_timer; float m_emergethread_trigger_timer; float m_savemap_timer; - + IntervalLimiter m_map_timer_and_unload_interval; + // NOTE: If connection and environment are both to be locked, // environment shall be locked first. // Environment - ServerEnvironment m_env; + ServerEnvironment *m_env; JMutex m_env_mutex; - + // Connection con::Connection m_con; JMutex m_con_mutex; // Connected clients (behind the con mutex) core::map m_clients; - // User authentication - AuthManager m_authmanager; - + // Bann checking + BanManager m_banmanager; + + // Rollback manager (behind m_env_mutex) + IRollbackManager *m_rollback; + bool m_rollback_sink_enabled; + bool m_enable_rollback_recording; // Updated once in a while + + // Emerge manager + EmergeManager *m_emerge; + + // Biome Definition Manager + BiomeDefManager *m_biomedef; + + // Scripting + // Envlock and conlock should be locked when using Lua + lua_State *m_lua; + + // Item definition manager + IWritableItemDefManager *m_itemdef; + + // Node definition manager + IWritableNodeDefManager *m_nodedef; + + // Craft definition manager + IWritableCraftDefManager *m_craftdef; + + // Event manager + EventManager *m_event; + + // Mods + std::vector m_mods; + /* Threads */ - + // A buffer for time steps // step() increments and AsyncRunStep() run by m_thread reads it. float m_step_dtime; @@ -566,20 +785,16 @@ private: EmergeThread m_emergethread; // Queue of block coordinates to be processed by the emerge thread BlockEmergeQueue m_emerge_queue; - + /* Time related stuff */ - // 0-23999 - //MutexedVariable m_time_of_day; - // Used to buffer dtime for adding to m_time_of_day - float m_time_counter; // Timer for sending time of day over network float m_time_of_day_send_timer; // Uptime of server in seconds MutexedVariable m_uptime; - + /* Peer change queue. Queues stuff from peerAdded() and deletingPeer() to @@ -602,11 +817,11 @@ private: Random stuff */ - // Map directory - std::string m_mapsavedir; + // Mod parent directory paths + core::list m_modspaths; bool m_shutdown_requested; - + /* Map edit event queue. Automatically receives all map edits. The constructor of this class registers us to receive them through @@ -627,6 +842,13 @@ private: This is behind m_env_mutex */ bool m_ignore_map_edit_events; + /* + If a non-empty area, map edit events contained within are left + unsent. Done at map generation time to speed up editing of the + generated area, as it will be sent anyway. + This is behind m_env_mutex + */ + VoxelArea m_ignore_map_edit_events_area; /* If set to !=0, the incoming MapEditEvents are modified to have this peed id as the disabled recipient @@ -634,10 +856,22 @@ private: */ u16 m_ignore_map_edit_events_peer_id; - Profiler *m_profiler; - friend class EmergeThread; friend class RemoteClient; + + std::map m_media; + + /* + Sounds + */ + std::map m_playing_sounds; + s32 m_next_sound_id; + + /* + Detached inventories (behind m_env_mutex) + */ + // key = name + std::map m_detached_inventories; }; /*