bitbuff dbg markers, rough arg parsing

This commit is contained in:
jacob 2025-02-26 11:36:34 -06:00
parent f9cbe61b7b
commit 153290d57e
8 changed files with 242 additions and 47 deletions

105
src/app.c
View File

@ -122,6 +122,87 @@ void app_register_exit_callback(app_exit_callback_func *func)
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
/* ========================== *
* Args
* ========================== */
struct app_arg {
struct string key;
struct string value;
struct app_arg *next;
};
struct app_arg_list {
struct app_arg *first;
struct app_arg *last;
u64 count;
};
/* TODO: Remove this and do real argument parsing */
INTERNAL struct app_arg_list parse_args(struct arena *arena, struct string args_str)
{
struct app_arg_list res = ZI;
i64 mode = 0;
i64 i = 0;
i64 key_start = -1;
i64 key_end = -1;
i64 value_start = -1;
i64 value_end = -1;
while (i < (i64)args_str.len) {
u8 c = args_str.text[i];
switch (mode) {
case 0:
{
if (c == '-') {
mode = 1;
key_start = i + 1;
}
++i;
} break;
case 1:
{
if (c == '=') {
key_end = i;
value_start = i + 1;
mode = 2;
}
++i;
} break;
case 2:
{
if (c == '-' || i == (i64)args_str.len - 1) {
if (c == '-') {
value_end = i;
} else {
value_end = i + 1;
}
if (key_start >= 0 && key_end > key_start && key_end <= (i64)args_str.len && value_start >= 0 && value_end > value_start && value_end <= (i64)args_str.len) {
struct string key = string_copy(arena, STRING(key_end - key_start, args_str.text + key_start));
struct string value = string_copy(arena, STRING(value_end - value_start, args_str.text + value_start));
struct app_arg *arg = arena_push_zero(arena, struct app_arg);
arg->key = key;
arg->value = value;
if (res.last) {
res.last->next = arg;
} else {
res.first = arg;
}
res.last = arg;
++res.count;
}
key_start = i + 1;
mode = 1;
}
++i;
} break;
default: break;
}
}
return res;
}
/* ========================== * /* ========================== *
* Entry point * Entry point
* ========================== */ * ========================== */
@ -130,6 +211,19 @@ void app_entry_point(struct string args_str)
{ {
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
struct app_arg_list args = parse_args(scratch.arena, args_str);
struct string logfile_name = LIT("log.txt");
struct string connect_address = ZI;
for (struct app_arg *arg = args.first; arg; arg = arg->next) {
struct string key = arg->key;
struct string value = arg->value;
if (string_eq(key, LIT("log"))) {
logfile_name = value;
} else if (string_eq(key, LIT("connect"))) {
connect_address = value;
}
}
#if !RTC #if !RTC
/* Verify test modes aren't left on by accident in release mode */ /* Verify test modes aren't left on by accident in release mode */
CT_ASSERT(BITBUFF_DEBUG == 0); CT_ASSERT(BITBUFF_DEBUG == 0);
@ -167,13 +261,18 @@ void app_entry_point(struct string args_str)
/* Startup logging */ /* Startup logging */
{ {
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
struct string logfile_path = app_write_path_cat(temp.arena, LIT("log.txt"));
struct string logfile_path = logfile_path = app_write_path_cat(temp.arena, logfile_name);
struct log_startup_receipt log_sr = log_startup(logfile_path); struct log_startup_receipt log_sr = log_startup(logfile_path);
(UNUSED)log_sr; (UNUSED)log_sr;
logf_info("Start of logs"); logf_info("Start of logs");
arena_temp_end(temp); arena_temp_end(temp);
} }
logf_info("App started with args: \"%F\"", FMT_STR(args_str)); logf_info("App started with args \"%F\" (%F parsed)", FMT_STR(args_str), FMT_UINT(args.count));
for (struct app_arg *arg = args.first; arg; arg = arg->next) {
logf_info("Parsed arg: key = \"%F\", value = \"%F\"", FMT_STR(arg->key), FMT_STR(arg->value));
}
/* Create window */ /* Create window */
struct sys_window window = sys_window_alloc(); struct sys_window window = sys_window_alloc();
@ -235,7 +334,7 @@ void app_entry_point(struct string args_str)
struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr); struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr);
struct phys_startup_receipt phys_sr = phys_startup(); struct phys_startup_receipt phys_sr = phys_startup();
struct sim_startup_receipt sim_sr = sim_startup(); struct sim_startup_receipt sim_sr = sim_startup();
struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &phys_sr, &host_sr, &sim_sr, args_str, &window); struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &phys_sr, &host_sr, &sim_sr, connect_address, &window);
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr); struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
(UNUSED)user_sr; (UNUSED)user_sr;

