sim ctx decoupling progress

This commit is contained in:
jacob 2025-02-18 13:49:40 -06:00
parent 253104b2ce
commit 3204e97dcf
4 changed files with 184 additions and 163 deletions

View File

@ -212,12 +212,11 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world)
//e->control_force = 500; //e->control_force = 500;
e->control_force = 500; e->control_force = 500;
e->control_force_max_speed = 4; e->control_force_max_speed = 4;
e->control_torque = 5000;
//e->control_torque = F32_INFINITY; //e->control_torque = 5000;
//e->control_force_max_speed = F32_INFINITY; e->control_torque = F32_INFINITY;
sim_ent_enable_prop(e, SIM_ENT_PROP_PHYSICAL_DYNAMIC); sim_ent_enable_prop(e, SIM_ENT_PROP_PHYSICAL_DYNAMIC);
@ -447,6 +446,7 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
if (!world->contact_lookup.arena.base) { if (!world->contact_lookup.arena.base) {
world->contact_lookup = sim_ent_lookup_alloc(4096); world->contact_lookup = sim_ent_lookup_alloc(4096);
} }
world->phys_iteration = prev_snapshot->phys_iteration;
@ -588,46 +588,34 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
* tad. */ * tad. */
case SIM_CMD_KIND_CLIENT_CONTROL: case SIM_CMD_KIND_CLIENT_CONTROL:
{ {
struct v2 move = cmd->move_dir; struct sim_control old_control = client->control;
struct v2 focus = cmd->aim_dir; *control = cmd->control;
if (v2_len_sq(move) > 1) { if (v2_len_sq(control->move) > 1) {
/* Cap movement vector magnitude at 1 */ /* Cap movement vector magnitude at 1 */
move = v2_norm(move); control->move = v2_norm(control->move);
} }
control->move = move;
control->focus = focus;
control->firing = cmd->is_firing;
client->cursor_pos = cmd->cursor_pos; client->cursor_pos = cmd->cursor_pos;
if (cmd->is_firing) { u32 flags = control->flags;
DEBUGBREAKABLE; if (flags & SIM_CONTROL_FLAG_DRAGGING) {
if (!(old_control.flags & SIM_CONTROL_FLAG_DRAGGING)) {
client->dbg_drag_start = true;
}
} else {
if (old_control.flags & SIM_CONTROL_FLAG_DRAGGING) {
client->dbg_drag_stop = true;
}
} }
} break; if (flags & SIM_CONTROL_FLAG_CLEAR_ALL) {
test_clear_level(world);
case SIM_CMD_KIND_DRAG_OBJECT_START: }
{ if (flags & SIM_CONTROL_FLAG_SPAWN_TEST) {
client->dbg_drag_start = true; logf_info("Spawning (test)");
} break; u32 count = 1;
f32 spread = 1;
case SIM_CMD_KIND_DRAG_OBJECT_STOP: for (u32 j = 0; j < count; ++j) {
{ spawn_test_entities(world, V2(0, (((f32)j / (f32)count) - 0.5) * spread));
client->dbg_drag_stop = true; }
} break;
/* Clear level */
case SIM_CMD_KIND_CLEAR_ALL:
{
test_clear_level(world);
} break;
/* Spawn test */
case SIM_CMD_KIND_SPAWN_TEST:
{
logf_info("Spawning (test)");
u32 count = 1;
f32 spread = 1;
for (u32 j = 0; j < count; ++j) {
spawn_test_entities(world, V2(0, (((f32)j / (f32)count) - 0.5) * spread));
} }
} break; } break;
@ -683,7 +671,7 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct
if (client->valid) { if (client->valid) {
ent->control = client->control; ent->control = client->control;
/* TODO: Move this */ /* TODO: Move this */
if (ent->control.firing) { if (ent->control.flags & SIM_CONTROL_FLAG_FIRING) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED); sim_ent_enable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
} else { } else {
sim_ent_disable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED); sim_ent_disable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
@ -1447,13 +1435,13 @@ void sim_cmd_frames_encode(struct bitbuff_writer *bw, struct sim_cmd_frame_list
switch (cmd->kind) { switch (cmd->kind) {
case SIM_CMD_KIND_CLIENT_CONTROL: case SIM_CMD_KIND_CLIENT_CONTROL:
{ {
bw_write_f32(bw, cmd->move_dir.x); bw_write_f32(bw, cmd->control.move.x);
bw_write_f32(bw, cmd->move_dir.y); bw_write_f32(bw, cmd->control.move.y);
bw_write_f32(bw, cmd->aim_dir.x); bw_write_f32(bw, cmd->control.focus.x);
bw_write_f32(bw, cmd->aim_dir.y); bw_write_f32(bw, cmd->control.focus.y);
bw_write_ubits(bw, cmd->control.flags, 32);
bw_write_f32(bw, cmd->cursor_pos.x); bw_write_f32(bw, cmd->cursor_pos.x);
bw_write_f32(bw, cmd->cursor_pos.y); bw_write_f32(bw, cmd->cursor_pos.y);
bw_write_bit(bw, cmd->is_firing);
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
cmd->collider_gjk_steps = br_read_ubits(&br, 32); cmd->collider_gjk_steps = br_read_ubits(&br, 32);
#endif #endif
@ -1537,13 +1525,13 @@ void sim_cmd_frames_decode(struct arena *arena, struct host_event_array host_eve
switch (cmd->kind) { switch (cmd->kind) {
case SIM_CMD_KIND_CLIENT_CONTROL: case SIM_CMD_KIND_CLIENT_CONTROL:
{ {
cmd->move_dir.x = br_read_f32(&br); cmd->control.move.x = br_read_f32(&br);
cmd->move_dir.y = br_read_f32(&br); cmd->control.move.y = br_read_f32(&br);
cmd->aim_dir.x = br_read_f32(&br); cmd->control.focus.x = br_read_f32(&br);
cmd->aim_dir.y = br_read_f32(&br); cmd->control.focus.y = br_read_f32(&br);
cmd->control.flags = br_read_ubits(&br, 32);
cmd->cursor_pos.x = br_read_f32(&br); cmd->cursor_pos.x = br_read_f32(&br);
cmd->cursor_pos.y = br_read_f32(&br); cmd->cursor_pos.y = br_read_f32(&br);
cmd->is_firing = br_read_bit(&br);
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
cmd->collider_gjk_steps = br_read_ubits(&br, 32); cmd->collider_gjk_steps = br_read_ubits(&br, 32);
#endif #endif

View File

@ -1,8 +1,6 @@
#ifndef SIM_H #ifndef SIM_H
#define SIM_H #define SIM_H
#include "sim_ent.h"
#include "sim_snapshot.h"
#include "bitbuff.h" #include "bitbuff.h"
struct sprite_startup_receipt; struct sprite_startup_receipt;
@ -28,25 +26,6 @@ enum sim_cmd_kind {
SIM_CMD_KIND_SIM_CLIENT_CONNECT, SIM_CMD_KIND_SIM_CLIENT_CONNECT,
SIM_CMD_KIND_SIM_CLIENT_DISCONNECT, SIM_CMD_KIND_SIM_CLIENT_DISCONNECT,
/* Testing */
SIM_CMD_KIND_CLEAR_ALL,
SIM_CMD_KIND_SPAWN_TEST,
SIM_CMD_KIND_PAUSE,
SIM_CMD_KIND_STEP,
SIM_CMD_KIND_DRAG_OBJECT_START,
SIM_CMD_KIND_DRAG_OBJECT_STOP,
SIM_CMD_KIND_CONNECT, SIM_CMD_KIND_CONNECT,
SIM_CMD_KIND_DISCONNECT, SIM_CMD_KIND_DISCONNECT,
SIM_CMD_KIND_SNAPSHOT, SIM_CMD_KIND_SNAPSHOT,
@ -55,31 +34,39 @@ enum sim_cmd_kind {
//SIM_CMD_KIND_ENTITY_CREATE, //SIM_CMD_KIND_ENTITY_CREATE,
//SIM_CMD_KIND_ENTITY_DESTROY //SIM_CMD_KIND_ENTITY_DESTROY
SIM_CMD_KIND_COUNT SIM_CMD_KIND_COUNT
}; };
enum sim_control_flag {
SIM_CONTROL_FLAG_NONE = 0,
SIM_CONTROL_FLAG_FIRING = 1 << 0,
/* Testing */
SIM_CONTROL_FLAG_CLEAR_ALL = 1 << 1,
SIM_CONTROL_FLAG_SPAWN_TEST = 1 << 2,
SIM_CONTROL_FLAG_PAUSE = 1 << 3,
SIM_CONTROL_FLAG_STEP = 1 << 4,
SIM_CONTROL_FLAG_DRAGGING = 1 << 5,
};
struct sim_control {
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
struct v2 focus; /* Focus direction vector (where does the controller want to look) */
u32 flags;
};
struct sim_cmd { struct sim_cmd {
struct sim_cmd *next; struct sim_cmd *next;
/* Cmd metadata */ /* Cmd metadata */
enum sim_cmd_kind kind; enum sim_cmd_kind kind;
u64 tick;
/* ====================================================================== */ /* ====================================================================== */
/* SIM_CMD_KIND_CLIENT_CONTROL */ /* SIM_CMD_KIND_CLIENT_CONTROL */
struct v2 move_dir;
struct v2 aim_dir;
struct v2 cursor_pos; struct v2 cursor_pos;
b32 is_firing; struct sim_control control;
#if RTC #if RTC
u32 collider_gjk_steps; u32 collider_gjk_steps;
@ -181,6 +168,7 @@ void sim_ctx_release(struct sim_ctx *ctx);
struct host; struct host;
struct bitbuff; struct bitbuff;
struct sim_snapshot; struct sim_snapshot;
struct sim_snapshot_store;
struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct sim_snapshot *prev_snapshot, struct sim_cmd_frame_list input_frames, i64 real_dt_ns); struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct sim_snapshot *prev_snapshot, struct sim_cmd_frame_list input_frames, i64 real_dt_ns);
/* ========================== * /* ========================== *

View File

@ -1,6 +1,7 @@
#ifndef SIM_ENT_H #ifndef SIM_ENT_H
#define SIM_ENT_H #define SIM_ENT_H
#include "sim.h"
#include "sprite.h" #include "sprite.h"
#include "mixer.h" #include "mixer.h"
#include "phys.h" #include "phys.h"
@ -76,12 +77,6 @@ struct sim_ent_lookup {
struct sim_ent_lookup_entry *first_free_entry; struct sim_ent_lookup_entry *first_free_entry;
}; };
struct sim_control {
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
struct v2 focus; /* Focus direction vector (where should the ent look) */
b32 firing;
};
struct sim_ent { struct sim_ent {
/* ====================================================================== */ /* ====================================================================== */
/* Metadata */ /* Metadata */

View File

@ -1438,22 +1438,44 @@ INTERNAL void user_update(void)
struct v2 input_aim_dir = v2_sub(G.world_cursor, sim_ent_get_xform(local_player).og); struct v2 input_aim_dir = v2_sub(G.world_cursor, sim_ent_get_xform(local_player).og);
/* Queue player control cmd */ /* Queue player control cmd */
if (!G.debug_camera) { {
i32 fire_presses = G.bind_states[USER_BIND_KIND_FIRE].num_presses - G.bind_states[USER_BIND_KIND_FIRE].num_releases; struct sim_control control = ZI;
if (!G.debug_camera) {
control.move = input_move_dir;
control.focus = input_aim_dir;
}
struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE];
struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG];
struct bind_state clear_state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
struct bind_state pause_state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
struct bind_state spawn_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
if ((fire_state.num_presses - fire_state.num_releases > 0) || fire_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_FIRING;
}
if ((drag_state.num_presses - drag_state.num_releases > 0) || drag_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_DRAGGING;
}
if (clear_state.num_presses) {
control.flags |= SIM_CONTROL_FLAG_CLEAR_ALL;
}
if (pause_state.num_presses) {
control.flags |= SIM_CONTROL_FLAG_PAUSE;
}
if (step_state.num_presses) {
control.flags |= SIM_CONTROL_FLAG_STEP;
}
if (spawn_state.num_presses) {
control.flags |= SIM_CONTROL_FLAG_SPAWN_TEST;
}
queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) { queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) {
.kind = SIM_CMD_KIND_CLIENT_CONTROL, .kind = SIM_CMD_KIND_CLIENT_CONTROL,
.move_dir = input_move_dir, .control = control,
.aim_dir = input_aim_dir,
.cursor_pos = G.world_cursor, .cursor_pos = G.world_cursor,
.is_firing = fire_presses > 0
});
}
/* Queue physics drag cmd */
i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases;
if (drag_presses != 0) {
queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) {
.kind = drag_presses > 0 ? SIM_CMD_KIND_DRAG_OBJECT_START : SIM_CMD_KIND_DRAG_OBJECT_STOP,
}); });
} }
@ -1469,52 +1491,6 @@ INTERNAL void user_update(void)
#endif #endif
} }
/* ========================== *
* Queue debug cmds
* ========================== */
{
/* Test clear world */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) {
.kind = SIM_CMD_KIND_CLEAR_ALL
});
}
}
/* Test pause */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) {
.kind = SIM_CMD_KIND_PAUSE
});
}
}
/* Test step */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
for (u32 i = 0; i < state.num_presses_and_repeats; ++i) {
queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) {
.kind = SIM_CMD_KIND_STEP
});
}
}
/* Test spawn */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_frame, (struct sim_cmd) {
.kind = SIM_CMD_KIND_SPAWN_TEST
});
}
}
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -1816,11 +1792,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
last_tick_ns = sys_time_ns(); last_tick_ns = sys_time_ns();
} }
/* Release old snapshots */
/* TODO: Remove this */ /* TODO: Remove this */
{ {
u64 keep_count = 40; u64 keep_count = 50;
u64 keep_tick = prev_ss->tick > keep_count ? prev_ss->tick - keep_count : 0; u64 keep_tick = prev_ss->tick > keep_count ? prev_ss->tick - keep_count : 0;
struct sim_snapshot *remss = sim_snapshot_from_tick(snapshot_store, snapshot_store->first_tick); struct sim_snapshot *remss = sim_snapshot_from_tick(snapshot_store, snapshot_store->first_tick);
@ -1835,27 +1810,103 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
} }
struct sim_cmd_frame_list raw_input_cmd_frames = ZI;
struct sim_cmd_frame_list input_frames = ZI;
{ {
host_update(host); host_update(host);
struct host_event_array host_events = host_pop_events(scratch.arena, host); struct host_event_array host_events = host_pop_events(scratch.arena, host);
sim_cmd_frames_decode(scratch.arena, host_events, &input_frames); sim_cmd_frames_decode(scratch.arena, host_events, &raw_input_cmd_frames);
} }
/* Automatically set all user cmd frames to current local sim tick */
/* FIXME: Only do this for local user cmds */
b32 should_break = false;
/* Merge cmd frames from user thread */
struct sim_cmd *user_control_cmd = NULL;
struct sim_cmd_frame user_cmd_frame = ZI;
struct sim_cmd_frame_list input_cmd_frames = ZI;
{ {
for (struct sim_cmd_frame *frame = input_frames.first; frame; frame = frame->next) { struct sim_cmd_frame *frame = raw_input_cmd_frames.first;
frame->tick = prev_ss->tick + 1; while (frame) {
struct sim_cmd_frame *next_frame = frame->next;
/* FIXME: Only do this for user cmds */
if (frame->tick == 0) {
/* All cmd frames from the user thread need to be merged into a single cmd frame representing inputs for one sim tick */
if (user_cmd_frame.tick == 0) {
user_cmd_frame = *frame;
user_cmd_frame.tick = prev_ss->tick + 1;
user_cmd_frame.next = NULL;
}
if (frame->ack > user_cmd_frame.ack) {
user_cmd_frame.ack = frame->ack;
}
struct sim_cmd *cmd = frame->first;
while (cmd) {
struct sim_cmd *next_cmd = cmd->next;
b32 should_insert = true;
if (cmd->kind == SIM_CMD_KIND_CLIENT_CONTROL) {
if (user_control_cmd) {
/* Merge with existing control cmd */
if (cmd->control.flags & SIM_CONTROL_FLAG_CLEAR_ALL) {
should_break = true;
DEBUGBREAKABLE;
}
should_insert = false;
u32 flags = user_control_cmd->control.flags;
*user_control_cmd = *cmd;
user_control_cmd->control.flags |= flags;
} else {
user_control_cmd = cmd;
}
}
if (should_insert) {
if (user_cmd_frame.last) {
user_cmd_frame.last->next = cmd;
} else {
user_cmd_frame.first = cmd;
}
user_cmd_frame.last = cmd;
}
cmd->next = NULL;
cmd = next_cmd;
}
} else {
if (input_cmd_frames.last) {
input_cmd_frames.last = frame;
} else {
input_cmd_frames.first = frame;
}
input_cmd_frames.last = frame;
}
frame->next = NULL;
frame = next_frame;
} }
} }
if (user_cmd_frame.tick != 0) {
if (input_cmd_frames.last) {
input_cmd_frames.last->next = &user_cmd_frame;
} else {
input_cmd_frames.first = &user_cmd_frame;
}
input_cmd_frames.last = &user_cmd_frame;
}
if (input_cmd_frames.first && input_cmd_frames.first->first && input_cmd_frames.first->first->control.flags & SIM_CONTROL_FLAG_CLEAR_ALL) {
DEBUGBREAKABLE;
} else if (should_break) {
DEBUGBREAKABLE;
}
/* Step */ /* Step */
struct sim_snapshot *ss = sim_step(snapshot_store, prev_ss, input_frames, target_dt_ns); struct sim_snapshot *ss = sim_step(snapshot_store, prev_ss, input_cmd_frames, target_dt_ns);
/* Publish snapshot cmds */ /* Publish snapshot cmds */
u64 oldest_ack_tick = 0; u64 oldest_ack_tick = 0;
@ -1875,7 +1926,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
struct sim_cmd snapshot_cmd = ZI; struct sim_cmd snapshot_cmd = ZI;
{ {
snapshot_cmd.kind = SIM_CMD_KIND_SNAPSHOT; snapshot_cmd.kind = SIM_CMD_KIND_SNAPSHOT;
snapshot_cmd.tick = ss->tick;
snapshot_cmd.snapshot_tick_start = ss0->tick; snapshot_cmd.snapshot_tick_start = ss0->tick;
snapshot_cmd.snapshot_tick_end = ss1->tick; snapshot_cmd.snapshot_tick_end = ss1->tick;
{ {