From 8e29fa447ba9c04f17163ad2df4b409d62358212 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 18 Jan 2026 00:59:49 -0600 Subject: [PATCH] server snapshot testing --- src/pp/pp.h | 6 +- src/pp/pp_sim/pp_sim_core.c | 191 ++++++++++++++++++++++-------------- src/pp/pp_transcode.c | 32 ++++-- src/pp/pp_vis/pp_vis_core.c | 114 +++++++++++++++------ 4 files changed, 226 insertions(+), 117 deletions(-) diff --git a/src/pp/pp.h b/src/pp/pp.h index 21660e86..859901d7 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -308,20 +308,19 @@ Struct(P_UserSnapshot) Enum(P_MsgKind) { P_MsgKind_None, + P_MsgKind_Raw, // Server <-> Client P_MsgKind_Chat, P_MsgKind_Connect, // Client -> Server - // P_MsgKind_UserSnapshot, P_MsgKind_SaveWorld, P_MsgKind_ResetWorld, P_MsgKind_TileEdit, P_MsgKind_EntEdit, // Server -> Client - // P_MsgKind_SimSnapshot, P_MsgKind_Tiles, }; @@ -331,9 +330,6 @@ Struct(P_Msg) NET_Key src; NET_Key dst; - // P_UserSnapshot user_snapshot; - // P_SimSnapshot sim_snapshot; - P_TileKind tile_kind; Rng2I32 tile_range; u64 tiles_hash; diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 1958102a..eca32808 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -167,76 +167,12 @@ void S_TickForever(WaveLaneCtx *lane) { NET_Key net_key = net_msg->sender; - String address_str = NET_StringFromKey(frame_arena, net_key); - LogDebugF("Received message from client \"%F\"", FmtString(address_str)); - - // String test_address_str = NET_StringFromKey(frame_arena, net_key); - // LogDebugF("Sending test msg to client \"%F\"", FmtString(test_address_str)); - // NET_Send(net_pipe, net_key, Lit("HIII"), NET_SendFlag_None); + // String address_str = NET_StringFromKey(frame_arena, net_key); + // LogDebugF("Received message from client \"%F\"", FmtString(address_str)); String packed = net_msg->data; P_MsgList client_msgs = P_UnpackMessages(frame_arena, packed, net_key); - // if (client_msgs.count > 0) - // { - // S_Client *client = S_ClientFromNetKey(net_key); - - // // Create client - // if (S_IsClientNil(client)) - // { - // P_Msg *msg = &client_msgs.first->msg; - // if (msg->kind == P_MsgKind_Connect) - // { - // u64 hash = NET_HashFromKey(net_key); - // S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count]; - - // String src_name = msg->data; - // src_name = TrimWhitespace(src_name); - // if (src_name.len < P_MinPlayerNameLen) - // { - // src_name = Lit("Player"); - // } - // src_name.len = MinI64(src_name.len, P_MaxPlayerNameLen); - - // // FIXME: Freelist client - // client = PushStruct(perm, S_Client); - // client->hash = hash; - // client->net_key = net_key; - // client->name_len = MinI64(countof(client->name_text), src_name.len); - // CopyBytes(client->name_text, src_name.text, client->name_len); - - // DllQueuePushNPZ(&S_NilClient, S.first_client, S.last_client, client, next, prev); - // DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin); - - // { - // P_Msg *out_msg = P_PushMsg(P_MsgKind_Connect, Zstr); - // out_msg->dst = net_key; - // } - - // { - // String name = STRING(client->name_len, client->name_text); - - // if (MatchString(name, src_name)) - // { - // LogDebugF("Client \"%F\" connecting with name \"%F\"", FmtString(address_str), FmtString(src_name)); - // } - // else - // { - // LogDebugF("Client \"%F\" connecting with name \"%F\" (reassigned to \"%F\")", FmtString(address_str), FmtString(src_name), FmtString(name)); - // } - - // P_Msg *out_msg = P_PushMsg( - // P_MsgKind_Chat, - // StringF( - // frame_arena, - // "Player %F is connecting", - // FmtString(name) - // )); - // } - // } - // } - // } - if (client_msgs.first) { if (in_msgs.last) @@ -269,8 +205,8 @@ void S_TickForever(WaveLaneCtx *lane) u64 hash = NET_HashFromKey(net_key); S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count]; - String src_name = msg->data; - src_name = TrimWhitespace(src_name); + String orig_src_name = msg->data; + String src_name = TrimWhitespace(orig_src_name); if (src_name.len < P_MinPlayerNameLen) { src_name = Lit("Player"); @@ -296,13 +232,13 @@ void S_TickForever(WaveLaneCtx *lane) // Broadcast player connection notification { String name = STRING(client->name_len, client->name_text); - if (MatchString(name, src_name)) + if (MatchString(name, orig_src_name)) { - LogDebugF("Client \"%F\" connecting with name \"%F\"", FmtString(address_str), FmtString(src_name)); + LogInfoF("Client \"%F\" connecting with name \"%F\"", FmtString(address_str), FmtString(name)); } else { - LogDebugF("Client \"%F\" connecting with name \"%F\" (reassigned to \"%F\")", FmtString(address_str), FmtString(src_name), FmtString(name)); + LogInfoF("Client \"%F\" connecting with name \"%F\" (reassigned to \"%F\")", FmtString(address_str), FmtString(orig_src_name), FmtString(name)); } P_Msg *out_msg = P_PushMsg( P_MsgKind_Chat, @@ -649,6 +585,113 @@ void S_TickForever(WaveLaneCtx *lane) // } // } + ////////////////////////////// + //- Send snapshots + + for (S_Client *client = S.first_client; !S_IsClientNil(client); client = client->next) + { + Struct(PackedDeltaNode) + { + PackedDeltaNode *next; + String packed; + }; + i64 total_delta_bytes = 0; + PackedDeltaNode *first_delta_node = 0; + PackedDeltaNode *last_delta_node = 0; + + //- Pack entity deltas + P_Frame *src_frame = &P_NilFrame; + for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + b32 should_transmit = 0; + BB_ResetWriter(&packer_bbw); + u64 delta_start = BB_GetNumBytesWritten(&packer_bbw); + { + // TODO: Compress + should_transmit = 1; + BB_WriteBytes(&packer_bbw, StringFromStruct(ent)); + } + u64 delta_end = BB_GetNumBytesWritten(&packer_bbw); + if (should_transmit) + { + String packed = Zi; + packed.text = BB_GetWrittenRaw(&packer_bbw) + delta_start; + packed.len = delta_end - delta_start; + { + PackedDeltaNode *delta_node = PushStruct(frame_arena, PackedDeltaNode); + delta_node->packed = PushString(frame_arena, packed); + SllQueuePush(first_delta_node, last_delta_node, delta_node); + total_delta_bytes += packed.len; + } + } + } + + // Collect deltas into snapshots + { + u64 max_snapshot_size = NET_PacketSize / 2; + PackedDeltaNode *delta_node = first_delta_node; + + u64 snapshot_start = 0; + b32 new_snapshot = 1; + b32 done = 0; + while (!done) + { + PackedDeltaNode *next_delta_node = delta_node ? delta_node->next : 0; + { + //- Init snapshot + if (new_snapshot) + { + new_snapshot = 0; + BB_ResetWriter(&packer_bbw); + snapshot_start = BB_GetNumBytesWritten(&packer_bbw); + BB_WriteBit(&packer_bbw, 1); // Raw + BB_WriteIV(&packer_bbw, src_frame->tick); + BB_WriteIV(&packer_bbw, world_frame->tick); + BB_WriteIV(&packer_bbw, world_frame->time_ns); + } + + //- Append packed delta + BB_WriteAlignToNextByte(&packer_bbw); + if (delta_node) + { + BB_WriteBytes(&packer_bbw, delta_node->packed); + } + + //- Submit snapshot + { + if (!delta_node || !next_delta_node) + { + new_snapshot = 1; + done = 1; + } + u64 next_len = 0; + if (next_delta_node) + { + next_len = next_delta_node->packed.len; + } + u64 cur_snapshot_len = BB_GetNumBytesWritten(&packer_bbw); + if ((cur_snapshot_len - snapshot_start) + next_len >= max_snapshot_size) + { + new_snapshot = 1; + } + } + if (new_snapshot) + { + u64 snapshot_end = BB_GetNumBytesWritten(&packer_bbw); + String snapshot = Zi; + snapshot.text = BB_GetWrittenRaw(&packer_bbw) + snapshot_start; + snapshot.len = snapshot_end - snapshot_start; + + // FIXME: Send raw snapshots + // NET_Send(net_pipe, client->net_key, snapshot, NET_SendFlag_Raw); + NET_Send(net_pipe, client->net_key, snapshot, NET_SendFlag_None); + } + } + delta_node = next_delta_node; + } + } + } + ////////////////////////////// //- Send messages @@ -688,11 +731,11 @@ void S_TickForever(WaveLaneCtx *lane) P_MsgList msgs = client->out_msgs; if (msgs.count > 0) { + BB_ResetWriter(&packer_bbw); String packed = P_PackMessages(&packer_bbw, msgs); - - String address_str = NET_StringFromKey(frame_arena, client->net_key); - LogDebugF("Sending message to client \"%F\"", FmtString(address_str)); + // String address_str = NET_StringFromKey(frame_arena, client->net_key); + // LogDebugF("Sending message to client \"%F\"", FmtString(address_str)); NET_Send(net_pipe, client->net_key, packed, NET_SendFlag_None); ZeroStruct(&client->out_msgs); diff --git a/src/pp/pp_transcode.c b/src/pp/pp_transcode.c index 037ffa07..bcc87fde 100644 --- a/src/pp/pp_transcode.c +++ b/src/pp/pp_transcode.c @@ -206,6 +206,7 @@ String P_PackMessages(BB_Writer *bbw, P_MsgList msgs) { // TODO: Compress P_Msg *msg = &msg_node->msg; + BB_WriteBit(bbw, 0); // Not raw BB_WriteBytes(bbw, StringFromStruct(msg)); BB_WriteString(bbw, msg->data); } @@ -225,23 +226,38 @@ P_MsgList P_UnpackMessages(Arena *arena, String packed, NET_Key sender) b32 done = 0; while (!done) { - u8 *msg_raw = BB_ReadBytesRaw(&bbr, sizeof(P_Msg)); - if (msg_raw != 0) + b32 is_raw = BB_ReadBit(&bbr); + if (is_raw) { - // Read msg header P_MsgNode *dst_msg_node = PushStruct(arena, P_MsgNode); - CopyStruct(&dst_msg_node->msg, msg_raw); DllQueuePush(result.first, result.last, dst_msg_node); result.count += 1; - // Read msg data string - String data_str = BB_ReadString(arena, &bbr); + dst_msg_node->msg.kind = P_MsgKind_Raw; dst_msg_node->msg.src = sender; dst_msg_node->msg.dst = NET_NilKey; - dst_msg_node->msg.data = data_str; + dst_msg_node->msg.data = PushString(arena, packed); + done = 1; } else { - done = 1; + u8 *msg_src = BB_ReadBytesRaw(&bbr, sizeof(P_Msg)); + if (msg_src != 0) + { + // Read msg header + P_MsgNode *dst_msg_node = PushStruct(arena, P_MsgNode); + CopyStruct(&dst_msg_node->msg, msg_src); + DllQueuePush(result.first, result.last, dst_msg_node); + result.count += 1; + // Read msg data string + String data_str = BB_ReadString(arena, &bbr); + dst_msg_node->msg.src = sender; + dst_msg_node->msg.dst = NET_NilKey; + dst_msg_node->msg.data = data_str; + } + else + { + done = 1; + } } } return result; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 2601bb1e..08408332 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -2629,29 +2629,29 @@ void V_TickForever(WaveLaneCtx *lane) // } // } 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_spawn_dummy: + { + P_Msg *msg = P_PushMsg(P_MsgKind_EntEdit, Zstr); + P_Ent *ent = &msg->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_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_delete: + { + if (!P_IsEntNil(hovered_ent)) + { + P_Msg *msg = P_PushMsg(P_MsgKind_EntEdit, Zstr); + P_Ent *ent = &msg->ent; + ent->key = hovered_ent->key; + ent->exists = 0; + } + } break; // case V_CmdKind_save_level: // { @@ -2670,8 +2670,6 @@ void V_TickForever(WaveLaneCtx *lane) { // V_PushNotif(Lit("Hello!!!")); P_Msg *chat_msg = P_PushMsg(P_MsgKind_Chat, Lit("Hello!!!")); - - } break; } } @@ -2701,7 +2699,7 @@ void V_TickForever(WaveLaneCtx *lane) { P_MsgNode tmp_msg_node = Zi; tmp_msg_node.msg.kind = P_MsgKind_Connect; - tmp_msg_node.msg.data = Lit("Guy"); + tmp_msg_node.msg.data = Lit("Bro"); P_MsgList tmp_msglist = Zi; tmp_msglist.count = 1; @@ -2734,8 +2732,8 @@ void V_TickForever(WaveLaneCtx *lane) { NET_Key net_key = net_msg->sender; - String address_str = NET_StringFromKey(frame->arena, net_key); - LogDebugF("Received message from server \"%F\"", FmtString(address_str)); + // String address_str = NET_StringFromKey(frame->arena, net_key); + // LogDebugF("Received message from server \"%F\"", FmtString(address_str)); if (NET_MatchKey(net_key, frame->desired_sim_key)) { @@ -2845,10 +2843,67 @@ void V_TickForever(WaveLaneCtx *lane) // UnlockTicketMutex(&P.s2v_snapshot_mutex); // } + ////////////////////////////// + //- Apply sim snapshots + + { + for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) + { + P_Msg *msg = &msg_node->msg; + + + //- Snapshot + if (msg->kind == P_MsgKind_Raw) + { + BB_Buff bb = BB_BuffFromString(msg->data); + BB_Reader bbr = BB_ReaderFromBuff(&bb); + + //- Read header + BB_ReadBit(&bbr); // Raw + i64 src_tick = BB_ReadIV(&bbr); + i64 dst_tick = BB_ReadIV(&bbr); + i64 time_ns = BB_ReadIV(&bbr); + + P_Frame *src_frame = P_FrameFromTick(sim_world, src_tick); + if (src_frame->tick == src_tick) + { + P_Frame *dst_frame = P_FrameFromTick(sim_world, dst_tick); + if (P_IsFrameNil(dst_frame)) + { + dst_frame = P_PushFrame(sim_world, src_frame, dst_tick); + } + dst_frame->time_ns = time_ns; + + //- Read deltas + BB_ReadAlignToNextByte(&bbr); + + b32 done = 0; + while (!done && BB_NumBitsRemaining(&bbr) > 0) + { + P_Ent *src_ent = (P_Ent *)BB_ReadBytesRaw(&bbr, sizeof(P_Ent)); + if (src_ent) + { + P_EntListNode tmp_ent_node = Zi; + CopyStruct(&tmp_ent_node.ent, src_ent); + P_EntList ent_list = Zi; + ent_list.first = &tmp_ent_node; + ent_list.last = &tmp_ent_node; + ++ent_list.count; + P_SpawnEntsFromList(dst_frame, ent_list); + } + else + { + done = 1; + } + } + } + } + } + } + ////////////////////////////// //- Apply sim msgs - P_Msg *newest_snapshot_msg = 0; { for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) { @@ -3086,7 +3141,6 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Update blended world - b32 tiles_dirty = 0; b32 should_clear_particles = 0; @@ -3744,7 +3798,7 @@ void V_TickForever(WaveLaneCtx *lane) // Upload tiles if (tiles_dirty) { - LogDebugF("Uploading tiles to gpu"); + // LogDebugF("Uploading tiles to gpu"); G_DumbMemoryLayoutSync(frame->cl, gpu_tiles, G_Layout_DirectQueue_CopyWrite); G_CopyCpuToTexture( frame->cl,