View File

@ -48,10 +48,10 @@ INTERNAL void _dbg_read_magic(struct bitbuff_reader *br, enum dbg_magic expected
u8 stored_num_bits = (stored >> 16) & 0xFF; u8 stored_num_bits = (stored >> 16) & 0xFF;
/* Verify stored magic match */ /* Verify stored magic match */
ASSERT(stored_magic == expected_magic); ASSERT(expected_magic == stored_magic);
/* Verify stored bit count match */ /* Verify stored bit count match */
ASSERT(stored_num_bits == expected_num_bits); ASSERT(expected_num_bits == stored_num_bits);
} }
} }
@ -259,9 +259,11 @@ void bw_write_ibits(struct bitbuff_writer *bw, i64 value, u8 num_bits)
bw_write_ubits(bw, ubits, num_bits); bw_write_ubits(bw, ubits, num_bits);
} }
void bw_write_bit(struct bitbuff_writer *bw, u8 value) /* Returns written bit to make writing delta encoding logic cleaner */
b32 bw_write_bit(struct bitbuff_writer *bw, u8 value)
{ {
bw_write_ubits(bw, value, 1); bw_write_ubits(bw, value, 1);
return value;
} }
/* Writes a variable length unsigned integer. /* Writes a variable length unsigned integer.
@ -359,6 +361,16 @@ void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes)
bw->cur_bit += num_bits; bw->cur_bit += num_bits;
} }
#if BITBUFF_DEBUG
void bw_write_dbg_marker(struct bitbuff_writer *bw, struct string name)
{
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
for (u64 i = 0; i < name.len; ++i) {
bw_write_ubits_nomagic(bw, name.text[i], 8);
}
}
#endif
/* ========================== * /* ========================== *
* Reader * Reader
* ========================== */ * ========================== */
@ -652,6 +664,18 @@ void br_seek_to_byte(struct bitbuff_reader *br, u64 pos)
} }
#if BITBUFF_DEBUG
void br_read_dbg_marker(struct bitbuff_reader *br, struct string name)
{
br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
for (u64 i = 0; i < name.len; ++i) {
u8 c_stored = br_read_ubits_nomagic(br, 8);
u8 c_expected = name.text[i];
ASSERT(c_expected == c_stored);
}
}
#endif
/* ========================== * /* ========================== *
* Test * Test
* ========================== */ * ========================== */

View File

@ -50,7 +50,7 @@ void bw_align(struct bitbuff_writer *bw);
void bw_write_ubits(struct bitbuff_writer *bw, u64 value, u8 num_bits); void bw_write_ubits(struct bitbuff_writer *bw, u64 value, u8 num_bits);
void bw_write_ibits(struct bitbuff_writer *bw, i64 value, u8 num_bits); void bw_write_ibits(struct bitbuff_writer *bw, i64 value, u8 num_bits);
void bw_write_bit(struct bitbuff_writer *bw, u8 value); b32 bw_write_bit(struct bitbuff_writer *bw, u8 value);
void bw_write_uv(struct bitbuff_writer *bw, u64 value); void bw_write_uv(struct bitbuff_writer *bw, u64 value);
void bw_write_iv(struct bitbuff_writer *bw, i64 value); void bw_write_iv(struct bitbuff_writer *bw, i64 value);
@ -63,6 +63,12 @@ void bw_write_string(struct bitbuff_writer *bw, struct string s);
void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes); void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes);
#if BITBUFF_DEBUG
void bw_write_dbg_marker(struct bitbuff_writer *bw, struct string name);
#else
#define bw_write_dbg_marker(bw, name)
#endif
/* ========================== * /* ========================== *
* Reader * Reader
* ========================== */ * ========================== */
@ -108,6 +114,12 @@ u8 *br_read_bytes_raw(struct bitbuff_reader *br, u64 num_bytes);
void br_seek_bytes(struct bitbuff_reader *br, u64 num_bytes); void br_seek_bytes(struct bitbuff_reader *br, u64 num_bytes);
void br_seek_to_byte(struct bitbuff_reader *br, u64 pos); void br_seek_to_byte(struct bitbuff_reader *br, u64 pos);
#if BITBUFF_DEBUG
void br_read_dbg_marker(struct bitbuff_reader *br, struct string name);
#else
#define br_read_dbg_marker(br, name)
#endif
#if BITBUFF_TEST #if BITBUFF_TEST
void bitbuff_test(void); void bitbuff_test(void);
#endif #endif

View File

