From f5a9733525158d6ff89dd4505e0644c3ada9ee0a Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 13 Jan 2026 14:01:54 -0600 Subject: [PATCH] send tile data via msgs separate from snapshots --- src/pp/pp.h | 38 +++-- src/pp/pp_sim/pp_sim_core.c | 234 ++++++++++++++++-------------- src/pp/pp_transcode.c | 5 - src/pp/pp_vis/pp_vis_core.c | 281 +++++++----------------------------- 4 files changed, 202 insertions(+), 356 deletions(-) diff --git a/src/pp/pp.h b/src/pp/pp.h index b34977d5..260b6471 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -192,6 +192,7 @@ Struct(P_World) P_FrameBin *frame_bins; P_Frame *first_free_frame; + u64 tiles_hash; u8 *tiles; }; @@ -219,7 +220,6 @@ Struct(P_DeltaNode) Struct(P_Snapshot) { u64 world_seed; - // i64 src_world_tick; i64 src_tick; i64 tick; i64 time_ns; @@ -233,34 +233,38 @@ Struct(P_Snapshot) i64 debug_draw_nodes_count; }; -Struct(P_SnapshotNode) -{ - P_SnapshotNode *next; - P_Snapshot snapshot; -}; - -Struct(P_SnapshotList) -{ - i64 count; - P_SnapshotNode *first; - P_SnapshotNode *last; -}; - //////////////////////////////////////////////////////////// //~ Message types Enum(P_MsgKind) { P_MsgKind_None, - P_MsgKind_Tile, + P_MsgKind_Tiles, }; Struct(P_Msg) { + P_MsgKind kind; + + u64 tiles_hash; Rng2I32 tile_range; u8 *raw_tiles; }; +Struct(P_MsgNode) +{ + P_MsgNode *next; + P_MsgNode *prev; + P_Msg msg; +}; + +Struct(P_MsgList) +{ + P_MsgNode *first; + P_MsgNode *last; + i64 count; +}; + //////////////////////////////////////////////////////////// //~ Collision types @@ -368,6 +372,7 @@ Enum(P_CmdKind) Struct(P_Cmd) { i64 tick; + b32 predicted; P_CmdKind kind; // Tile edit @@ -410,7 +415,8 @@ Struct(P_OutputState) { Arena *arena; - P_SnapshotList snapshots; + P_Snapshot snapshot; + P_MsgList msgs; }; //////////////////////////////////////////////////////////// diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index bf8e2ed2..de9fc616 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -36,7 +36,7 @@ void S_TickForever(WaveLaneCtx *lane) // FIXME: Header - Rng user_cmd_tick_range = RNG(0, SIM_TICKS_PER_SECOND * 0.5); + Rng user_cmd_tick_range = RNG(0, SIM_TICKS_PER_SECOND * 1.0); P_CmdList queued_user_cmds = Zi; P_CmdNode *first_free_user_cmd_node = 0; @@ -60,62 +60,16 @@ void S_TickForever(WaveLaneCtx *lane) P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 1); ResetArena(frame_arena); - ////////////////////////////// - //- Swap - - // { - // b32 swapin = IsSwappedIn(); - // b32 swapout = shutdown && IsSwappingOut(); - - // //- Swap in - // if (!world) - // { - // String packed = Zi; - // if (swapin) - // { - // packed = SwappedStateFromName(frame_arena, Lit("pp_sim.swp")); - // } - // P_UnpackedWorld unpacked = P_UnpackWorld(frame_arena, packed); - - // ResetArena(world_arena); - // world = PushStruct(world_arena, P_World); - // world->seed = unpacked.seed; - // world_frame->tick = unpacked.tick; - // world_frame->time_ns = unpacked.time_ns; - // if (world->seed == 0) - // { - // TrueRand(StringFromStruct(&world->seed)); - // } - - // world_frame->ent_bins_count = Kibi(16); - // world_frame->ent_bins = PushStructs(world_arena, P_EntBin, world_frame->ent_bins_count); - - // // Copy tiles - // world->tiles = PushStructsNoZero(world_arena, u8, P_TilesCount); - // CopyStructs(world->tiles, unpacked.tiles, P_TilesCount); - - // // Copy ents - // P_SpawnEntsFromList(world_arena, world, unpacked.ents); - // } - - // //- Swap out - // if (swapout) - // { - // String packed = P_PackWorld(frame_arena, world); - // WriteSwappedState(Lit("pp_sim.swp"), packed); - // } - // } - ////////////////////////////// //- Begin sim frame P_Frame *prev_world_frame = world->last_frame; P_Frame *world_frame = P_PushFrame(world, prev_world_frame, prev_world_frame->tick + 1); + b32 tiles_dirty = 0; // TDOO: Remove this P_ClearFrames(world, I64Min, prev_world_frame->tick - 1); - i64 frame_begin_ns = TimeNs(); i64 sim_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND; f64 sim_dt = SecondsFromNs(sim_dt_ns); @@ -139,7 +93,7 @@ void S_TickForever(WaveLaneCtx *lane) { 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 user cmds + // Prune queued user cmds { for (P_CmdNode *cmd_node = queued_user_cmds.first; cmd_node;) { @@ -184,10 +138,18 @@ void S_TickForever(WaveLaneCtx *lane) { for (P_CmdNode *src_cmd_node = queued_user_cmds.first; src_cmd_node; src_cmd_node = src_cmd_node->next) { - if (src_cmd_node->cmd.tick == world_frame->tick) + i64 cmd_tick = src_cmd_node->cmd.tick; + if (!src_cmd_node->cmd.predicted) + { + // We can execute unpredicted cmds this frame, since they don't + // need to be buffered to match predicted behavior + cmd_tick = world_frame->tick; + } + if (cmd_tick == world_frame->tick) { P_CmdNode *dst_cmd_node = PushStruct(frame_arena, P_CmdNode); dst_cmd_node->cmd = src_cmd_node->cmd; + dst_cmd_node->cmd.tick = cmd_tick; DllQueuePush(user_cmds.first, user_cmds.last, dst_cmd_node); ++user_cmds.count; } @@ -195,6 +157,57 @@ void S_TickForever(WaveLaneCtx *lane) } } + ////////////////////////////// + //- Swap + + { + b32 swapin = IsSwappedIn(); + b32 swapout = shutdown && IsSwappingOut(); + + //- Swap in + if (world->last_frame->tick == 1) + { + String packed = Zi; + if (swapin) + { + packed = SwappedStateFromName(frame_arena, Lit("pp_sim.swp")); + } + P_UnpackedWorld unpacked = P_UnpackWorld(frame_arena, packed); + + world_frame = P_PushFrame(world, &P_NilFrame, world->last_frame->tick); + + world->seed = unpacked.seed; + world_frame->time_ns = unpacked.time_ns; + if (world->seed == 0) + { + TrueRand(StringFromStruct(&world->seed)); + } + + // Copy tiles + CopyStructs(world->tiles, unpacked.tiles, P_TilesCount); + + // Spawn ents + P_SpawnEntsFromList(world_frame, unpacked.ents); + + // 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; + } + } + } + + //- Swap out + if (swapout) + { + String packed = P_PackWorld(frame_arena, world); + WriteSwappedState(Lit("pp_sim.swp"), packed); + } + } + ////////////////////////////// //- Update double-buffered entity data @@ -225,15 +238,13 @@ void S_TickForever(WaveLaneCtx *lane) // } ////////////////////////////// - //- Process user world delta commands + //- Process user edit commands // FIXME: Only accept world deltas from users that can edit // FIXME: Only apply relevant cmds based on tick - { - b32 tiles_dirty = 0; for (P_CmdNode *cmd_node = user_cmds.first; cmd_node; cmd_node = cmd_node->next) { P_Cmd *cmd = &cmd_node->cmd; @@ -266,13 +277,17 @@ void S_TickForever(WaveLaneCtx *lane) 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; + } + } } } - - // TODO: Hash tiles here - // if (tiles_dirty) - // { - // } } ////////////////////////////// @@ -1305,65 +1320,70 @@ void S_TickForever(WaveLaneCtx *lane) LockTicketMutex(&P.sim_output_back_tm); { P_OutputState *output = &P.sim_output_states[P.sim_output_back_idx]; - P_SnapshotNode *snapshot_node = PushStruct(output->arena, P_SnapshotNode); - P_Snapshot *snapshot = &snapshot_node->snapshot; - SllQueuePush(output->snapshots.first, output->snapshots.last, snapshot_node); - ++output->snapshots.count; - snapshot->world_seed = world->seed; - snapshot->tick = world_frame->tick; - snapshot->time_ns = world_frame->time_ns; - - // Push full tile delta - // if (!has_sent_initial_tick) - // { - // P_Delta *delta = 0; - // { - // P_DeltaNode *dn = PushStruct(output->arena, P_DeltaNode); - // snapshot->deltas_count += 1; - // SllQueuePush(snapshot->first_delta_node, snapshot->last_delta_node, dn); - // delta = &dn->delta; - // } - // delta->kind = P_DeltaKind_RawTiles; - // delta->raw_tiles = PushStructsNoZero(output->arena, u8, P_TilesCount); - // delta->tile_range = RNG2I32(VEC2I32(0, 0), VEC2I32(P_TilesPitch, P_TilesPitch)); - // CopyBytes(delta->raw_tiles, world->tiles, P_TilesCount); - // has_sent_initial_tick = 1; - // } - - // Push raw entity deltas - for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + // Build messages { - P_Delta *delta = 0; + // Push tiles + if (tiles_dirty) { - P_DeltaNode *dn = PushStruct(output->arena, P_DeltaNode); - snapshot->deltas_count += 1; - SllQueuePush(snapshot->first_delta_node, snapshot->last_delta_node, dn); - delta = &dn->delta; + P_Msg *msg = 0; + { + P_MsgNode *msg_node = PushStruct(output->arena, P_MsgNode); + DllQueuePush(output->msgs.first, output->msgs.last, msg_node); + ++output->msgs.count; + msg = &msg_node->msg; + } + msg->kind = P_MsgKind_Tiles; + msg->tiles_hash = world->tiles_hash; + msg->raw_tiles = PushStructsNoZero(output->arena, u8, P_TilesCount); + msg->tile_range = RNG2I32(VEC2I32(0, 0), VEC2I32(P_TilesPitch, P_TilesPitch)); + CopyBytes(msg->raw_tiles, world->tiles, P_TilesCount); + has_sent_initial_tick = 1; } - delta->kind = P_DeltaKind_RawEnt; - delta->ent = *ent; } - // Push debug draw information + // Build snapshot { - i64 dst_idx = 0; - snapshot->first_debug_draw_node = 0; - snapshot->last_debug_draw_node = 0; - snapshot->debug_draw_nodes_count = P_tl.debug_draw_nodes_count; - P_DebugDrawNode *dst_nodes = PushStructsNoZero(output->arena, P_DebugDrawNode, snapshot->debug_draw_nodes_count); - for (P_DebugDrawNode *src = P_tl.first_debug_draw_node; src; src = src->next) + P_Snapshot *snapshot = &output->snapshot; + + snapshot->world_seed = world->seed; + snapshot->tick = world_frame->tick; + snapshot->time_ns = world_frame->time_ns; + + // Push entity deltas + for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) { - P_DebugDrawNode *dst = &dst_nodes[dst_idx]; - *dst = *src; - dst_idx += 1; - SllQueuePush(snapshot->first_debug_draw_node, snapshot->last_debug_draw_node, dst); + P_Delta *delta = 0; + { + P_DeltaNode *dn = PushStruct(output->arena, P_DeltaNode); + snapshot->deltas_count += 1; + SllQueuePush(snapshot->first_delta_node, snapshot->last_delta_node, dn); + delta = &dn->delta; + } + delta->kind = P_DeltaKind_RawEnt; + delta->ent = *ent; } - ResetArena(P_tl.debug_arena); - P_tl.first_debug_draw_node = 0; - P_tl.last_debug_draw_node = 0; - P_tl.debug_draw_nodes_count = 0; + // Push debug draw information + { + i64 dst_idx = 0; + snapshot->first_debug_draw_node = 0; + snapshot->last_debug_draw_node = 0; + snapshot->debug_draw_nodes_count = P_tl.debug_draw_nodes_count; + P_DebugDrawNode *dst_nodes = PushStructsNoZero(output->arena, P_DebugDrawNode, snapshot->debug_draw_nodes_count); + for (P_DebugDrawNode *src = P_tl.first_debug_draw_node; src; src = src->next) + { + P_DebugDrawNode *dst = &dst_nodes[dst_idx]; + *dst = *src; + dst_idx += 1; + SllQueuePush(snapshot->first_debug_draw_node, snapshot->last_debug_draw_node, dst); + } + + ResetArena(P_tl.debug_arena); + P_tl.first_debug_draw_node = 0; + P_tl.last_debug_draw_node = 0; + P_tl.debug_draw_nodes_count = 0; + } } } UnlockTicketMutex(&P.sim_output_back_tm); diff --git a/src/pp/pp_transcode.c b/src/pp/pp_transcode.c index f1b0b6f4..8b071623 100644 --- a/src/pp/pp_transcode.c +++ b/src/pp/pp_transcode.c @@ -12,7 +12,6 @@ String P_PackWorld(Arena *arena, P_World *src_world) result.len += StringF(arena, "\n").len; result.len += StringF(arena, "seed: 0x%F\n", FmtHex(src_world->seed)).len; - result.len += StringF(arena, "tick: %F\n", FmtSint(src_frame->tick)).len; result.len += StringF(arena, "time: %F\n", FmtSint(src_frame->time_ns)).len; // Pack entities @@ -100,10 +99,6 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed) { result.seed = CR_IntFromString(top_item->value); } - if (MatchString(top_item->name, Lit("tick"))) - { - result.tick = CR_IntFromString(top_item->value); - } if (MatchString(top_item->name, Lit("time"))) { result.time_ns = CR_IntFromString(top_item->value); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 2022fa28..216a4fc3 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -639,117 +639,6 @@ void V_TickForever(WaveLaneCtx *lane) frame->ui_dims.y = MaxF32(frame->ui_dims.y, 64); frame->draw_dims = frame->ui_dims; - // ////////////////////////////// - // //- 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 snapshots - - // // FIXME: Only apply latest snapshot - - - - // // FIXME: Real ping - // i64 ping_ns = NsFromSeconds(0.250); - - // // TODO: Remove this (testing) - - - - // // b32 received_unseen_tick = 0; - // // b32 tiles_dirty = 0; - // // b32 should_clear_particles = 0; - // // for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next) - // // { - // // P_Snapshot *snapshot = &n->snapshot; - // // if (snapshot->tick > world->tick) - // // { - // // world->seed = snapshot->seed; - // // world->tick = snapshot->tick; - // // world->time_ns = snapshot->time_ns; - // // for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) - // // { - // // P_Delta *delta = &dn->delta; - // // if (delta->kind == P_DeltaKind_Reset) - // // { - // // tiles_dirty = 1; - // // should_clear_particles = 1; - // // } - // // if (delta->kind == P_DeltaKind_RawTiles || delta->kind == P_DeltaKind_Tile) - // // { - // // tiles_dirty = 1; - // // } - // // P_UpdateWorldFromDelta(world, delta); - // // } - // // received_unseen_tick = 1; - // // } - // // } - - - // { - // P_SnapshotList sim_snapshots = sim_output->snapshots; - // P_UpdateWorldFromSnapshots(sim_world, sim_snapshots); - // } - - - - - - - - - - // ////////////////////////////// - // //- Update tiles from sim - - // { - // for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next) - // { - // P_Snapshot *snapshot = &n->snapshot; - // if (snapshot->tick > world->tick) - // { - // for (u64 placement_idx = 0; placement_idx < snapshot->tile_placements_count; ++placement_idx) - // { - // P_TilePlacement placement = snapshot->tile_placements[placement_idx]; - // Rng2I32 dirty_rect = P_UpdateTilesInPlaceFromPlacement(tiles, placement); - // G_CopyCpuToTexture( - // frame->cl, - // gpu_tiles, VEC3I32(dirty_rect.p0.x, dirty_rect.p0.y, 0), - // tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1), - // RNG3I32(VEC3I32(dirty_rect.p0.x, dirty_rect.p0.y, 0), VEC3I32(dirty_rect.p1.x, dirty_rect.p1.y, 1)) - // ); - // } - // } - // } - // } - - // ////////////////////////////// - // //- Update world from sim - - // if (sim_output->last_snapshot_node && sim_output->last_snapshot_node->snapshot.tick > world->tick) - // { - // ResetArena(world_arena); - // world = P_WorldFromSnapshot(world_arena, &sim_output->last_snapshot_node->snapshot); - // V.lookup = P_LookupFromWorld(world_arena, world); - - // // Copy sim debug info - // sim_debug_draw_descs_count = sim_output->debug_draw_descs_count; - // sim_debug_draw_descs = PushStructsNoZero(world_arena, P_DebugDrawDesc, sim_debug_draw_descs_count); - // CopyStructs(sim_debug_draw_descs, sim_output->debug_draw_descs, sim_debug_draw_descs_count); - // } - ////////////////////////////// //- Process controller events into vis cmds @@ -2631,10 +2520,6 @@ void V_TickForever(WaveLaneCtx *lane) } } - - - - ////////////////////////////// //- Pop sim output @@ -2651,80 +2536,58 @@ void V_TickForever(WaveLaneCtx *lane) UnlockTicketMutex(&P.sim_output_back_tm); ////////////////////////////// - //- Apply sim snapshots - - // FIXME: Only apply latest snapshot - - - // TODO: Remove this (testing) - - - - // b32 received_unseen_tick = 0; - // b32 tiles_dirty = 0; - // b32 should_clear_particles = 0; - // for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next) - // { - // P_Snapshot *snapshot = &n->snapshot; - // if (snapshot->tick > world->tick) - // { - // world->seed = snapshot->seed; - // world->tick = snapshot->tick; - // world->time_ns = snapshot->time_ns; - // for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) - // { - // P_Delta *delta = &dn->delta; - // if (delta->kind == P_DeltaKind_Reset) - // { - // tiles_dirty = 1; - // should_clear_particles = 1; - // } - // if (delta->kind == P_DeltaKind_RawTiles || delta->kind == P_DeltaKind_Tile) - // { - // tiles_dirty = 1; - // } - // P_UpdateWorldFromDelta(world, delta); - // } - // received_unseen_tick = 1; - // } - // } + //- Apply sim msgs // Apply msgs { - // P_Msg + for (P_MsgNode *msg_node = sim_output->msgs.first; msg_node; msg_node = msg_node->next) + { + P_Msg *msg = &msg_node->msg; + + //- 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 snapshot + ////////////////////////////// + //- Apply sim snapshots + { - if (sim_output->snapshots.last && sim_output->snapshots.last->snapshot.tick > sim_world->last_frame->tick) + P_Snapshot *snapshot = &sim_output->snapshot; + b32 skip_snapshot = 0; + skip_snapshot = snapshot->tick < sim_world->last_frame->tick; + if (!skip_snapshot) { - P_Snapshot *snapshot = &sim_output->snapshots.last->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 + //- Apply deltas for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) { P_Delta *delta = &dn->delta; - // FIXME: Bounds check tile deltas - if (0) - { - } - //- Reset - // else if (delta->kind == P_DeltaKind_Reset) - // { - // // FIXME: Freelist entities - // dst_frame->ents_count = 0; - // dst_frame->first_ent = 0; - // dst_frame->last_ent = 0; - // ZeroStructs(sim_world->tiles, P_TilesCount); - // ZeroStructs(dst_frame->ent_bins, dst_frame->ent_bins_count); - // tiles_dirty = 1; - // } //- Raw ent - else if (delta->kind == P_DeltaKind_RawEnt) + if (delta->kind == P_DeltaKind_RawEnt) { P_Ent tmp_ent = delta->ent; P_EntListNode tmp_ent_node = Zi; @@ -2734,46 +2597,9 @@ void V_TickForever(WaveLaneCtx *lane) ent_list.last = &tmp_ent_node; P_SpawnEntsFromList(dst_frame, ent_list); } - //- Raw tiles - // else if (delta->kind == P_DeltaKind_RawTiles) - // { - // Rng2I32 range = delta->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 = delta->raw_tiles[src_tile_idx]; - - // Vec2 tile_pos = VEC2(tile_x, tile_y); - // i32 tile_idx = P_TileIdxFromTilePos(tile_pos); - // sim_world->tiles[tile_idx] = src_tile; - // } - // } - // tiles_dirty = 1; - // } - //- Tile range - // else if (delta->kind == P_DeltaKind_Tile) - // { - // P_TileKind tile = delta->tile_kind; - // Rng2I32 range = delta->tiles_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); - // sim_world->tiles[tile_idx] = (u8)tile; - // } - // } - // tiles_dirty = 1; - // } } - // Update sim debug info + //- Update sim debug info { ResetArena(sim_debug_arena); first_sim_debug_draw_node = 0; @@ -2790,19 +2616,7 @@ void V_TickForever(WaveLaneCtx *lane) } } } - - - // FIXME: Real prune - // for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) - // { - // ent->exists = 0; - // } } - - // TODO: Rehash statics - // if (tiles_dirty) - // { - // } } // TODO: Remove this @@ -2830,6 +2644,7 @@ void V_TickForever(WaveLaneCtx *lane) // 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; @@ -2874,6 +2689,12 @@ void V_TickForever(WaveLaneCtx *lane) // Predict P_Frame *predict_frame = 0; { + if (predict_world->tiles_hash != sim_world->tiles_hash) + { + predict_world->tiles_hash = sim_world->tiles_hash; + CopyStructs(predict_world->tiles, sim_world->tiles, P_TilesCount); + } + // i64 step_count = predict_to - sim_world->last_frame->tick; // // TODO: Preserve constraints? @@ -2912,20 +2733,24 @@ void V_TickForever(WaveLaneCtx *lane) //- Update blended world + b32 tiles_dirty = 0; + b32 should_clear_particles = 0; // TODO: Remove this P_Frame *blend_frame = 0; { + if (blend_world->tiles_hash != predict_world->tiles_hash) + { + blend_world->tiles_hash = predict_world->tiles_hash; + CopyStructs(blend_world->tiles, predict_world->tiles, P_TilesCount); + tiles_dirty = 1; + } + P_ClearFrames(blend_world, I64Min, I64Max); blend_frame = P_PushFrame(blend_world, predict_world->last_frame, predict_world->last_frame->tick); } - // FIXME: Compare tile hashes - b32 tiles_dirty = 0; - b32 should_clear_particles = 0; - -