DEADSOFTWARE

buffer network messages (broke a lot of shit)
authorfgsfds <pvt.fgsfds@gmail.com>
Wed, 16 Aug 2017 17:44:19 +0000 (20:44 +0300)
committerfgsfds <pvt.fgsfds@gmail.com>
Wed, 16 Aug 2017 17:44:19 +0000 (20:44 +0300)
src/engine/e_fixedbuffer.pas
src/game/g_game.pas
src/game/g_net.pas
src/game/g_nethandler.pas
src/game/g_netmaster.pas
src/game/g_netmsg.pas
src/game/g_window.pas

index c59302102436e38a1ad715ec74df08c7e908d315..3b6dbf801b28d8208d13ce71236afde048b5bd3e 100644 (file)
@@ -28,7 +28,7 @@ type
     Data: array [0..BUF_SIZE] of Byte; // îäèí áàéò ñâåðõó íà âñÿêèé ñëó÷àé
     ReadPos: Cardinal;
     WritePos: Cardinal;
-    Len: Cardinal;
+    Cap: Cardinal;
   end;
   pTBuffer = ^TBuffer;
 
@@ -57,6 +57,8 @@ procedure e_Buffer_Write(B: pTBuffer; V: string); overload;
 
 procedure e_Buffer_Write(B: pTBuffer; V: TMD5Digest); overload;
 
+procedure e_Buffer_Write(B: pTBuffer; V: pTBuffer); overload;
+
 
 function  e_Buffer_Read_Char(B: pTBuffer): Char;
 
@@ -100,15 +102,15 @@ procedure e_Buffer_Clear(B: pTBuffer);
 begin
   B^.WritePos := 0;
   B^.ReadPos := 0;
-  B^.Len := 0;
+  B^.Cap := 0;
 end;
 
 
 procedure e_Buffer_Write_Generic(B: pTBuffer; var V; N: Cardinal);
 begin
   if (B^.WritePos + N >= BUF_SIZE) then Exit;
-  if (B^.WritePos + N > B^.Len) then
-    B^.Len := B^.WritePos + N + 1;
+  if (B^.WritePos + N > B^.Cap) then
+    B^.Cap := B^.WritePos + N + 1;
 
   CopyMemory(Pointer(NativeUInt(Addr(B^.Data)) + B^.WritePos),
              @V, N);
@@ -177,7 +179,7 @@ begin
     P := BUF_SIZE;
   end;
 
-  if (P > B^.Len) then B^.Len := P;
+  if (P > B^.Cap) then B^.Cap := P;
 
   CopyMemory(Pointer(NativeUInt(Addr(B^.Data)) + B^.WritePos),
              @V[1], Len);
@@ -193,6 +195,25 @@ begin
     e_Buffer_Write(B, V[I]);
 end;
 
+procedure e_Buffer_Write(B: pTBuffer; V: pTBuffer); overload;
+var
+  N: Cardinal;
+begin
+  if V = nil then Exit;
+  N := V^.WritePos;
+
+  e_Buffer_Write(B, Word(N));
+
+  if (B^.WritePos + N >= BUF_SIZE) then Exit;
+  if (B^.WritePos + N > B^.Cap) then
+    B^.Cap := B^.WritePos + N + 1;
+
+  CopyMemory(Pointer(NativeUInt(Addr(B^.Data)) + B^.WritePos),
+             Addr(V^.Data), N);
+
+  B^.WritePos := B^.WritePos + N;
+end;
+
 
 function e_Buffer_Read_Char(B: pTBuffer): Char;
 begin
@@ -237,8 +258,8 @@ begin
   Result := '';
   if Len = 0 then Exit;
 
-  if B^.ReadPos + Len > B^.Len then
-    Len := B^.Len - B^.ReadPos;
+  if B^.ReadPos + Len > B^.Cap then
+    Len := B^.Cap - B^.ReadPos;
 
   SetLength(Result, Len);
   CopyMemory(@Result[1], Pointer(NativeUInt(Addr(B^.Data)) + B^.ReadPos), Len);
index 18f56398b60c03eec7734ebc8eada624a9e2b82d..36b1016abb6720dab7e7006448c8ef2ad7e966c5 100644 (file)
@@ -3639,6 +3639,7 @@ var
   State: Byte;
   OuterLoop: Boolean;
   newResPath: string;
