diff --git a/src/sim.c b/src/sim.c index c5daaf8d..25f54623 100644 --- a/src/sim.c +++ b/src/sim.c @@ -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_max_speed = 4; - e->control_torque = 5000; - //e->control_torque = F32_INFINITY; - //e->control_force_max_speed = F32_INFINITY; + //e->control_torque = 5000; + e->control_torque = F32_INFINITY; + 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) { 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. */ case SIM_CMD_KIND_CLIENT_CONTROL: { - struct v2 move = cmd->move_dir; - struct v2 focus = cmd->aim_dir; - if (v2_len_sq(move) > 1) { + struct sim_control old_control = client->control; + *control = cmd->control; + if (v2_len_sq(control->move) > 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; - if (cmd->is_firing) { - DEBUGBREAKABLE; + u32 flags = control->flags; + 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; - - case SIM_CMD_KIND_DRAG_OBJECT_START: - { - client->dbg_drag_start = true; - } break; - - case SIM_CMD_KIND_DRAG_OBJECT_STOP: - { - 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)); + if (flags & SIM_CONTROL_FLAG_CLEAR_ALL) { + test_clear_level(world); + } + if (flags & SIM_CONTROL_FLAG_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; @@ -683,7 +671,7 @@ struct sim_snapshot *sim_step(struct sim_snapshot_store *snapshot_store, struct if (client->valid) { ent->control = client->control; /* 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); } else { 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) { case SIM_CMD_KIND_CLIENT_CONTROL: { - bw_write_f32(bw, cmd->move_dir.x); - bw_write_f32(bw, cmd->move_dir.y); - bw_write_f32(bw, cmd->aim_dir.x); - bw_write_f32(bw, cmd->aim_dir.y); + bw_write_f32(bw, cmd->control.move.x); + bw_write_f32(bw, cmd->control.move.y); + bw_write_f32(bw, cmd->control.focus.x); + 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.y); - bw_write_bit(bw, cmd->is_firing); #if COLLIDER_DEBUG cmd->collider_gjk_steps = br_read_ubits(&br, 32); #endif @@ -1537,13 +1525,13 @@ void sim_cmd_frames_decode(struct arena *arena, struct host_event_array host_eve switch (cmd->kind) { case SIM_CMD_KIND_CLIENT_CONTROL: { - cmd->move_dir.x = br_read_f32(&br); - cmd->move_dir.y = br_read_f32(&br); - cmd->aim_dir.x = br_read_f32(&br); - cmd->aim_dir.y = br_read_f32(&br); + cmd->control.move.x = br_read_f32(&br); + cmd->control.move.y = br_read_f32(&br); + cmd->control.focus.x = 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.y = br_read_f32(&br); - cmd->is_firing = br_read_bit(&br); #if COLLIDER_DEBUG cmd->collider_gjk_steps = br_read_ubits(&br, 32); #endif diff --git a/src/sim.h b/src/sim.h index 6c5e14b6..e87eea21 100644 --- a/src/sim.h +++ b/src/sim.h @@ -1,8 +1,6 @@ #ifndef SIM_H #define SIM_H -#include "sim_ent.h" -#include "sim_snapshot.h" #include "bitbuff.h" struct sprite_startup_receipt; @@ -28,25 +26,6 @@ enum sim_cmd_kind { SIM_CMD_KIND_SIM_CLIENT_CONNECT, 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_DISCONNECT, SIM_CMD_KIND_SNAPSHOT, @@ -55,31 +34,39 @@ enum sim_cmd_kind { //SIM_CMD_KIND_ENTITY_CREATE, //SIM_CMD_KIND_ENTITY_DESTROY - - - - - - - - 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 *next; /* Cmd metadata */ enum sim_cmd_kind kind; - u64 tick; /* ====================================================================== */ /* SIM_CMD_KIND_CLIENT_CONTROL */ - struct v2 move_dir; - struct v2 aim_dir; struct v2 cursor_pos; - b32 is_firing; + struct sim_control control; #if RTC u32 collider_gjk_steps; @@ -181,6 +168,7 @@ void sim_ctx_release(struct sim_ctx *ctx); struct host; struct bitbuff; 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); /* ========================== * diff --git a/src/sim_ent.h b/src/sim_ent.h index e746a054..fdfa4374 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -1,6 +1,7 @@ #ifndef SIM_ENT_H #define SIM_ENT_H +#include "sim.h" #include "sprite.h" #include "mixer.h" #include "phys.h" @@ -76,12 +77,6 @@ struct sim_ent_lookup { 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 { /* ====================================================================== */ /* Metadata */ diff --git a/src/user.c b/src/user.c index 4bf5b7e9..a16a4414 100644 --- a/src/user.c +++ b/src/user.c @@ -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); /* 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) { .kind = SIM_CMD_KIND_CLIENT_CONTROL, - .move_dir = input_move_dir, - .aim_dir = input_aim_dir, + .control = control, .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 } - /* ========================== * - * 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(); } - - + /* Release old snapshots */ /* 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; 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 input_frames = ZI; + struct sim_cmd_frame_list raw_input_cmd_frames = ZI; { host_update(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) { - frame->tick = prev_ss->tick + 1; + struct sim_cmd_frame *frame = raw_input_cmd_frames.first; + 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 */ - 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 */ 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; { snapshot_cmd.kind = SIM_CMD_KIND_SNAPSHOT; - snapshot_cmd.tick = ss->tick; snapshot_cmd.snapshot_tick_start = ss0->tick; snapshot_cmd.snapshot_tick_end = ss1->tick; {