X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_netmsg.pas;h=ddef35df216b9f645023eef3ab3d511aee45fe38;hb=8ab76228a45f13481cc1162b6d84cb3bdb50b9c6;hp=0ea771329dbf0358acd332b70e85d8e4fe24e90c;hpb=b7c26c7f1787937245991190591ef4a6ee4d152e;p=d2df-sdl.git diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 0ea7713..ddef35d 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -67,10 +66,12 @@ const NET_MSG_TIME_SYNC = 194; NET_MSG_VOTE_EVENT = 195; + { NET_MSG_MAP_REQUEST = 201; NET_MSG_MAP_RESPONSE = 202; NET_MSG_RES_REQUEST = 203; NET_MSG_RES_RESPONSE = 204; + } NET_CHAT_SYSTEM = 0; NET_CHAT_PLAYER = 1; @@ -110,6 +111,7 @@ const NET_EV_KILLCOMBO = 17; NET_EV_PLAYER_TOUCH = 18; NET_EV_SECRET = 19; + NET_EV_INTER_READY = 20; NET_VE_STARTED = 1; NET_VE_PASSED = 2; @@ -125,6 +127,7 @@ const NET_CHEAT_SUICIDE = 1; NET_CHEAT_SPECTATE = 2; + NET_CHEAT_READY = 3; NET_MAX_DIFFTIME = 5000 div 36; @@ -138,8 +141,8 @@ procedure MH_RECV_PlayerSettings(C: pTNetClient; var M: TMsg); procedure MH_RECV_CheatRequest(C: pTNetClient; var M: TMsg); procedure MH_RECV_RCONPassword(C: pTNetClient; var M: TMsg); procedure MH_RECV_RCONCommand(C: pTNetClient; var M: TMsg); -procedure MH_RECV_MapRequest(C: pTNetClient; var M: TMsg); -procedure MH_RECV_ResRequest(C: pTNetClient; var M: TMsg); +//procedure MH_RECV_MapRequest(C: pTNetClient; var M: TMsg); +//procedure MH_RECV_ResRequest(C: pTNetClient; var M: TMsg); procedure MH_RECV_Vote(C: pTNetClient; var M: TMsg); // GAME @@ -240,8 +243,9 @@ procedure MC_SEND_RCONPassword(Password: string); procedure MC_SEND_RCONCommand(Cmd: string); procedure MC_SEND_Vote(Start: Boolean = False; Command: string = 'a'); // DOWNLOAD -procedure MC_SEND_MapRequest(); -procedure MC_SEND_ResRequest(const resName: AnsiString); +//procedure MC_SEND_MapRequest(); +//procedure MC_SEND_ResRequest(const resName: AnsiString); + type TExternalResourceInfo = record @@ -262,8 +266,9 @@ type ExternalResources: array of TExternalResourceInfo; end; -function MapDataFromMsgStream(msgStream: TMemoryStream):TMapDataMsg; -function ResDataFromMsgStream(msgStream: TMemoryStream):TResDataMsg; +function IsValidFileName(const S: String): Boolean; +function IsValidFilePath(const S: String): Boolean; + implementation @@ -291,6 +296,33 @@ const //kDirPrev: TDirection = D_LEFT; //HostGameTime: Word = 0; + +function IsValidFileName(const S: String): Boolean; +const + Forbidden: set of Char = ['<', '>', '|', '"', ':', '*', '?']; +var + I: Integer; +begin + Result := S <> ''; + for I := 1 to Length(S) do + Result := Result and (not(S[I] in Forbidden)); +end; + +function IsValidFilePath(const S: String): Boolean; +var + I: Integer; +begin + Result := False; + if not IsValidFileName(S) then exit; + if FileExists(S) then exit; + I := LastDelimiter('\/', S); + if (I > 0) then + if (not DirectoryExists(Copy(S, 1, I-1))) then + exit; + Result := True; +end; + + // HOST MESSAGES // @@ -511,6 +543,21 @@ begin else Pl.Spectate; end; + NET_CHEAT_READY: + begin + if gState <> STATE_INTERCUSTOM then Exit; + Pl.FReady := not Pl.FReady; + if Pl.FReady then + begin + MH_SEND_GameEvent(NET_EV_INTER_READY, Pl.UID, 'Y'); + Inc(gInterReadyCount); + end + else + begin + MH_SEND_GameEvent(NET_EV_INTER_READY, Pl.UID, 'N'); + Dec(gInterReadyCount); + end; + end; end; end; @@ -712,6 +759,8 @@ begin 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); @@ -1645,6 +1694,7 @@ var i1, i2: TStrings_Locale; pln: String; cnt: Byte; + goodCmd: Boolean = true; begin FillChar(EvHash, Sizeof(EvHash), 0); EvType := M.ReadByte(); @@ -1660,33 +1710,60 @@ begin gTime := EvTime; + if (g_Res_received_map_start <> 0) then + begin + if (g_Res_received_map_start < 0) then exit; + goodCmd := false; + case EvType of + NET_EV_MAPSTART: goodCmd := true; + NET_EV_MAPEND: goodCmd := true; + NET_EV_PLAYER_KICK: goodCmd := true; + NET_EV_PLAYER_BAN: goodCmd := true; + end; + if not goodCmd then exit; + end; + case EvType of NET_EV_MAPSTART: begin - gGameOn := False; - g_Game_ClearLoading(); - g_Game_StopAllSounds(True); + if (g_Res_received_map_start <> 0) then + begin + g_Res_received_map_start := -1; + end + else + begin + gGameOn := False; + g_Game_ClearLoading(); + g_Game_StopAllSounds(True); - gSwitchGameMode := Byte(EvNum); - gGameSettings.GameMode := gSwitchGameMode; + gSwitchGameMode := Byte(EvNum); + gGameSettings.GameMode := gSwitchGameMode; - gWADHash := EvHash; - if not g_Game_StartMap(EvStr, True) then - begin - if not isWadPath(EvStr) then - g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [gGameSettings.WAD + ':\' + EvStr])) - else - g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [EvStr])); - Exit; - end; + gWADHash := EvHash; + if not g_Game_StartMap(EvStr, True) then + begin + if not isWadPath(EvStr) then + g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [gGameSettings.WAD + ':\' + EvStr])) + else + g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [EvStr])); + Exit; + end; - MC_SEND_FullStateRequest; + MC_SEND_FullStateRequest; + end; end; NET_EV_MAPEND: begin - gMissionFailed := EvNum <> 0; - gExit := EXIT_ENDLEVELCUSTOM; + if (g_Res_received_map_start <> 0) then + begin + g_Res_received_map_start := -1; + end + else + begin + gMissionFailed := EvNum <> 0; + gExit := EXIT_ENDLEVELCUSTOM; + end; end; NET_EV_RCON: @@ -1710,10 +1787,16 @@ begin end; NET_EV_PLAYER_KICK: - g_Console_Add(Format(_lc[I_PLAYER_KICK], [EvStr]), True); + begin + g_Console_Add(Format(_lc[I_PLAYER_KICK], [EvStr]), True); + if (g_Res_received_map_start <> 0) then g_Res_received_map_start := -1; + end; NET_EV_PLAYER_BAN: - g_Console_Add(Format(_lc[I_PLAYER_BAN], [EvStr]), True); + begin + g_Console_Add(Format(_lc[I_PLAYER_BAN], [EvStr]), True); + if (g_Res_received_map_start <> 0) then g_Res_received_map_start := -1; + end; NET_EV_LMS_WARMUP: g_Console_Add(Format(_lc[I_MSG_WARMUP_START], [EvNum]), True); @@ -1842,6 +1925,11 @@ begin end; end; + NET_EV_INTER_READY: + begin + pl := g_Player_Get(EvNum); + if pl <> nil then pl.FReady := (EvStr = 'Y'); + end; end; end; @@ -2555,12 +2643,13 @@ begin MPlaying := M.ReadByte() <> 0; MPos := M.ReadLongWord(); MPaused := M.ReadByte() <> 0; + MPos := MPos+1; //k8: stfu, fpc! if MPlaying then begin gMusic.SetByName(MName); gMusic.Play(True); - gMusic.SetPosition(MPos); + // gMusic.SetPosition(MPos); gMusic.SpecPause := MPaused; end else @@ -2812,13 +2901,17 @@ begin if gPlayerAction[0, ACTION_STRAFE] then begin // new strafe mechanics - if (strafeDir = 0) then strafeDir := P1MoveButton; // start strafing + if (strafeDir = 0) then + strafeDir := P1MoveButton; // start strafing // now set direction according to strafe (reversed) - if (strafeDir = 2) then gPlayer1.SetDirection(TDirection.D_LEFT) - else if (strafeDir = 1) then gPlayer1.SetDirection(TDirection.D_RIGHT); + if (strafeDir = 2) then + gPlayer1.SetDirection(TDirection.D_LEFT) + else if (strafeDir = 1) then + gPlayer1.SetDirection(TDirection.D_RIGHT) end else begin + strafeDir := 0; // not strafing anymore if (P1MoveButton = 2) and gPlayerAction[0, ACTION_MOVELEFT] then gPlayer1.SetDirection(TDirection.D_LEFT) else if (P1MoveButton = 1) and gPlayerAction[0, ACTION_MOVERIGHT] then @@ -2938,201 +3031,5 @@ begin g_Net_Client_Send(True, NET_CHAN_SERVICE); end; -// i have no idea why all this stuff is in here - -function ReadFile(const FileName: TFileName): AByte; -var - FileStream : TStream; - fname: string; -begin - e_WriteLog(Format('NETWORK: looking for file "%s"', [FileName]), TMsgType.Notify); - fname := findDiskWad(FileName); - if length(fname) = 0 then - begin - e_WriteLog(Format('NETWORK: file "%s" not found!', [FileName]), TMsgType.Fatal); - SetLength(Result, 0); - exit; - end; - e_WriteLog(Format('NETWORK: found file "%s"', [fname]), TMsgType.Notify); - Result := nil; - FileStream := openDiskFileRO(fname); - try - if FileStream.Size > 0 then - begin - SetLength(Result, FileStream.Size); - FileStream.Read(Result[0], FileStream.Size); - end; - finally - FileStream.Free; - end; -end; - -function CreateMapDataMsg(const FileName: TFileName; ResList: TStringList): TMapDataMsg; -var - i: Integer; -begin - Result.MsgId := NET_MSG_MAP_RESPONSE; - Result.FileData := ReadFile(FileName); - Result.FileSize := Length(Result.FileData); - - SetLength(Result.ExternalResources, ResList.Count); - for i:=0 to ResList.Count-1 do - begin - Result.ExternalResources[i].Name := ResList.Strings[i]; - Result.ExternalResources[i].md5 := MD5File(GameDir+'/wads/'+ResList.Strings[i]); - end; -end; - -procedure ResDataMsgToBytes(var bytes: AByte; const ResData: TResDataMsg); -var - ResultStream: TMemoryStream; -begin - ResultStream := TMemoryStream.Create; - - 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 - - SetLength(bytes, ResultStream.Size); - ResultStream.Seek(0, soFromBeginning); - ResultStream.ReadBuffer(bytes[0], ResultStream.Size); - - ResultStream.Free; -end; - -function ResDataFromMsgStream(msgStream: TMemoryStream):TResDataMsg; -begin - msgStream.ReadBuffer(Result.MsgId, SizeOf(Result.MsgId)); - msgStream.ReadBuffer(Result.FileSize, SizeOf(Result.FileSize)); - SetLength(Result.FileData, Result.FileSize); - msgStream.ReadBuffer(Result.FileData[0], Result.FileSize); -end; - -procedure MapDataMsgToBytes(var bytes: AByte; const MapDataMsg: TMapDataMsg); -var - ResultStream: TMemoryStream; - resCount: Integer; -begin - resCount := Length(MapDataMsg.ExternalResources); - - ResultStream := TMemoryStream.Create; - - 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 - - ResultStream.WriteBuffer(resCount, SizeOf(resCount)); //res count - ResultStream.WriteBuffer(MapDataMsg.ExternalResources[0], resCount*SizeOf(TExternalResourceInfo)); //res data - - SetLength(bytes, ResultStream.Size); - ResultStream.Seek(0, soFromBeginning); - ResultStream.ReadBuffer(bytes[0], ResultStream.Size); - - ResultStream.Free; -end; - -function MapDataFromMsgStream(msgStream: TMemoryStream):TMapDataMsg; -var - resCount: Integer; -begin - msgStream.ReadBuffer(Result.MsgId, SizeOf(Result.MsgId)); - msgStream.ReadBuffer(Result.FileSize, SizeOf(Result.FileSize)); //file size - - SetLength(Result.FileData, Result.FileSize); - msgStream.ReadBuffer(Result.FileData[0], Result.FileSize); //file data - - msgStream.ReadBuffer(resCount, SizeOf(resCount)); //res count - SetLength(Result.ExternalResources, resCount); - - msgStream.ReadBuffer(Result.ExternalResources[0], resCount * SizeOf(TExternalResourceInfo)); //res data -end; - -function IsValidFileName(const S: String): Boolean; -const - Forbidden: set of Char = ['<', '>', '|', '"', ':', '*', '?']; -var - I: Integer; -begin - Result := S <> ''; - for I := 1 to Length(S) do - Result := Result and (not(S[I] in Forbidden)); -end; - -function IsValidFilePath(const S: String): Boolean; -var - I: Integer; -begin - Result := False; - if not IsValidFileName(S) then exit; - if FileExists(S) then exit; - I := LastDelimiter('\/', S); - if (I > 0) then - if (not DirectoryExists(Copy(S, 1, I-1))) then - exit; - Result := True; -end; - -procedure MC_SEND_MapRequest(); -begin - NetOut.Write(Byte(NET_MSG_MAP_REQUEST)); - g_Net_Client_Send(True, NET_CHAN_IMPORTANT); -end; - -procedure MC_SEND_ResRequest(const resName: AnsiString); -begin - NetOut.Write(Byte(NET_MSG_RES_REQUEST)); - NetOut.Write(resName); - g_Net_Client_Send(True, NET_CHAN_IMPORTANT); -end; - -procedure MH_RECV_MapRequest(C: pTNetClient; var M: TMsg); -var - payload: AByte; - peer: pENetPeer; - mapDataMsg: TMapDataMsg; -begin - e_WriteLog('NET: Received map request from ' + - DecodeIPV4(C^.Peer.address.host), TMsgType.Notify); - - mapDataMsg := CreateMapDataMsg(MapsDir + gGameSettings.WAD, gExternalResources); - peer := NetClients[C^.ID].Peer; - - MapDataMsgToBytes(payload, mapDataMsg); - g_Net_SendData(payload, peer, True, NET_CHAN_DOWNLOAD); - - payload := nil; - mapDataMsg.FileData := nil; - mapDataMsg.ExternalResources := nil; -end; - -procedure MH_RECV_ResRequest(C: pTNetClient; var M: TMsg); -var - payload: AByte; - peer: pENetPeer; - FileName: String; - resDataMsg: TResDataMsg; -begin - FileName := ExtractFileName(M.ReadString()); - e_WriteLog('NET: Received res request: ' + FileName + - ' from ' + DecodeIPV4(C^.Peer.address.host), TMsgType.Notify); - - if not IsValidFilePath(FileName) then - begin - e_WriteLog('Invalid filename: ' + FileName, TMsgType.Warning); - exit; - end; - - peer := NetClients[C^.ID].Peer; - - if gExternalResources.IndexOf(FileName) > -1 then - begin - resDataMsg.MsgId := NET_MSG_RES_RESPONSE; - resDataMsg.FileData := ReadFile(GameDir+'/wads/'+FileName); - resDataMsg.FileSize := Length(resDataMsg.FileData); - - ResDataMsgToBytes(payload, resDataMsg); - g_Net_SendData(payload, peer, True, NET_CHAN_DOWNLOAD); - end; -end; end.