+  Len: Word;
 begin
   g_Game_Free();
 
@@ -3688,6 +3689,7 @@ begin
         Ptr := NetEvent.packet^.data;
         e_Raw_Seek(0);
 
+        Len := e_Raw_Read_Word(Ptr);
         MID := e_Raw_Read_Byte(Ptr);
 
         if (MID = NET_MSG_INFO) and (State = 0) then
@@ -3794,7 +3796,7 @@ begin
 
   g_Player_Init();
   NetState := NET_STATE_GAME;
-  MC_SEND_FullStateRequest;
+  MC_SEND_FullStateRequest();
   e_WriteLog('NET: Connection successful.', MSG_NOTIFY);
 end;
 
index 35968491ebc828dc90f30cbcf5cd56d2d447db16..ee7ee2a5bc67c2faf5f337453042141f83bb81e7 100644 (file)
@@ -25,7 +25,6 @@ const
   NET_PROTOCOL_VER = 171;
 
   NET_MAXCLIENTS = 24;
-  NET_CHANS = 11;
 
   NET_CHAN_SERVICE = 0;
   NET_CHAN_IMPORTANT = 1;
@@ -39,6 +38,13 @@ const
   NET_CHAN_DOWNLOAD = 9;
   NET_CHAN_SHOTS = 10;
 
+  CH_RELIABLE = 0;
+  CH_UNRELIABLE = 1;
+  CH_DOWNLOAD = 2;
+  CH_MAX = CH_UNRELIABLE; // don't change this
+
+  NET_CHANS = 3;
+
   NET_NONE = 0;
   NET_SERVER = 1;
   NET_CLIENT = 2;
@@ -67,14 +73,15 @@ const
 
 type
   TNetClient = record
-    ID:      Byte;
-    Used:    Boolean;
-    State:   Byte;
-    Peer:    pENetPeer;
-    Player:  Word;
+    ID:       Byte;
+    Used:     Boolean;
+    State:    Byte;
+    Peer:     pENetPeer;
+    Player:   Word;
     RequestedFullUpdate: Boolean;
     RCONAuth: Boolean;
     Voted:    Boolean;
+    SendBuf:  array [0..CH_MAX] of TBuffer;
   end;
   TBanRecord = record
     IP: LongWord;
@@ -117,11 +124,12 @@ var
   NetClientPort: Word   = 25666;
 
   NetIn, NetOut: TBuffer;
+  NetSend: array [0..CH_MAX] of TBuffer;
 
-  NetClients:     array of TNetClient;
+  NetClients:     array of TNetClient = nil;
   NetClientCount: Byte = 0;
   NetMaxClients:  Byte = 255;
-  NetBannedHosts: array of TBanRecord;
+  NetBannedHosts: array of TBanRecord = nil;
 
   NetState:      Integer = NET_STATE_NONE;
 