@ -60,7 +60,7 @@
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0 #define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0
/* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */ /* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */
#define BITBUFF_DEBUG 0 #define BITBUFF_DEBUG 1
#define BITBUFF_TEST RTC #define BITBUFF_TEST RTC
/* If enabled, things like network writes & memory allocations will be tracked in a global statistics struct */ /* If enabled, things like network writes & memory allocations will be tracked in a global statistics struct */

View File

@ -657,6 +657,8 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
{ {
__prof; __prof;
bw_write_dbg_marker(bw, LIT("SNAPSHOT START"));
bw_write_iv(bw, ss1->sim_dt_ns); bw_write_iv(bw, ss1->sim_dt_ns);
bw_write_iv(bw, ss1->sim_time_ns); bw_write_iv(bw, ss1->sim_time_ns);
@ -667,6 +669,7 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
/* Id bins */ /* Id bins */
/* TODO: Don't encode these */ /* TODO: Don't encode these */
bw_write_dbg_marker(bw, LIT("SNAPSHOT BINS"));
for (u64 i = 0; i < ss1->num_id_bins; ++i) { for (u64 i = 0; i < ss1->num_id_bins; ++i) {
u32 old_first = 0; u32 old_first = 0;
u32 old_last = 0; u32 old_last = 0;
@ -676,21 +679,15 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
old_last = old_bin->last; old_last = old_bin->last;
} }
struct sim_ent_bin *bin = &ss1->id_bins[i]; struct sim_ent_bin *bin = &ss1->id_bins[i];
u32 new_first = bin->first; b32 first_diff = bin->first != old_first;
u32 new_last = bin->last; b32 last_diff = bin->last != old_last;
if (new_first != old_first || new_last != old_last) { if (first_diff || last_diff) {
bw_write_bit(bw, 1); bw_write_bit(bw, 1);
bw_write_uv(bw, i); bw_write_uv(bw, i);
if (old_first == bin->first) { if (bw_write_bit(bw, first_diff)) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, bin->first); bw_write_uv(bw, bin->first);
} }
if (old_last == bin->last) { if (bw_write_bit(bw, last_diff)) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, bin->last); bw_write_uv(bw, bin->last);
} }
} }
@ -698,19 +695,18 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
bw_write_bit(bw, 0); bw_write_bit(bw, 0);
/* Ents */ /* Ents */
if (ss1->num_ents_allocated == ss0->num_ents_allocated) { bw_write_dbg_marker(bw, LIT("SNAPSHOT NUM ENTS"));
bw_write_bit(bw, 0); if (bw_write_bit(bw, ss1->num_ents_allocated != ss0->num_ents_allocated)) {
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, ss1->num_ents_allocated); bw_write_uv(bw, ss1->num_ents_allocated);
} }
if (ss1->num_ents_reserved == ss0->num_ents_reserved) { if (bw_write_bit(bw, ss1->num_ents_reserved != ss0->num_ents_reserved)) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, ss1->num_ents_reserved); bw_write_uv(bw, ss1->num_ents_reserved);
} }
for (u64 i = 0; i < ss1->num_ents_reserved; ++i) {
bw_write_dbg_marker(bw, LIT("SNAPSHOT ENTS"));
bw_write_dbg_marker(bw, STRING_FROM_STRUCT(&ss1->num_ents_reserved));
for (u64 i = 1; i < ss1->num_ents_reserved; ++i) {
struct sim_ent *e0 = sim_ent_nil(); struct sim_ent *e0 = sim_ent_nil();
if (i < ss0->num_ents_reserved) { if (i < ss0->num_ents_reserved) {
e0 = &ss0->ents[i]; e0 = &ss0->ents[i];
@ -718,6 +714,8 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
struct sim_ent *e1 = &ss1->ents[i]; struct sim_ent *e1 = &ss1->ents[i];
sim_ent_encode(bw, e0, e1); sim_ent_encode(bw, e0, e1);
} }
bw_write_dbg_marker(bw, LIT("SNAPSHOT END"));
} }
/* ========================== * /* ========================== *
@ -728,6 +726,8 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
{ {
__prof; __prof;
br_read_dbg_marker(br, LIT("SNAPSHOT START"));
ss->sim_dt_ns = br_read_iv(br); ss->sim_dt_ns = br_read_iv(br);
ss->sim_time_ns = br_read_iv(br); ss->sim_time_ns = br_read_iv(br);
@ -738,6 +738,7 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
/* Id bins */ /* Id bins */
/* TODO: Don't decode these, determine them implicitly from decoded ents */ /* TODO: Don't decode these, determine them implicitly from decoded ents */
br_read_dbg_marker(br, LIT("SNAPSHOT BINS"));
{ {
b32 bin_changed = br_read_bit(br); b32 bin_changed = br_read_bit(br);
while (bin_changed) { while (bin_changed) {
@ -760,10 +761,12 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
} }
/* Ents */ /* Ents */
br_read_dbg_marker(br, LIT("SNAPSHOT NUM ENTS"));
if (br_read_bit(br)) { if (br_read_bit(br)) {
ss->num_ents_allocated = br_read_uv(br); ss->num_ents_allocated = br_read_uv(br);
} }
if (br_read_bit(br)) { b32 num_ents_reserved_changed = br_read_bit(br);
if (num_ents_reserved_changed) {
u64 old_num_ents_reserved = ss->num_ents_reserved; u64 old_num_ents_reserved = ss->num_ents_reserved;
ss->num_ents_reserved = br_read_uv(br); ss->num_ents_reserved = br_read_uv(br);
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved; i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
@ -774,13 +777,22 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
*e = *sim_ent_nil(); *e = *sim_ent_nil();
e->ss = ss; e->ss = ss;
} }
} else if (reserve_diff < 0) {
/* TODO: Handle this */
/* NOTE: Should be impossible for snasphot reserve count to decrease at the moment */
ASSERT(false);
} }
} }
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
br_read_dbg_marker(br, LIT("SNAPSHOT ENTS"));
br_read_dbg_marker(br, STRING_FROM_STRUCT(&ss->num_ents_reserved));
for (u64 i = 1; i < ss->num_ents_reserved; ++i) {
struct sim_ent *e = &ss->ents[i]; struct sim_ent *e = &ss->ents[i];
e->ss = ss; e->ss = ss;
sim_ent_decode(br, e); sim_ent_decode(br, e);
} }
br_read_dbg_marker(br, LIT("SNAPSHOT END"));
} }

