#include "mods.h"
#include "inventorymanager.h"
#include "subgame.h"
+#include "tileanimation.h" // struct TileAnimationParams
#include "util/numeric.h"
#include "util/thread.h"
-#include "environment.h"
+#include "util/basic_macros.h"
+#include "serverenvironment.h"
+#include "chat_interface.h"
#include "clientiface.h"
+#include "remoteplayer.h"
#include "network/networkpacket.h"
#include <string>
#include <list>
#include <map>
#include <vector>
-#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
-
class IWritableItemDefManager;
class IWritableNodeDefManager;
class IWritableCraftDefManager;
class BanManager;
class EventManager;
class Inventory;
-class Player;
class PlayerSAO;
class IRollbackManager;
struct RollbackAction;
class EmergeManager;
-class GameScripting;
+class ServerScripting;
class ServerEnvironment;
struct SimpleSoundSpec;
class ServerThread;
CDR_DENY
};
-/*
- Some random functions
-*/
-v3f findSpawnPos(ServerMap &map);
-
-class MapEditEventIgnorer
-{
-public:
- MapEditEventIgnorer(bool *flag):
- m_flag(flag)
- {
- if(*m_flag == false)
- *m_flag = true;
- else
- m_flag = NULL;
- }
-
- ~MapEditEventIgnorer()
- {
- if(m_flag)
- {
- assert(*m_flag);
- *m_flag = false;
- }
- }
-
-private:
- bool *m_flag;
-};
-
class MapEditEventAreaIgnorer
{
public:
u16 object;
float max_hear_distance;
bool loop;
+ float fade;
ServerSoundParams():
gain(1.0),
pos(0,0,0),
object(0),
max_hear_distance(32*BS),
- loop(false)
+ loop(false),
+ fade(0)
{}
v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
struct ServerPlayingSound
{
ServerSoundParams params;
- std::set<u16> clients; // peer ids
+ SimpleSoundSpec spec;
+ UNORDERED_SET<u16> clients; // peer ids
};
class Server : public con::PeerHandler, public MapEventReceiver,
const std::string &path_world,
const SubgameSpec &gamespec,
bool simple_singleplayer_mode,
- bool ipv6
+ bool ipv6,
+ bool dedicated,
+ ChatInterface *iface = NULL
);
~Server();
void start(Address bind_addr);
void handleCommand_Null(NetworkPacket* pkt) {};
void handleCommand_Deprecated(NetworkPacket* pkt);
void handleCommand_Init(NetworkPacket* pkt);
+ void handleCommand_Init_Legacy(NetworkPacket* pkt);
void handleCommand_Init2(NetworkPacket* pkt);
void handleCommand_RequestMedia(NetworkPacket* pkt);
- void handleCommand_ReceivedMedia(NetworkPacket* pkt);
void handleCommand_ClientReady(NetworkPacket* pkt);
void handleCommand_GotBlocks(NetworkPacket* pkt);
void handleCommand_PlayerPos(NetworkPacket* pkt);
void handleCommand_InventoryAction(NetworkPacket* pkt);
void handleCommand_ChatMessage(NetworkPacket* pkt);
void handleCommand_Damage(NetworkPacket* pkt);
- void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_Password(NetworkPacket* pkt);
void handleCommand_PlayerItem(NetworkPacket* pkt);
void handleCommand_Respawn(NetworkPacket* pkt);
void handleCommand_RemovedSounds(NetworkPacket* pkt);
void handleCommand_NodeMetaFields(NetworkPacket* pkt);
void handleCommand_InventoryFields(NetworkPacket* pkt);
+ void handleCommand_FirstSrp(NetworkPacket* pkt);
+ void handleCommand_SrpBytesA(NetworkPacket* pkt);
+ void handleCommand_SrpBytesM(NetworkPacket* pkt);
- void ProcessData(u8 *data, u32 datasize, u16 peer_id);
+ void ProcessData(NetworkPacket *pkt);
void Send(NetworkPacket* pkt);
- // Environment must be locked when called
+ // Helper for handleCommand_PlayerPos and handleCommand_Interact
+ void process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
+ NetworkPacket *pkt);
+
+ // Both setter and getter need no envlock,
+ // can be called freely from threads
void setTimeOfDay(u32 time);
/*
Shall be called with the environment and the connection locked.
*/
Inventory* getInventory(const InventoryLocation &loc);
- void setInventoryModified(const InventoryLocation &loc);
+ void setInventoryModified(const InventoryLocation &loc, bool playerSend = true);
// Connection must be locked when called
std::wstring getStatusString();
+ inline double getUptime() const { return m_uptime.m_value; }
// read shutdown state
- inline bool getShutdownRequested()
- { return m_shutdown_requested; }
+ inline bool getShutdownRequested() const { return m_shutdown_requested; }
// request server to shutdown
- inline void requestShutdown(void)
- { m_shutdown_requested = true; }
+ void requestShutdown(const std::string &msg, bool reconnect, float delay = 0.0f);
// Returns -1 if failed, sound handle on success
// Envlock
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms);
void stopSound(s32 handle);
+ void fadeSound(s32 handle, float step, float gain);
// Envlock
std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
void notifyPlayer(const char *name, const std::wstring &msg);
void notifyPlayers(const std::wstring &msg);
- void spawnParticle(const char *playername,
+ void spawnParticle(const std::string &playername,
v3f pos, v3f velocity, v3f acceleration,
float expirationtime, float size,
- bool collisiondetection, bool vertical, std::string texture);
+ bool collisiondetection, bool collision_removal,
+ bool vertical, const std::string &texture,
+ const struct TileAnimationParams &animation, u8 glow);
- void spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
- float expirationtime, float size,
- bool collisiondetection, bool vertical, std::string texture);
-
- u32 addParticleSpawner(const char *playername,
- u16 amount, float spawntime,
+ u32 addParticleSpawner(u16 amount, float spawntime,
v3f minpos, v3f maxpos,
v3f minvel, v3f maxvel,
v3f minacc, v3f maxacc,
float minexptime, float maxexptime,
float minsize, float maxsize,
- bool collisiondetection, bool vertical, std::string texture);
+ bool collisiondetection, bool collision_removal,
+ ServerActiveObject *attached,
+ bool vertical, const std::string &texture,
+ const std::string &playername, const struct TileAnimationParams &animation,
+ u8 glow);
- u32 addParticleSpawnerAll(u16 amount, float spawntime,
- v3f minpos, v3f maxpos,
- v3f minvel, v3f maxvel,
- v3f minacc, v3f maxacc,
- float minexptime, float maxexptime,
- float minsize, float maxsize,
- bool collisiondetection, bool vertical, std::string texture);
-
- void deleteParticleSpawner(const char *playername, u32 id);
- void deleteParticleSpawnerAll(u32 id);
+ void deleteParticleSpawner(const std::string &playername, u32 id);
// Creates or resets inventory
- Inventory* createDetachedInventory(const std::string &name);
+ Inventory* createDetachedInventory(const std::string &name, const std::string &player="");
// Envlock and conlock should be locked when using scriptapi
- GameScripting *getScriptIface(){ return m_script; }
-
- //TODO: determine what (if anything) should be locked to access EmergeManager
- EmergeManager *getEmergeManager(){ return m_emerge; }
+ ServerScripting *getScriptIface(){ return m_script; }
// actions: time-reversed list
// Return value: success/failure
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 scene::ISceneManager* getSceneManager();
- virtual IRollbackManager *getRollbackManager() { return m_rollback; }
-
+ IRollbackManager *getRollbackManager() { return m_rollback; }
+ virtual EmergeManager *getEmergeManager() { return m_emerge; }
IWritableItemDefManager* getWritableItemDefManager();
IWritableNodeDefManager* getWritableNodeDefManager();
IWritableCraftDefManager* getWritableCraftDefManager();
- const ModSpec* getModSpec(const std::string &modname);
- void getModNames(std::list<std::string> &modlist);
+ virtual const std::vector<ModSpec> &getMods() const { return m_mods; }
+ virtual const ModSpec* getModSpec(const std::string &modname) const;
+ void getModNames(std::vector<std::string> &modlist);
std::string getBuiltinLuaPath();
- inline std::string getWorldPath()
- { return m_path_world; }
+ virtual std::string getWorldPath() const { return m_path_world; }
+ virtual std::string getModStoragePath() const;
inline bool isSingleplayer()
{ return m_simple_singleplayer_mode; }
bool showFormspec(const char *name, const std::string &formspec, const std::string &formname);
Map & getMap() { return m_env->getMap(); }
ServerEnvironment & getEnv() { return *m_env; }
-
- u32 hudAdd(Player *player, HudElement *element);
- bool hudRemove(Player *player, u32 id);
- bool hudChange(Player *player, u32 id, HudElementStat stat, void *value);
- bool hudSetFlags(Player *player, u32 flags, u32 mask);
- bool hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount);
- void hudSetHotbarImage(Player *player, std::string name);
- void hudSetHotbarSelectedImage(Player *player, std::string name);
+ v3f findSpawnPos();
+
+ u32 hudAdd(RemotePlayer *player, HudElement *element);
+ bool hudRemove(RemotePlayer *player, u32 id);
+ bool hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *value);
+ bool hudSetFlags(RemotePlayer *player, u32 flags, u32 mask);
+ bool hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount);
+ s32 hudGetHotbarItemcount(RemotePlayer *player) const
+ { return player->getHotbarItemcount(); }
+ void hudSetHotbarImage(RemotePlayer *player, std::string name);
+ std::string hudGetHotbarImage(RemotePlayer *player);
+ void hudSetHotbarSelectedImage(RemotePlayer *player, std::string name);
+ const std::string &hudGetHotbarSelectedImage(RemotePlayer *player) const
+ {
+ return player->getHotbarSelectedImage();
+ }
inline Address getPeerAddress(u16 peer_id)
{ return m_con.GetPeerAddress(peer_id); }
- bool setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed);
- bool setPlayerEyeOffset(Player *player, v3f first, v3f third);
+ bool setLocalPlayerAnimations(RemotePlayer *player, v2s32 animation_frames[4],
+ f32 frame_speed);
+ bool setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third);
- bool setSky(Player *player, const video::SColor &bgcolor,
- const std::string &type, const std::vector<std::string> ¶ms);
+ bool setSky(RemotePlayer *player, const video::SColor &bgcolor,
+ const std::string &type, const std::vector<std::string> ¶ms,
+ bool &clouds);
+ bool setClouds(RemotePlayer *player, float density,
+ const video::SColor &color_bright,
+ const video::SColor &color_ambient,
+ float height,
+ float thickness,
+ const v2f &speed);
- bool overrideDayNightRatio(Player *player, bool do_override,
- float brightness);
+ bool overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness);
/* con::PeerHandler implementation. */
void peerAdded(con::Peer *peer);
void deletingPeer(con::Peer *peer, bool timeout);
- void DenyAccess(u16 peer_id, const std::wstring &reason);
+ void DenySudoAccess(u16 peer_id);
+ void DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
+ const std::string &str_reason = "", bool reconnect = false);
+ void DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason="");
+ void acceptAuth(u16 peer_id, bool forSudoMode);
+ void DenyAccess_Legacy(u16 peer_id, const std::wstring &reason);
bool getClientConInfo(u16 peer_id, con::rtt_stat_type type,float* retval);
bool getClientInfo(u16 peer_id,ClientState* state, u32* uptime,
u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch,
std::string* vers_string);
- void SendPlayerHPOrDie(u16 peer_id, bool die) { die ? DiePlayer(peer_id) : SendPlayerHP(peer_id); }
+ void printToConsoleOnly(const std::string &text);
+
+ void SendPlayerHPOrDie(PlayerSAO *player);
+ void SendPlayerBreath(PlayerSAO *sao);
+ void SendInventory(PlayerSAO* playerSAO);
+ void SendMovePlayer(u16 peer_id);
+
+ virtual bool registerModStorage(ModMetadata *storage);
+ virtual void unregisterModStorage(const std::string &name);
+
// Bind address
Address m_bind_addr;
+ // Environment mutex (envlock)
+ Mutex m_env_mutex;
+
private:
friend class EmergeThread;
void SendMovement(u16 peer_id);
void SendHP(u16 peer_id, u8 hp);
void SendBreath(u16 peer_id, u16 breath);
- void SendAccessDenied(u16 peer_id,const std::wstring &reason);
+ void SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
+ const std::string &custom_reason, bool reconnect = false);
+ void SendAccessDenied_Legacy(u16 peer_id, const std::wstring &reason);
void SendDeathscreen(u16 peer_id,bool set_camera_point_target, v3f camera_point_target);
void SendItemDef(u16 peer_id,IItemDefManager *itemdef, u16 protocol_version);
void SendNodeDef(u16 peer_id,INodeDefManager *nodedef, u16 protocol_version);
/* mark blocks not sent for all clients */
void SetBlocksNotSent(std::map<v3s16, MapBlock *>& block);
- // Envlock and conlock should be locked when calling these
- void SendInventory(u16 peer_id);
+
void SendChatMessage(u16 peer_id, const std::wstring &message);
void SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed);
void SendPlayerHP(u16 peer_id);
- void SendPlayerBreath(u16 peer_id);
- void SendMovePlayer(u16 peer_id);
+
void SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed);
void SendEyeOffset(u16 peer_id, v3f first, v3f third);
void SendPlayerPrivileges(u16 peer_id);
void SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask);
void SendHUDSetParam(u16 peer_id, u16 param, const std::string &value);
void SendSetSky(u16 peer_id, const video::SColor &bgcolor,
- const std::string &type, const std::vector<std::string> ¶ms);
+ const std::string &type, const std::vector<std::string> ¶ms,
+ bool &clouds);
+ void SendCloudParams(u16 peer_id, float density,
+ const video::SColor &color_bright,
+ const video::SColor &color_ambient,
+ float height,
+ float thickness,
+ const v2f &speed);
void SendOverrideDayNightRatio(u16 peer_id, bool do_override, float ratio);
/*
*/
// Envlock and conlock should be locked when calling these
void sendRemoveNode(v3s16 p, u16 ignore_id=0,
- std::list<u16> *far_players=NULL, float far_d_nodes=100);
+ std::vector<u16> *far_players=NULL, float far_d_nodes=100);
void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
- std::list<u16> *far_players=NULL, float far_d_nodes=100,
+ std::vector<u16> *far_players=NULL, float far_d_nodes=100,
bool remove_metadata=true);
void setBlockNotSent(v3s16 p);
void fillMediaCache();
void sendMediaAnnouncement(u16 peer_id);
void sendRequestedMedia(u16 peer_id,
- const std::list<std::string> &tosend);
+ const std::vector<std::string> &tosend);
void sendDetachedInventory(const std::string &name, u16 peer_id);
void sendDetachedInventories(u16 peer_id);
// Adds a ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all)
- void SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime,
+ void SendAddParticleSpawner(u16 peer_id, u16 protocol_version,
+ u16 amount, float spawntime,
v3f minpos, v3f maxpos,
v3f minvel, v3f maxvel,
v3f minacc, v3f maxacc,
float minexptime, float maxexptime,
float minsize, float maxsize,
- bool collisiondetection, bool vertical, std::string texture, u32 id);
+ bool collisiondetection, bool collision_removal,
+ u16 attached_id,
+ bool vertical, const std::string &texture, u32 id,
+ const struct TileAnimationParams &animation, u8 glow);
void SendDeleteParticleSpawner(u16 peer_id, u32 id);
// Spawns particle on peer with peer_id (PEER_ID_INEXISTENT == all)
- void SendSpawnParticle(u16 peer_id,
+ void SendSpawnParticle(u16 peer_id, u16 protocol_version,
v3f pos, v3f velocity, v3f acceleration,
float expirationtime, float size,
- bool collisiondetection, bool vertical, std::string texture);
+ bool collisiondetection, bool collision_removal,
+ bool vertical, const std::string &texture,
+ const struct TileAnimationParams &animation, u8 glow);
+ u32 SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas);
+ void SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable = true);
/*
Something random
*/
void DiePlayer(u16 peer_id);
void RespawnPlayer(u16 peer_id);
void DeleteClient(u16 peer_id, ClientDeletionReason reason);
- void UpdateCrafting(u16 peer_id);
+ void UpdateCrafting(RemotePlayer *player);
+
+ void handleChatInterfaceEvent(ChatEvent *evt);
+
+ // This returns the answer to the sender of wmessage, or "" if there is none
+ std::wstring handleChat(const std::string &name, const std::wstring &wname,
+ const std::wstring &wmessage,
+ bool check_shout_priv = false,
+ RemotePlayer *player = NULL);
+ void handleAdminChat(const ChatEventChat *evt);
// When called, connection mutex should be locked
RemoteClient* getClient(u16 peer_id,ClientState state_min=CS_Active);
Call with env and con locked.
*/
- PlayerSAO *emergePlayer(const char *name, u16 peer_id);
+ PlayerSAO *emergePlayer(const char *name, u16 peer_id, u16 proto_version);
void handlePeerChanges();
// If true, do not allow multiple players and hide some multiplayer
// functionality
bool m_simple_singleplayer_mode;
+ u16 m_max_chatmessage_length;
+ // For "dedicated" server list flag
+ bool m_dedicated;
// Thread can set; step() will throw as ServerError
MutexedVariable<std::string> m_async_fatal_error;
// Some timers
float m_liquid_transform_timer;
float m_liquid_transform_every;
- float m_print_info_timer;
float m_masterserver_timer;
- float m_objectdata_timer;
float m_emergethread_trigger_timer;
float m_savemap_timer;
IntervalLimiter m_map_timer_and_unload_interval;
// Environment
ServerEnvironment *m_env;
- JMutex m_env_mutex;
// server connection
con::Connection m_con;
// Scripting
// Envlock and conlock should be locked when using Lua
- GameScripting *m_script;
+ ServerScripting *m_script;
// Item definition manager
IWritableItemDefManager *m_itemdef;
// A buffer for time steps
// step() increments and AsyncRunStep() run by m_thread reads it.
float m_step_dtime;
- JMutex m_step_dtime_mutex;
+ Mutex m_step_dtime_mutex;
// current server step lag counter
float m_lag;
float m_time_of_day_send_timer;
// Uptime of server in seconds
MutexedVariable<double> m_uptime;
-
/*
Client interface
*/
Queues stuff from peerAdded() and deletingPeer() to
handlePeerChanges()
*/
- Queue<con::PeerChange> m_peer_change_queue;
+ std::queue<con::PeerChange> m_peer_change_queue;
/*
Random stuff
*/
- // Mod parent directory paths
- std::list<std::string> m_modspaths;
-
bool m_shutdown_requested;
+ std::string m_shutdown_msg;
+ bool m_shutdown_ask_reconnect;
+ float m_shutdown_timer;
+
+ ChatInterface *m_admin_chat;
+ std::string m_admin_nick;
/*
Map edit event queue. Automatically receives all map edits.
Queue of map edits from the environment for sending to the clients
This is behind m_env_mutex
*/
- Queue<MapEditEvent*> m_unsent_map_edit_queue;
+ std::queue<MapEditEvent*> m_unsent_map_edit_queue;
/*
Set to true when the server itself is modifying the map and does
all sending of information by itself.
u16 m_ignore_map_edit_events_peer_id;
// media files known to server
- std::map<std::string,MediaInfo> m_media;
+ UNORDERED_MAP<std::string, MediaInfo> m_media;
/*
Sounds
*/
- std::map<s32, ServerPlayingSound> m_playing_sounds;
+ UNORDERED_MAP<s32, ServerPlayingSound> m_playing_sounds;
s32 m_next_sound_id;
/*
*/
// key = name
std::map<std::string, Inventory*> m_detached_inventories;
+ // value = "" (visible to all players) or player name
+ std::map<std::string, std::string> m_detached_inventories_player;
- /*
- Particles
- */
- std::vector<u32> m_particlespawner_ids;
+ UNORDERED_MAP<std::string, ModMetadata *> m_mod_storages;
+ float m_mod_storage_save_timer;
+
+ DISABLE_CLASS_COPY(Server);
};
/*
Runs a simple dedicated server loop.
- Shuts down when run is set to false.
+ Shuts down when kill is set to true.
*/
-void dedicated_server_loop(Server &server, bool &run);
+void dedicated_server_loop(Server &server, bool &kill);
#endif