@@ -151,12 +159,14 @@ function  g_Net_Host(IPAddr: LongWord; Port: enet_uint16; MaxClients: Cardinal =
 procedure g_Net_Host_Die();
 procedure g_Net_Host_Send(ID: Integer; Reliable: Boolean; Chan: Byte = NET_CHAN_GAME);
 function  g_Net_Host_Update(): enet_size_t;
+procedure g_Net_Host_FlushBuffers();
 
 function  g_Net_Connect(IP: string; Port: enet_uint16): Boolean;
 procedure g_Net_Disconnect(Forced: Boolean = False);
 procedure g_Net_Client_Send(Reliable: Boolean; Chan: Byte = NET_CHAN_GAME);
 function  g_Net_Client_Update(): enet_size_t;
 function  g_Net_Client_UpdateWhileLoading(): enet_size_t;
+procedure g_Net_Client_FlushBuffers();
 
 function  g_Net_Client_ByName(Name: string): pTNetClient;
 function  g_Net_Client_ByPlayer(PID: Word): pTNetClient;
@@ -192,6 +202,27 @@ uses
 { /// SERVICE FUNCTIONS /// }
 
 
+procedure SendBuffer(B: pTBuffer; Ch: Integer; Peer: pENetPeer);
+var
+  P: pENetPacket;
+  Fl: enet_uint32;
+begin
+  if Ch = CH_RELIABLE then Fl := ENET_PACKET_FLAG_RELIABLE
+  else Fl := 0;
+  if B^.WritePos > 0 then
+  begin
+    P := enet_packet_create(Addr(B^.Data), B^.WritePos, Fl);
+    if P <> nil then
+    begin
+      if Peer = nil then
+        enet_host_broadcast(NetHost, Ch, P)
+      else
+        enet_peer_send(Peer, Ch, P);
+    end;
+    e_Buffer_Clear(B);
+  end;
+end;
+
 function g_Net_FindSlot(): Integer;
 var
   I: Integer;
@@ -237,6 +268,9 @@ begin
     NetClients[N].RCONAuth := False;
     NetClients[N].Voted := False;
     NetClients[N].Player := 0;
+    NetClients[N].Peer := nil;
+      for I := 0 to CH_MAX do
+        e_Buffer_Clear(Addr(NetClients[N].SendBuf[CH_MAX]));
   end;
 
   Result := N;
@@ -247,9 +281,12 @@ var
   F: TextFile;
   IPstr: string;
   IP: LongWord;
+  I: Integer;
 begin
   e_Buffer_Clear(@NetIn);
   e_Buffer_Clear(@NetOut);
+  for I := 0 to CH_MAX do
+    e_Buffer_Clear(@NetSend[i]);
   SetLength(NetClients, 0);
   NetPeer := nil;
   NetHost := nil;
@@ -277,13 +314,21 @@ end;
 
 procedure g_Net_Flush();
 begin
+  if NetMode = NET_SERVER then
+    g_Net_Host_FlushBuffers()
+  else
+    g_Net_Client_FlushBuffers();
   enet_host_flush(NetHost);
 end;
 
 procedure g_Net_Cleanup();
+var
+  I: Integer;
 begin
   e_Buffer_Clear(@NetIn);
   e_Buffer_Clear(@NetOut);
+  for i := 0 to CH_MAX do
+    e_Buffer_Clear(@NetSend[i]);
 
   SetLength(NetClients, 0);
   NetClientCount := 0;
@@ -417,37 +462,48 @@ begin
   e_WriteLog('NET: Server stopped', MSG_NOTIFY);
 end;
 
+procedure g_Net_Host_FlushBuffers();
+var
+  I: Integer;
+begin
+  // send broadcast
+  SendBuffer(@NetSend[CH_RELIABLE], CH_RELIABLE, nil);
+  SendBuffer(@NetSend[CH_UNRELIABLE], CH_UNRELIABLE, nil);
+  // send to individual clients
+  if NetClients <> nil then
+    for I := Low(NetClients) to High(NetClients) do
+      with NetClients[I] do
+      begin
+        SendBuffer(@SendBuf[CH_RELIABLE], CH_RELIABLE, Peer);
+        SendBuffer(@SendBuf[CH_UNRELIABLE], CH_UNRELIABLE, Peer);
+      end;
+end;
 
 procedure g_Net_Host_Send(ID: Integer; Reliable: Boolean; Chan: Byte = NET_CHAN_GAME);
 var
-  P: pENetPacket;
-  F: enet_uint32;
+  I: Integer;
+  B: pTBuffer;
 begin
   if (Reliable) then
-    F := LongWord(ENET_PACKET_FLAG_RELIABLE)
+    I := CH_RELIABLE
   else
-    F := 0;
+    I := CH_UNRELIABLE;
 
   if (ID >= 0) then
   begin
-    if ID > High(NetClients) then Exit;
-    if NetClients[ID].Peer = nil then Exit;
-
-    P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, F);
-    if not Assigned(P) then Exit;
-
-    enet_peer_send(NetClients[ID].Peer, Chan, P);
+    if (ID > High(NetClients)) or (NetClients[ID].Peer = nil) then 
+    begin 
+      e_Buffer_Clear(@NetOut);
+      Exit;
+    end;
+    B := Addr(NetClients[ID].SendBuf[I]);
   end
   else
   begin
-    P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, F);
-    if not Assigned(P) then Exit;
-
-    enet_host_broadcast(NetHost, Chan, P);
+    B := Addr(NetSend[I]);
   end;
 
-  if NetDump then g_Net_DumpSendBuffer();
-  g_Net_Flush();
+  e_Buffer_Write(B, @NetOut);
   e_Buffer_Clear(@NetOut);
 end;
 