View File

@ -617,8 +617,6 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1) void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1)
{ {
struct sim_snapshot *ss = e1->ss; struct sim_snapshot *ss = e1->ss;
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. /* FIXME: Things like xforms need to be retreived manually rather than memcopied.
* This will also be true for things like ent handles once uids are implemented. */ * This will also be true for things like ent handles once uids are implemented. */
@ -630,10 +628,7 @@ void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_en
u64 chunk_size = min_u64(pos + 8, sizeof(*e1)) - pos; u64 chunk_size = min_u64(pos + 8, sizeof(*e1)) - pos;
u8 *chunk0 = (u8 *)e0 + pos; u8 *chunk0 = (u8 *)e0 + pos;
u8 *chunk1 = (u8 *)e1 + pos; u8 *chunk1 = (u8 *)e1 + pos;
if (MEMEQ(chunk0, chunk1, chunk_size)) { if (bw_write_bit(bw, MEMEQ(chunk0, chunk1, chunk_size))) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
u64 bits = 0; u64 bits = 0;
MEMCPY(&bits, chunk1, chunk_size); MEMCPY(&bits, chunk1, chunk_size);
bw_write_ubits(bw, bits, 64); bw_write_ubits(bw, bits, 64);
@ -663,6 +658,7 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
} }
} }
e->ss = old_ss; e->ss = old_ss;
} }
#else #else

View File

