diff --git a/src/base/base_win32/base_win32.h b/src/base/base_win32/base_win32.h index a66ba422..8f57e14e 100644 --- a/src/base/base_win32/base_win32.h +++ b/src/base/base_win32/base_win32.h @@ -16,6 +16,7 @@ #include #include #include + #include #include #include #include diff --git a/src/net/net.h b/src/net/net.h index aece5091..1b3a7a46 100644 --- a/src/net/net.h +++ b/src/net/net.h @@ -1,8 +1,4 @@ -// NOTE: Burst messages with lengths exceeding packet size will degrade -// into sequenced messages - #define NET_PacketSize 1024 - #define NET_Ephemeral 0xFFFFFFFFFFFFFFFFull //////////////////////////////////////////////////////////// @@ -23,6 +19,17 @@ Struct(NET_Key) #define NET_NilKey ((NET_Key) { 0 }) #define NET_IsKeyNil(k) (MatchStructZero(&k)) +//////////////////////////////////////////////////////////// +//~ Send types + +Enum(NET_SendFlag) +{ + NET_SendFlag_None = 0, + + // NOTE: Messages marked "raw" that exceed packet size will drop + NET_SendFlag_Raw = (1 << 0), +}; + //////////////////////////////////////////////////////////// //~ Message types @@ -69,6 +76,6 @@ NET_PipeHandle NET_AcquirePipe(void); void NET_Bind(NET_PipeHandle pipe_handle, u64 port); NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle); -void NET_Push(NET_PipeHandle pipe_handle, NET_Key dst, String data, b32 burst); +void NET_Send(NET_PipeHandle pipe_handle, NET_Key dst, String data, NET_SendFlag flags); NET_PipeStatistics NET_StatsFromPipe(NET_PipeHandle pipe_handle); diff --git a/src/net/net_win32/net_win32.c b/src/net/net_win32/net_win32.c index 3edef48c..7365f596 100644 --- a/src/net/net_win32/net_win32.c +++ b/src/net/net_win32/net_win32.c @@ -46,8 +46,12 @@ struct sockaddr_in6 NET_W32_AddressFromKey(NET_Key key) void NET_W32_SignalWorker(void) { - // TODO: Only post if previous signal was seen - PostQueuedCompletionStatus(NET_W32.iocp, 0, 0, 0); + i64 signal = Atomic64Fetch(&NET_W32.signal); + if (Atomic64Fetch(&NET_W32.seen_signal) == signal) + { + Atomic64FetchAdd(&NET_W32.signal, 1); + PostQueuedCompletionStatus(NET_W32.iocp, 0, 0, 0); + } } NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key) @@ -122,7 +126,7 @@ void NET_W32_PostRecv(NET_W32_Pipe *pipe) pipe->iocp_count += 1; DWORD flags = 0; - i32 ret = WSARecvFrom( + WSARecvFrom( pipe->udp, &pipe->recv_wsabuff, 1, 0, @@ -249,7 +253,11 @@ NET_PipeHandle NET_AcquirePipe(void) void NET_Bind(NET_PipeHandle pipe_handle, u64 port) { NET_W32_Pipe *pipe = NET_W32_PipeFromHandle(pipe_handle); - Atomic64Set(&pipe->desired_port, port); + u64 prev_desired_port = Atomic64FetchSet(&pipe->desired_port, port); + if (prev_desired_port != port) + { + NET_W32_SignalWorker(); + } } NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle) @@ -270,7 +278,7 @@ NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle) return msg_buff->msgs; } -void NET_Push(NET_PipeHandle pipe_handle, NET_Key dst, String data, b32 burst) +void NET_Send(NET_PipeHandle pipe_handle, NET_Key dst, String data, NET_SendFlag flags) { NET_W32_Pipe *pipe = NET_W32_PipeFromHandle(pipe_handle); if (Atomic64Fetch(&pipe->desired_port) == 0) @@ -283,7 +291,7 @@ void NET_Push(NET_PipeHandle pipe_handle, NET_Key dst, String data, b32 burst) NET_W32_Cmd *cmd = PushStruct(cmd_buff->arena, NET_W32_Cmd); cmd->key = dst; cmd->data = PushString(cmd_buff->arena, data); - cmd->burst = burst; + cmd->send_flags = flags; SllQueuePush(cmd_buff->cmds.first, cmd_buff->cmds.last, cmd); ++cmd_buff->cmds.count; } @@ -371,27 +379,25 @@ void NET_W32_TickForever(WaveLaneCtx *lane) i32 timeout_ms = MsFromNs(passive_run_threshold_ns); if (wake_count > 0) { - // Keep processing without sleeping if we've already received a completion this frame + // Continue processing without sleeping if we've already received a completion this frame timeout_ms = 0; } // // NOTE: We're really only using IOCP so that we have a way to wake // the worker mid-wait without having to use WSAPoll + a dummy socket. // This is because any data sent to that dummy socket will itself be - // affected by network testing tools such as Clumsy, adding additional - // unpredictability. E.g. if Clumsy is set to add 50ms of artificial - // and drop 10% of packets on loopback, attempts to wake the worker - // thread so that it can process queued cmds will be affected as well. + // affected by network testing tools such as Clumsy. // ok = GetQueuedCompletionStatus(NET_W32.iocp, &len, &iocp_key, &ovl, timeout_ms); wake_count += 1; - if (!ok) + Atomic64Set(&NET_W32.seen_signal, Atomic64Fetch(&NET_W32.signal)); + } + i32 err = GetLastError(); + if (!ok) + { + if (err == WAIT_TIMEOUT) { - i32 err = GetLastError(); - if (err == WAIT_TIMEOUT) - { - done = 1; - } + done = 1; } } @@ -399,6 +405,7 @@ void NET_W32_TickForever(WaveLaneCtx *lane) { NET_W32_Pipe *pipe = (NET_W32_Pipe *)ovl; pipe->iocp_count -= 1; + if (ok) { String recv = STRING(len, (u8 *)pipe->recv_wsabuff.buf); @@ -551,8 +558,11 @@ void NET_W32_TickForever(WaveLaneCtx *lane) } } } + } - // Re-post recv + // Re-post recv + if (err != ERROR_OPERATION_ABORTED) + { NET_W32_PostRecv(pipe); } } @@ -586,6 +596,8 @@ void NET_W32_TickForever(WaveLaneCtx *lane) (pipe->last_attempted_bind_ns == 0 || now_ns - pipe->last_attempted_bind_ns > bind_retry_threshold_ns) ) { + // LogDebugF("Binding to port \"%F\"", FmtUint(desired_port)); + b32 ok = 1; String port_str = StringF(scratch.arena, "%F", FmtUint(desired_port)); char *port_cstr = CstrFromString(scratch.arena, port_str); @@ -679,6 +691,32 @@ void NET_W32_TickForever(WaveLaneCtx *lane) ok = ioctlsocket(sock, FIONBIO, &nonblocking) == 0; } + //- Disable ICMP reporting + { + DWORD bytes = 0; + b32 report = 0; + int rc = WSAIoctl( + sock, + SIO_UDP_CONNRESET, + &report, sizeof(report), + 0, 0, + &bytes, + 0, 0 + ); + } + { + DWORD bytes = 0; + b32 report = 0; + int rc = WSAIoctl( + sock, + SIO_UDP_NETRESET, + &report, sizeof(report), + 0, 0, + &bytes, + 0, 0 + ); + } + //- Fetch bound port u64 bound_port = 0; { @@ -715,6 +753,8 @@ void NET_W32_TickForever(WaveLaneCtx *lane) // Post initial recv CreateIoCompletionPort((HANDLE)sock, NET_W32.iocp, 0, 0); + + NET_W32_PostRecv(pipe); } else @@ -835,7 +875,7 @@ void NET_W32_TickForever(WaveLaneCtx *lane) i64 msg_seq = ++peer->msg_seq; // LogDebugF("Queued msg with seq %F", FmtSint(msg_seq)); - // TODO: Burst packets + // TODO: Raw packets b32 is_msg_end = 0; while (!is_msg_end) diff --git a/src/net/net_win32/net_win32.h b/src/net/net_win32/net_win32.h index 1a0ad128..d1e73b46 100644 --- a/src/net/net_win32/net_win32.h +++ b/src/net/net_win32/net_win32.h @@ -7,7 +7,7 @@ Struct(NET_W32_Cmd) NET_Key key; String data; - b32 burst; + NET_SendFlag send_flags; }; Struct(NET_W32_CmdList) @@ -43,7 +43,7 @@ Enum(NET_W32_PacketFlag) NET_W32_PacketFlag_EndMsg = (1 << 0), NET_W32_PacketFlag_Heartbeat = (1 << 2), - // NET_W32_PacketFlag_Burst = (1 << 3), + // NET_W32_PacketFlag_Raw = (1 << 3), }; Struct(NET_W32_PacketHeader) @@ -136,7 +136,8 @@ Struct(NET_W32_Pipe) NET_W32_Pipe *next; NET_W32_Pipe *prev; - Atomic64 desired_port; // >64k means ephemeral + Atomic64 desired_port; // ports >64k become ephemeral + Atomic64 seen_desired_port; Atomic64 total_bytes_sent; Atomic64 total_bytes_received; @@ -184,6 +185,9 @@ Struct(NET_W32_Ctx) NET_W32_Packet *first_free_packet; HANDLE iocp; + + Atomic64 signal; + Atomic64 seen_signal; }; extern NET_W32_Ctx NET_W32; diff --git a/src/pp/pp.c b/src/pp/pp.c index 71666f27..ee6a5c4c 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -1166,6 +1166,49 @@ void P_DebugDrawShape(P_Shape shape, Vec4 srgb) } } + +void P_DebugDrawFrame(P_Frame *frame, Vec4 tint) +{ + if (P_tl.debug_draw_enabled) + { + for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + P_Shape world_shape = P_WorldShapeFromEnt(ent); + + // Draw aabb + { + Vec4 color = VEC4(0.4, 0.2, 0.2, 1); + Rng2 bb = P_BoundingBoxFromShape(world_shape); + P_DebugDrawRect(bb, color); + } + + // Draw shape + { + // Vec4 color = Color_Cyan; + // Vec4 color = VEC4(0.2, 0.4, 0.2, 1); + Vec4 color = MulVec4Vec4(VEC4(1, 1, 1, 1), tint); + P_DebugDrawShape(world_shape, color); + } + + // Draw rot + { + Vec4 color = VEC4(0.8, 0.8, 0.8, 1); + Vec2 p0 = world_shape.centroid; + Vec2 p1 = P_EdgePointFromShape(world_shape, UpFromXform(ent->xf)); + P_DebugDrawLine(p0, p1, color); + } + + // Draw look + { + Vec4 color = VEC4(0.4, 0.8, 0.4, 1); + Vec2 p0 = world_shape.centroid; + Vec2 p1 = P_EdgePointFromShape(world_shape, ent->control.look); + P_DebugDrawLine(p0, p1, color); + } + } + } +} + //////////////////////////////////////////////////////////// //~ Msg @@ -2038,47 +2081,6 @@ void P_StepFrame(P_Frame *frame) } } - ////////////////////////////// - //- Debug draw entities - - if (P_tl.debug_draw_enabled) - { - for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) - { - P_Shape world_shape = P_WorldShapeFromEnt(ent); - - // Draw aabb - { - Vec4 color = VEC4(0.4, 0.2, 0.2, 1); - Rng2 bb = P_BoundingBoxFromShape(world_shape); - P_DebugDrawRect(bb, color); - } - - // Draw shape - { - // Vec4 color = Color_Cyan; - Vec4 color = VEC4(0.2, 0.4, 0.2, 1); - P_DebugDrawShape(world_shape, color); - } - - // Draw rot - { - Vec4 color = VEC4(0.8, 0.8, 0.8, 1); - Vec2 p0 = world_shape.centroid; - Vec2 p1 = P_EdgePointFromShape(world_shape, UpFromXform(ent->xf)); - P_DebugDrawLine(p0, p1, color); - } - - // Draw look - { - Vec4 color = VEC4(0.4, 0.8, 0.4, 1); - Vec2 p0 = world_shape.centroid; - Vec2 p1 = P_EdgePointFromShape(world_shape, ent->control.look); - P_DebugDrawLine(p0, p1, color); - } - } - } - ////////////////////////////// //- End frame diff --git a/src/pp/pp.h b/src/pp/pp.h index 9c669fa2..21660e86 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -69,6 +69,9 @@ Struct(P_DebugDrawNode) // TODO: Pack efficiently, deduplicate redundant fields +#define P_MinPlayerNameLen 1 +#define P_MaxPlayerNameLen 24 + Struct(P_Control) { Vec2 move; @@ -128,7 +131,7 @@ Struct(P_Ent) NET_Key net; u8 string_len; - u8 string_text[32]; + u8 string_text[P_MaxPlayerNameLen + 8]; //- Solver @@ -308,6 +311,7 @@ Enum(P_MsgKind) // Server <-> Client P_MsgKind_Chat, + P_MsgKind_Connect, // Client -> Server // P_MsgKind_UserSnapshot, @@ -324,6 +328,7 @@ Enum(P_MsgKind) Struct(P_Msg) { P_MsgKind kind; + NET_Key src; NET_Key dst; // P_UserSnapshot user_snapshot; @@ -525,6 +530,7 @@ void P_DebugDrawPoint(Vec2 p, Vec4 srgb); void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb); void P_DebugDrawRect(Rng2 rect, Vec4 srgb); void P_DebugDrawShape(P_Shape shape, Vec4 srgb); +void P_DebugDrawFrame(P_Frame *frame, Vec4 tint); //////////////////////////////////////////////////////////// //~ Msg diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index f038f551..1958102a 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -157,56 +157,85 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Pop messages - u64 port = 22121; NET_Bind(net_pipe, port); - - - - - - P_MsgList in_msgs = Zi; { NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) { 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)); - - - // Create client - S_Client *client = S_ClientFromNetKey(net_key); - if (S_IsClientNil(client)) - { - u64 hash = NET_HashFromKey(net_key); - S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count]; - - // FIXME: Freelist client - client = PushStruct(perm, S_Client); - client->hash = hash; - client->net_key = net_key; - DllQueuePushNPZ(&S_NilClient, S.first_client, S.last_client, client, next, prev); - DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin); - - { - - } - } - - - - - + // 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 packed = net_msg->data; + P_MsgList client_msgs = P_UnpackMessages(frame_arena, packed, net_key); - P_MsgList client_msgs = P_UnpackMessages(frame_arena, packed); + // if (client_msgs.count > 0) + // { + // S_Client *client = S_ClientFromNetKey(net_key); - // FIXME: Set src user here based on net key (or maybe just attach net key to msg instead of user) + // // 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) { @@ -225,49 +254,66 @@ void S_TickForever(WaveLaneCtx *lane) } } + ////////////////////////////// + //- Connect clients + for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) + { + P_Msg *msg = &msg_node->msg; + NET_Key net_key = msg->src; + S_Client *client = S_ClientFromNetKey(net_key); + if (S_IsClientNil(client)) + { + String address_str = NET_StringFromKey(frame_arena, net_key); + 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); + // Acknowledge player connection + { + P_Msg *out_msg = P_PushMsg(P_MsgKind_Connect, Zstr); + out_msg->dst = net_key; + } - - // P_MsgList in_msgs = Zi; - // { - // NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); - // for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) - // { - // 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)); - - // NET_Push(net_pipe, net_key, Lit("HIII"), 0); - - // String packed = net_msg->data; - // P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); - // P_Msg *dst_msg = &dst_msg_node->msg; - // *dst_msg = P_UnpackMsg(frame_arena, packed); - // // FIXME: Set src user here based on net key - // // dst_msg->src_user = - // DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); - // ++in_msgs.count; - - - - // // { - // // LogDebugF( - // // "Server received msg (%F bytes): \"%F\"", - // // FmtUint(packed.len), - // // FmtString(packed) - // // ); - // // } - - // } - // } - - - + // Broadcast player connection notification + { + 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, + "\"%F\" connected", + FmtString(name) + )); + } + } + } ////////////////////////////// //- Process connection messages @@ -292,8 +338,8 @@ void S_TickForever(WaveLaneCtx *lane) // // FIXME: Set net key here - // i32 min_name_len = 3; - // i32 max_name_len = countof(user->string_text) - 8; + // i32 min_name_len = P_MinPlayerNameLen; + // i32 max_name_len = P_MaxPlayerNameLen; // // De-duplicate user name // String user_name = msg->data; @@ -526,9 +572,10 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Step frame - // { - // P_StepFrame(world_frame, user_msgs); - // } + { + P_StepFrame(world_frame); + P_DebugDrawFrame(world_frame, VEC4(0.2, 0.4, 0.2, 0.75)); + } ////////////////////////////// //- Push tile messages @@ -560,7 +607,7 @@ void S_TickForever(WaveLaneCtx *lane) // Arena *msgs_arena = P_tl.out_msgs_arena; // P_Msg *msg = P_PushMsg(P_MsgKind_SimSnapshot, Zstr); // msg->dst_user = user->key; - // msg->burst = 1; + // NET_SendFlag_None = 1; // P_SimSnapshot *snapshot = &msg->sim_snapshot; // { // snapshot->world_seed = world->seed; @@ -642,7 +689,12 @@ void S_TickForever(WaveLaneCtx *lane) if (msgs.count > 0) { String packed = P_PackMessages(&packer_bbw, msgs); - NET_Push(net_pipe, client->net_key, packed, 0); + + + 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); } } @@ -699,7 +751,7 @@ void S_TickForever(WaveLaneCtx *lane) // { // if (user->is_user) // { - // NET_Push(net_pipe, user->net, packed, msg->burst); + // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None); // } // } // } @@ -709,7 +761,7 @@ void S_TickForever(WaveLaneCtx *lane) // if (!NET_IsKeyNil(user->net)) // { // String packed = P_PackMessage(frame_arena, msg); - // NET_Push(net_pipe, user->net, packed, msg->burst); + // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None); // } // } // } @@ -732,7 +784,7 @@ void S_TickForever(WaveLaneCtx *lane) // { // if (user->is_user) // { - // NET_Push(net_pipe, user->net, packed, msg->burst); + // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None); // } // } // } @@ -742,7 +794,7 @@ void S_TickForever(WaveLaneCtx *lane) // if (!NET_IsKeyNil(user->net)) // { // String packed = P_PackMessage(frame_arena, msg); - // NET_Push(net_pipe, user->net, packed, msg->burst); + // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None); // } // } // } @@ -862,9 +914,28 @@ void S_TickForever(WaveLaneCtx *lane) P.s2v.arena = old_arena; P.s2v.gen = old_gen; } - ZeroStruct(P.s2v.arena); + ResetArena(P.s2v.arena); P.s2v.gen += 1; P.s2v.pipe_stats = NET_StatsFromPipe(net_pipe); + + { + i64 dst_idx = 0; + P.s2v.first_debug_draw_node = 0; + P.s2v.last_debug_draw_node = 0; + P.s2v.debug_draw_nodes_count = P_tl.debug_draw_nodes_count; + P_DebugDrawNode *dst_nodes = PushStructsNoZero(P.s2v.arena, P_DebugDrawNode, P.s2v.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(P.s2v.first_debug_draw_node, P.s2v.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.s2v_tm); } diff --git a/src/pp/pp_sim/pp_sim_core.h b/src/pp/pp_sim/pp_sim_core.h index ecd8d390..4733a0b0 100644 --- a/src/pp/pp_sim/pp_sim_core.h +++ b/src/pp/pp_sim/pp_sim_core.h @@ -12,6 +12,9 @@ Struct(S_Client) NET_Key net_key; P_MsgList out_msgs; + i32 name_len; + u8 name_text[P_MaxPlayerNameLen]; + u64 remote_tiles_hash; }; diff --git a/src/pp/pp_transcode.c b/src/pp/pp_transcode.c index 6d3cd353..037ffa07 100644 --- a/src/pp/pp_transcode.c +++ b/src/pp/pp_transcode.c @@ -217,7 +217,7 @@ String P_PackMessages(BB_Writer *bbw, P_MsgList msgs) return result; } -P_MsgList P_UnpackMessages(Arena *arena, String packed) +P_MsgList P_UnpackMessages(Arena *arena, String packed, NET_Key sender) { P_MsgList result = Zi; BB_Buff bb = BB_BuffFromString(packed); @@ -235,6 +235,8 @@ P_MsgList P_UnpackMessages(Arena *arena, String packed) 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 diff --git a/src/pp/pp_transcode.h b/src/pp/pp_transcode.h index 8825d095..de036c2d 100644 --- a/src/pp/pp_transcode.h +++ b/src/pp/pp_transcode.h @@ -33,4 +33,4 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed); //~ Message String P_PackMessages(BB_Writer *bbw, P_MsgList msgs); -P_MsgList P_UnpackMessages(Arena *arena, String packed); +P_MsgList P_UnpackMessages(Arena *arena, String packed, NET_Key sender); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 9b8a852e..2601bb1e 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -543,6 +543,8 @@ void V_TickForever(WaveLaneCtx *lane) frame->equipped_tile = prev_frame->equipped_tile; frame->edit_camera_pos = prev_frame->edit_camera_pos; frame->edit_camera_zoom = prev_frame->edit_camera_zoom; + frame->sim_key = prev_frame->sim_key; + frame->desired_sim_key = prev_frame->desired_sim_key; frame->tick = V.current_frame_tick; frame->time_ns = TimeNs(); @@ -659,6 +661,23 @@ void V_TickForever(WaveLaneCtx *lane) { s2v_gen = P.s2v.gen; sim_pipe_stats = P.s2v.pipe_stats; + + { + 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, P.s2v.debug_draw_nodes_count); + for (P_DebugDrawNode *src = P.s2v.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); + } + } + } } } UnlockTicketMutex(&P.s2v_tm); @@ -2657,6 +2676,47 @@ void V_TickForever(WaveLaneCtx *lane) } } + ////////////////////////////// + //- Try to connect to server + + frame->desired_sim_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121")); + if (!NET_MatchKey(frame->sim_key, frame->desired_sim_key)) + { + i64 now_ns = TimeNs(); + // i64 retry_rate_ns = NsFromSeconds(0.100); + i64 retry_rate_ns = NsFromSeconds(0); + + b32 should_try = 0; + if (!NET_MatchKey(prev_frame->desired_sim_key, frame->desired_sim_key)) + { + should_try = 1; + } + if (V.connect_try_ns == 0 || now_ns - V.connect_try_ns > retry_rate_ns) + { + should_try = 1; + } + + // if (should_try && now_ns > NsFromSeconds(1.5)) + if (should_try) + { + P_MsgNode tmp_msg_node = Zi; + tmp_msg_node.msg.kind = P_MsgKind_Connect; + tmp_msg_node.msg.data = Lit("Guy"); + + P_MsgList tmp_msglist = Zi; + tmp_msglist.count = 1; + tmp_msglist.first = &tmp_msg_node; + tmp_msglist.last = &tmp_msg_node; + + BB_ResetWriter(&packer_bbw); + String packed = P_PackMessages(&packer_bbw, tmp_msglist); + + // FIXME: Real connection packet + NET_Send(net_pipe, frame->desired_sim_key, packed, NET_SendFlag_None); + V.connect_try_ns = now_ns; + } + } + ////////////////////////////// //- Pop messages from sim @@ -2667,35 +2727,42 @@ void V_TickForever(WaveLaneCtx *lane) // FIXME: Reject messages if not from currently connected sim - - - P_MsgList in_msgs = Zi; { NET_MsgList net_msgs = NET_Swap(frame->arena, net_pipe); for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) { 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 packed = net_msg->data; - - P_MsgList server_msgs = P_UnpackMessages(frame->arena, packed); - if (server_msgs.first) + if (NET_MatchKey(net_key, frame->desired_sim_key)) { - if (in_msgs.last) + frame->sim_key = net_key; + + // String address_str = NET_StringFromKey(frame->arena, net_key); + // LogDebugF("Received message from server \"%F\"", FmtString(address_str)); + + String packed = net_msg->data; + + P_MsgList server_msgs = P_UnpackMessages(frame->arena, packed, net_key); + if (server_msgs.first) { - in_msgs.last->next = server_msgs.first; + if (in_msgs.last) + { + in_msgs.last->next = server_msgs.first; + } + else + { + in_msgs.first = server_msgs.first; + } + server_msgs.first->prev = in_msgs.last; + in_msgs.last = server_msgs.last; + in_msgs.count += server_msgs.count; } - else - { - in_msgs.first = server_msgs.first; - } - server_msgs.first->prev = in_msgs.last; - in_msgs.last = server_msgs.last; - in_msgs.count += server_msgs.count; } + } } @@ -2979,6 +3046,7 @@ void V_TickForever(WaveLaneCtx *lane) P_ClearFrames(predict_world, I64Min, I64Max); predict_frame = P_PushFrame(predict_world, sim_world->last_frame, sim_world->last_frame->tick); + P_DebugDrawFrame(predict_frame, VEC4(0, 0, 1, 0.75)); @@ -3458,66 +3526,66 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Debug draw - // { - // // Merge vis debug draws with sim debug draws - // P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node; - // P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node; - // if (P_tl.first_debug_draw_node) - // { - // if (last_debug_draw_node) - // { - // last_debug_draw_node->next = P_tl.first_debug_draw_node; - // } - // else - // { - // first_debug_draw_node = P_tl.first_debug_draw_node; - // } - // last_debug_draw_node = P_tl.last_debug_draw_node; - // } + { + // Merge vis debug draws with sim debug draws + P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node; + P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node; + if (P_tl.first_debug_draw_node) + { + if (last_debug_draw_node) + { + last_debug_draw_node->next = P_tl.first_debug_draw_node; + } + else + { + first_debug_draw_node = P_tl.first_debug_draw_node; + } + last_debug_draw_node = P_tl.last_debug_draw_node; + } - // // Push draws - // for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next) - // { - // Vec4 color = Vec4FromU32(n->srgb32); - // i32 detail = 24; - // f32 radius = 5; - // switch(n->kind) - // { - // case P_DebugDrawKind_Point: - // { - // Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p); - // V_DrawPoint(ui_p, color); - // } break; + // Push draws + for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next) + { + Vec4 color = Vec4FromU32(n->srgb32); + i32 detail = 24; + f32 radius = 5; + switch(n->kind) + { + case P_DebugDrawKind_Point: + { + Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p); + V_DrawPoint(ui_p, color); + } break; - // case P_DebugDrawKind_Line: - // { - // Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0); - // Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1); - // V_DrawLine(ui_p0, ui_p1, color); - // } break; + case P_DebugDrawKind_Line: + { + Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0); + Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1); + V_DrawLine(ui_p0, ui_p1, color); + } break; - // case P_DebugDrawKind_Rect: - // { - // Rng2 ui_rect = Zi; - // ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0); - // ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1); - // V_DrawRect(ui_rect, color, V_DrawFlag_Line); - // } break; + case P_DebugDrawKind_Rect: + { + Rng2 ui_rect = Zi; + ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0); + ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1); + V_DrawRect(ui_rect, color, V_DrawFlag_Line); + } break; - // case P_DebugDrawKind_Shape: - // { - // P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape); - // V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line); - // } break; - // } - // } + case P_DebugDrawKind_Shape: + { + P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape); + V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line); + } break; + } + } - // // Reset vis debug draws - // 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; - // } + // Reset vis debug draws + 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; + } ////////////////////////////// @@ -3843,13 +3911,11 @@ void V_TickForever(WaveLaneCtx *lane) // FIXME: Remove this (testing) - NET_Key server_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121")); - if (frame->held_buttons[Button_R] && !prev_frame->held_buttons[Button_R]) { LogDebugF("Sending test payload"); - // NET_Push(net_pipe, server_key, STRING(P_TilesCount, predict_world->tiles), 0); - NET_Push(net_pipe, server_key, Lit("Hello there!"), 0); + NET_Send(net_pipe, frame->sim_key, STRING(P_TilesCount, predict_world->tiles), NET_SendFlag_None); + // NET_Send(net_pipe, frame->sim_key, Lit("Hello there!"), NET_SendFlag_None); } @@ -3859,7 +3925,7 @@ void V_TickForever(WaveLaneCtx *lane) // { // P_Msg *msg = &msg_node->msg; // String packed = P_PackMessage(frame->arena, msg); - // NET_Push(net_pipe, server_key, packed, msg->burst); + // NET_Send(net_pipe, frame->sim_key, packed, NET_SendFlag_None); // } { @@ -3867,7 +3933,7 @@ void V_TickForever(WaveLaneCtx *lane) { BB_ResetWriter(&packer_bbw); String packed = P_PackMessages(&packer_bbw, P_tl.out_msgs); - NET_Push(net_pipe, server_key, packed, 0); + NET_Send(net_pipe, frame->sim_key, packed, NET_SendFlag_None); } } diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index e7506c2d..f9271282 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -235,6 +235,9 @@ Struct(V_Frame) f64 dt; RandState rand; + NET_Key sim_key; + NET_Key desired_sim_key; + Button held_buttons[Button_COUNT]; V_Palette palette; @@ -305,6 +308,8 @@ Struct(V_Ctx) V_Panel *root_panel; V_Window *dragging_window; + i64 connect_try_ns; + // Notifications V_Notif *first_notif; V_Notif *last_notif;