@@ -497,7 +553,7 @@ function g_Net_Host_Update(): enet_size_t;
 var
   IP: string;
   Port: Word;
-  ID: Integer;
+  ID, I: Integer;
   TC: pTNetClient;
   TP: TPlayer;
 begin
@@ -561,8 +617,6 @@ begin
         ID := Byte(NetEvent.peer^.data^);
         if ID > High(NetClients) then Exit;
         TC := @NetClients[ID];
-
-        if NetDump then g_Net_DumpRecvBuffer(NetEvent.packet^.data, NetEvent.packet^.dataLength);
         g_Net_HostMsgHandler(TC, NetEvent.packet);
       end;
 
@@ -653,22 +707,21 @@ begin
   e_WriteLog('NET: Disconnected', MSG_NOTIFY);
 end;
 
+procedure g_Net_Client_FlushBuffers();
+begin
+  SendBuffer(@NetSend[CH_RELIABLE], CH_RELIABLE, NetPeer);
+  SendBuffer(@NetSend[CH_UNRELIABLE], CH_UNRELIABLE, NetPeer);
+end;
+
 procedure g_Net_Client_Send(Reliable: Boolean; Chan: Byte = NET_CHAN_GAME);
 var
-  P: pENetPacket;
-  F: enet_uint32;
+  I: Integer;
 begin
   if (Reliable) then
-    F := LongWord(ENET_PACKET_FLAG_RELIABLE)
+    I := CH_RELIABLE
   else
-    F := 0;
-
-  P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, F);
-  if not Assigned(P) then Exit;
-
-  enet_peer_send(NetPeer, Chan, P);
-  if NetDump then g_Net_DumpSendBuffer();
-  g_Net_Flush();
+    I := CH_UNRELIABLE;
+  e_Buffer_Write(@NetSend[I], @NetOut);
   e_Buffer_Clear(@NetOut);
 end;
 
@@ -680,7 +733,6 @@ begin
     case NetEvent.kind of
       ENET_EVENT_TYPE_RECEIVE:
       begin
-        if NetDump then g_Net_DumpRecvBuffer(NetEvent.packet^.data, NetEvent.packet^.dataLength);
         g_Net_ClientMsgHandler(NetEvent.packet);
       end;
 
@@ -702,7 +754,6 @@ begin
     case NetEvent.kind of
       ENET_EVENT_TYPE_RECEIVE:
       begin
-        if NetDump then g_Net_DumpRecvBuffer(NetEvent.packet^.data, NetEvent.packet^.dataLength);
         g_Net_ClientLightMsgHandler(NetEvent.packet);
       end;
 
@@ -714,7 +765,6 @@ begin
       end;
     end;
   end;
-  g_Net_Flush();
 end;
 
 function g_Net_Connect(IP: string; Port: enet_uint16): Boolean;
@@ -897,13 +947,13 @@ begin
   begin
     P := enet_packet_create(@Data[0], dataLength, F);
     if not Assigned(P) then Exit;
-    enet_peer_send(peer, Chan, P);
+    enet_peer_send(peer, CH_DOWNLOAD, P);
   end
   else
   begin
     P := enet_packet_create(@Data[0], dataLength, F);
     if not Assigned(P) then Exit;
-    enet_host_broadcast(NetHost, Chan, P);
+    enet_host_broadcast(NetHost, CH_DOWNLOAD, P);
   end;
 
   enet_host_flush(NetHost);
@@ -924,17 +974,16 @@ begin
   begin
     while (enet_host_service(NetHost, @downloadEvent, 0) > 0) do
     begin
-      if (downloadEvent.kind = ENET_EVENT_TYPE_RECEIVE) then
+      if (downloadEvent.kind = ENET_EVENT_TYPE_RECEIVE) and (downloadEvent.packet^.dataLength > 2) then
       begin
-        Ptr := downloadEvent.packet^.data;
-
+        Ptr := downloadEvent.packet^.data + 2; // skip length
         MID := Byte(Ptr^);
 
         if (MID = msgId) then
         begin
           msgStream := TMemoryStream.Create;
-          msgStream.SetSize(downloadEvent.packet^.dataLength);
-          msgStream.WriteBuffer(Ptr^, downloadEvent.packet^.dataLength);
+          msgStream.SetSize(downloadEvent.packet^.dataLength - 2);
+          msgStream.WriteBuffer(Ptr^, downloadEvent.packet^.dataLength - 2);
           msgStream.Seek(0, soFromBeginning);
 
           OuterLoop := False;
