X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_netmsg.pas;h=5e95a6a57dd97b42a4d31178c153e94589092816;hb=11b921b75f679ec727a0af28a6499bbaba17eca2;hp=ddef35df216b9f645023eef3ab3d511aee45fe38;hpb=8ab76228a45f13481cc1162b6d84cb3bdb50b9c6;p=d2df-sdl.git diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index ddef35d..5e95a6a 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -112,6 +112,7 @@ const NET_EV_PLAYER_TOUCH = 18; NET_EV_SECRET = 19; NET_EV_INTER_READY = 20; + NET_EV_LMS_NOSPAWN = 21; NET_VE_STARTED = 1; NET_VE_PASSED = 2; @@ -133,6 +134,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 +149,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 +417,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) + @@ -426,37 +430,88 @@ begin Name := PName; FClientID := C^.ID; // round in progress, don't spawn - if (gGameSettings.MaxLives > 0) and (gLMSRespawn = LMS_RESPAWN_NONE) then - begin - Lives := 0; - FNoRespawn := True; - Spectate; - FWantsInGame := True; // TODO: look into this later - end - else - Respawn(gGameSettings.GameType = GT_SINGLE); + 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 "request full state" packet + Lives := 0; + Spectate; + FNoRespawn := True; + // `FWantsInGame` seems to mean "spawn the player on the next occasion". + // that is, if we'll set it to `true`, the player can be spawned after + // warmup time ran out, for example, regardless of the real player state. + // also, this seems to work only for the initial connection. further + // map changes could initiate resource downloading, but the player will + // be spawned immediately. + // the proper solution will require another player state, "ephemeral". + // the player should start any map in "ephemeral" state, and turned into + // real mobj only when they sent a special "i am ready" packet. this packet + // must be sent after receiving the full state, so the player will get a full + // map view before going into game. + FWantsInGame := false; + C^.WaitForFirstSpawn := true; 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 MH_SEND_GameEvent(NET_EV_MAPEND, 0, 'N', C^.ID); - if NetUseMaster then g_Net_Slist_Update; + if NetUseMaster then + begin + //g_Net_Slist_Update; + g_Net_Slist_Pulse(); + end; +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; + g_Net_Slist_ServerPlayerComes(); + 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 + + if (gGameSettings.MaxLives > 0) and (gLMSRespawn = LMS_RESPAWN_NONE) then + begin + plr.Spectate; + MH_SEND_GameEvent(NET_EV_LMS_NOSPAWN, 0, 'N', C.ID); + end + else + begin + plr.Respawn(False); + if gLMSRespawn > LMS_RESPAWN_NONE then + MH_SEND_GameEvent(NET_EV_LMS_WARMUP, gLMSRespawnTime - gTime, 'N', C.ID); + end; 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 @@ -539,7 +594,12 @@ begin NET_CHEAT_SPECTATE: begin if Pl.FSpectator then - Pl.Respawn(False) + begin + if (gGameSettings.MaxLives = 0) or (gLMSRespawn > LMS_RESPAWN_NONE) then + Pl.Respawn(False) + else + MH_SEND_GameEvent(NET_EV_LMS_NOSPAWN, Pl.UID); + end else Pl.Spectate; end; @@ -674,7 +734,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 +758,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 @@ -755,27 +821,18 @@ begin if CreatePlayers and (ID >= 0) then NetClients[ID].State := NET_STATE_GAME; - if gLMSRespawn > LMS_RESPAWN_NONE then - begin - MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000, 'N', ID); - end; - g_Net_Flush(); end; procedure MH_SEND_Info(ID: Byte); -var - Map: string; begin - Map := g_ExtractFileName(gMapInfo.Map); - NetOut.Clear(); NetOut.Write(Byte(NET_MSG_INFO)); NetOut.Write(ID); NetOut.Write(NetClients[ID].Player); - NetOut.Write(gGameSettings.WAD); - NetOut.Write(Map); + NetOut.Write(ExtractFileName(gGameSettings.WAD)); + NetOut.Write(g_ExtractFileName(gMapInfo.Map)); NetOut.Write(gWADHash); NetOut.Write(gGameSettings.GameMode); NetOut.Write(gGameSettings.GoalLimit); @@ -1121,6 +1178,7 @@ begin NetOut.Write(Byte(FJetpack)); NetOut.Write(FFireTime); NetOut.Write(Byte(FFlaming)); + NetOut.Write(FSpawnInvul); end; g_Net_Host_Send(ID, True, NET_CHAN_PLAYER); @@ -1719,6 +1777,7 @@ begin NET_EV_MAPEND: goodCmd := true; NET_EV_PLAYER_KICK: goodCmd := true; NET_EV_PLAYER_BAN: goodCmd := true; + NET_EV_LMS_WARMUP: goodCmd := true; end; if not goodCmd then exit; end; @@ -1740,7 +1799,7 @@ begin gGameSettings.GameMode := gSwitchGameMode; gWADHash := EvHash; - if not g_Game_StartMap(EvStr, True) then + if not g_Game_StartMap(false{asMegawad}, EvStr, True) then begin if not isWadPath(EvStr) then g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [gGameSettings.WAD + ':\' + EvStr])) @@ -1755,6 +1814,8 @@ begin NET_EV_MAPEND: begin + gLMSRespawn := LMS_RESPAWN_NONE; + gLMSRespawnTime := 0; if (g_Res_received_map_start <> 0) then begin g_Res_received_map_start := -1; @@ -1799,7 +1860,18 @@ begin end; NET_EV_LMS_WARMUP: - g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [EvNum]), True); + begin + if EvNum > 0 then + begin + gLMSRespawn := LMS_RESPAWN_WARMUP; + gLMSRespawnTime := gTime + EvNum; + g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [EvNum div 1000]), True); + end + else if gPlayer1 = nil then + begin + g_Console_Add(_lc[I_PLAYER_SPECT4], True); + end; + end; NET_EV_LMS_SURVIVOR: g_Console_Add('*** ' + _lc[I_MESSAGE_LMS_SURVIVOR] + ' ***', True); @@ -1885,6 +1957,7 @@ begin NET_EV_LMS_START: begin g_Player_RemoveAllCorpses; + gLMSRespawn := LMS_RESPAWN_NONE; g_Game_Message(_lc[I_MESSAGE_LMS_START], 144); end; @@ -1905,6 +1978,9 @@ begin NET_EV_LMS_DRAW: g_Game_Message(_lc[I_GAME_WIN_DRAW], 144); + NET_EV_LMS_NOSPAWN: + g_Console_Add(_lc[I_PLAYER_SPECT4], True); + NET_EV_KILLCOMBO: g_Game_Announce_KillCombo(EvNum); @@ -2268,23 +2344,29 @@ begin FSpectator := M.ReadByte() <> 0; if FSpectator then begin - if Pl = gPlayer1 then + if UID = NetPlrUID1 then begin - gLMSPID1 := UID; + gSpectLatchPID1 := UID; gPlayer1 := nil; end; - if Pl = gPlayer2 then + if UID = NetPlrUID2 then begin - gLMSPID2 := UID; + gSpectLatchPID2 := UID; gPlayer2 := nil; end; end else begin - if (gPlayer1 = nil) and (gLMSPID1 > 0) then - gPlayer1 := g_Player_Get(gLMSPID1); - if (gPlayer2 = nil) and (gLMSPID2 > 0) then - gPlayer2 := g_Player_Get(gLMSPID2); + if (gPlayer1 = nil) and (gSpectLatchPID1 > 0) and (UID = gSpectLatchPID1) then + begin + gPlayer1 := Pl; + gSpectLatchPID1 := 0; + end; + if (gPlayer2 = nil) and (gSpectLatchPID2 > 0) and (UID = gSpectLatchPID2) then + begin + gPlayer2 := Pl; + gSpectLatchPID2 := 0; + end; end; FGhost := M.ReadByte() <> 0; FPhysics := M.ReadByte() <> 0; @@ -2296,6 +2378,7 @@ begin if (OldFire <= 0) and (FFireTime > 0) then g_Sound_PlayExAt('SOUND_IGNITE', Obj.X, Obj.Y); Flam := M.ReadByte() <> 0; + FSpawnInvul := M.ReadLongInt(); if OldJet and not FJetpack then JetpackOff else if not OldJet and FJetpack then