@ -1262,7 +1262,7 @@ void sim_step(struct sim_step_ctx *ctx)
if (publish_client->valid) { if (publish_client->valid) {
struct sim_snapshot *pub_world = sim_snapshot_from_tick(publish_client, world->tick); struct sim_snapshot *pub_world = sim_snapshot_from_tick(publish_client, world->tick);
if (!pub_world->valid) { if (!pub_world->valid) {
struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick); struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, world->tick - 1);
pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick); pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
/* Sync */ /* Sync */
sim_snapshot_sync_ents(pub_world, world, world_client->ent_id); sim_snapshot_sync_ents(pub_world, world, world_client->ent_id);

View File

@ -1880,16 +1880,17 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* TODO: Host system should allocate & copy string stored in local_listen_addr */ /* TODO: Host system should allocate & copy string stored in local_listen_addr */
//host_listen(host, local_listen_addr); //host_listen(host, local_listen_addr);
//host_listen(host, net_listen_addr); //host_listen(host, net_listen_addr);
#else
struct host *host = host_alloc(12345);
#endif #endif
(UNUSED)arg; (UNUSED)arg;
b32 is_master = false; b32 is_master = false;
struct host *host;
if (G.connect_address_str.len > 0) { if (G.connect_address_str.len > 0) {
host = host_alloc(0);
struct sock_address addr = sock_address_from_string(G.connect_address_str); struct sock_address addr = sock_address_from_string(G.connect_address_str);
host_queue_connect_to_address(host, addr); host_queue_connect_to_address(host, addr);
} else { } else {
host = host_alloc(12345);
is_master = true; is_master = true;
} }
@ -1909,16 +1910,40 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
i64 last_tick_from_master = 0;
i64 last_ticks_ahead_from_master = 0;
i64 last_publish_ns = 0; i64 last_publish_ns = 0;
i64 last_tick_ns = 0; i64 last_tick_ns = 0;
i64 step_dt_ns = NS_FROM_SECONDS(1) / SIM_TICKS_PER_SECOND; i64 step_dt_ns = NS_FROM_SECONDS(1) / SIM_TICKS_PER_SECOND;
i64 compute_dt_ns = step_dt_ns; f64 compute_timescale = 1.0;
while (!atomic_i32_eval(&G.local_sim_thread_shutdown)) { while (!atomic_i32_eval(&G.local_sim_thread_shutdown)) {
__profscope(local_sim_loop); __profscope(local_sim_loop);
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
{ {
__profscope(local_sim_sleep); __profscope(local_sim_sleep);
sleep_frame(last_tick_ns, compute_dt_ns); sleep_frame(last_tick_ns, step_dt_ns * compute_timescale);
last_tick_ns = sys_time_ns(); last_tick_ns = sys_time_ns();
} }
@ -2106,9 +2131,19 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Release unneeded user input snapshots */ /* Release unneeded user input snapshots */
sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->first_tick - 1); sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->first_tick - 1);
if (master_client->valid) {
last_tick_from_master = master_client->last_tick;
last_ticks_ahead_from_master = master_client->ack - last_tick_from_master;
if (last_ticks_ahead_from_master > 4) {
compute_timescale = 0.9;
} else if (last_ticks_ahead_from_master < 2) {
compute_timescale = 1.1;
} else {
compute_timescale = 1;
}
}
#if 0
/* Determine step tick */ /* Determine step tick */
u64 desired_step_tick = 0; u64 desired_step_tick = 0;
if (is_master) { if (is_master) {
@ -2120,12 +2155,29 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
num_predict_ticks += 2; /* Jitter buffer */ num_predict_ticks += 2; /* Jitter buffer */
desired_step_tick = master_client->last_tick + num_predict_ticks; desired_step_tick = master_client->last_tick + num_predict_ticks;
} }
#else
/* Snap to master sim tick if too far */
i64 num_sim_ticks = 1;
if (!is_master && math_abs_i64(last_ticks_ahead_from_master) > 50) {
i64 rtt_ns = master_client->rtt_ns;
f64 rtt_tick_ratio = (f64)(rtt_ns + (step_dt_ns - 1)) / (f64)step_dt_ns;
i64 num_predict_ticks = math_round_to_int64(rtt_tick_ratio) + 2;
i64 desired_step_tick = master_client->last_tick + num_predict_ticks;
sim_snapshot_release_ticks_in_range(local_client, desired_step_tick, U64_MAX);
sim_snapshot_release_ticks_in_range(user_input_client, desired_step_tick, U64_MAX);
num_sim_ticks = desired_step_tick - num_sim_ticks;
}
#endif
/* Create user input */ /* Create user input */
{ {
struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick); struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, local_client->last_tick + 1); struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, local_client->last_tick + num_sim_ticks);
struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID); struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
/* Find / create local control cmd ent */ /* Find / create local control cmd ent */
struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL); struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL);
@ -2184,9 +2236,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
user_input_client->ent_id = master_ss->local_client_ent; user_input_client->ent_id = master_ss->local_client_ent;
struct sim_snapshot *prev_world = sim_snapshot_alloc(local_client, master_ss, master_ss->tick); struct sim_snapshot *prev_world = sim_snapshot_alloc(local_client, master_ss, master_ss->tick);
/* FIXME: Don't take use desired_step_tick at face value. Dilate compute_dt to work towards it. */
i64 num_predict_ticks = desired_step_tick - master_ss->tick; i64 num_steps = (local_client->last_tick + num_sim_ticks) - master_ss->tick;
for (i64 i = 0; i < num_predict_ticks; ++i) { for (i64 i = 0; i < num_steps; ++i) {
ctx.world = sim_snapshot_alloc(local_client, prev_world, prev_world->tick + 1); ctx.world = sim_snapshot_alloc(local_client, prev_world, prev_world->tick + 1);
sim_step(&ctx); sim_step(&ctx);
prev_world = ctx.world; prev_world = ctx.world;