diff --git a/luprex/cpp/core/animqueue.hpp b/luprex/cpp/core/animqueue.hpp index 8a3e1d7f..9a20959e 100644 --- a/luprex/cpp/core/animqueue.hpp +++ b/luprex/cpp/core/animqueue.hpp @@ -249,6 +249,10 @@ public: eng::string steps_debug_string() const; eng::string full_debug_string() const; + // Get the final hash value. + // + uint64_t get_final_hash() const { return steps_.back().hash; } + // Get the final entry, xyz and plane only. // AnimCoreState get_final_core_state() const; diff --git a/luprex/cpp/core/drivenengine.cpp b/luprex/cpp/core/drivenengine.cpp index 2d3a2188..844f7b8f 100644 --- a/luprex/cpp/core/drivenengine.cpp +++ b/luprex/cpp/core/drivenengine.cpp @@ -414,6 +414,7 @@ uint64_t DrivenEngine::drv_get_actor_id() const { } void DrivenEngine::drv_get_tangibles_near(uint64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids) { + uint32_t hash1 = eng::memhash(); scan_result_.clear(); if ((visible_world_ != 0) && (tanid != 0)) { PlaneScan scan; @@ -430,8 +431,19 @@ void DrivenEngine::drv_get_tangibles_near(uint64_t tanid, double rx, double ry, } else { *ids = nullptr; } + uint32_t hash2 = eng::memhash(); + assert(hash1 == hash2); } +void DrivenEngine::drv_get_animation_queue_hashes(uint32_t count, const int64_t *ids, uint64_t *hashes) { + if (visible_world_ == 0) { + for (int i = 0; i < int(count); i++) { + hashes[i] = 0; + } + } else { + visible_world_->get_animation_queue_hashes(count, ids, hashes); + } +} ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -562,6 +574,9 @@ static void drv_get_tangibles_near(EngineWrapper *w, uint64_t tanid, double rx, return w->engine->drv_get_tangibles_near(tanid, rx, ry, rz, count, ids); } +static void drv_get_animation_queue_hashes(EngineWrapper *w, uint32_t count, const int64_t *ids, uint64_t *hashes) { + return w->engine->drv_get_animation_queue_hashes(count, ids, hashes); +} ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -959,6 +974,7 @@ static void init_engine_wrapper_helper(EngineWrapper *w) { w->get_stop_driver = drv_get_stop_driver; w->get_actor_id = drv_get_actor_id; w->get_tangibles_near = drv_get_tangibles_near; + w->get_animation_queue_hashes = drv_get_animation_queue_hashes; w->play_initialize = play_initialize; w->play_clear_new_outgoing = play_clear_new_outgoing; diff --git a/luprex/cpp/core/drivenengine.hpp b/luprex/cpp/core/drivenengine.hpp index 882a3adc..476e2537 100644 --- a/luprex/cpp/core/drivenengine.hpp +++ b/luprex/cpp/core/drivenengine.hpp @@ -282,6 +282,7 @@ public: bool drv_get_stop_driver() const; uint64_t drv_get_actor_id() const; void drv_get_tangibles_near(uint64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids); + void drv_get_animation_queue_hashes(uint32_t count, const int64_t *ids, uint64_t *hashes); void drv_initialize(uint32_t srcpklen, const char *srcpk, int argc, char **argv); void drv_clear_new_outgoing(); diff --git a/luprex/cpp/core/enginewrapper.hpp b/luprex/cpp/core/enginewrapper.hpp index 81a1abd0..4569636d 100644 --- a/luprex/cpp/core/enginewrapper.hpp +++ b/luprex/cpp/core/enginewrapper.hpp @@ -114,9 +114,13 @@ struct EngineWrapper { // uint64_t (*get_actor_id)(EngineWrapper *w); - // Get the results of the last scan radius. + // Do a scan to find tangibles near the specified player. // void (*get_tangibles_near)(EngineWrapper *w, uint64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids); + + // Get the hash value of the final animation step for each tangible. + // + void (*get_animation_queue_hashes)(EngineWrapper *w, uint32_t count, const int64_t *ids, uint64_t *hashes); ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 8a77eac0..90b89959 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -202,7 +202,6 @@ void World::tangible_delete(int64_t id) { } void World::get_near(PlaneScan &scan, util::IdVector *into) const { - uint32_t hash1 = eng::memhash(); into->clear(); // If 'near' is set, update the plane and center. int64_t actor_id = scan.near(); @@ -216,8 +215,6 @@ void World::get_near(PlaneScan &scan, util::IdVector *into) const { scan.set_center(util::XYZ(pi.x(), pi.y(), pi.z())); } plane_map_.scan(scan, into); - uint32_t hash2 = eng::memhash(); - assert(hash1 == hash2); } void World::get_near(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player, bool sorted, util::IdVector *into) const { @@ -230,6 +227,17 @@ void World::get_near(int64_t player_id, float radius, bool exclude_nowhere, bool get_near(scan, into); } +void World::get_animation_queue_hashes(uint32_t count, const int64_t *ids, uint64_t *hashes) { + for (int i = 0; i < int(count); i++) { + Tangible *tan = tangible_get(ids[i]); + if (tan == 0) { + hashes[i] = 0; + } else { + hashes[i] = tan->anim_queue_.get_final_hash(); + } + } +} + World::Redirects World::fetch_redirects() { World::Redirects result = std::move(redirects_); redirects_.clear(); diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index bb874997..8eab8edb 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -120,20 +120,27 @@ public: // 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 (but still include the player himself). - // The unsorted version returns the tangibles in an unpredictable order. If sorted - // is false, return them in an unpredictable order. + // Get a list of tangibles in any arbitrary region. // - void get_near(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player, bool sorted, IdVector *into) const; + void get_near(PlaneScan &sc, IdVector *into) const; // get_near // - // Get a list of tangibles in any arbitrary region. This differs from - // PlaneMap::scan in that if the scan specifies a 'near', then the plane - // and center of the scan are updated from the near tangible. + // Get a list of the tangibles that are near the player. If + // 'exclude_nowhere' is true, exclude any tangibles on the nowhere plane + // (but still include the player himself). The unsorted version returns the + // tangibles in an unpredictable order. If sorted is false, return them in + // an unpredictable order. This is a thin wrapper around the more general + // form of 'get_near', above. // - void get_near(PlaneScan &sc, IdVector *into) const; + void get_near(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player, bool sorted, IdVector *into) const; + + // get animation queue hashes. + // + // This is used by the graphics engine to check if any of the specified + // animation queues has changed in any way. + // + void get_animation_queue_hashes(uint32_t count, const int64_t *ids, uint64_t *hashes); // Make a tangible. //