@@ -1085,9 +1134,9 @@ end;
 procedure g_Net_DumpSendBuffer();
 begin
   writeInt(NetDumpFile, gTime);
-  writeInt(NetDumpFile, LongWord(NetOut.Len));
+  writeInt(NetDumpFile, LongWord(NetOut.WritePos));
   writeInt(NetDumpFile, Byte(1));
-  NetDumpFile.WriteBuffer(NetOut.Data[0], NetOut.Len);
+  NetDumpFile.WriteBuffer(NetOut.Data[0], NetOut.WritePos);
 end;
 
 procedure g_Net_DumpRecvBuffer(Buf: penet_uint8; Len: LongWord);
index a4711af631f8eecaeeb15156fa333871c4f316b8..f505d62ecc848f9d4812fb6fbfcebea405a38149 100644 (file)
@@ -26,11 +26,12 @@ procedure g_Net_HostMsgHandler(S: pTNetClient; P: pENetPacket);
 
 implementation
 
-uses e_fixedbuffer;
+uses e_fixedbuffer, e_log, StrUtils, SysUtils;
 
 procedure g_Net_ClientMsgHandler(P: pENetPacket);
 var
   MID: Byte;
+  Len: Word;
   B: Pointer;
 begin
   e_Raw_Seek(0);
@@ -38,48 +39,51 @@ begin
   B := P^.data;
   if B = nil then Exit;
 
