Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/game_legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ struct LogThingDesyncInfo {
struct CoordDelta3d veloc_base;
struct CoordDelta3d veloc_push_once;
struct CoordDelta3d veloc_push_add;
TbBool is_creature;
struct Coord3d moveto_pos;
TbBool is_special_digger;
struct Coord3d digger_moveto_pos;
short digger_dragtng_idx;
Expand Down
13 changes: 12 additions & 1 deletion src/game_merge.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,19 @@ extern "C" {

// Random number generation system with synchronized and unsynchronized variants

void imp_random_log_push(uint16_t thing_idx, const char *func, unsigned long line, unsigned long range, unsigned long result, unsigned long seed_after);

static inline unsigned long thing_random_impl(struct Thing *thing, unsigned long range, const char *func_name, unsigned long line)
{
unsigned long result = LbRandomSeries(range, &thing->random_seed, func_name, line);
if (thing_is_creature_special_digger(thing)) {
imp_random_log_push(thing->index, func_name, line, range, result, (unsigned long)thing->random_seed);
}
return result;
}

// Thing-specific random for deterministic per-thing behavior (creatures, objects, etc.)
#define THING_RANDOM(thing, range) LbRandomSeries(range, &((struct Thing*)(thing))->random_seed, __func__, __LINE__)
#define THING_RANDOM(thing, range) thing_random_impl((struct Thing*)(thing), range, __func__, __LINE__)
// Global game events requiring synchronization across network (scripts, AI decisions, player events)
#define GAME_RANDOM(range) LbRandomSeries(range, &game.action_random_seed, __func__, __LINE__)
// Unsynchronized random for visual/audio effects that don't affect game state (lighting, particles)
Expand Down
71 changes: 68 additions & 3 deletions src/net_checksums.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,49 @@ extern "C" {
/******************************************************************************/
#define CHECKSUM_ADD(checksum, value) checksum = ((checksum << 5) | (checksum >> 27)) ^ (ulong)(value)
#define SNAPSHOT_BUFFER_SIZE 15
#define IMP_RANDOM_LOG_SIZE 16384

struct ImpRandomEntry {
const char *func;
unsigned long line;
unsigned long range;
unsigned long result;
unsigned long seed_after;
uint16_t thing_idx;
};

static struct ImpRandomEntry imp_random_log[IMP_RANDOM_LOG_SIZE];
static int imp_random_log_pos = 0;
static int imp_random_log_count = 0;

void imp_random_log_push(uint16_t thing_idx, const char *func, unsigned long line, unsigned long range, unsigned long result, unsigned long seed_after)
{
struct ImpRandomEntry *entry = &imp_random_log[imp_random_log_pos];
entry->thing_idx = thing_idx;
entry->func = func;
entry->line = line;
entry->range = range;
entry->result = result;
entry->seed_after = seed_after;
imp_random_log_pos = (imp_random_log_pos + 1) % IMP_RANDOM_LOG_SIZE;
if (imp_random_log_count < IMP_RANDOM_LOG_SIZE) {
imp_random_log_count++;
}
}

void imp_random_log_dump(uint16_t thing_idx)
{
ERRORLOG(" Imp Thing[%u] THING_RANDOM history (last %d entries):", (unsigned)thing_idx, imp_random_log_count);
int start = (imp_random_log_pos - imp_random_log_count + IMP_RANDOM_LOG_SIZE) % IMP_RANDOM_LOG_SIZE;
for (int i = 0; i < imp_random_log_count; i++) {
struct ImpRandomEntry *entry = &imp_random_log[(start + i) % IMP_RANDOM_LOG_SIZE];
if (entry->thing_idx != thing_idx) {
continue;
}
ERRORLOG(" Thing[%u] %s:%lu range=%lu result=%lu seed_after=%08lx",
(unsigned)entry->thing_idx, entry->func, entry->line, entry->range, entry->result, entry->seed_after);
}
}

struct ChecksumSnapshot {
GameTurn turn;
Expand Down Expand Up @@ -86,11 +129,14 @@ 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)) {
if (thing->class_id == TCls_Creature) {
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);
}
if (thing_is_creature_special_digger(thing)) {
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
CHECKSUM_ADD(checksum, cctrl->dragtng_idx);
CHECKSUM_ADD(checksum, cctrl->arming_thing_id);
CHECKSUM_ADD(checksum, cctrl->pickup_object_id);
Expand Down Expand Up @@ -255,6 +301,11 @@ 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_creature = (thing->class_id == TCls_Creature);
if (thing_snapshot->is_creature) {
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
thing_snapshot->moveto_pos = cctrl->moveto_pos;
}
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);
Expand Down Expand Up @@ -338,6 +389,11 @@ void pack_desync_history_for_resync(void) {
}
game.host_checksums = snapshot->checksums;
game.log_snapshot = snapshot->log_details;
for (int i = 0; i < game.log_snapshot.thing_count; i++) {
if (game.log_snapshot.things[i].is_special_digger) {
imp_random_log_dump(game.log_snapshot.things[i].index);
}
}
}

static void log_thing_differences(struct LogDetailedSnapshot* client, const char* name, TbBigChecksum client_sum, TbBigChecksum host_sum, ThingClass filter_class) {
Expand Down Expand Up @@ -388,9 +444,17 @@ 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_creature) {
if (host_thing != NULL) {
ERRORLOG(" [Host] moveto_pos=(%ld,%ld,%ld)",
(long)host_thing->moveto_pos.x.val, (long)host_thing->moveto_pos.y.val, (long)host_thing->moveto_pos.z.val);
}
ERRORLOG(" [Client] moveto_pos=(%ld,%ld,%ld)",
(long)client_thing->moveto_pos.x.val, (long)client_thing->moveto_pos.y.val, (long)client_thing->moveto_pos.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",
ERRORLOG(" [Host] digger_moveto_pos=(%ld,%ld,%ld) dragtng_idx=%d arming_thing_id=%d pickup_object_id=%d pickup_creature_id=%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,
Expand All @@ -400,7 +464,7 @@ static void log_thing_differences(struct LogDetailedSnapshot* client, const char
(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",
ERRORLOG(" [Client] digger_moveto_pos=(%ld,%ld,%ld) dragtng_idx=%d arming_thing_id=%d pickup_object_id=%d pickup_creature_id=%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,
Expand All @@ -409,6 +473,7 @@ static void log_thing_differences(struct LogDetailedSnapshot* client, const char
(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);
imp_random_log_dump(client_thing->index);
}
shown++;
}
Expand Down
2 changes: 2 additions & 0 deletions src/net_checksums.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ TbBigChecksum get_thing_checksum(const struct Thing *thing);
short checksums_different(void);
CoroutineLoopState perform_checksum_verification(CoroutineLoop *con);
CoroutineLoopState verify_sprite_zip_checksums(CoroutineLoop *con);
void imp_random_log_push(uint16_t thing_idx, const char *func, unsigned long line, unsigned long range, unsigned long result, unsigned long seed_after);
void imp_random_log_dump(uint16_t thing_idx);

/******************************************************************************/
#ifdef __cplusplus
Expand Down
Loading