DEADSOFTWARE

net: tried to spawn a "real" player only after it requested the first full state...
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Sun, 13 Oct 2019 02:57:50 +0000 (05:57 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Sun, 13 Oct 2019 02:58:32 +0000 (05:58 +0300)
src/game/g_net.pas
src/game/g_netmsg.pas
src/game/g_player.pas

index 4deca1e4c2f65356a7a2ebfcb886a0480bfb9aef..63b1270d9653e1306b34b7249f38e3ee554a6f86 100644 (file)
@@ -108,6 +108,7 @@ type
     Peer:     pENetPeer;
     Player:   Word;
     RequestedFullUpdate: Boolean;
+    WaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request
     RCONAuth: Boolean;
     Voted:    Boolean;
     Transfer: TNetFileTransfer; // only one transfer may be active
@@ -1274,6 +1275,7 @@ begin
     NetClients[N].Used := True;
     NetClients[N].ID := N;
     NetClients[N].RequestedFullUpdate := False;
+    NetClients[N].WaitForFirstSpawn := False;
     NetClients[N].RCONAuth := False;
     NetClients[N].Voted := False;
     NetClients[N].Player := 0;
@@ -1711,6 +1713,7 @@ begin
         TC^.Peer := nil;
         TC^.Player := 0;
         TC^.RequestedFullUpdate := False;
+        TC^.WaitForFirstSpawn := False;
         TC^.NetOut[NET_UNRELIABLE].Free();
         TC^.NetOut[NET_RELIABLE].Free();
 
index ddef35df216b9f645023eef3ab3d511aee45fe38..244b2ebd716ef55a21674fbd4b375f9c2324aad8 100644 (file)
@@ -133,6 +133,8 @@ const
 
 // HOST MESSAGES
 
+procedure MH_ProcessFirstSpawn (C: pTNetClient);
+
 procedure MH_RECV_Info(C: pTNetClient; var M: TMsg);
 procedure MH_RECV_Chat(C: pTNetClient; var M: TMsg);
 procedure MH_RECV_FullStateRequest(C: pTNetClient; var M: TMsg);
@@ -146,7 +148,7 @@ procedure MH_RECV_RCONCommand(C: pTNetClient; var M: TMsg);
 procedure MH_RECV_Vote(C: pTNetClient; var M: TMsg);
 
 // GAME
-procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_EVERYONE);
+procedure MH_SEND_Everything(CreatePlayers: Boolean {= False}; ID: Integer {= NET_EVERYONE});
 procedure MH_SEND_Info(ID: Byte);
 procedure MH_SEND_Chat(Txt: string; Mode: Byte; ID: Integer = NET_EVERYONE);
 procedure MH_SEND_Effect(X, Y: Integer; Ang: SmallInt; Kind: Byte; ID: Integer = NET_EVERYONE);
@@ -414,6 +416,7 @@ begin
   end;
 
   C^.Player := PID;
+  C^.WaitForFirstSpawn := false;
 
   g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True);
   e_WriteLog('NET: Client ' + PName + ' [' + IntToStr(C^.ID) +
@@ -432,17 +435,31 @@ begin
       FNoRespawn := True;
       Spectate;
       FWantsInGame := True; // TODO: look into this later
+      C^.WaitForFirstSpawn := true;
     end
     else
-      Respawn(gGameSettings.GameType = GT_SINGLE);
+    begin
+      e_LogWritefln('*** client #%u (cid #%u) authenticated...', [C.ID, C.Player]);
+      //e_LogWritefln('spawning player with pid #%u...', [PID]);
+      //Respawn(gGameSettings.GameType = GT_SINGLE);
+      //k8: no, do not spawn a player yet, wait for a 'i am ready' packet
+      Lives := 0;
+      Spectate;
+      FNoRespawn := True;
+      FWantsInGame := false; // TODO: look into this later
+      C^.WaitForFirstSpawn := true;
+    end;
   end;
 
-  for I := Low(NetClients) to High(NetClients) do
+  //if not C^.WaitForFirstSpawn then
   begin
-    if NetClients[I].ID = C^.ID then Continue;
-    MH_SEND_PlayerCreate(PID, NetClients[I].ID);
-    MH_SEND_PlayerPos(True, PID, NetClients[I].ID);
-    MH_SEND_PlayerStats(PID, NetClients[I].ID);
+    for I := Low(NetClients) to High(NetClients) do
+    begin
+      if NetClients[I].ID = C^.ID then Continue;
+      MH_SEND_PlayerCreate(PID, NetClients[I].ID);
+      MH_SEND_PlayerPos(True, PID, NetClients[I].ID);
+      MH_SEND_PlayerStats(PID, NetClients[I].ID);
+    end;
   end;
 
   if gState in [STATE_INTERCUSTOM, STATE_FOLD] then
@@ -451,12 +468,33 @@ begin
   if NetUseMaster then g_Net_Slist_Update;
 end;
 
+
+procedure MH_ProcessFirstSpawn (C: pTNetClient);
+var
+  plr: TPlayer;
+begin
+  if not C.WaitForFirstSpawn then exit;
+  plr := g_Player_Get(C^.Player);
+  if not assigned(plr) then exit;
+  e_LogWritefln('*** client #%u (cid #%u) first spawn', [C.ID, C.Player]);
+  C.WaitForFirstSpawn := false;
+  plr.FNoRespawn := false;
+  plr.FWantsInGame := true; // TODO: look into this later
+  plr.Respawn(False);
+end;
+
+
 procedure MH_RECV_FullStateRequest(C: pTNetClient; var M: TMsg);
 begin
+  //e_LogWritefln('*** client #%u (cid #%u) full state request', [C.ID, C.Player]);
   if gGameOn then
+  begin
     MH_SEND_Everything((C^.State = NET_STATE_AUTH), C^.ID)
+  end
   else
+  begin
     C^.RequestedFullUpdate := True;
+  end;
 end;
 
 // PLAYER
@@ -674,7 +712,7 @@ end;
 
 // GAME (SEND)
 
-procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_EVERYONE);
+procedure MH_SEND_Everything(CreatePlayers: Boolean {= False}; ID: Integer {= NET_EVERYONE});
 
   function sendItemRespawn (it: PItem): Boolean;
   begin
@@ -698,6 +736,12 @@ procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_E
 var
   I: Integer;
 begin
+  if (ID >= 0) and (ID < length(NetClients)) then
+  begin
+    e_LogWritefln('*** client #%u (cid #%u) will get everything', [ID, NetClients[ID].Player]);
+    MH_ProcessFirstSpawn(@NetClients[ID]);
+  end;
+
   if gPlayers <> nil then
   begin
     for I := Low(gPlayers) to High(gPlayers) do
@@ -757,6 +801,7 @@ begin
 
   if gLMSRespawn > LMS_RESPAWN_NONE then
   begin
+    e_LogWritefln('*** client #%u (cid #%u) WARMUP', [ID, NetClients[ID].Player]);
     MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000, 'N', ID);
   end;
 
index a66245c952aaaf8e381074bce18505d455796b00..cc6afb07be47661fa320584d0d6ecb2f80f5df1e 100644 (file)
@@ -268,6 +268,7 @@ type
     FDummy:     Boolean;
     FFireTime:  Integer;
     FHandicap:  Integer;
+    FWaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request
 
     // debug: viewport offset
     viewPortX, viewPortY, viewPortW, viewPortH: Integer;
@@ -2178,6 +2179,8 @@ begin
   FJustTeleported := False;
   FNetTime := 0;
 
+  FWaitForFirstSpawn := false;
+
   resetWeaponQueue();
 end;