From c0388d67c96230ebb801614ef88d42ea17de33b5 Mon Sep 17 00:00:00 2001 From: rainlizard <15337628+rainlizard@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:46:36 +1000 Subject: [PATCH 1/2] More thing checksums --- src/game_legacy.h | 13 +++++++++ src/net_checksums.c | 69 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/game_legacy.h b/src/game_legacy.h index 4eb281fb83..ea4c8841df 100644 --- a/src/game_legacy.h +++ b/src/game_legacy.h @@ -136,6 +136,19 @@ struct LogThingDesyncInfo { HitPoints health; GameTurn creation_turn; uint32_t random_seed; + unsigned char current_frame; + unsigned char max_frames; + unsigned char active_state; + unsigned char continue_state; + unsigned short movement_flags; + short move_angle_xy; + short move_angle_z; + PlayerNumber holding_player; + short parent_idx; + unsigned char fall_acceleration; + struct CoordDelta3d veloc_base; + struct CoordDelta3d veloc_push_once; + struct CoordDelta3d veloc_push_add; TbBigChecksum checksum; }; diff --git a/src/net_checksums.c b/src/net_checksums.c index d01d37fab5..006cf063c8 100644 --- a/src/net_checksums.c +++ b/src/net_checksums.c @@ -66,12 +66,23 @@ TbBigChecksum get_thing_checksum(const struct Thing* thing) { CHECKSUM_ADD(checksum, thing->health); CHECKSUM_ADD(checksum, thing->current_frame); CHECKSUM_ADD(checksum, thing->max_frames); - - if (thing->class_id == TCls_Creature) { - struct CreatureControl* creature_control = creature_control_get_from_thing(thing); - CHECKSUM_ADD(checksum, creature_control->inst_turn); - CHECKSUM_ADD(checksum, creature_control->instance_id); - } + CHECKSUM_ADD(checksum, thing->active_state); + CHECKSUM_ADD(checksum, thing->continue_state); + CHECKSUM_ADD(checksum, thing->movement_flags); + CHECKSUM_ADD(checksum, thing->move_angle_xy); + CHECKSUM_ADD(checksum, thing->move_angle_z); + CHECKSUM_ADD(checksum, thing->holding_player); + CHECKSUM_ADD(checksum, thing->parent_idx); + CHECKSUM_ADD(checksum, thing->fall_acceleration); + CHECKSUM_ADD(checksum, thing->veloc_base.x.val); + CHECKSUM_ADD(checksum, thing->veloc_base.y.val); + CHECKSUM_ADD(checksum, thing->veloc_base.z.val); + CHECKSUM_ADD(checksum, thing->veloc_push_once.x.val); + CHECKSUM_ADD(checksum, thing->veloc_push_once.y.val); + CHECKSUM_ADD(checksum, thing->veloc_push_once.z.val); + CHECKSUM_ADD(checksum, thing->veloc_push_add.x.val); + CHECKSUM_ADD(checksum, thing->veloc_push_add.y.val); + CHECKSUM_ADD(checksum, thing->veloc_push_add.z.val); return checksum; } @@ -209,6 +220,19 @@ void update_turn_checksums(void) { thing_snapshot->health = thing->health; thing_snapshot->creation_turn = thing->creation_turn; thing_snapshot->random_seed = thing->random_seed; + thing_snapshot->current_frame = thing->current_frame; + thing_snapshot->max_frames = thing->max_frames; + thing_snapshot->active_state = thing->active_state; + thing_snapshot->continue_state = thing->continue_state; + thing_snapshot->movement_flags = thing->movement_flags; + thing_snapshot->move_angle_xy = thing->move_angle_xy; + thing_snapshot->move_angle_z = thing->move_angle_z; + thing_snapshot->holding_player = thing->holding_player; + thing_snapshot->parent_idx = thing->parent_idx; + thing_snapshot->fall_acceleration = thing->fall_acceleration; + thing_snapshot->veloc_base = thing->veloc_base; + thing_snapshot->veloc_push_once = thing->veloc_push_once; + thing_snapshot->veloc_push_add = thing->veloc_push_add; thing_snapshot->checksum = get_thing_checksum(thing); } for (int i = 0; i < PLAYERS_COUNT; i++) { @@ -297,11 +321,33 @@ static void log_thing_differences(struct LogDetailedSnapshot* client, const char } if (host_thing == NULL || client_thing->checksum != host_thing->checksum) { if (host_thing != NULL) { - ERRORLOG(" [Host] Thing[%d] class_id=%d model=%d owner=%d mappos=(%ld,%ld,%ld) health=%ld creation_turn=%lu random_seed=%08x", host_thing->index, host_thing->class_id, host_thing->model, host_thing->owner, (long)host_thing->mappos.x.val, (long)host_thing->mappos.y.val, (long)host_thing->mappos.z.val, (long)host_thing->health, (unsigned long)host_thing->creation_turn, host_thing->random_seed); + ERRORLOG(" [Host] Thing[%d] class_id=%d model=%d owner=%d mappos=(%ld,%ld,%ld) health=%ld creation_turn=%lu random_seed=%08x current_frame=%u max_frames=%u active_state=%u continue_state=%u movement_flags=%04x move_angle_xy=%d move_angle_z=%d holding_player=%d parent_idx=%d fall_acceleration=%u veloc_base=(%ld,%ld,%ld) veloc_push_once=(%ld,%ld,%ld) veloc_push_add=(%ld,%ld,%ld)", + host_thing->index, host_thing->class_id, host_thing->model, host_thing->owner, + (long)host_thing->mappos.x.val, (long)host_thing->mappos.y.val, (long)host_thing->mappos.z.val, + (long)host_thing->health, (unsigned long)host_thing->creation_turn, host_thing->random_seed, + (unsigned)host_thing->current_frame, (unsigned)host_thing->max_frames, + (unsigned)host_thing->active_state, (unsigned)host_thing->continue_state, + (unsigned)host_thing->movement_flags, + (int)host_thing->move_angle_xy, (int)host_thing->move_angle_z, + (int)host_thing->holding_player, (int)host_thing->parent_idx, (unsigned)host_thing->fall_acceleration, + (long)host_thing->veloc_base.x.val, (long)host_thing->veloc_base.y.val, (long)host_thing->veloc_base.z.val, + (long)host_thing->veloc_push_once.x.val, (long)host_thing->veloc_push_once.y.val, (long)host_thing->veloc_push_once.z.val, + (long)host_thing->veloc_push_add.x.val, (long)host_thing->veloc_push_add.y.val, (long)host_thing->veloc_push_add.z.val); } else { ERRORLOG(" [Host] Thing[%d] missing", client_thing->index); } - ERRORLOG(" [Client] Thing[%d] class_id=%d model=%d owner=%d mappos=(%ld,%ld,%ld) health=%ld creation_turn=%lu random_seed=%08x", client_thing->index, client_thing->class_id, client_thing->model, client_thing->owner, (long)client_thing->mappos.x.val, (long)client_thing->mappos.y.val, (long)client_thing->mappos.z.val, (long)client_thing->health, (unsigned long)client_thing->creation_turn, client_thing->random_seed); + ERRORLOG(" [Client] Thing[%d] class_id=%d model=%d owner=%d mappos=(%ld,%ld,%ld) health=%ld creation_turn=%lu random_seed=%08x current_frame=%u max_frames=%u active_state=%u continue_state=%u movement_flags=%04x move_angle_xy=%d move_angle_z=%d holding_player=%d parent_idx=%d fall_acceleration=%u veloc_base=(%ld,%ld,%ld) veloc_push_once=(%ld,%ld,%ld) veloc_push_add=(%ld,%ld,%ld)", + client_thing->index, client_thing->class_id, client_thing->model, client_thing->owner, + (long)client_thing->mappos.x.val, (long)client_thing->mappos.y.val, (long)client_thing->mappos.z.val, + (long)client_thing->health, (unsigned long)client_thing->creation_turn, client_thing->random_seed, + (unsigned)client_thing->current_frame, (unsigned)client_thing->max_frames, + (unsigned)client_thing->active_state, (unsigned)client_thing->continue_state, + (unsigned)client_thing->movement_flags, + (int)client_thing->move_angle_xy, (int)client_thing->move_angle_z, + (int)client_thing->holding_player, (int)client_thing->parent_idx, (unsigned)client_thing->fall_acceleration, + (long)client_thing->veloc_base.x.val, (long)client_thing->veloc_base.y.val, (long)client_thing->veloc_base.z.val, + (long)client_thing->veloc_push_once.x.val, (long)client_thing->veloc_push_once.y.val, (long)client_thing->veloc_push_once.z.val, + (long)client_thing->veloc_push_add.x.val, (long)client_thing->veloc_push_add.y.val, (long)client_thing->veloc_push_add.z.val); shown++; } } @@ -360,8 +406,11 @@ void compare_desync_history_from_host(void) { ERRORLOG(" Room[%d] missing from host", client_room->index); shown++; } else if (client_room->checksum != host_room->checksum) { - ERRORLOG(" Room[%d] slabs_count: Host=%d Client=%d, efficiency: Host=%d Client=%d", - client_room->index, host_room->slabs_count, client_room->slabs_count, host_room->efficiency, client_room->efficiency); + ERRORLOG(" Room[%d] slabs_count: Host=%d Client=%d, efficiency: Host=%d Client=%d, used_capacity: Host=%d Client=%d, central_stl: Host=(%d,%d) Client=(%d,%d)", + client_room->index, host_room->slabs_count, client_room->slabs_count, host_room->efficiency, client_room->efficiency, + (int)host_room->used_capacity, (int)client_room->used_capacity, + (int)host_room->central_stl_x, (int)host_room->central_stl_y, + (int)client_room->central_stl_x, (int)client_room->central_stl_y); shown++; } } From 549ee9d27f0042085d3a229f99d248298d254ecc Mon Sep 17 00:00:00 2001 From: rainlizard <15337628+rainlizard@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:57:35 +1000 Subject: [PATCH 2/2] digger-only --- src/game_legacy.h | 15 ++++++++++++ src/net_checksums.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/game_legacy.h b/src/game_legacy.h index ea4c8841df..edcd8ba73f 100644 --- a/src/game_legacy.h +++ b/src/game_legacy.h @@ -149,6 +149,21 @@ struct LogThingDesyncInfo { struct CoordDelta3d veloc_base; struct CoordDelta3d veloc_push_once; struct CoordDelta3d veloc_push_add; + TbBool is_special_digger; + struct Coord3d digger_moveto_pos; + short digger_dragtng_idx; + ThingIndex digger_arming_thing_id; + ThingIndex digger_pickup_object_id; + ThingIndex digger_pickup_creature_id; + unsigned char digger_move_flags; + int32_t digger_stack_update_turn; + SubtlCodedCoords digger_working_stl; + SubtlCodedCoords digger_task_stl; + unsigned short digger_task_idx; + unsigned char digger_consecutive_reinforcements; + unsigned char digger_last_did_job; + unsigned char digger_task_stack_pos; + unsigned short digger_task_repeats; TbBigChecksum checksum; }; diff --git a/src/net_checksums.c b/src/net_checksums.c index 006cf063c8..cfdfe8ccee 100644 --- a/src/net_checksums.c +++ b/src/net_checksums.c @@ -26,6 +26,7 @@ #include "thing_data.h" #include "room_list.h" #include "creature_control.h" +#include "thing_creature.h" #include "frontend.h" #include "thing_list.h" #include "post_inc.h" @@ -83,6 +84,25 @@ TbBigChecksum get_thing_checksum(const struct Thing* thing) { CHECKSUM_ADD(checksum, thing->veloc_push_add.x.val); CHECKSUM_ADD(checksum, thing->veloc_push_add.y.val); CHECKSUM_ADD(checksum, thing->veloc_push_add.z.val); + if (thing_is_creature_special_digger(thing)) { + struct CreatureControl* cctrl = creature_control_get_from_thing(thing); + CHECKSUM_ADD(checksum, cctrl->moveto_pos.x.val); + CHECKSUM_ADD(checksum, cctrl->moveto_pos.y.val); + CHECKSUM_ADD(checksum, cctrl->moveto_pos.z.val); + CHECKSUM_ADD(checksum, cctrl->dragtng_idx); + CHECKSUM_ADD(checksum, cctrl->arming_thing_id); + CHECKSUM_ADD(checksum, cctrl->pickup_object_id); + CHECKSUM_ADD(checksum, cctrl->pickup_creature_id); + CHECKSUM_ADD(checksum, cctrl->move_flags); + CHECKSUM_ADD(checksum, cctrl->digger.stack_update_turn); + CHECKSUM_ADD(checksum, cctrl->digger.working_stl); + CHECKSUM_ADD(checksum, cctrl->digger.task_stl); + CHECKSUM_ADD(checksum, cctrl->digger.task_idx); + CHECKSUM_ADD(checksum, cctrl->digger.consecutive_reinforcements); + CHECKSUM_ADD(checksum, cctrl->digger.last_did_job); + CHECKSUM_ADD(checksum, cctrl->digger.task_stack_pos); + CHECKSUM_ADD(checksum, cctrl->digger.task_repeats); + } return checksum; } @@ -233,6 +253,24 @@ void update_turn_checksums(void) { thing_snapshot->veloc_base = thing->veloc_base; thing_snapshot->veloc_push_once = thing->veloc_push_once; thing_snapshot->veloc_push_add = thing->veloc_push_add; + thing_snapshot->is_special_digger = thing_is_creature_special_digger(thing); + if (thing_snapshot->is_special_digger) { + struct CreatureControl* cctrl = creature_control_get_from_thing(thing); + thing_snapshot->digger_moveto_pos = cctrl->moveto_pos; + thing_snapshot->digger_dragtng_idx = cctrl->dragtng_idx; + thing_snapshot->digger_arming_thing_id = cctrl->arming_thing_id; + thing_snapshot->digger_pickup_object_id = cctrl->pickup_object_id; + thing_snapshot->digger_pickup_creature_id = cctrl->pickup_creature_id; + thing_snapshot->digger_move_flags = cctrl->move_flags; + thing_snapshot->digger_stack_update_turn = cctrl->digger.stack_update_turn; + thing_snapshot->digger_working_stl = cctrl->digger.working_stl; + thing_snapshot->digger_task_stl = cctrl->digger.task_stl; + thing_snapshot->digger_task_idx = cctrl->digger.task_idx; + thing_snapshot->digger_consecutive_reinforcements = cctrl->digger.consecutive_reinforcements; + thing_snapshot->digger_last_did_job = cctrl->digger.last_did_job; + thing_snapshot->digger_task_stack_pos = cctrl->digger.task_stack_pos; + thing_snapshot->digger_task_repeats = cctrl->digger.task_repeats; + } thing_snapshot->checksum = get_thing_checksum(thing); } for (int i = 0; i < PLAYERS_COUNT; i++) { @@ -348,6 +386,28 @@ static void log_thing_differences(struct LogDetailedSnapshot* client, const char (long)client_thing->veloc_base.x.val, (long)client_thing->veloc_base.y.val, (long)client_thing->veloc_base.z.val, (long)client_thing->veloc_push_once.x.val, (long)client_thing->veloc_push_once.y.val, (long)client_thing->veloc_push_once.z.val, (long)client_thing->veloc_push_add.x.val, (long)client_thing->veloc_push_add.y.val, (long)client_thing->veloc_push_add.z.val); + if (client_thing->is_special_digger) { + if (host_thing != NULL) { + ERRORLOG(" [Host] digger moveto=(%ld,%ld,%ld) dragtng=%d arming=%d pickup_obj=%d pickup_cr=%d move_flags=%u stack_update_turn=%ld working_stl=%u task_stl=%u task_idx=%u consecutive_reinforcements=%u last_did_job=%u task_stack_pos=%u task_repeats=%u", + (long)host_thing->digger_moveto_pos.x.val, (long)host_thing->digger_moveto_pos.y.val, (long)host_thing->digger_moveto_pos.z.val, + (int)host_thing->digger_dragtng_idx, (int)host_thing->digger_arming_thing_id, + (int)host_thing->digger_pickup_object_id, (int)host_thing->digger_pickup_creature_id, + (unsigned)host_thing->digger_move_flags, (long)host_thing->digger_stack_update_turn, + (unsigned)host_thing->digger_working_stl, (unsigned)host_thing->digger_task_stl, + (unsigned)host_thing->digger_task_idx, (unsigned)host_thing->digger_consecutive_reinforcements, + (unsigned)host_thing->digger_last_did_job, + (unsigned)host_thing->digger_task_stack_pos, (unsigned)host_thing->digger_task_repeats); + } + ERRORLOG(" [Client] digger moveto=(%ld,%ld,%ld) dragtng=%d arming=%d pickup_obj=%d pickup_cr=%d move_flags=%u stack_update_turn=%ld working_stl=%u task_stl=%u task_idx=%u consecutive_reinforcements=%u last_did_job=%u task_stack_pos=%u task_repeats=%u", + (long)client_thing->digger_moveto_pos.x.val, (long)client_thing->digger_moveto_pos.y.val, (long)client_thing->digger_moveto_pos.z.val, + (int)client_thing->digger_dragtng_idx, (int)client_thing->digger_arming_thing_id, + (int)client_thing->digger_pickup_object_id, (int)client_thing->digger_pickup_creature_id, + (unsigned)client_thing->digger_move_flags, (long)client_thing->digger_stack_update_turn, + (unsigned)client_thing->digger_working_stl, (unsigned)client_thing->digger_task_stl, + (unsigned)client_thing->digger_task_idx, (unsigned)client_thing->digger_consecutive_reinforcements, + (unsigned)client_thing->digger_last_did_job, + (unsigned)client_thing->digger_task_stack_pos, (unsigned)client_thing->digger_task_repeats); + } shown++; } }