-  MID := e_Raw_Read_Byte(B);
-
-  case MID of
-    NET_MSG_CHAT:   MC_RECV_Chat(B);
-    NET_MSG_GFX:    MC_RECV_Effect(B);
-    NET_MSG_SND:    MC_RECV_Sound(B);
-    NET_MSG_SCORE:  MC_RECV_GameStats(B);
-    NET_MSG_COOP:   MC_RECV_CoopStats(B);
-    NET_MSG_GEVENT: MC_RECV_GameEvent(B);
-    NET_MSG_FLAG:   MC_RECV_FlagEvent(B);
-    NET_MSG_GSET:   MC_RECV_GameSettings(B);
-
-    NET_MSG_PLR:    MC_RECV_PlayerCreate(B);
-    NET_MSG_PLRPOS: MC_RECV_PlayerPos(B);
-    NET_MSG_PLRSTA: MC_RECV_PlayerStats(B);
-    NET_MSG_PLRDEL: MC_RECV_PlayerDelete(B);
-    NET_MSG_PLRDMG: MC_RECV_PlayerDamage(B);
-    NET_MSG_PLRDIE: MC_RECV_PlayerDeath(B);
-    NET_MSG_PLRFIRE:MC_RECV_PlayerFire(B);
-    NET_MSG_PLRSET: MC_RECV_PlayerSettings(B);
-
-    NET_MSG_MSPAWN: MC_RECV_MonsterSpawn(B);
-    NET_MSG_MPOS:   MC_RECV_MonsterPos(B);
-    NET_MSG_MSTATE: MC_RECV_MonsterState(B);
-    NET_MSG_MSHOT:  MC_RECV_MonsterShot(B);
-    NET_MSG_MDEL:   MC_RECV_MonsterDelete(B);
-
-    NET_MSG_SHADD:  MC_RECV_CreateShot(B);
-    NET_MSG_SHPOS:  MC_RECV_UpdateShot(B);
-    NET_MSG_SHDEL:  MC_RECV_DeleteShot(B);
-
-    NET_MSG_ISPAWN: MC_RECV_ItemSpawn(B);
-    NET_MSG_IDEL:   MC_RECV_ItemDestroy(B);
-
-    NET_MSG_PSTATE: MC_RECV_PanelState(B);
-    NET_MSG_PTEX:   MC_RECV_PanelTexture(B);
-
-    NET_MSG_TSOUND: MC_RECV_TriggerSound(B);
-    NET_MSG_TMUSIC: MC_RECV_TriggerMusic(B);
-
-    NET_MSG_TIME_SYNC:  MC_RECV_TimeSync(B);
-    NET_MSG_VOTE_EVENT: MC_RECV_VoteEvent(B);
+  while RawPos < P^.dataLength do
+  begin
+    Len := e_Raw_Read_Word(B);
+    MID := e_Raw_Read_Byte(B);
+    case MID of
+      NET_MSG_CHAT:   MC_RECV_Chat(B);
+      NET_MSG_GFX:    MC_RECV_Effect(B);
+      NET_MSG_SND:    MC_RECV_Sound(B);
+      NET_MSG_SCORE:  MC_RECV_GameStats(B);
+      NET_MSG_COOP:   MC_RECV_CoopStats(B);
+      NET_MSG_GEVENT: MC_RECV_GameEvent(B);
+      NET_MSG_FLAG:   MC_RECV_FlagEvent(B);
+      NET_MSG_GSET:   MC_RECV_GameSettings(B);
+
+      NET_MSG_PLR:    MC_RECV_PlayerCreate(B);
+      NET_MSG_PLRPOS: MC_RECV_PlayerPos(B);
+      NET_MSG_PLRSTA: MC_RECV_PlayerStats(B);
+      NET_MSG_PLRDEL: MC_RECV_PlayerDelete(B);
+      NET_MSG_PLRDMG: MC_RECV_PlayerDamage(B);
+      NET_MSG_PLRDIE: MC_RECV_PlayerDeath(B);
+      NET_MSG_PLRFIRE:MC_RECV_PlayerFire(B);
+      NET_MSG_PLRSET: MC_RECV_PlayerSettings(B);
+
+      NET_MSG_MSPAWN: MC_RECV_MonsterSpawn(B);
+      NET_MSG_MPOS:   MC_RECV_MonsterPos(B);
+      NET_MSG_MSTATE: MC_RECV_MonsterState(B);
+      NET_MSG_MSHOT:  MC_RECV_MonsterShot(B);
+      NET_MSG_MDEL:   MC_RECV_MonsterDelete(B);
+
+      NET_MSG_SHADD:  MC_RECV_CreateShot(B);
+      NET_MSG_SHPOS:  MC_RECV_UpdateShot(B);
+      NET_MSG_SHDEL:  MC_RECV_DeleteShot(B);
+
+      NET_MSG_ISPAWN: MC_RECV_ItemSpawn(B);
+      NET_MSG_IDEL:   MC_RECV_ItemDestroy(B);
+
+      NET_MSG_PSTATE: MC_RECV_PanelState(B);
+      NET_MSG_PTEX:   MC_RECV_PanelTexture(B);
+
+      NET_MSG_TSOUND: MC_RECV_TriggerSound(B);
+      NET_MSG_TMUSIC: MC_RECV_TriggerMusic(B);
+
+      NET_MSG_TIME_SYNC:  MC_RECV_TimeSync(B);
+      NET_MSG_VOTE_EVENT: MC_RECV_VoteEvent(B);
+    end;
   end;
 
   enet_packet_destroy(P);
@@ -88,6 +92,7 @@ end;
 procedure g_Net_ClientLightMsgHandler(P: pENetPacket);
 var
   MID: Byte;
+  Len: Word;
   B: Pointer;
 begin
   e_Raw_Seek(0);
@@ -95,14 +100,19 @@ begin
   B := P^.data;
   if B = nil then Exit;
 
-  MID := e_Raw_Read_Byte(B);
+  while RawPos < P^.dataLength do
+  begin
+    Len := e_Raw_Read_Word(B);
+    MID := e_Raw_Read_Byte(B);
+    case MID of
+      NET_MSG_GEVENT: MC_RECV_GameEvent(B);
+      NET_MSG_GSET:   MC_RECV_GameSettings(B);
 
-  case MID of
-    NET_MSG_GEVENT: MC_RECV_GameEvent(B);
-    NET_MSG_GSET:   MC_RECV_GameSettings(B);
+      NET_MSG_PLR:    if NetState <> NET_STATE_AUTH then MC_RECV_PlayerCreate(B);
+      NET_MSG_PLRDEL: if NetState <> NET_STATE_AUTH then MC_RECV_PlayerDelete(B);
 
-    NET_MSG_PLR:    if NetState <> NET_STATE_AUTH then MC_RECV_PlayerCreate(B);
-    NET_MSG_PLRDEL: if NetState <> NET_STATE_AUTH then MC_RECV_PlayerDelete(B);
+      else RawPos := RawPos + Len;
+    end;
   end;
 
   enet_packet_destroy(P);
