#ifndef WORLD_HPP #define WORLD_HPP #include "luastack.hpp" #include "planemap.hpp" #include "idalloc.hpp" #include "animqueue.hpp" #include "invocation.hpp" #include "streambuffer.hpp" #include "sched.hpp" #include "source.hpp" #include "gui.hpp" #include "luasnap.hpp" #include #include #include #include class World; class Tangible { private: friend class World; // Serialize and deserialize // // The tangible's ID is not serialized. When you serialize a tangible, you // should probably serialize the ID separately. // // The Lua portion of the tangible is not serialized here. Instead, the lua // portion is serialized when you serialize the lua state as a whole. // // PlaneItem is not serialized. The deserialize routine rebuilds the // PlaneItem from the AnimQueue. // // World pointer is not serialized. // void serialize(StreamBuffer *sb); void deserialize(StreamBuffer *sb); public: // Always points back to the world model. World *world_; // Animation queue. // AnimQueue anim_queue_; // Plane Item. // // The PlaneItem also contains this tangible's ID. // To move this PlaneItem, update the anim_queue first, then call // update_plane_item, which copies the data from the anim_queue. // PlaneItem plane_item_; // Player ID pool // // This is present in every tangible, whether a player or not. // However, the fifo is only enabled in logged-in players. // IdPlayerPool id_player_pool_; // constructor. // Tangible(World *w, int64_t id); // Get the ID // int64_t id() const { return plane_item_.id(); } void update_plane_item(); bool is_an_actor() { return (id_player_pool_.get_fifo_capacity() > 0); } void configure_id_pool_for_actor() { id_player_pool_.set_fifo_capacity(20); } }; class World { public: using IdVector = util::IdVector; using TanVector = std::vector; using Redirects = std::map; // Constructor. // // The constructor also calls 'lua_open' to create a new // lua interpreter for this world model. // World(util::WorldType wt); // Destructor. // // Not currently functional. // ~World(); // get_lua_state // // Get the lua interpreter associated with this world model. // lua_State *state() const { return lua_snap_.state(); } // get_near // // Get a list of the tangibles that are near the player. If 'exclude_nowhere' is // true, exclude any tangibles on the nowhere plane. // IdVector get_near(int64_t player_id, float radius, bool exclude_nowhere) const; // Make a tangible. // // If the ID is zero, allocates an ID using the thread's ID allocator. If // pushdb is true, pushes the tangible's database onto the lua stack. // Otherwise, leaves the lua stack untouched. // Tangible *tangible_make(lua_State *L, int64_t id, bool pushdb); // Get a pointer to the specified tangible. // Tangible *tangible_get(int64_t id); const Tangible *tangible_get(int64_t id) const; // Get a pointer to the specified tangible. // // The value on the lua stack should be a valid lua tangible. If not, // a lua error is generated. // Tangible *tangible_get(lua_State *L, int idx); // Get pointers to many tangibles. // TanVector tangible_get_all(const IdVector &ids) const; // Delete the specified tangible. // void tangible_delete(lua_State *L, int64_t id); // Create a login actor. // // Creates a tangible of class 'login' and returns its ID. // This is used to create a temporary actor which is used during // the login process. // int64_t create_login_actor(); // Fetch all redirects and clear the redirects table. // Redirects fetch_redirects(); // Probe the 'interface' function of the specified sprite. // void update_gui(int64_t actor_id, int64_t place_id, Gui *gui); // Invoke an Invocation object. // // This is the primary dispatcher for all operations that mutate a world model. // To mutate a world model, create an invocation, then invoke it. // void invoke(const Invocation &inv); // Update the source database from disk. // void update_source() { source_db_.update(); source_db_.rebuild(); } // Run all unit tests. // void run_unittests() { source_db_.run_unittests(); } // fetch_global_pointer // // Given a lua state, fetch the world model associated with // that lua state. // static World *fetch_global_pointer(lua_State *L); // Serialize and deserialize. // void serialize(StreamBuffer *sb); void deserialize(StreamBuffer *sb); // Snapshot and rollback. // void snapshot(); void rollback(); // Difference transmission. // // This generates diffs and stores them in the specified buffer, // so that they can be sent to the client. It also applies the diffs // to this model. // void difference_transmit(int64_t actor, const World *master, StreamBuffer *sb); // Apply differences. // // Note that difference_transmit applies the differences to the server // synchronous model, so this is only used by the client synchronous model. // void apply_differences(StreamBuffer *sb); public: //////////////////////////////////////////////////////////////////////////// // // TESTING SUPPORT // // The following functions are not designed to be useful for production // code, they're designed to be helpful for unit testing. // //////////////////////////////////////////////////////////////////////////// // Add a 'walkto' animation to the specified tangible. // void tangible_walkto(int64_t id, int64_t animid, float x, float y); // Get a list of all existing tangibles as a comma-separated string. // std::string tangible_ids_debug_string() const; private: // Run any threads which according to the scheduler queue are ready. // void run_scheduled_threads(int64_t clk); // Store a pointer to a world model into a lua registry. // static void store_global_pointer(lua_State *L, World *w); // Check that the main thread has nothing on the stack // bool stack_is_clear() const { return lua_gettop(state()) == 0; } // Invoke a plan. // void invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, const InvocationData &idata); // pass 1 of difference transmission: actor essentials. // // Before we do anything else, we need to get the actor in the right place. // We also update the actor's ID allocation pipeline. // static void diff_actor_essentials(const Tangible *mactor, const Tangible *sactor, StreamBuffer *sb); void patch_actor_essentials(StreamBuffer *sb); // Pass 2 of difference transmission: visible animations. // // Synchronizes the animation status of every tangible inside the visibility // radius of either model. Creates missing tangibles and deletes excess tangibles. // static void diff_visible_animations(const TanVector &mvis, const TanVector &svis, StreamBuffer *sb); void patch_visible_animations(StreamBuffer *sb); private: // Type of model util::WorldType world_type_; // A lua intepreter with snapshot function. // LuaSnap lua_snap_; // The Global ID Pool. // IdGlobalPool id_global_pool_; // Source Database. // SourceDB source_db_; PlaneMap plane_map_; // Tangibles table. // std::unordered_map> tangibles_; // Thread schedule: must include every thread, except // for the one currently-executing thread. // Schedule thread_sched_; // Serialized snapshot of world model. StreamBuffer snapshot_; // Redirects. // Redirects redirects_; friend class Tangible; friend int tangible_animate(lua_State *L); friend int tangible_build(lua_State *L); friend int tangible_redirect(lua_State *L); }; #endif // WORLD_HPP