From: <gi...@cr...> - 2025-07-10 12:35:11
|
via bb92c9d70428e48777545ae3884f0e780995c5e2 (commit) via f72e9069bfe63de11eaa828750857da25ad3fef5 (commit) via e64c27fa7ce588b53477c71df053ebd92be5f873 (commit) from 8c5cb908cfc73e627762bdf7436b292a5c2d4e03 (commit) ----------------------------------------------------------------------- commit bb92c9d70428e48777545ae3884f0e780995c5e2 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 09:42:52 2025 -0230 Adjust offlevel tesseract turn cap (acrobat) The comment mistakenly talk about turns when the value involved was in aut, but that made me also realize the cap was too small (since it was aut.) I have raised the cap to 1000 turns (ie: 10,000 aut). The comment should now also be accurate. commit f72e9069bfe63de11eaa828750857da25ad3fef5 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 09:40:11 2025 -0230 Add milestones for tesseracts activating/dying (gammafunk) commit e64c27fa7ce588b53477c71df053ebd92be5f873 Author: Isaac Clancy <ik...@ya...> Date: Thu Jul 10 12:47:33 2025 +1200 Fix a webtiles desync when a spectator joins When a spectactor joins we send the full map data to the spectator that just joined and record this map data is the last sent map data. However, the player and any pre-exiting spectators might not have received this map data yet and as we set it as the last sent map data it won't be sent again until it changes. To fix this, make sure all the pre-existing clients have the most up to date map data before sending the full map data to the new spectator. Fixes #1474 Fixes #1637 Fixes #2473 Fixes #2499 Fixes #2704 Fixes #3153 Fixes #3222 Fixes #3489 Fixes #3974 Fixes #4013 Fixes #4169 Fixes #4536 ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/mon-abil.cc | 7 ++++--- crawl-ref/source/mon-death.cc | 7 ++++++- crawl-ref/source/tileweb.cc | 23 +++++++++++++++++++--- crawl-ref/source/tileweb.h | 2 +- .../source/webserver/webtiles/process_handler.py | 12 +++++++++-- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index 39acbf7a06..f1d077450b 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -1471,6 +1471,7 @@ void tesseract_action(monster& mon) if (mon.behaviour != BEH_SLEEP && !mon.props.exists(TESSERACT_START_TIME_KEY)) { mprf(MSGCH_WARN, "You feel the power of Zot begin to gather its forces!"); + mark_milestone("tesseract.activate", ""); for (monster_iterator mi; mi; ++mi) { @@ -1502,10 +1503,10 @@ void tesseract_action(monster& mon) // Handle regular spawning int& timer = mon.props[TESSERACT_SPAWN_TIMER_KEY].get_int(); - // Don't act as if more than 3000 turns have passed off-level (in case the + // Don't act as if more than 1000 turns have passed off-level (in case the // player goes to do Extended in the meantime). - if (you.elapsed_time - timer > 3000) - timer = you.elapsed_time - 3000; + if (you.elapsed_time - timer > 10000) + timer = you.elapsed_time - 10000; // Catch up however many spawns should have happened since the last time // we activated. diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index c120b39a5c..454ab5680a 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -3184,7 +3184,12 @@ item_def* monster_die(monster& mons, killer_type killer, } } } - you.props.erase(TESSERACT_START_TIME_KEY); + + if (you.props.exists(TESSERACT_START_TIME_KEY)) + { + mark_milestone("tesseract.kill", ""); + you.props.erase(TESSERACT_START_TIME_KEY); + } } if (mons_is_tentacle_head(mons_base_type(mons))) { diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 66f0c554df..e8ca97965a 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1825,7 +1825,7 @@ void TilesFramework::_mcache_ref(bool inc) } } -void TilesFramework::_send_map(bool force_full) +void TilesFramework::_send_map(bool spectator_only) { // TODO: prevent in some other / better way? if (_send_lock) @@ -1835,7 +1835,7 @@ void TilesFramework::_send_map(bool force_full) map<uint32_t, coord_def> new_monster_locs; - force_full = force_full || m_need_full_map; + bool force_full = spectator_only || m_need_full_map; m_need_full_map = false; json_open_object(); @@ -1843,6 +1843,10 @@ void TilesFramework::_send_map(bool force_full) json_treat_as_empty(); // cautionary note: this is used in heuristic ways in process_handler.py, + // see `_is_spectator_only` + if (spectator_only) + json_write_bool("spect_only", true); + // cautionary note: this is used in heuristic ways in process_handler.py, // see `_is_full_map_msg` if (force_full) json_write_bool("clear", true); @@ -1939,6 +1943,10 @@ void TilesFramework::_send_map(bool force_full) if (force_full) _send_cursor(CURSOR_MAP); + // Everything should already be up to date when called with spectator_only + if (spectator_only) + return; + if (m_mcache_ref_done) _mcache_ref(false); @@ -2128,7 +2136,16 @@ void TilesFramework::_send_everything() // Map is sent after player, otherwise HP/MP bar can be left behind in the // old location if the player has moved - _send_map(true); + + // The player might not have received the latest map data yet and + // _send_map(true) only sends the full map to the newly connected + // spectator but resets the dirty flags. So make sure the player's + // map data is up to date first. + const bool sent_full_map = m_need_full_map; + _send_map(false); + // If we didn't send the full map, send it to the new spectator + if (!sent_full_map) + _send_map(true); // Menus json_open_object(); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index 70712eeac8..affd2a0477 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -323,7 +323,7 @@ protected: void _mcache_ref(bool inc); void _send_cursor(cursor_type type); - void _send_map(bool force_full = false); + void _send_map(bool spectator_only = false); void _send_cell(const coord_def &gc, const screen_cell_t ¤t_sc, const screen_cell_t &next_sc, const map_cell ¤t_mc, const map_cell &next_mc, diff --git a/crawl-ref/source/webserver/webtiles/process_handler.py b/crawl-ref/source/webserver/webtiles/process_handler.py index e506c3b284..971c4c62c7 100644 --- a/crawl-ref/source/webserver/webtiles/process_handler.py +++ b/crawl-ref/source/webserver/webtiles/process_handler.py @@ -189,6 +189,10 @@ class CrawlProcessHandlerBase(object): return (re.search(r'"msg" *: *"map"', tocheck) and re.search(r'"clear" *: *true', tocheck)) + def _is_spectator_only(self, msg): + tocheck = msg[0:50] + return re.search(r'"spect_only" *: *true', tocheck) + def handle_process_message(self, msg, send): # type: (str, bool) -> None # special handling for map messages on a new spectator: these can be # massive, and the deflate time adds up, so only send it to new @@ -197,8 +201,12 @@ class CrawlProcessHandlerBase(object): # TODO: if multiple spectators join at the same time, it's probably # possible for this heuristic to fail and send a full map to everyone if self._fresh_watchers and self._is_full_map_msg(msg): - for w in self._fresh_watchers: - w.append_message(msg, send) + if self._is_spectator_only(msg): + for w in self._fresh_watchers: + w.append_message(msg, send) + else: + for receiver in self._receivers: + receiver.append_message(msg, send) self._fresh_watchers = set() return for receiver in self._receivers: -- Dungeon Crawl Stone Soup |