@@ -111,6 +121,7 @@ end;
 procedure g_Net_HostMsgHandler(S: pTNetClient; P: pENetPacket);
 var
   MID: Byte;
+  Len: Word;
   B: Pointer;
 begin
   e_Raw_Seek(0);
@@ -118,24 +129,27 @@ begin
   B := P^.data;
   if B = nil then Exit;
 
-  MID := e_Raw_Read_Byte(B);
+  while RawPos < P^.dataLength do
+  begin
+    Len := e_Raw_Read_Word(B);
+    MID := e_Raw_Read_Byte(B);
+    case MID of
+      NET_MSG_INFO: MH_RECV_Info(S, B);
+      NET_MSG_CHAT: MH_RECV_Chat(S, B);
+      NET_MSG_REQFST: MH_RECV_FullStateRequest(S, B);
 
-  case MID of
-    NET_MSG_INFO: MH_RECV_Info(S, B);
-    NET_MSG_CHAT: MH_RECV_Chat(S, B);
-    NET_MSG_REQFST: MH_RECV_FullStateRequest(S, B);
+      NET_MSG_PLRPOS: MH_RECV_PlayerPos(S, B);
+      NET_MSG_PLRSET: MH_RECV_PlayerSettings(S, B);
+      NET_MSG_CHEAT:  MH_RECV_CheatRequest(S, B);
 
-    NET_MSG_PLRPOS: MH_RECV_PlayerPos(S, B);
-    NET_MSG_PLRSET: MH_RECV_PlayerSettings(S, B);
-    NET_MSG_CHEAT:  MH_RECV_CheatRequest(S, B);
+      NET_MSG_RCON_AUTH: MH_RECV_RCONPassword(S, B);
+      NET_MSG_RCON_CMD:  MH_RECV_RCONCommand(S, B);
 
-    NET_MSG_RCON_AUTH: MH_RECV_RCONPassword(S, B);
-    NET_MSG_RCON_CMD:  MH_RECV_RCONCommand(S, B);
+      NET_MSG_MAP_REQUEST: MH_RECV_MapRequest(S, B);
+      NET_MSG_RES_REQUEST: MH_RECV_ResRequest(S, B);
 
-    NET_MSG_MAP_REQUEST: MH_RECV_MapRequest(S, B);
-    NET_MSG_RES_REQUEST: MH_RECV_ResRequest(S, B);
-
-    NET_MSG_VOTE_EVENT: MH_RECV_Vote(S, B);
+      NET_MSG_VOTE_EVENT: MH_RECV_Vote(S, B);
+    end;
   end;
 
   enet_packet_destroy(P);
index 64681c3946e49dc51d88e16a0bf428249471d307..bc7d4ae30aaa7e19d9d8671d5e32106ab5166b1f 100644 (file)
@@ -130,7 +130,7 @@ begin
   e_Buffer_Clear(@NetOut);
   e_Buffer_Write(@NetOut, Byte(NET_MMSG_GET));
 
-  P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, Cardinal(ENET_PACKET_FLAG_RELIABLE));
+  P := enet_packet_create(Addr(NetOut.Data), NetOut.WritePos, Cardinal(ENET_PACKET_FLAG_RELIABLE));
   enet_peer_send(NetMPeer, NET_MCHAN_MAIN, P);
   enet_host_flush(NetMHost);
 
@@ -201,7 +201,7 @@ begin
 
     RX := enet_socket_receive(Sock, @SvAddr, @Buf, 1);
     if RX <= 0 then continue;
-    NetIn.Len := RX + 1;
+    NetIn.Cap := RX + 1;
     NetIn.ReadPos := 0;
 
     if e_Buffer_Read_Char(@NetIn) <> 'D' then continue;
@@ -269,7 +269,7 @@ begin
 
   g_Net_Slist_WriteInfo();
 
-  P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, Cardinal(ENET_PACKET_FLAG_RELIABLE));
+  P := enet_packet_create(Addr(NetOut.Data), NetOut.WritePos, Cardinal(ENET_PACKET_FLAG_RELIABLE));
   enet_peer_send(NetMPeer, NET_MCHAN_UPD, P);
 
   enet_host_flush(NetMHost);
@@ -285,7 +285,7 @@ begin
   e_Buffer_Write(@NetOut, Byte(NET_MMSG_DEL));
   e_Buffer_Write(@NetOut, NetAddr.port);
 
