diff --git a/src/base/base.cgh b/src/base/base.cgh index b47602a4..12c7d525 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -525,10 +525,9 @@ #define IsNan(x) isnan(x) //- u128 -#if IsLanguageC - Struct(u128) { u64 lo; u64 hi; }; - #define U128(_hi, _lo) ((u128) { .hi = (_hi), .lo = (_lo) }) -#endif +Struct(u128) { u64 lo; u64 hi; }; +Inline u128 U128(u64 hi, u64 lo) { u128 result; result.hi = hi; result.lo = lo; return result; } +Inline b32 MatchU128(u128 a, u128 b) { return a.lo == b.lo && a.hi == b.hi; } //////////////////////////////////////////////////////////// //~ Atomics diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 95455264..bcfbb103 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -1006,8 +1006,10 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_CommandListHandle DllQueueRemove(gpu_arena->reset_resources.first, gpu_arena->reset_resources.last, resource); --gpu_arena->reset_resources.count; - D3D12_RESOURCE_DESC1 reset_d3d_desc = resource->d3d_desc; - D3D12_RESOURCE_DESC1 compare_d3d_desc = reset_d3d_desc; + D3D12_RESOURCE_DESC1 reset_d3d_desc = Zi; + D3D12_RESOURCE_DESC1 compare_d3d_desc = Zi; + CopyStruct(&reset_d3d_desc, &resource->d3d_desc); + CopyStruct(&compare_d3d_desc, &reset_d3d_desc); // Buffers can be reused if size fits if (d3d_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && reset_d3d_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) diff --git a/src/pp/pp.c b/src/pp/pp.c index 6f848a31..65ba1d29 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -16,17 +16,8 @@ Readonly P_Frame P_NilFrame = { void P_Bootstrap(void) { - // Initialize shared state - for (u64 i = 0; i < countof(P.sim_input_states); ++i) - { - P_InputState *input = &P.sim_input_states[i]; - input->arena = AcquireArena(Gibi(64)); - } - for (u64 i = 0; i < countof(P.sim_output_states); ++i) - { - P_OutputState *output = &P.sim_output_states[i]; - output->arena = AcquireArena(Gibi(64)); - } + P.u2s_msgs_arena = AcquireArena(Gibi(64)); + P.s2u_msgs_arena = AcquireArena(Gibi(64)); } //////////////////////////////////////////////////////////// @@ -73,6 +64,24 @@ u64 P_RandU64FromEnt(P_Ent *ent) return result; } +//////////////////////////////////////////////////////////// +//~ String helpers + +String P_StringFromEnt(P_Ent *ent) +{ + String result = Zi; + result.len = ent->string_len; + result.text = ent->string_text; + return result; +} + +void P_SetEntString(P_Ent *ent, String str) +{ + i64 len = MinI64(countof(ent->string_text), str.len); + CopyBytes(ent->string_text, str.text, len); + ent->string_len = len; +} + //////////////////////////////////////////////////////////// //~ Tile helpers @@ -1158,6 +1167,14 @@ void P_DebugDrawShape(P_Shape shape, Vec4 srgb) } } +//////////////////////////////////////////////////////////// +//~ Msg + +P_Msg *P_PushMsg(P_MsgKind kind, String data) +{ + // TODO +} + //////////////////////////////////////////////////////////// //~ World @@ -1362,7 +1379,7 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick) //////////////////////////////////////////////////////////// //~ Step -void P_StepFrame(P_Frame *frame, P_CmdList cmds) +void P_StepFrame(P_Frame *frame) { TempArena scratch = BeginScratchNoConflict(); P_World *world = frame->world; @@ -1379,32 +1396,6 @@ void P_StepFrame(P_Frame *frame, P_CmdList cmds) ent->prev_xf = ent->xf; } - ////////////////////////////// - //- Update ent controls - - // FIXME: Only apply relevant cmds based on tick - - for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) - { - ent->fire_presses = 0; - } - - for (P_CmdNode *cmd_node = cmds.first; cmd_node; cmd_node = cmd_node->next) - { - P_Cmd cmd = cmd_node->cmd; - if (cmd.kind == P_CmdKind_Control) - { - P_Ent *target = P_EntFromKey(frame, cmd.target); - if (!P_IsEntNil(target)) - { - target->move = ClampVec2Len(cmd.move, 1); - target->look = cmd.look; - target->fire_held = cmd.fire_held; - target->fire_presses += cmd.fire_presses; - } - } - } - ////////////////////////////// //- Spawn entities @@ -1797,7 +1788,7 @@ void P_StepFrame(P_Frame *frame, P_CmdList cmds) f32 mass_scale = 1.0; f32 impulse_scale = 0.0; - // TDOO: Do a relaxation pass without bias + // TODO: Do a relaxation pass without bias b32 apply_bias = 1; if (separation > 0.0) { diff --git a/src/pp/pp.h b/src/pp/pp.h index 701e42eb..443067a4 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -71,7 +71,6 @@ Struct(P_DebugDrawNode) Struct(P_Ent) { - ////////////////////////////// //- Internal world state P_Ent *next; @@ -80,18 +79,17 @@ Struct(P_Ent) P_Ent *next_in_bin; P_Ent *prev_in_bin; - ////////////////////////////// //- Persistent data P_Key key; u64 rand_seq; - ////////////////////////////// //- Build data f32 exists; b32 is_player; + b32 is_dummy; f32 health; Xform prev_xf; @@ -115,8 +113,16 @@ Struct(P_Ent) Vec2 hit_entry; Vec2 hit_entry_normal; - ////////////////////////////// - //- Solver data + //- User + + b32 is_user; + + P_Key player; + + u8 string_len; + u8 string_text[32]; + + //- Solver Vec2 solved_v; f32 solved_w; @@ -231,36 +237,36 @@ Struct(P_World) P_Frame *first_frame; P_Frame *last_frame; + P_Frame *first_free_frame; i64 frame_bins_count; P_FrameBin *frame_bins; - P_Frame *first_free_frame; u64 tiles_hash; u8 *tiles; }; //////////////////////////////////////////////////////////// -//~ Snapshot types +//~ Sim snapshot types -Enum(P_DeltaKind) +Enum(P_SimDeltaKind) { - P_DeltaKind_None, - P_DeltaKind_RawEnt, + P_SimDeltaKind_None, + P_SimDeltaKind_RawEnt, }; -Struct(P_Delta) +Struct(P_SimDelta) { - P_DeltaKind kind; + P_SimDeltaKind kind; P_Ent ent; }; -Struct(P_DeltaNode) +Struct(P_SimDeltaNode) { - P_DeltaNode *next; - P_Delta delta; + P_SimDeltaNode *next; + P_SimDelta delta; }; -Struct(P_Snapshot) +Struct(P_SimSnapshot) { u64 world_seed; i64 src_tick; @@ -268,12 +274,27 @@ Struct(P_Snapshot) i64 time_ns; i64 deltas_count; - P_DeltaNode *first_delta_node; - P_DeltaNode *last_delta_node; + P_SimDeltaNode *first_delta_node; + P_SimDeltaNode *last_delta_node; + i64 debug_draw_nodes_count; P_DebugDrawNode *first_debug_draw_node; P_DebugDrawNode *last_debug_draw_node; - i64 debug_draw_nodes_count; +}; + +//////////////////////////////////////////////////////////// +//~ User snapshot types + +Struct(P_UserSnapshot) +{ + P_Key user; + i64 src_tick; + i64 tick; + + Vec2 move; + Vec2 look; + b32 fire_held; + i32 fire_presses; }; //////////////////////////////////////////////////////////// @@ -282,16 +303,30 @@ Struct(P_Snapshot) Enum(P_MsgKind) { P_MsgKind_None, + + // User -> sim + P_MsgKind_SaveWorld, + P_MsgKind_ResetWorld, + P_MsgKind_TileEdit, + P_MsgKind_EntEdit, + + // Sim -> user P_MsgKind_Tiles, }; Struct(P_Msg) { P_MsgKind kind; + P_Key src_user; + P_Key dst_user; // If dst is 0, then cmd is meant to be broadcast - u64 tiles_hash; + P_TileKind tile_kind; Rng2I32 tile_range; - u8 *raw_tiles; + u64 tiles_hash; + + P_Ent ent; + + String data; }; Struct(P_MsgNode) @@ -361,94 +396,39 @@ Struct(P_RaycastResult) Vec2 p; Vec2 normal; }; - -//////////////////////////////////////////////////////////// -//~ Command types - -Enum(P_CmdKind) -{ - P_CmdKind_Nop, - P_CmdKind_SaveWorld, - P_CmdKind_ResetWorld, - P_CmdKind_TileEdit, - P_CmdKind_EntEdit, - P_CmdKind_Control, -}; - -Struct(P_Cmd) -{ - i64 tick; - b32 predicted; - P_CmdKind kind; - - // Tile edit - P_TileKind tile_kind; - Rng2I32 tile_range; - - // Ent edit - P_Ent ent; - - // Control - P_Key target; - Vec2 move; - Vec2 look; - b32 fire_held; - i32 fire_presses; -}; - -Struct(P_CmdNode) -{ - P_CmdNode *next; - P_CmdNode *prev; - P_Cmd cmd; -}; - -Struct(P_CmdList) -{ - i64 count; - P_CmdNode *first; - P_CmdNode *last; -}; - -Struct(P_InputState) -{ - Arena *arena; - - P_CmdList cmds; -}; - -Struct(P_OutputState) -{ - Arena *arena; - - P_Snapshot snapshot; - P_MsgList msgs; -}; - //////////////////////////////////////////////////////////// //~ State types Struct(P_Ctx) { - //- Sim input - TicketMutex sim_input_back_tm; - i32 sim_input_back_idx; - P_InputState sim_input_states[2]; + //- User -> sim messages + Arena *u2s_msgs_arena; + TicketMutex u2s_msgs_mutex; + P_MsgList u2s_msgs; - //- Sim output - TicketMutex sim_output_back_tm; - i32 sim_output_back_idx; - P_OutputState sim_output_states[2]; + //- Sim -> user messages + Arena *s2u_msgs_arena; + TicketMutex s2u_msgs_mutex; + P_MsgList s2u_msgs; + + //- Sim -> user snapshot + Arena *s2u_snapshot_arena; + TicketMutex s2u_snapshot_mutex; + P_SimSnapshot s2u_snapshot; }; Struct(P_ThreadLocalCtx) { - // TODO: Move this to world frame + //- Per-thread debug info Arena *debug_arena; b32 debug_draw_enabled; P_DebugDrawNode *first_debug_draw_node; P_DebugDrawNode *last_debug_draw_node; i64 debug_draw_nodes_count; + + //- Per-thread outbound messages + Arena *out_msgs_arena; + P_MsgList out_msgs; }; extern P_Ctx P; @@ -478,6 +458,12 @@ u64 P_RandU64FromEnt(P_Ent *ent); #define P_FmtKey(key) FmtHandle((key).v) +//////////////////////////////////////////////////////////// +//~ String helpers + +String P_StringFromEnt(P_Ent *ent); +void P_SetEntString(P_Ent *ent, String str); + //////////////////////////////////////////////////////////// //~ Tile helpers @@ -533,6 +519,11 @@ void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb); void P_DebugDrawRect(Rng2 rect, Vec4 srgb); void P_DebugDrawShape(P_Shape shape, Vec4 srgb); +//////////////////////////////////////////////////////////// +//~ Msg + +P_Msg *P_PushMsg(P_MsgKind kind, String data); + //////////////////////////////////////////////////////////// //~ World @@ -546,4 +537,4 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick); //////////////////////////////////////////////////////////// //~ Step -void P_StepFrame(P_Frame *frame, P_CmdList queued_cmds); +void P_StepFrame(P_Frame *frame); diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index fa7e1a02..bfae91ed 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -23,6 +23,7 @@ void S_TickForever(WaveLaneCtx *lane) Arena *perm = PermArena(); Arena *frame_arena = AcquireArena(Gibi(64)); P_tl.debug_arena = AcquireArena(Gibi(64)); + P_tl.out_msgs_arena = AcquireArena(Gibi(64)); P_World *world = P_AcquireWorld(); @@ -36,9 +37,9 @@ void S_TickForever(WaveLaneCtx *lane) // FIXME: Header - Rng user_cmd_tick_range = RNG(SIM_TICKS_PER_SECOND * -SIM_MAX_PING, SIM_TICKS_PER_SECOND * SIM_MAX_PING); - P_CmdList queued_user_cmds = Zi; - P_CmdNode *first_free_user_cmd_node = 0; + Rng user_msg_tick_range = RNG(SIM_TICKS_PER_SECOND * -SIM_MAX_PING, SIM_TICKS_PER_SECOND * SIM_MAX_PING); + P_MsgList queued_user_msgs = Zi; + P_MsgNode *first_free_user_msg_node = 0; @@ -67,95 +68,12 @@ void S_TickForever(WaveLaneCtx *lane) P_Frame *world_frame = P_PushFrame(world, prev_world_frame, prev_world_frame->tick + 1); b32 tiles_dirty = 0; - // TDOO: Remove this + // TODO: Remove this + // TODO: Keep old frames around for user snapshot deltas P_ClearFrames(world, I64Min, prev_world_frame->tick - 1); i64 frame_begin_ns = TimeNs(); - ////////////////////////////// - //- Pop commands - - P_InputState *input = 0; - LockTicketMutex(&P.sim_input_back_tm); - { - input = &P.sim_input_states[P.sim_input_back_idx]; - ++P.sim_input_back_idx; - if (P.sim_input_back_idx >= countof(P.sim_input_states)) - { - P.sim_input_back_idx = 0; - } - } - UnlockTicketMutex(&P.sim_input_back_tm); - - P_CmdList user_cmds = Zi; - { - i64 user_cmds_min_tick = world_frame->tick + user_cmd_tick_range.min; - i64 user_cmds_max_tick = world_frame->tick + user_cmd_tick_range.max; - // Prune queued user cmds - { - for (P_CmdNode *cmd_node = queued_user_cmds.first; cmd_node;) - { - P_CmdNode *next = cmd_node->next; - b32 prune = 0; - if (cmd_node->cmd.predicted && (cmd_node->cmd.tick < user_cmds_min_tick || cmd_node->cmd.tick > user_cmds_max_tick)) - { - prune = 1; - } - if (prune) - { - DllQueueRemove(queued_user_cmds.first, queued_user_cmds.last, cmd_node); - SllStackPush(first_free_user_cmd_node, cmd_node); - --queued_user_cmds.count; - } - cmd_node = next; - } - } - // Push user cmds to queue - { - for (P_CmdNode *src_cmd_node = input->cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) - { - if (!src_cmd_node->cmd.predicted || (src_cmd_node->cmd.tick >= user_cmds_min_tick && src_cmd_node->cmd.tick <= user_cmds_max_tick)) - { - P_CmdNode *dst_cmd_node = first_free_user_cmd_node; - if (dst_cmd_node) - { - SllStackPop(first_free_user_cmd_node); - ZeroStruct(dst_cmd_node); - } - else - { - dst_cmd_node = PushStruct(perm, P_CmdNode); - } - dst_cmd_node->cmd = src_cmd_node->cmd; - DllQueuePush(queued_user_cmds.first, queued_user_cmds.last, dst_cmd_node); - ++queued_user_cmds.count; - } - } - } - // Pop frame user cmds from queue - { - for (P_CmdNode *src_cmd_node = queued_user_cmds.first; src_cmd_node;) - { - P_CmdNode *next = src_cmd_node->next; - if (!src_cmd_node->cmd.predicted || src_cmd_node->cmd.tick == world_frame->tick) - { - { - P_CmdNode *dst_cmd_node = PushStruct(frame_arena, P_CmdNode); - dst_cmd_node->cmd = src_cmd_node->cmd; - DllQueuePush(user_cmds.first, user_cmds.last, dst_cmd_node); - ++user_cmds.count; - } - { - DllQueueRemove(queued_user_cmds.first, queued_user_cmds.last, src_cmd_node); - SllStackPush(first_free_user_cmd_node, src_cmd_node); - --queued_user_cmds.count; - } - } - src_cmd_node = next; - } - } - } - ////////////////////////////// //- Swap @@ -208,67 +126,257 @@ void S_TickForever(WaveLaneCtx *lane) } ////////////////////////////// - //- Process user edit commands + //- Pop messages from user - // FIXME: Only accept world deltas from users that can edit + P_MsgList in_msgs = Zi; + { + LockTicketMutex(&P.u2s_msgs_mutex); + { + for (P_MsgNode *src_msg_node = P.u2s_msgs.first; src_msg_node; src_msg_node = src_msg_node->next) + { + P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); + P_Msg *src_msg = &src_msg_node->msg; + P_Msg *dst_msg = &dst_msg_node->msg; + *dst_msg = *src_msg; + dst_msg->data = PushString(frame_arena, src_msg->data); + DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); + ++in_msgs.count; + } + ResetArena(P.u2s_msgs_arena); + ZeroStruct(&P.u2s_msgs); + } + UnlockTicketMutex(&P.u2s_msgs_mutex); + } - // FIXME: Only apply relevant cmds based on tick + ////////////////////////////// + //- Register users { - b32 should_save = 0; - for (P_CmdNode *cmd_node = user_cmds.first; cmd_node; cmd_node = cmd_node->next) + for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) { - P_Cmd *cmd = &cmd_node->cmd; - b32 allow = 0; - if (cmd->kind == P_CmdKind_SaveWorld) + P_Msg *msg = &msg_node->msg; + + P_Key user_key = msg->src_user; + P_Ent *user = P_EntFromKey(world_frame, user_key); + if (P_EntIsNil(user)) { - // FIXME: Only accept save from local user - should_save = 1; - } - if (cmd->kind == P_CmdKind_ResetWorld) - { - // TODO: Real reset - for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + P_EntList tmp_list = Zi; + user = P_PushTempEnt(frame_arena, &tmp_list); + user->key = user_key; + user->is_user = 1; + user->exists = 1; + + i32 min_name_len = 3; + i32 max_name_len = countof(user->string_text) - 8; + + // De-duplicate user name + String user_name = msg->data; + user_name = TrimWhitespace(user_name); + user_name.len = MinI64(user_name.len, max_name_len); + user_name = TrimWhitespace(user_name); + if (user_name.len < min_name_len) { - ent->exists = 0; + user_name = Lit("Player"); } - } - if (cmd->kind == P_CmdKind_EntEdit) - { - P_EntList ents = Zi; - P_Ent *dst = P_PushTempEnt(frame_arena, &ents); - *dst = cmd->ent; - P_SpawnEntsFromList(world_frame, ents); - } - if (cmd->kind == P_CmdKind_TileEdit) - { - P_TileKind tile = cmd->tile_kind; - Rng2I32 range = cmd->tile_range; - for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) { - for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + String orig_user_name = user_name; + i64 duplicate_id = 0; + while (duplicate_id < 1000) { - Vec2 tile_pos = VEC2(tile_x, tile_y); - i32 tile_idx = P_TileIdxFromTilePos(tile_pos); - world->tiles[tile_idx] = (u8)tile; - } - } - // Hash tiles - { - u64 old_tiles_hash = world->tiles_hash; - world->tiles_hash = HashString(STRING(P_TilesCount, world->tiles)); - if (world->tiles_hash != old_tiles_hash) - { - tiles_dirty = 1; + b32 is_duplicate = 0; + for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + if (ent->is_user && MatchString(P_StringFromEnt(ent), user_name)) + { + is_duplicate = 1; + break; + } + } + if (is_duplicate) + { + duplicate_id += 1; + user_name = StringF(frame_arena, "%F (%F)", FmtString(orig_user_name), FmtSint(duplicate_id)); + } + else + { + break; + } } } + P_SetEntString(user, user_name); + P_Msg *msg = P_PushMsg( + P_MsgKind_Chat, + StringF( + frame_arena, + "Player %F connected", + FmtString(user_name) + )); + ) + + P_SpawnEntsFromList(world_frame, tmp_list); + } + { + P_Msg *msg = P_PushMsg(P_MsgKind_RegisterSuccess, Zstr); + msg->dst_user = user->key; } } - // Save world - if (should_save) + } + + ////////////////////////////// + //- Apply user snapshots + + // P_MsgList user_msgs = Zi; + // { + // i64 user_msgs_min_tick = world_frame->tick + user_msg_tick_range.min; + // i64 user_msgs_max_tick = world_frame->tick + user_msg_tick_range.max; + // // Prune queued user msgs + // { + // for (P_MsgNode *msg_node = queued_user_msgs.first; msg_node;) + // { + // P_MsgNode *next = msg_node->next; + // b32 prune = 0; + // if (msg_node->msg.predicted && (msg_node->msg.tick < user_msgs_min_tick || msg_node->msg.tick > user_msgs_max_tick)) + // { + // prune = 1; + // } + // if (prune) + // { + // DllQueueRemove(queued_user_msgs.first, queued_user_msgs.last, msg_node); + // SllStackPush(first_free_user_msg_node, msg_node); + // --queued_user_msgs.count; + // } + // msg_node = next; + // } + // } + // // Push user msgs to queue + // { + // for (P_MsgNode *src_msg_node = input->msgs.first; src_msg_node; src_msg_node = src_msg_node->next) + // { + // if (!src_msg_node->msg.predicted || (src_msg_node->msg.tick >= user_msgs_min_tick && src_msg_node->msg.tick <= user_msgs_max_tick)) + // { + // P_MsgNode *dst_msg_node = first_free_user_msg_node; + // if (dst_msg_node) + // { + // SllStackPop(first_free_user_msg_node); + // ZeroStruct(dst_msg_node); + // } + // else + // { + // dst_msg_node = PushStruct(perm, P_MsgNode); + // } + // dst_msg_node->msg = src_msg_node->msg; + // DllQueuePush(queued_user_msgs.first, queued_user_msgs.last, dst_msg_node); + // ++queued_user_msgs.count; + // } + // } + // } + // // Pop frame user msgs from queue + // { + // for (P_MsgNode *src_msg_node = queued_user_msgs.first; src_msg_node;) + // { + // P_MsgNode *next = src_msg_node->next; + // if (!src_msg_node->msg.predicted || src_msg_node->msg.tick == world_frame->tick) + // { + // { + // P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); + // dst_msg_node->msg = src_msg_node->msg; + // DllQueuePush(user_msgs.first, user_msgs.last, dst_msg_node); + // ++user_msgs.count; + // } + // { + // DllQueueRemove(queued_user_msgs.first, queued_user_msgs.last, src_msg_node); + // SllStackPush(first_free_user_msg_node, src_msg_node); + // --queued_user_msgs.count; + // } + // } + // src_msg_node = next; + // } + // } + // } + + ////////////////////////////// + //- Process user edit messages + + // FIXME: Only accept edits from privileged users + + // { + // b32 should_save = 0; + // for (P_MsgNode *msg_node = user_msgs.first; msg_node; msg_node = msg_node->next) + // { + // P_Msg *msg = &msg_node->msg; + // b32 allow = 0; + // if (msg->kind == P_MsgKind_SaveWorld) + // { + // // FIXME: Only accept save from local user + // should_save = 1; + // } + // if (msg->kind == P_MsgKind_ResetWorld) + // { + // // TODO: Real reset + // for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + // { + // ent->exists = 0; + // } + // } + // if (msg->kind == P_MsgKind_EntEdit) + // { + // P_EntList ents = Zi; + // P_Ent *dst = P_PushTempEnt(frame_arena, &ents); + // *dst = msg->ent; + // P_SpawnEntsFromList(world_frame, ents); + // } + // if (msg->kind == P_MsgKind_TileEdit) + // { + // P_TileKind tile = msg->tile_kind; + // Rng2I32 range = msg->tile_range; + // for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + // { + // for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + // { + // Vec2 tile_pos = VEC2(tile_x, tile_y); + // i32 tile_idx = P_TileIdxFromTilePos(tile_pos); + // world->tiles[tile_idx] = (u8)tile; + // } + // } + // // Hash tiles + // { + // u64 old_tiles_hash = world->tiles_hash; + // world->tiles_hash = HashString(STRING(P_TilesCount, world->tiles)); + // if (world->tiles_hash != old_tiles_hash) + // { + // tiles_dirty = 1; + // } + // } + // } + // } + // // Save world + // if (should_save) + // { + // String path = Lit("..."); + // LogInfoF("Saving world to %F", FmtString(path)); + // } + // } + + ////////////////////////////// + //- Update ent controls + + for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + ent->fire_presses = 0; + } + + for (P_Ent *user = P_FirstEnt(frame); !P_IsEntNil(user); user = P_NextEnt(user)) + { + if (user->is_iser) { - String path = Lit("..."); - LogInfoF("Saving world to %F", FmtString(path)); + P_Ent *target = P_EntFromKey(user->player); + if (!P_IsEntNil(target)) + { + target->move = ClampVec2Len(user->move, 1); + target->look = user->look; + target->fire_held = user->fire_held; + target->fire_presses += user->fire_presses; + } } } @@ -276,12 +384,23 @@ void S_TickForever(WaveLaneCtx *lane) //- Step frame { - P_StepFrame(world_frame, user_cmds); + P_StepFrame(world_frame, user_msgs); } ////////////////////////////// //- Publish sim state + for (P_Ent *user = P_FirstEnt(world_frame); !P_IsEntNil(user); user = P_NextEnt(user)) + { + if (user->is_user) + { + P_Frame *src_frame = P_FrameFromTick(world, user->acked_tick); + if (user->is_local) + { + } + } + } + // TODO: Only copy active entities LockTicketMutex(&P.sim_output_back_tm); { diff --git a/src/pp/pp_transcode.c b/src/pp/pp_transcode.c index 8b071623..0529831f 100644 --- a/src/pp/pp_transcode.c +++ b/src/pp/pp_transcode.c @@ -33,6 +33,14 @@ String P_PackWorld(Arena *arena, P_World *src_world) { result.len += PushString(arena, Lit(" player\n")).len; } + if (ent->is_dummy) + { + result.len += PushString(arena, Lit(" dummy\n")).len; + } + if (ent->has_weapon) + { + result.len += PushString(arena, Lit(" has_weapon\n")).len; + } if (ent->is_bullet) { result.len += PushString(arena, Lit(" bullet\n")).len; @@ -120,6 +128,13 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed) if (MatchString(prop->value, Lit("player"))) { ent->is_player = 1; + } + if (MatchString(prop->value, Lit("dummy"))) + { + ent->is_dummy = 1; + } + if (MatchString(prop->value, Lit("has_weapon"))) + { ent->has_weapon = 1; } if (MatchString(prop->value, Lit("bullet"))) diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 86d6ce54..6f58c99a 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -41,25 +41,6 @@ V_Cmd *V_PushVisCmd(String name) return cmd; } -P_Cmd *V_PushSimCmd(P_CmdKind kind) -{ - Arena *perm = PermArena(); - P_CmdNode *n = V.first_free_sim_cmd_node; - if (n) - { - SllStackPop(V.first_free_sim_cmd_node); - ZeroStruct(n); - } - else - { - n = PushStruct(perm, P_CmdNode); - } - n->cmd.kind = kind; - DllQueuePush(V.sim_cmds.first, V.sim_cmds.last, n); - ++V.sim_cmds.count; - return &n->cmd; -} - String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey) { TempArena scratch = BeginScratch(arena); @@ -345,7 +326,7 @@ void V_PushNotif(String msg) notif->seq = V.first_notif->seq + 1; } SllQueuePushFront(V.first_notif, V.last_notif, notif); - LogInfoF("Notif: %F", FmtString(notif->msg)); + LogInfoF("[Notif] %F", FmtString(notif->msg)); } //////////////////////////////////////////////////////////// @@ -356,6 +337,7 @@ void V_TickForever(WaveLaneCtx *lane) Arena *perm = PermArena(); G_ArenaHandle gpu_perm = G_PermArena(); P_tl.debug_arena = AcquireArena(Gibi(64)); + P_tl.out_msgs_arena = AcquireArena(Gibi(64)); const i32 world_pitch = P_WorldPitch; const f32 zoom_rate = 1.50; @@ -366,9 +348,8 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Init vis state - Arena *sim_debug_arena = AcquireArena(Gibi(64)); - P_DebugDrawNode *first_sim_debug_draw_node = 0; - P_DebugDrawNode *last_sim_debug_draw_node = 0; + Arena *sim_snapshot_arena = AcquireArena(Gibi(64)); + P_SimSnapshot sim_snapshot = Zi; P_World *sim_world = P_AcquireWorld(); P_World *predict_world = P_AcquireWorld(); @@ -562,9 +543,9 @@ void V_TickForever(WaveLaneCtx *lane) frame->dt = SecondsFromNs(frame->dt_ns); frame->rand = prev_frame->rand; - if (P_IsKeyNil(V.player_key)) + if (P_IsKeyNil(V.user_key)) { - V.player_key = P_RandKey(); + TrueRand(StringFromStruct(&V.user_key)); } ////////////////////////////// @@ -596,7 +577,7 @@ void V_TickForever(WaveLaneCtx *lane) //- Transcode swap state if (swapout) { - BB_WriteUBits(&bw, V.player_key.v, 64); + BB_WriteUBits(&bw, V.user_key.v, 64); BB_WriteBit(&bw, prev_frame->is_editing); BB_WriteF32(&bw, prev_frame->edit_camera_pos.x); BB_WriteF32(&bw, prev_frame->edit_camera_pos.y); @@ -605,7 +586,7 @@ void V_TickForever(WaveLaneCtx *lane) } else { - V.player_key.v = BB_ReadUBits(&br, 64); + V.user_key.v = BB_ReadUBits(&br, 64); frame->is_editing = BB_ReadBit(&br); frame->edit_camera_pos.x = BB_ReadF32(&br); frame->edit_camera_pos.y = BB_ReadF32(&br); @@ -788,7 +769,8 @@ void V_TickForever(WaveLaneCtx *lane) Vec2 look_ratio = Zi; look_ratio.y = 0.5; look_ratio.x = look_ratio.y / (16.0 / 9.0); - P_Ent *player = P_EntFromKey(blend_world->last_frame, V.player_key); + P_Ent *user = P_EntFromKey(blend_world->last_frame, V.user_key); + P_Ent *player = P_EntFromKey(blend_world->last_frame, user->player); Vec2 player_center = P_WorldShapeFromEnt(player).centroid; Vec2 ui_center = MulVec2(frame->ui_dims, 0.5); Vec2 look = MulXformBasisV2(prev_frame->xf.ui_to_world, SubVec2(ui_frame->cursor_pos, ui_center)); @@ -934,16 +916,17 @@ void V_TickForever(WaveLaneCtx *lane) tile_range.p0 = Vec2I32FromVec(FloorVec2(MulXformV2(frame->xf.world_to_tile, prev_frame->world_selection.p0))); tile_range.p1 = Vec2I32FromVec(CeilVec2(MulXformV2(frame->xf.world_to_tile, prev_frame->world_selection.p1))); - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_TileEdit); - cmd->tile_kind = prev_frame->equipped_tile; - cmd->tile_range = tile_range; + P_Msg *msg = P_PushMsg(P_MsgKind_TileEdit, Zstr); + msg->tile_kind = prev_frame->equipped_tile; + msg->tile_range = tile_range; } } ////////////////////////////// //- Query entities - P_Ent *player = P_EntFromKey(blend_world->last_frame, V.player_key); + P_Ent *user = P_EntFromKey(blend_world->last_frame, V.user_key); + P_Ent *player = P_EntFromKey(blend_world->last_frame, user->player); P_Ent *hovered_ent = &P_NilEnt; { // TODO: Real world query @@ -2566,62 +2549,63 @@ void V_TickForever(WaveLaneCtx *lane) } } break; - case V_CmdKind_reset_world: - case V_CmdKind_spawn: - { - // Reset world - Vec2 player_pos = VEC2(5, 0); - if (kind == V_CmdKind_reset_world) - { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_ResetWorld); - } - else - { - player_pos = frame->world_cursor; - } - // Spawn player - { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_EntEdit); - P_Ent *ent = &cmd->ent; - *ent = P_NilEnt; - ent->key = V.player_key; - ent->xf = XformFromPos(player_pos); - ent->is_player = 1; - ent->has_weapon = 1; - ent->exists = 1; - } - } break; + // case V_CmdKind_reset_world: + // case V_CmdKind_spawn: + // { + // // Reset world + // Vec2 player_pos = VEC2(5, 0); + // if (kind == V_CmdKind_reset_world) + // { + // P_Msg *msg = P_PushMsg(P_MsgKind_ResetWorld, Zstr); + // } + // else + // { + // player_pos = frame->world_cursor; + // } + // // Spawn player + // { + // P_Msg *msg = P_PushMsg(P_MsgKind_EntEdit, Zstr); + // P_Ent *ent = &cmd->ent; + // *ent = P_NilEnt; + // ent->key = V.player_key; + // ent->xf = XformFromPos(player_pos); + // ent->is_player = 1; + // ent->has_weapon = 1; + // ent->exists = 1; + // } + // } break; - case V_CmdKind_spawn_dummy: - { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_EntEdit); - P_Ent *ent = &cmd->ent; - *ent = P_NilEnt; - ent->key = P_RandKey(); - ent->xf = XformFromPos(frame->world_cursor); - ent->is_player = 1; - ent->has_weapon = 1; - ent->exists = 1; - } break; + // case V_CmdKind_spawn_dummy: + // { + // P_Msg *msg = P_PushMsg(P_MsgKind_EntEdit, Zstr); + // P_Ent *ent = &cmd->ent; + // *ent = P_NilEnt; + // ent->key = P_RandKey(); + // ent->xf = XformFromPos(frame->world_cursor); + // ent->is_player = 1; + // ent->is_dummy = 1; + // ent->has_weapon = 1; + // ent->exists = 1; + // } break; - case V_CmdKind_delete: - { - if (!P_IsEntNil(hovered_ent)) - { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_EntEdit); - P_Ent *ent = &cmd->ent; - ent->key = hovered_ent->key; - ent->exists = 0; - } - } break; + // case V_CmdKind_delete: + // { + // if (!P_IsEntNil(hovered_ent)) + // { + // P_Msg *msg = P_PushMsg(P_MsgKind_EntEdit, Zstr); + // P_Ent *ent = &cmd->ent; + // ent->key = hovered_ent->key; + // ent->exists = 0; + // } + // } break; - case V_CmdKind_save_level: - { - if (frame->is_editing) - { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_SaveWorld); - } - } break; + // case V_CmdKind_save_level: + // { + // if (frame->is_editing) + // { + // P_Msg *msg = P_PushMsg(P_MsgKind_SaveWorld, Zstr); + // } + // } break; // case V_CmdKind_clear_particles: // { @@ -2635,9 +2619,169 @@ void V_TickForever(WaveLaneCtx *lane) } } + ////////////////////////////// + //- Pop messages from sim + + P_MsgList in_msgs = Zi; + { + LockTicketMutex(&P.s2u_msgs_mutex); + { + for (P_MsgNode *src_msg_node = P.s2u_msgs.first; src_msg_node; src_msg_node = src_msg_node->next) + { + P_MsgNode *dst_msg_node = PushStruct(frame->arena, P_MsgNode); + P_Msg *src_msg = &src_msg_node->msg; + P_Msg *dst_msg = &dst_msg_node->msg; + *dst_msg = *src_msg; + dst_msg->data = PushString(frame->arena, src_msg->data); + DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); + ++in_msgs.count; + } + ResetArena(P.s2u_msgs_arena); + ZeroStruct(&P.s2u_msgs); + } + UnlockTicketMutex(&P.s2u_msgs_mutex); + } + + ////////////////////////////// + //- Pop snapshot from sim + + { + LockTicketMutex(&P.s2u_snapshot_mutex); + P_SimSnapshot *src_snapshot = &P.s2u_snapshot; + if (src_snapshot->tick > sim_snapshot.tick) + { + ResetArena(sim_snapshot_arena); + ZeroStruct(&sim_snapshot); + sim_snapshot.world_seed = src_snapshot->world_seed; + sim_snapshot.src_tick = src_snapshot->src_tick; + sim_snapshot.tick = src_snapshot->tick; + sim_snapshot.time_ns = src_snapshot->time_ns; + { + //- Copy deltas + { + P_SimDeltaNode *dst_nodes = PushStructsNoZero(sim_snapshot_arena, P_SimDeltaNode, src_snapshot->deltas_count); + for (P_SimDeltaNode *src_delta_node = src_snapshot->first_delta_node; src_delta_node; src_delta_node = src_delta_node->next) + { + P_SimDeltaNode *dst_delta_node = &dst_nodes[sim_snapshot.deltas_count]; + *dst_delta_node = *src_delta_node; + SllQueuePush(sim_snapshot.first_delta_node, sim_snapshot.last_delta_node, dst_delta_node); + sim_snapshot.deltas_count += 1; + } + } + //- Copy debug info + { + P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_snapshot_arena, P_DebugDrawNode, src_snapshot->debug_draw_nodes_count); + for (P_DebugDrawNode *src = src_snapshot->first_debug_draw_node; src; src = src->next) + { + P_DebugDrawNode *dst = &dst_nodes[sim_snapshot.debug_draw_nodes_count]; + *dst = *src; + SllQueuePush(sim_snapshot.first_debug_draw_node, sim_snapshot.last_debug_draw_node, dst); + sim_snapshot.debug_draw_nodes_count += 1; + } + } + } + ResetArena(P.s2u_snapshot_arena); + ZeroStruct(&P.s2u_snapshot); + } + UnlockTicketMutex(&P.s2u_snapshot_mutex); + } + + ////////////////////////////// + //- Apply sim msgs + + { + for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) + { + P_Msg *msg = &msg_node->msg; + + //- Chat + // if (msg->kind == P_MsgKind_Chat) + // { + + // } + + //- Tiles + if (msg->kind == P_MsgKind_Tiles && sim_world->tiles_hash != msg->tiles_hash) + { + // TODO: Remove this check. Allow non-whole-map tile ranges. + Rng2I32 range = msg->tile_range; + if (msg->data.len == P_TilesCount) + { + for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + { + i32 src_tile_y = tile_y - range.p0.y; + for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + { + i32 src_tile_x = tile_x - range.p0.x; + Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y); + i32 src_tile_idx = P_TileIdxFromTilePos(src_tile_pos); + u8 src_tile = msg->data.text[src_tile_idx]; + + Vec2 tile_pos = VEC2(tile_x, tile_y); + i32 tile_idx = P_TileIdxFromTilePos(tile_pos); + sim_world->tiles_hash = msg->tiles_hash; + sim_world->tiles[tile_idx] = src_tile; + } + } + } + } + } + } + + ////////////////////////////// + //- Apply sim snapshots + + // if (sim_snapshot.tick > sim_world->last_frame->tick) + // { + // P_Frame *src_frame = P_FrameFromTick(sim_world, snapshot->src_tick); + // P_Frame *dst_frame = P_PushFrame(sim_world, src_frame, snapshot->tick); + // sim_world->seed = snapshot->world_seed; + // dst_frame->time_ns = snapshot->time_ns; + + // //- Apply deltas + // for (P_SimDeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) + // { + // P_SimDelta *delta = &dn->delta; + // //- Raw ent + // if (delta->kind == P_SimDeltaKind_RawEnt) + // { + // P_Ent tmp_ent = delta->ent; + // P_EntListNode tmp_ent_node = Zi; + // tmp_ent_node.ent = tmp_ent; + // P_EntList ent_list = Zi; + // ent_list.first = &tmp_ent_node; + // ent_list.last = &tmp_ent_node; + // P_SpawnEntsFromList(dst_frame, ent_list); + // } + // } + + // //- Update sim debug info + // { + // ResetArena(sim_debug_arena); + // first_sim_debug_draw_node = 0; + // last_sim_debug_draw_node = 0; + // { + // i64 dst_idx = 0; + // P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, snapshot->debug_draw_nodes_count); + // for (P_DebugDrawNode *src = snapshot->first_debug_draw_node; src; src = src->next) + // { + // P_DebugDrawNode *dst = &dst_nodes[dst_idx]; + // *dst = *src; + // dst_idx += 1; + // SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst); + // } + // } + // } + // } + + // TODO: Remove this + P_ClearFrames(sim_world, I64Min, sim_world->last_frame->tick - 1); + P_Frame *sim_frame = sim_world->last_frame; + ////////////////////////////// //- Compute movement & look + if (frame->predict_to != prev_frame->predict_to) { Vec2 move = Zi; { @@ -2671,122 +2815,7 @@ void V_TickForever(WaveLaneCtx *lane) } ////////////////////////////// - //- Pop sim output - - P_OutputState *sim_output = 0; - LockTicketMutex(&P.sim_output_back_tm); - { - sim_output = &P.sim_output_states[P.sim_output_back_idx]; - ++P.sim_output_back_idx; - if (P.sim_output_back_idx >= countof(P.sim_output_states)) - { - P.sim_output_back_idx = 0; - } - } - UnlockTicketMutex(&P.sim_output_back_tm); - - ////////////////////////////// - //- Apply sim msgs - - // Apply msgs - { - for (P_MsgNode *msg_node = sim_output->msgs.first; msg_node; msg_node = msg_node->next) - { - P_Msg *msg = &msg_node->msg; - - //- Chat - // if (msg->kind == P_MsgKind_Chat) - // { - - // } - - //- Tiles - if (msg->kind == P_MsgKind_Tiles && sim_world->tiles_hash != msg->tiles_hash) - { - Rng2I32 range = msg->tile_range; - for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) - { - i32 src_tile_y = tile_y - range.p0.y; - for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) - { - i32 src_tile_x = tile_x - range.p0.x; - Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y); - i32 src_tile_idx = P_TileIdxFromTilePos(src_tile_pos); - u8 src_tile = msg->raw_tiles[src_tile_idx]; - - Vec2 tile_pos = VEC2(tile_x, tile_y); - i32 tile_idx = P_TileIdxFromTilePos(tile_pos); - sim_world->tiles_hash = msg->tiles_hash; - sim_world->tiles[tile_idx] = src_tile; - } - } - } - } - } - - ////////////////////////////// - //- Apply sim snapshots - - { - P_Snapshot *snapshot = &sim_output->snapshot; - b32 skip_snapshot = 0; - skip_snapshot = snapshot->tick < sim_world->last_frame->tick; - if (!skip_snapshot) - { - P_Frame *src_frame = P_FrameFromTick(sim_world, snapshot->src_tick); - P_Frame *dst_frame = P_PushFrame(sim_world, src_frame, snapshot->tick); - sim_world->seed = snapshot->world_seed; - dst_frame->time_ns = snapshot->time_ns; - - //- Apply deltas - for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) - { - P_Delta *delta = &dn->delta; - //- Raw ent - if (delta->kind == P_DeltaKind_RawEnt) - { - P_Ent tmp_ent = delta->ent; - P_EntListNode tmp_ent_node = Zi; - tmp_ent_node.ent = tmp_ent; - P_EntList ent_list = Zi; - ent_list.first = &tmp_ent_node; - ent_list.last = &tmp_ent_node; - P_SpawnEntsFromList(dst_frame, ent_list); - } - } - - //- Update sim debug info - { - ResetArena(sim_debug_arena); - first_sim_debug_draw_node = 0; - last_sim_debug_draw_node = 0; - { - i64 dst_idx = 0; - P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, snapshot->debug_draw_nodes_count); - for (P_DebugDrawNode *src = snapshot->first_debug_draw_node; src; src = src->next) - { - P_DebugDrawNode *dst = &dst_nodes[dst_idx]; - *dst = *src; - dst_idx += 1; - SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst); - } - } - } - } - } - - // TODO: Remove this - P_ClearFrames(sim_world, I64Min, sim_world->last_frame->tick - 1); - P_Frame *sim_frame = sim_world->last_frame; - - - - - - - - ////////////////////////////// - //- Submit sim commands + //- Push user snapshot // FIXME: Real ping // f64 ping = 0.250; @@ -2794,27 +2823,31 @@ void V_TickForever(WaveLaneCtx *lane) i64 ping_ns = NsFromSeconds(ping); frame->predict_to = sim_world->last_frame->tick + MaxF64(CeilF64(ping * SIM_TICKS_PER_SECOND), 1.0); - - b32 should_send_sim_cmds = frame->predict_to != prev_frame->predict_to; - if (should_send_sim_cmds) + if (frame->predict_to != prev_frame->predict_to) { - // Push control cmd { - P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Control); - cmd->predicted = 1; - cmd->target = V.player_key; - cmd->move = frame->move; - cmd->look = frame->look; - cmd->fire_held = frame->fire_held; - cmd->fire_presses = frame->fire_presses; + P_UserSnapshot snapshot = Zi; + snapshot->user = V.user_user; + snapshot->src_tick = 0; + // FIXME: Generate snapshots for all new frames, not just last + snapshot->tick = frame->predict_to; + snapshot->move = frame->move; + snapshot->look = frame->look; + snapshot->fire_held = frame->fire_held; + snapshot->fire_presses = frame->fire_presses; } + } + ////////////////////////////// + //- Submit sim commands + + { LockTicketMutex(&P.sim_input_back_tm); { P_InputState *v2s = &P.sim_input_states[P.sim_input_back_idx]; - for (P_CmdNode *src_cmd_node = V.sim_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) + for (P_MsgNode *src_cmd_node = V.sim_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) { - P_CmdNode *dst_cmd_node = PushStruct(v2s->arena, P_CmdNode); + P_MsgNode *dst_cmd_node = PushStruct(v2s->arena, P_MsgNode); dst_cmd_node->cmd = src_cmd_node->cmd; dst_cmd_node->cmd.tick = frame->predict_to; DllQueuePush(v2s->cmds.first, v2s->cmds.last, dst_cmd_node); @@ -2855,12 +2888,12 @@ void V_TickForever(WaveLaneCtx *lane) // P_Frame *step_frame = P_PushFrame(predict_world, predict_world->last_frame, predict_world->last_frame->tick + 1); // // FIXME: Cmds - // P_CmdList step_cmds = Zi; - // for (P_CmdNode *src_cmd_node = V.sim_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) + // P_MsgList step_cmds = Zi; + // for (P_MsgNode *src_cmd_node = V.sim_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) // { // if (src_cmd_node->cmd.predicted && src_cmd_node->cmd.tick == step_frame->tick) // { - // P_CmdNode *dst_cmd_node = PushStruct(frame->arena, P_CmdNode); + // P_MsgNode *dst_cmd_node = PushStruct(frame->arena, P_MsgNode); // DllQueuePush(step_cmds.first, step_cmds.last, dst_cmd_node); // ++step_cmds.count; // } @@ -2921,22 +2954,6 @@ void V_TickForever(WaveLaneCtx *lane) // } - ////////////////////////////// - //- Reset queued sim cmds - - if (should_send_sim_cmds) - { - if (V.sim_cmds.first) - { - V.sim_cmds.last->next = V.first_free_sim_cmd_node; - V.first_free_sim_cmd_node = V.sim_cmds.first; - } - V.sim_cmds.first = 0; - V.sim_cmds.last = 0; - V.sim_cmds.count = 0; - } - - @@ -3670,7 +3687,26 @@ void V_TickForever(WaveLaneCtx *lane) } ////////////////////////////// - //- Prune ents + //- Prune sim cmds + + { + for (P_MsgNode *msg_node = V.sim_cmds.first; cmd_node;) + { + P_MsgNode *next = cmd_node->next; + { + if (!cmd_node->cmd.predicted || cmd_node->cmd.tick <= sim_world->last_frame->tick) + { + DllQueueRemove(V.sim_cmds.first, V.sim_cmds.last, cmd_node); + SllStackPush(V.first_free_sim_cmd_node, cmd_node); + --V.sim_cmds.count; + } + } + cmd_node = next; + } + } + + ////////////////////////////// + //- Prune sim ents { i64 ents_to_prune_count = 0; diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index b228fe1d..e7506c2d 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -298,7 +298,7 @@ Struct(V_Frame) Struct(V_Ctx) { - P_Key player_key; + P_Key user_key; i64 panels_count; i64 windows_count; @@ -309,10 +309,6 @@ Struct(V_Ctx) V_Notif *first_notif; V_Notif *last_notif; - // Sim commands - P_CmdList sim_cmds; - P_CmdNode *first_free_sim_cmd_node; - // Atomic monotonically increasing allocation counter sequence for GPU particle ring buffer u32 particle_seq; @@ -337,7 +333,6 @@ void V_Shutdown(void); V_Frame *V_CurrentFrame(void); V_Frame *V_PrevFrame(void); V_Cmd *V_PushVisCmd(String name); -P_Cmd *V_PushSimCmd(P_CmdKind kind); String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey); void V_PushParticles(V_Emitter src);