X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fenvironment.h;h=4bee40e57f223936bf81aebe8d4cd1be8064641f;hb=ad4bf2ccf966ac21b94f1778a017ac98f8957ab6;hp=a3e43dbb4af5d7de62c885b0881953bec0e2b353;hpb=69367aa7998d3817db1d4b101f36a6e25b1becf8;p=minetest.git diff --git a/src/environment.h b/src/environment.h index a3e43dbb4..4bee40e57 100644 --- a/src/environment.h +++ b/src/environment.h @@ -32,24 +32,29 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -#include "irrlichttypes_extrabloated.h" -#include "player.h" -#include +#include +#include +#include "irr_v3d.h" #include "activeobject.h" -#include "util/container.h" #include "util/numeric.h" #include "mapnode.h" #include "mapblock.h" +#include "threading/mutex.h" +#include "threading/atomic.h" +#include "network/networkprotocol.h" // for AccessDeniedCode class ServerEnvironment; class ActiveBlockModifier; class ServerActiveObject; -typedef struct lua_State lua_State; class ITextureSource; class IGameDef; class Map; class ServerMap; class ClientMap; +class GameScripting; +class Player; +class RemotePlayer; +class PlayerSAO; class Environment { @@ -68,53 +73,69 @@ class Environment virtual Map & getMap() = 0; - virtual void addPlayer(Player *player); - void removePlayer(u16 peer_id); - Player * getPlayer(u16 peer_id); - Player * getPlayer(const char *name); - Player * getRandomConnectedPlayer(); - Player * getNearestConnectedPlayer(v3f pos); - std::list getPlayers(); - std::list getPlayers(bool ignore_disconnected); - void printPlayers(std::ostream &o); - u32 getDayNightRatio(); - + // 0-23999 - virtual void setTimeOfDay(u32 time) - { - m_time_of_day = time; - m_time_of_day_f = (float)time / 24000.0; - } + virtual void setTimeOfDay(u32 time); + u32 getTimeOfDay(); + float getTimeOfDayF(); - u32 getTimeOfDay() - { return m_time_of_day; } + void stepTimeOfDay(float dtime); - float getTimeOfDayF() - { return m_time_of_day_f; } + void setTimeOfDaySpeed(float speed); - void stepTimeOfDay(float dtime); + void setDayNightRatioOverride(bool enable, u32 value); + + u32 getDayCount(); - void setTimeOfDaySpeed(float speed) - { m_time_of_day_speed = speed; } - - float getTimeOfDaySpeed() - { return m_time_of_day_speed; } + // counter used internally when triggering ABMs + u32 m_added_objects; protected: - // peer_ids in here should be unique, except that there may be many 0s - std::list m_players; + GenericAtomic m_time_of_day_speed; + + /* + * Below: values managed by m_time_lock + */ // Time of day in milli-hours (0-23999); determines day and night u32 m_time_of_day; // Time of day in 0...1 float m_time_of_day_f; - float m_time_of_day_speed; - // Used to buffer dtime for adding to m_time_of_day - float m_time_counter; + // Stores the skew created by the float -> u32 conversion + // to be applied at next conversion, so that there is no real skew. + float m_time_conversion_skew; + // Overriding the day-night ratio is useful for custom sky visuals + bool m_enable_day_night_ratio_override; + u32 m_day_night_ratio_override; + // Days from the server start, accounts for time shift + // in game (e.g. /time or bed usage) + Atomic m_day_count; + /* + * Above: values managed by m_time_lock + */ + + /* TODO: Add a callback function so these can be updated when a setting + * changes. At this point in time it doesn't matter (e.g. /set + * is documented to change server settings only) + * + * TODO: Local caching of settings is not optimal and should at some stage + * be updated to use a global settings object for getting thse values + * (as opposed to the this local caching). This can be addressed in + * a later release. + */ + bool m_cache_enable_shaders; + float m_cache_active_block_mgmt_interval; + float m_cache_abm_interval; + float m_cache_nodetimer_interval; + +private: + Mutex m_time_lock; + + DISABLE_CLASS_COPY(Environment); }; /* - Active block modifier interface. + {Active, Loading} block modifier interface. These are fed into ServerEnvironment at initialization time; ServerEnvironment handles deleting them. @@ -125,7 +146,7 @@ class ActiveBlockModifier public: ActiveBlockModifier(){}; virtual ~ActiveBlockModifier(){}; - + // Set of contents to trigger on virtual std::set getTriggerContents()=0; // Set of required neighbors (trigger doesn't happen if none are found) @@ -136,6 +157,8 @@ class ActiveBlockModifier virtual float getTriggerInterval() = 0; // Random chance of (1 / return value), 0 is disallowed virtual u32 getTriggerChance() = 0; + // Whether to modify chance to simulate time lost by an unnattended block + virtual bool getSimpleCatchUp() = 0; // This is called usually at interval for 1/chance of the nodes virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){}; virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, @@ -150,6 +173,77 @@ struct ABMWithState ABMWithState(ActiveBlockModifier *abm_); }; +struct LoadingBlockModifierDef +{ + // Set of contents to trigger on + std::set trigger_contents; + std::string name; + bool run_at_every_load; + + virtual ~LoadingBlockModifierDef() {} + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){}; +}; + +struct LBMContentMapping +{ + typedef std::map > container_map; + container_map map; + + std::vector lbm_list; + + // Needs to be separate method (not inside destructor), + // because the LBMContentMapping may be copied and destructed + // many times during operation in the lbm_lookup_map. + void deleteContents(); + void addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamedef); + const std::vector *lookup(content_t c) const; +}; + +class LBMManager +{ +public: + LBMManager(): + m_query_mode(false) + {} + + ~LBMManager(); + + // Don't call this after loadIntroductionTimes() ran. + void addLBMDef(LoadingBlockModifierDef *lbm_def); + + void loadIntroductionTimes(const std::string ×, + IGameDef *gamedef, u32 now); + + // Don't call this before loadIntroductionTimes() ran. + std::string createIntroductionTimesString(); + + // Don't call this before loadIntroductionTimes() ran. + void applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp); + + // Warning: do not make this std::unordered_map, order is relevant here + typedef std::map lbm_lookup_map; + +private: + // Once we set this to true, we can only query, + // not modify + bool m_query_mode; + + // For m_query_mode == false: + // The key of the map is the LBM def's name. + // TODO make this std::unordered_map + std::map m_lbm_defs; + + // For m_query_mode == true: + // The key of the map is the LBM def's first introduction time. + lbm_lookup_map m_lbm_lookup; + + // Returns an iterator to the LBMs that were introduced + // after the given time. This is guaranteed to return + // valid values for everything + lbm_lookup_map::const_iterator getLBMsIntroducedAfter(u32 time) + { return m_lbm_lookup.lower_bound(time); } +}; + /* List of active blocks, used by ServerEnvironment */ @@ -157,7 +251,7 @@ struct ABMWithState class ActiveBlockList { public: - void update(std::list &active_positions, + void update(std::vector &active_positions, s16 radius, std::set &blocks_removed, std::set &blocks_added); @@ -171,14 +265,21 @@ class ActiveBlockList } std::set m_list; + std::set m_forceloaded_list; private: }; -class IBackgroundBlockEmerger -{ -public: - virtual void queueBlockEmerge(v3s16 blockpos, bool allow_generate)=0; +/* + Operation mode for ServerEnvironment::clearObjects() +*/ +enum ClearObjectsMode { + // Load and go through every mapblock, clearing objects + CLEAR_OBJECTS_MODE_FULL, + + // Clear objects immediately in loaded mapblocks; + // clear objects in unloaded mapblocks only when the mapblocks are next activated. + CLEAR_OBJECTS_MODE_QUICK, }; /* @@ -187,19 +288,22 @@ class IBackgroundBlockEmerger This is not thread-safe. Server uses an environment mutex. */ +typedef UNORDERED_MAP ActiveObjectMap; + class ServerEnvironment : public Environment { public: - ServerEnvironment(ServerMap *map, lua_State *L, IGameDef *gamedef, - IBackgroundBlockEmerger *emerger); + ServerEnvironment(ServerMap *map, GameScripting *scriptIface, + IGameDef *gamedef, const std::string &path_world); ~ServerEnvironment(); Map & getMap(); ServerMap & getServerMap(); - lua_State* getLua() - { return m_lua; } + //TODO find way to remove this fct! + GameScripting* getScriptIface() + { return m_script; } IGameDef *getGameDef() { return m_gamedef; } @@ -207,17 +311,27 @@ class ServerEnvironment : public Environment float getSendRecommendedInterval() { return m_recommended_send_interval; } - /* - Save players - */ - void serializePlayers(const std::string &savedir); - void deSerializePlayers(const std::string &savedir); + void kickAllPlayers(AccessDeniedCode reason, + const std::string &str_reason, bool reconnect); + // Save players + void saveLoadedPlayers(); + void savePlayer(RemotePlayer *player); + RemotePlayer *loadPlayer(const std::string &playername, PlayerSAO *sao); + void addPlayer(RemotePlayer *player); + void removePlayer(RemotePlayer *player); /* Save and load time of day and game timer */ - void saveMeta(const std::string &savedir); - void loadMeta(const std::string &savedir); + void saveMeta(); + void loadMeta(); + // to be called instead of loadMeta if + // env_meta.txt doesn't exist (e.g. new world) + void loadDefaultMeta(); + + u32 addParticleSpawner(float exptime); + u32 addParticleSpawner(float exptime, u16 attached_id); + void deleteParticleSpawner(u32 id, bool remove_from_object = true); /* External ActiveObject interface @@ -235,7 +349,7 @@ class ServerEnvironment : public Environment Returns 0 if not added and thus deleted. */ u16 addActiveObject(ServerActiveObject *object); - + /* Add an active object as a static object to the corresponding MapBlock. @@ -244,23 +358,25 @@ class ServerEnvironment : public Environment (note: not used, pending removal from engine) */ //bool addActiveObjectAsStatic(ServerActiveObject *object); - + /* Find out what new objects have been added to inside a radius around a position */ - void getAddedActiveObjects(v3s16 pos, s16 radius, + void getAddedActiveObjects(PlayerSAO *playersao, s16 radius, + s16 player_radius, std::set ¤t_objects, - std::set &added_objects); + std::queue &added_objects); /* Find out what new objects have been removed from inside a radius around a position */ - void getRemovedActiveObjects(v3s16 pos, s16 radius, + void getRemovedActiveObjects(PlayerSAO *playersao, s16 radius, + s16 player_radius, std::set ¤t_objects, - std::set &removed_objects); - + std::queue &removed_objects); + /* Get the next message emitted by some active object. Returns a message with id=0 if no messages are available. @@ -274,11 +390,12 @@ class ServerEnvironment : public Environment void activateBlock(MapBlock *block, u32 additional_dtime=0); /* - ActiveBlockModifiers + {Active,Loading}BlockModifiers ------------------------------------------- */ void addActiveBlockModifier(ActiveBlockModifier *abm); + void addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm); /* Other stuff @@ -288,19 +405,34 @@ class ServerEnvironment : public Environment // Script-aware node setters bool setNode(v3s16 p, const MapNode &n); bool removeNode(v3s16 p); - + bool swapNode(v3s16 p, const MapNode &n); + // Find all active objects inside a radius around a point - std::set getObjectsInsideRadius(v3f pos, float radius); - - // Clear all objects, loading and going through every MapBlock - void clearAllObjects(); - + void getObjectsInsideRadius(std::vector &objects, v3f pos, float radius); + + // Clear objects, loading and going through every MapBlock + void clearObjects(ClearObjectsMode mode); + // This makes stuff happen void step(f32 dtime); - + //check if there's a line of sight between two positions - bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0); + bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0, v3s16 *p=NULL); + u32 getGameTime() { return m_game_time; } + + void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; } + float getMaxLagEstimate() { return m_max_lag_estimate; } + + std::set* getForceloadedBlocks() { return &m_active_blocks.m_forceloaded_list; }; + + // Sets the static object status all the active objects in the specified block + // This is only really needed for deleting blocks from the map + void setStaticForActiveObjectsInBlock(v3s16 blockpos, + bool static_exists, v3s16 static_block=v3s16(0,0,0)); + + RemotePlayer *getPlayer(const u16 peer_id); + RemotePlayer *getPlayer(const char* name); private: /* @@ -319,17 +451,17 @@ class ServerEnvironment : public Environment Returns 0 if not added and thus deleted. */ u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed, u32 dtime_s); - + /* Remove all objects that satisfy (m_removed && m_known_by_count==0) */ void removeRemovedObjects(); - + /* Convert stored objects from block to active */ void activateObjects(MapBlock *block, u32 dtime_s); - + /* Convert objects that are not in active blocks to static. @@ -344,21 +476,20 @@ class ServerEnvironment : public Environment /* Member variables */ - + // The map ServerMap *m_map; // Lua state - lua_State *m_lua; + GameScripting* m_script; // Game definition IGameDef *m_gamedef; - // Background block emerger (the server, in practice) - IBackgroundBlockEmerger *m_emerger; + // World path + const std::string m_path_world; // Active object list - std::map m_active_objects; + ActiveObjectMap m_active_objects; // Outgoing network message buffer for active objects - Queue m_active_object_messages; + std::queue m_active_object_messages; // Some timers - float m_random_spawn_timer; // used for experimental code float m_send_recommended_timer; IntervalLimiter m_object_management_interval; // List of active blocks @@ -372,14 +503,32 @@ class ServerEnvironment : public Environment u32 m_game_time; // A helper variable for incrementing the latter float m_game_time_fraction_counter; - std::list m_abms; + // Time of last clearObjects call (game time). + // When a mapblock older than this is loaded, its objects are cleared. + u32 m_last_clear_objects_time; + // Active block modifiers + std::vector m_abms; + LBMManager m_lbm_mgr; // An interval for generally sending object positions and stuff float m_recommended_send_interval; + // Estimate for general maximum lag as determined by server. + // Can raise to high values like 15s with eg. map generation mods. + float m_max_lag_estimate; + + // peer_ids in here should be unique, except that there may be many 0s + std::vector m_players; + + // Particles + IntervalLimiter m_particle_management_interval; + UNORDERED_MAP m_particle_spawners; + UNORDERED_MAP m_particle_spawner_attachments; }; #ifndef SERVER #include "clientobject.h" +#include "content_cao.h" + class ClientSimpleObject; /* @@ -393,19 +542,23 @@ class ClientSimpleObject; enum ClientEnvEventType { CEE_NONE, - CEE_PLAYER_DAMAGE + CEE_PLAYER_DAMAGE, + CEE_PLAYER_BREATH }; struct ClientEnvEvent { ClientEnvEventType type; union { - struct{ - } none; + //struct{ + //} none; struct{ u8 amount; bool send_to_server; } player_damage; + struct{ + u16 amount; + } player_breath; }; }; @@ -425,9 +578,9 @@ class ClientEnvironment : public Environment void step(f32 dtime); - virtual void addPlayer(Player *player); - LocalPlayer * getLocalPlayer(); - + virtual void setLocalPlayer(LocalPlayer *player); + LocalPlayer *getLocalPlayer() { return m_local_player; } + /* ClientSimpleObjects */ @@ -437,7 +590,8 @@ class ClientEnvironment : public Environment /* ActiveObjects */ - + + GenericCAO* getGenericCAO(u16 id); ClientActiveObject* getActiveObject(u16 id); /* @@ -460,39 +614,43 @@ class ClientEnvironment : public Environment */ void damageLocalPlayer(u8 damage, bool handle_hp=true); + void updateLocalPlayerBreath(u16 breath); /* Client likes to call these */ - + // Get all nearby objects void getActiveObjects(v3f origin, f32 max_d, std::vector &dest); - + // Get event from queue. CEE_NONE is returned if queue is empty. ClientEnvEvent getClientEvent(); - std::vector > attachment_list; // X is child ID, Y is parent ID + u16 attachement_parent_ids[USHRT_MAX + 1]; - std::list getPlayerNames() - { return m_player_names; } - void addPlayerName(std::string name) - { m_player_names.push_back(name); } - void removePlayerName(std::string name) - { m_player_names.remove(name); } - + const std::list &getPlayerNames() { return m_player_names; } + void addPlayerName(const std::string &name) { m_player_names.push_back(name); } + void removePlayerName(const std::string &name) { m_player_names.remove(name); } + void updateCameraOffset(v3s16 camera_offset) + { m_camera_offset = camera_offset; } + v3s16 getCameraOffset() const { return m_camera_offset; } private: ClientMap *m_map; + LocalPlayer *m_local_player; scene::ISceneManager *m_smgr; ITextureSource *m_texturesource; IGameDef *m_gamedef; IrrlichtDevice *m_irr; - std::map m_active_objects; - std::list m_simple_objects; - Queue m_client_event_queue; + UNORDERED_MAP m_active_objects; + std::vector m_simple_objects; + std::queue m_client_event_queue; IntervalLimiter m_active_object_light_update_interval; IntervalLimiter m_lava_hurt_interval; + IntervalLimiter m_drowning_interval; + IntervalLimiter m_breathing_interval; std::list m_player_names; + v3s16 m_camera_offset; }; #endif