-  P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, Cardinal(ENET_PACKET_FLAG_RELIABLE));
+  P := enet_packet_create(Addr(NetOut.Data), NetOut.WritePos, Cardinal(ENET_PACKET_FLAG_RELIABLE));
   enet_peer_send(NetMPeer, NET_MCHAN_MAIN, P);
 
   enet_host_flush(NetMHost);
index 3049838d8ce65254c5b48877aec87f35b0a51277..b4612d3ec5cc8e7d676cc89ccac23d6f71d9066b 100644 (file)
@@ -2777,6 +2777,7 @@ begin
   e_Buffer_Write(@NetOut, gPlayer1Settings.Team);
 
   g_Net_Client_Send(True, NET_CHAN_SERVICE);
+  g_Net_Flush(); // send immediately, there's no frames yet
 end;
 
 procedure MC_SEND_Chat(Txt: string; Mode: Byte);
@@ -2914,6 +2915,7 @@ begin
   e_Buffer_Write(@NetOut, Byte(NET_MSG_REQFST));
 
   g_Net_Client_Send(True, NET_CHAN_SERVICE);
+  g_Net_Flush(); // send immediately, because loading
 end;
 
 procedure MC_SEND_CheatRequest(Kind: Byte);
@@ -2986,9 +2988,11 @@ end;
 procedure ResDataMsgToBytes(var bytes: AByte; const ResData: TResDataMsg);
 var
   ResultStream: TMemoryStream;
+  dummy: Word = $FFFE;
 begin
   ResultStream := TMemoryStream.Create;
 
+  ResultStream.WriteBuffer(dummy, 2); //dummy length
   ResultStream.WriteBuffer(ResData.MsgId, SizeOf(ResData.MsgId)); //msgId
   ResultStream.WriteBuffer(ResData.FileSize, SizeOf(ResData.FileSize));  //file size
   ResultStream.WriteBuffer(ResData.FileData[0], ResData.FileSize);       //file data
@@ -3012,11 +3016,13 @@ procedure MapDataMsgToBytes(var bytes: AByte; const MapDataMsg: TMapDataMsg);
 var
   ResultStream: TMemoryStream;
   resCount: Integer;
+  dummy: Word = $FFFF;
 begin
   resCount := Length(MapDataMsg.ExternalResources);
 
   ResultStream := TMemoryStream.Create;
 
+  ResultStream.WriteBuffer(dummy, 2); //dummy length
   ResultStream.WriteBuffer(MapDataMsg.MsgId, SizeOf(MapDataMsg.MsgId)); //msgId
   ResultStream.WriteBuffer(MapDataMsg.FileSize, SizeOf(MapDataMsg.FileSize));  //file size
   ResultStream.WriteBuffer(MapDataMsg.FileData[0], MapDataMsg.FileSize);       //file data
index 89511af81cd2c15fc309ba95ad06e9c2009db0c5..a8c6b6a7b3c3bf8302e95d712e2a2b875750359a 100644 (file)
@@ -545,10 +545,17 @@ begin
   e_SoundUpdate();
 
   if NetMode = NET_SERVER then
-    g_Net_Host_Update
-  else
-    if (NetMode = NET_CLIENT) and (NetState <> NET_STATE_AUTH) then
-      g_Net_Client_UpdateWhileLoading;
+  begin
+    g_Net_Host_Update();
+    g_Net_Flush();
+  end
+  else if NetMode = NET_CLIENT then
+    if (NetState <> NET_STATE_AUTH) then
+    begin
+      g_Net_Client_UpdateWhileLoading();
+      g_Net_Flush();
+    end;
+
   wLoadingProgress := False;
 end;
 
@@ -586,12 +593,14 @@ begin
       if NetMode = NET_SERVER then g_Net_Host_Update()
       else if NetMode = NET_CLIENT then g_Net_Client_Update();
       Update();
+      if NetMode <> NET_NONE then g_Net_Flush();
     end;
   end
-  else
+  else if NetMode <> NET_NONE then
   begin
     if NetMode = NET_SERVER then g_Net_Host_Update()
     else if NetMode = NET_CLIENT then g_Net_Client_Update();
+    g_Net_Flush();
   end;
 
   if wLoadingQuit then