X-Git-Url: http://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=blobdiff_plain;f=src%2Fgame%2Fg_netmsg.pas;h=a7ff31a9639fe68fdf2efdae7e308b54a1683a5d;hp=9b0614dd1dede069f2297c84a61919fe5fbe3bc0;hb=ef4db75afec0dcd71f0bbe75b5f0b20537c8eac1;hpb=af3c404e11867c6794975f1d45dd98932d804ede diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 9b0614d..a7ff31a 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -1,9 +1,24 @@ -{$MODE DELPHI} +(* Copyright (C) Doom 2D: Forever Developers + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} unit g_netmsg; interface -uses g_net, g_triggers, Classes, SysUtils, md5; +uses e_msg, g_net, g_triggers, Classes, SysUtils, md5; const NET_MSG_INFO = 100; @@ -37,8 +52,8 @@ const NET_MSG_MSHOT = 134; NET_MSG_MDEL = 135; - NET_MSG_PSTATE = 141; - NET_MSG_PTEX = 142; + NET_MSG_PSTATE = 141; + NET_MSG_PTEX = 142; NET_MSG_TSOUND = 151; NET_MSG_TMUSIC = 152; @@ -114,24 +129,24 @@ const // HOST MESSAGES -procedure MH_RECV_Info(C: pTNetClient; P: Pointer); -procedure MH_RECV_Chat(C: pTNetClient; P: Pointer); -procedure MH_RECV_FullStateRequest(C: pTNetClient; P: Pointer); -function MH_RECV_PlayerPos(C: pTNetClient; P: Pointer): Word; -procedure MH_RECV_PlayerSettings(C: pTNetClient; P: Pointer); -procedure MH_RECV_CheatRequest(C: pTNetClient; P: Pointer); -procedure MH_RECV_RCONPassword(C: pTNetClient; P: Pointer); -procedure MH_RECV_RCONCommand(C: pTNetClient; P: Pointer); -procedure MH_RECV_MapRequest(C: pTNetClient; P: Pointer); -procedure MH_RECV_ResRequest(C: pTNetClient; P: Pointer); -procedure MH_RECV_Vote(C: pTNetClient; P: Pointer); +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); +function MH_RECV_PlayerPos(C: pTNetClient; var M: TMsg): Word; +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_Vote(C: pTNetClient; var M: TMsg); // GAME 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); -procedure MH_SEND_Sound(X, Y: Integer; Name: string; ID: Integer = NET_EVERYONE); +procedure MH_SEND_Sound(X, Y: Integer; Name: string; Pos: Boolean = True; ID: Integer = NET_EVERYONE); procedure MH_SEND_CreateShot(Proj: LongInt; ID: Integer = NET_EVERYONE); procedure MH_SEND_UpdateShot(Proj: LongInt; ID: Integer = NET_EVERYONE); procedure MH_SEND_DeleteShot(Proj: LongInt; X, Y: LongInt; Loud: Boolean = True; ID: Integer = NET_EVERYONE); @@ -153,8 +168,8 @@ procedure MH_SEND_PlayerSettings(PID: Word; Mdl: string = ''; ID: Integer = NET_ procedure MH_SEND_ItemSpawn(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); procedure MH_SEND_ItemDestroy(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); // PANEL -procedure MH_SEND_PanelTexture(PType: Word; PID: LongWord; AnimLoop: Byte; ID: Integer = NET_EVERYONE); -procedure MH_SEND_PanelState(PType: Word; PID: LongWord; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelState(PGUID: Integer; ID: Integer = NET_EVERYONE); // MONSTER procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE); procedure MH_SEND_MonsterPos(UID: Word; ID: Integer = NET_EVERYONE); @@ -174,45 +189,45 @@ procedure MH_SEND_VoteEvent(EvType: Byte; // CLIENT MESSAGES // // GAME -procedure MC_RECV_Chat(P: Pointer); -procedure MC_RECV_Effect(P: Pointer); -procedure MC_RECV_Sound(P: Pointer); -procedure MC_RECV_GameStats(P: Pointer); -procedure MC_RECV_CoopStats(P: Pointer); -procedure MC_RECV_GameEvent(P: Pointer); -procedure MC_RECV_FlagEvent(P: Pointer); -procedure MC_RECV_GameSettings(P: Pointer); +procedure MC_RECV_Chat(var M: TMsg); +procedure MC_RECV_Effect(var M: TMsg); +procedure MC_RECV_Sound(var M: TMsg); +procedure MC_RECV_GameStats(var M: TMsg); +procedure MC_RECV_CoopStats(var M: TMsg); +procedure MC_RECV_GameEvent(var M: TMsg); +procedure MC_RECV_FlagEvent(var M: TMsg); +procedure MC_RECV_GameSettings(var M: TMsg); // PLAYER -function MC_RECV_PlayerCreate(P: Pointer): Word; -function MC_RECV_PlayerPos(P: Pointer): Word; -function MC_RECV_PlayerStats(P: Pointer): Word; -function MC_RECV_PlayerDelete(P: Pointer): Word; -function MC_RECV_PlayerDamage(P: Pointer): Word; -function MC_RECV_PlayerDeath(P: Pointer): Word; -function MC_RECV_PlayerFire(P: Pointer): Word; -procedure MC_RECV_PlayerSettings(P: Pointer); +function MC_RECV_PlayerCreate(var M: TMsg): Word; +function MC_RECV_PlayerPos(var M: TMsg): Word; +function MC_RECV_PlayerStats(var M: TMsg): Word; +function MC_RECV_PlayerDelete(var M: TMsg): Word; +function MC_RECV_PlayerDamage(var M: TMsg): Word; +function MC_RECV_PlayerDeath(var M: TMsg): Word; +function MC_RECV_PlayerFire(var M: TMsg): Word; +procedure MC_RECV_PlayerSettings(var M: TMsg); // ITEM -procedure MC_RECV_ItemSpawn(P: Pointer); -procedure MC_RECV_ItemDestroy(P: Pointer); +procedure MC_RECV_ItemSpawn(var M: TMsg); +procedure MC_RECV_ItemDestroy(var M: TMsg); // PANEL -procedure MC_RECV_PanelTexture(P: Pointer); -procedure MC_RECV_PanelState(P: Pointer); +procedure MC_RECV_PanelTexture(var M: TMsg); +procedure MC_RECV_PanelState(var M: TMsg); // MONSTER -procedure MC_RECV_MonsterSpawn(P: Pointer); -procedure MC_RECV_MonsterPos(P: Pointer); -procedure MC_RECV_MonsterState(P: Pointer); -procedure MC_RECV_MonsterShot(P: Pointer); -procedure MC_RECV_MonsterDelete(P: Pointer); +procedure MC_RECV_MonsterSpawn(var M: TMsg); +procedure MC_RECV_MonsterPos(var M: TMsg); +procedure MC_RECV_MonsterState(var M: TMsg); +procedure MC_RECV_MonsterShot(var M: TMsg); +procedure MC_RECV_MonsterDelete(var M: TMsg); // SHOT -procedure MC_RECV_CreateShot(P: Pointer); -procedure MC_RECV_UpdateShot(P: Pointer); -procedure MC_RECV_DeleteShot(P: Pointer); +procedure MC_RECV_CreateShot(var M: TMsg); +procedure MC_RECV_UpdateShot(var M: TMsg); +procedure MC_RECV_DeleteShot(var M: TMsg); // TRIGGER -procedure MC_RECV_TriggerSound(P: Pointer); -procedure MC_RECV_TriggerMusic(P: Pointer); +procedure MC_RECV_TriggerSound(var M: TMsg); +procedure MC_RECV_TriggerMusic(var M: TMsg); // MISC -procedure MC_RECV_TimeSync(P: Pointer); -procedure MC_RECV_VoteEvent(P: Pointer); +procedure MC_RECV_TimeSync(var M: TMsg); +procedure MC_RECV_VoteEvent(var M: TMsg); // SERVICE procedure MC_SEND_Info(Password: string); procedure MC_SEND_Chat(Txt: string; Mode: Byte); @@ -252,7 +267,7 @@ function ResDataFromMsgStream(msgStream: TMemoryStream):TResDataMsg; implementation uses - Math, ENet, e_input, e_fixedbuffer, e_graphics, e_log, + Math, ENet, e_input, e_graphics, e_log, g_textures, g_gfx, g_sound, g_console, g_basic, g_options, g_main, g_game, g_player, g_map, g_panel, g_items, g_weapons, g_phys, g_gui, g_language, g_monsters, g_netmaster, utils, wadreader, MAPDEF; @@ -280,7 +295,7 @@ const // GAME -procedure MH_RECV_Chat(C: pTNetClient; P: Pointer); +procedure MH_RECV_Chat(C: pTNetClient; var M: TMsg); var Txt: string; Mode: Byte; @@ -290,8 +305,8 @@ begin PID := C^.Player; Pl := g_Player_Get(PID); - Txt := e_Raw_Read_String(P); - Mode := e_Raw_Read_Byte(P); + Txt := M.ReadString(); + Mode := M.ReadByte(); if (Mode = NET_CHAT_SYSTEM) then Mode := NET_CHAT_PLAYER; // prevent sending system messages from clients if (Mode = NET_CHAT_TEAM) and (not gGameSettings.GameMode in [GM_TDM, GM_CTF]) then @@ -303,7 +318,7 @@ begin MH_SEND_Chat(Pl.Name + ': ' + Txt, Mode, IfThen(Mode = NET_CHAT_TEAM, Pl.Team, NET_EVERYONE)); end; -procedure MH_RECV_Info(C: pTNetClient; P: Pointer); +procedure MH_RECV_Info(C: pTNetClient; var M: TMsg); var Ver, PName, Model, Pw: string; R, G, B, T: Byte; @@ -311,14 +326,14 @@ var Color: TRGB; I: Integer; begin - Ver := e_Raw_Read_String(P); - Pw := e_Raw_Read_String(P); - PName := e_Raw_Read_String(P); - Model := e_Raw_Read_String(P); - R := e_Raw_Read_Byte(P); - G := e_Raw_Read_Byte(P); - B := e_Raw_Read_Byte(P); - T := e_Raw_Read_Byte(P); + Ver := M.ReadString(); + Pw := M.ReadString(); + PName := M.ReadString(); + Model := M.ReadString(); + R := M.ReadByte(); + G := M.ReadByte(); + B := M.ReadByte(); + T := M.ReadByte(); if Ver <> GAME_VERSION then begin @@ -369,7 +384,7 @@ begin g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True); e_WriteLog('NET: Client ' + PName + ' [' + IntToStr(C^.ID) + - '] connected. Assigned player #' + IntToStr(PID) + '.', MSG_NOTIFY); + '] connected. Assigned player #' + IntToStr(PID) + '.', TMsgType.Notify); MH_SEND_Info(C^.ID); @@ -403,7 +418,7 @@ begin if NetUseMaster then g_Net_Slist_Update; end; -procedure MH_RECV_FullStateRequest(C: pTNetClient; P: Pointer); +procedure MH_RECV_FullStateRequest(C: pTNetClient; var M: TMsg); begin if gGameOn then MH_SEND_Everything((C^.State = NET_STATE_AUTH), C^.ID) @@ -413,9 +428,10 @@ end; // PLAYER -function MH_RECV_PlayerPos(C: pTNetClient; P: Pointer): Word; +function MH_RECV_PlayerPos(C: pTNetClient; var M: TMsg): Word; var - Dir: Byte; + Dir, i: Byte; + WeaponSelect: Word; PID: Word; kByte: Word; Pl: TPlayer; @@ -424,7 +440,7 @@ begin Result := 0; if not gGameOn then Exit; - GT := e_Raw_Read_LongWord(P); + GT := M.ReadLongWord(); PID := C^.Player; Pl := g_Player_Get(PID); if Pl = nil then @@ -435,10 +451,13 @@ begin with Pl do begin NetTime := GT; - kByte := e_Raw_Read_Word(P); - Dir := e_Raw_Read_Byte(P); + kByte := M.ReadWord(); + Dir := M.ReadByte(); + WeaponSelect := M.ReadWord(); + //e_WriteLog(Format('R:ws=%d', [WeaponSelect]), MSG_WARNING); if Direction <> TDirection(Dir) then JustTeleported := False; + SetDirection(TDirection(Dir)); ReleaseKeys; @@ -457,12 +476,21 @@ begin if LongBool(kByte and NET_KEY_OPEN) then PressKey(KEY_OPEN, 10000); if LongBool(kByte and NET_KEY_NW) then PressKey(KEY_NEXTWEAPON, 10000); if LongBool(kByte and NET_KEY_PW) then PressKey(KEY_PREVWEAPON, 10000); + + for i := 0 to 15 do + begin + if (WeaponSelect and Word(1 shl i)) <> 0 then + begin + //e_WriteLog(Format(' R:wn=%d', [i]), MSG_WARNING); + QueueWeaponSwitch(i); + end; + end; end; // MH_SEND_PlayerPos(False, PID, C^.ID); end; -procedure MH_RECV_CheatRequest(C: pTNetClient; P: Pointer); +procedure MH_RECV_CheatRequest(C: pTNetClient; var M: TMsg); var CheatKind: Byte; Pl: TPlayer; @@ -470,7 +498,7 @@ begin Pl := g_Player_Get(C^.Player); if Pl = nil then Exit; - CheatKind := e_Raw_Read_Byte(P); + CheatKind := M.ReadByte(); case CheatKind of NET_CHEAT_SUICIDE: @@ -485,7 +513,7 @@ begin end; end; -procedure MH_RECV_PlayerSettings(C: pTNetClient; P: Pointer); +procedure MH_RECV_PlayerSettings(C: pTNetClient; var M: TMsg); var TmpName: string; TmpModel: string; @@ -493,12 +521,12 @@ var TmpTeam: Byte; Pl: TPlayer; begin - TmpName := e_Raw_Read_String(P); - TmpModel := e_Raw_Read_String(P); - TmpColor.R := e_Raw_Read_Byte(P); - TmpColor.G := e_Raw_Read_Byte(P); - TmpColor.B := e_Raw_Read_Byte(P); - TmpTeam := e_Raw_Read_Byte(P); + TmpName := M.ReadString(); + TmpModel := M.ReadString(); + TmpColor.R := M.ReadByte(); + TmpColor.G := M.ReadByte(); + TmpColor.B := M.ReadByte(); + TmpTeam := M.ReadByte(); Pl := g_Player_Get(C^.Player); if Pl = nil then Exit; @@ -522,11 +550,11 @@ end; // RCON -procedure MH_RECV_RCONPassword(C: pTNetClient; P: Pointer); +procedure MH_RECV_RCONPassword(C: pTNetClient; var M: TMsg); var Pwd: string; begin - Pwd := e_Raw_Read_String(P); + Pwd := M.ReadString(); if not NetAllowRCON then Exit; if Pwd = NetRCONPassword then begin @@ -537,11 +565,11 @@ begin MH_SEND_GameEvent(NET_EV_RCON, NET_RCON_PWBAD, 'N', C^.ID); end; -procedure MH_RECV_RCONCommand(C: pTNetClient; P: Pointer); +procedure MH_RECV_RCONCommand(C: pTNetClient; var M: TMsg); var Cmd: string; begin - Cmd := e_Raw_Read_String(P); + Cmd := M.ReadString(); if not NetAllowRCON then Exit; if not C^.RCONAuth then begin @@ -553,15 +581,15 @@ end; // MISC -procedure MH_RECV_Vote(C: pTNetClient; P: Pointer); +procedure MH_RECV_Vote(C: pTNetClient; var M: TMsg); var Start: Boolean; Name, Command: string; Need: Integer; Pl: TPlayer; begin - Start := e_Raw_Read_Byte(P) <> 0; - Command := e_Raw_Read_String(P); + Start := M.ReadByte() <> 0; + Command := M.ReadString(); Pl := g_Player_Get(C^.Player); if Pl = nil then Exit; @@ -599,11 +627,33 @@ end; // GAME (SEND) procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_EVERYONE); + + function sendItemRespawn (it: PItem): Boolean; + begin + result := false; // don't stop + MH_SEND_ItemSpawn(True, it.myid, ID); + end; + + function sendMonSpawn (mon: TMonster): Boolean; + begin + result := false; // don't stop + MH_SEND_MonsterSpawn(mon.UID, ID); + end; + + function sendPanelState (pan: TPanel): Boolean; + begin + result := false; // don't stop + MH_SEND_PanelState(pan.guid, ID); // anyway, to sync mplats + if (pan.CanChangeTexture) then MH_SEND_PanelTexture(pan.guid, pan.LastAnimLoop, ID); + end; + var I: Integer; begin if gPlayers <> nil then + begin for I := Low(gPlayers) to High(gPlayers) do + begin if gPlayers[I] <> nil then begin if CreatePlayers then MH_SEND_PlayerCreate(gPlayers[I].UID, ID); @@ -611,85 +661,38 @@ begin MH_SEND_PlayerStats(gPlayers[I].UID, ID); if (gPlayers[I].Flag <> FLAG_NONE) and (gGameSettings.GameMode = GM_CTF) then + begin MH_SEND_FlagEvent(FLAG_STATE_CAPTURED, gPlayers[I].Flag, gPlayers[I].UID, True, ID); + end; end; - - if gItems <> nil then - begin - for I := High(gItems) downto Low(gItems) do - if gItems[I].Live then - MH_SEND_ItemSpawn(True, I, ID); + end; end; - if gMonsters <> nil then - for I := 0 to High(gMonsters) do - if gMonsters[I] <> nil then - MH_SEND_MonsterSpawn(gMonsters[I].UID, ID); - - if gWalls <> nil then - for I := Low(gWalls) to High(gWalls) do - if gWalls[I] <> nil then - with gWalls[I] do - begin - if Door then - MH_SEND_PanelState(PanelType, I, ID); - - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - end; - - if gLifts <> nil then - for I := Low(gLifts) to High(gLifts) do - if gLifts[I] <> nil then - with gLifts[I] do - MH_SEND_PanelState(PanelType, I, ID); - - if gRenderForegrounds <> nil then - for I := Low(gRenderForegrounds) to High(gRenderForegrounds) do - if gRenderForegrounds[I] <> nil then - with gRenderForegrounds[I] do - if (GetTextureCount > 1) then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gRenderBackgrounds <> nil then - for I := Low(gRenderBackgrounds) to High(gRenderBackgrounds) do - if gRenderBackgrounds[I] <> nil then - with gRenderBackgrounds[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gWater <> nil then - for I := Low(gWater) to High(gWater) do - if gWater[I] <> nil then - with gWater[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gAcid1 <> nil then - for I := Low(gAcid1) to High(gAcid1) do - if gAcid1[I] <> nil then - with gAcid1[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gAcid2 <> nil then - for I := Low(gAcid2) to High(gAcid2) do - if gAcid2[I] <> nil then - with gAcid2[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gSteps <> nil then - for I := Low(gSteps) to High(gSteps) do - if gSteps[I] <> nil then - with gSteps[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); + g_Items_ForEachAlive(sendItemRespawn, true); // backwards + g_Mons_ForEach(sendMonSpawn); + g_Map_ForEachPanel(sendPanelState); if gTriggers <> nil then + begin for I := Low(gTriggers) to High(gTriggers) do + begin if gTriggers[I].TriggerType = TRIGGER_SOUND then + begin MH_SEND_TriggerSound(gTriggers[I], ID); + end; + end; + end; if Shots <> nil then + begin for I := Low(Shots) to High(Shots) do + begin if Shots[i].ShotType in [6, 7, 8] then + begin MH_SEND_CreateShot(i, ID); + end; + end; + end; MH_SEND_TriggerMusic(ID); @@ -698,16 +701,16 @@ begin if gGameSettings.GameMode = GM_CTF then begin - if gFlags[FLAG_RED].State <> FLAG_STATE_CAPTURED then - MH_SEND_FlagEvent(gFlags[FLAG_RED].State, FLAG_RED, 0, True, ID); - if gFlags[FLAG_BLUE].State <> FLAG_STATE_CAPTURED then - MH_SEND_FlagEvent(gFlags[FLAG_BLUE].State, FLAG_BLUE, 0, True, ID); + if gFlags[FLAG_RED].State <> FLAG_STATE_CAPTURED then MH_SEND_FlagEvent(gFlags[FLAG_RED].State, FLAG_RED, 0, True, ID); + if gFlags[FLAG_BLUE].State <> FLAG_STATE_CAPTURED then MH_SEND_FlagEvent(gFlags[FLAG_BLUE].State, FLAG_BLUE, 0, True, ID); end; 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; end; procedure MH_SEND_Info(ID: Byte); @@ -716,20 +719,20 @@ var begin Map := g_ExtractFileName(gMapInfo.Map); - e_Buffer_Clear(@NetOut); - - e_Buffer_Write(@NetOut, Byte(NET_MSG_INFO)); - e_Buffer_Write(@NetOut, ID); - e_Buffer_Write(@NetOut, NetClients[ID].Player); - e_Buffer_Write(@NetOut, gGameSettings.WAD); - e_Buffer_Write(@NetOut, Map); - e_Buffer_Write(@NetOut, gWADHash); - e_Buffer_Write(@NetOut, gGameSettings.GameMode); - e_Buffer_Write(@NetOut, gGameSettings.GoalLimit); - e_Buffer_Write(@NetOut, gGameSettings.TimeLimit); - e_Buffer_Write(@NetOut, gGameSettings.MaxLives); - e_Buffer_Write(@NetOut, gGameSettings.Options); - e_Buffer_Write(@NetOut, gTime); + 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(gWADHash); + NetOut.Write(gGameSettings.GameMode); + NetOut.Write(gGameSettings.GoalLimit); + NetOut.Write(gGameSettings.TimeLimit); + NetOut.Write(gGameSettings.MaxLives); + NetOut.Write(gGameSettings.Options); + NetOut.Write(gTime); g_Net_Host_Send(ID, True, NET_CHAN_SERVICE); end; @@ -750,9 +753,9 @@ begin if (gPlayers[i] <> nil) and (gPlayers[i].FClientID >= 0) and (gPlayers[i].Team = ID) then begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_CHAT)); - e_Buffer_Write(@NetOut, Txt); - e_Buffer_Write(@NetOut, Mode); + NetOut.Write(Byte(NET_MSG_CHAT)); + NetOut.Write(Txt); + NetOut.Write(Mode); g_Net_Host_Send(gPlayers[i].FClientID, True, NET_CHAN_CHAT); end; Team := ID; @@ -760,9 +763,9 @@ begin end else begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_CHAT)); - e_Buffer_Write(@NetOut, Txt); - e_Buffer_Write(@NetOut, Mode); + NetOut.Write(Byte(NET_MSG_CHAT)); + NetOut.Write(Txt); + NetOut.Write(Mode); g_Net_Host_Send(ID, True, NET_CHAN_CHAT); end; @@ -774,8 +777,8 @@ begin if Mode = NET_CHAT_PLAYER then begin g_Console_Add(Txt, True); - e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end else if Mode = NET_CHAT_TEAM then @@ -784,14 +787,14 @@ begin if (gPlayer1.Team = TEAM_RED) and (Team = TEAM_RED) then begin g_Console_Add(#18'[Team] '#2 + Txt, True); - e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end else if (gPlayer1.Team = TEAM_BLUE) and (Team = TEAM_BLUE) then begin g_Console_Add(#20'[Team] '#2 + Txt, True); - e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end; end; end @@ -799,28 +802,34 @@ begin begin Name := g_Net_ClientName_ByID(ID); g_Console_Add('-> ' + Name + ': ' + Txt, True); - e_WriteLog('[Tell ' + Name + '] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Tell ' + Name + '] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt), False); end; end; procedure MH_SEND_Effect(X, Y: Integer; Ang: SmallInt; Kind: Byte; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_GFX)); - e_Buffer_Write(@NetOut, Kind); - e_Buffer_Write(@NetOut, X); - e_Buffer_Write(@NetOut, Y); - e_Buffer_Write(@NetOut, Ang); + NetOut.Write(Byte(NET_MSG_GFX)); + NetOut.Write(Kind); + NetOut.Write(X); + NetOut.Write(Y); + NetOut.Write(Ang); g_Net_Host_Send(ID, False, NET_CHAN_GAME); end; -procedure MH_SEND_Sound(X, Y: Integer; Name: string; ID: Integer = NET_EVERYONE); +procedure MH_SEND_Sound(X, Y: Integer; Name: string; Pos: Boolean = True; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_SND)); - e_Buffer_Write(@NetOut, Name); - e_Buffer_Write(@NetOut, X); - e_Buffer_Write(@NetOut, Y); + NetOut.Write(Byte(NET_MSG_SND)); + NetOut.Write(Name); + if Pos then + begin + NetOut.Write(Byte(1)); + NetOut.Write(X); + NetOut.Write(Y); + end + else + NetOut.Write(Byte(0)); g_Net_Host_Send(ID, False, NET_CHAN_GAME); end; @@ -829,16 +838,16 @@ procedure MH_SEND_CreateShot(Proj: LongInt; ID: Integer = NET_EVERYONE); begin if (Shots = nil) or (Proj < 0) or (Proj > High(Shots)) then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_SHADD)); - e_Buffer_Write(@NetOut, Proj); - e_Buffer_Write(@NetOut, Shots[Proj].ShotType); - e_Buffer_Write(@NetOut, Shots[Proj].Target); - e_Buffer_Write(@NetOut, Shots[Proj].SpawnerUID); - e_Buffer_Write(@NetOut, Shots[Proj].Timeout); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.X); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.Y); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.Vel.X); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.Vel.Y); + NetOut.Write(Byte(NET_MSG_SHADD)); + NetOut.Write(Proj); + NetOut.Write(Shots[Proj].ShotType); + NetOut.Write(Shots[Proj].Target); + NetOut.Write(Shots[Proj].SpawnerUID); + NetOut.Write(Shots[Proj].Timeout); + NetOut.Write(Shots[Proj].Obj.X); + NetOut.Write(Shots[Proj].Obj.Y); + NetOut.Write(Shots[Proj].Obj.Vel.X); + NetOut.Write(Shots[Proj].Obj.Vel.Y); g_Net_Host_Send(ID, True, NET_CHAN_SHOTS); end; @@ -847,40 +856,40 @@ procedure MH_SEND_UpdateShot(Proj: LongInt; ID: Integer = NET_EVERYONE); begin if (Shots = nil) or (Proj < 0) or (Proj > High(Shots)) then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_SHPOS)); - e_Buffer_Write(@NetOut, Proj); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.X); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.Y); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.Vel.X); - e_Buffer_Write(@NetOut, Shots[Proj].Obj.Vel.Y); + NetOut.Write(Byte(NET_MSG_SHPOS)); + NetOut.Write(Proj); + NetOut.Write(Shots[Proj].Obj.X); + NetOut.Write(Shots[Proj].Obj.Y); + NetOut.Write(Shots[Proj].Obj.Vel.X); + NetOut.Write(Shots[Proj].Obj.Vel.Y); g_Net_Host_Send(ID, False, NET_CHAN_SHOTS); end; procedure MH_Send_DeleteShot(Proj: LongInt; X, Y: LongInt; Loud: Boolean = True; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_SHDEL)); - e_Buffer_Write(@NetOut, Proj); - e_Buffer_Write(@NetOut, Byte(Loud)); - e_Buffer_Write(@NetOut, X); - e_Buffer_Write(@NetOut, Y); + NetOut.Write(Byte(NET_MSG_SHDEL)); + NetOut.Write(Proj); + NetOut.Write(Byte(Loud)); + NetOut.Write(X); + NetOut.Write(Y); g_Net_Host_Send(ID, True, NET_CHAN_SHOTS); end; procedure MH_SEND_GameStats(ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_SCORE)); + NetOut.Write(Byte(NET_MSG_SCORE)); if gGameSettings.GameMode in [GM_TDM, GM_CTF] then begin - e_Buffer_Write(@NetOut, gTeamStat[TEAM_RED].Goals); - e_Buffer_Write(@NetOut, gTeamStat[TEAM_BLUE].Goals); + NetOut.Write(gTeamStat[TEAM_RED].Goals); + NetOut.Write(gTeamStat[TEAM_BLUE].Goals); end else if gGameSettings.GameMode = GM_COOP then begin - e_Buffer_Write(@NetOut, gCoopMonstersKilled); - e_Buffer_Write(@NetOut, gCoopSecretsFound); + NetOut.Write(gCoopMonstersKilled); + NetOut.Write(gCoopSecretsFound); end; g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT); @@ -888,58 +897,58 @@ end; procedure MH_SEND_CoopStats(ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_COOP)); - e_Buffer_Write(@NetOut, gTotalMonsters); - e_Buffer_Write(@NetOut, gSecretsCount); - e_Buffer_Write(@NetOut, gCoopTotalMonstersKilled); - e_Buffer_Write(@NetOut, gCoopTotalSecretsFound); - e_Buffer_Write(@NetOut, gCoopTotalMonsters); - e_Buffer_Write(@NetOut, gCoopTotalSecrets); + NetOut.Write(Byte(NET_MSG_COOP)); + NetOut.Write(gTotalMonsters); + NetOut.Write(gSecretsCount); + NetOut.Write(gCoopTotalMonstersKilled); + NetOut.Write(gCoopTotalSecretsFound); + NetOut.Write(gCoopTotalMonsters); + NetOut.Write(gCoopTotalSecrets); end; procedure MH_SEND_GameEvent(EvType: Byte; EvNum: Integer = 0; EvStr: string = 'N'; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_GEVENT)); - e_Buffer_Write(@NetOut, EvType); - e_Buffer_Write(@NetOut, EvNum); - e_Buffer_Write(@NetOut, EvStr); - e_Buffer_Write(@NetOut, Byte(gLastMap)); - e_Buffer_Write(@NetOut, gTime); - if (EvType = NET_EV_MAPSTART) and (Pos(':\', EvStr) > 0) then + NetOut.Write(Byte(NET_MSG_GEVENT)); + NetOut.Write(EvType); + NetOut.Write(EvNum); + NetOut.Write(EvStr); + NetOut.Write(Byte(gLastMap)); + NetOut.Write(gTime); + if (EvType = NET_EV_MAPSTART) and isWadPath(EvStr) then begin - e_Buffer_Write(@NetOut, Byte(1)); - e_Buffer_Write(@NetOut, gWADHash); + NetOut.Write(Byte(1)); + NetOut.Write(gWADHash); end else - e_Buffer_Write(@NetOut, Byte(0)); + NetOut.Write(Byte(0)); g_Net_Host_Send(ID, True, NET_CHAN_SERVICE); end; procedure MH_SEND_FlagEvent(EvType: Byte; Flag: Byte; PID: Word; Quiet: Boolean = False; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_FLAG)); - e_Buffer_Write(@NetOut, EvType); - e_Buffer_Write(@NetOut, Flag); - e_Buffer_Write(@NetOut, Byte(Quiet)); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, gFlags[Flag].State); - e_Buffer_Write(@NetOut, gFlags[Flag].CaptureTime); - e_Buffer_Write(@NetOut, gFlags[Flag].Obj.X); - e_Buffer_Write(@NetOut, gFlags[Flag].Obj.Y); - e_Buffer_Write(@NetOut, gFlags[Flag].Obj.Vel.X); - e_Buffer_Write(@NetOut, gFlags[Flag].Obj.Vel.Y); + NetOut.Write(Byte(NET_MSG_FLAG)); + NetOut.Write(EvType); + NetOut.Write(Flag); + NetOut.Write(Byte(Quiet)); + NetOut.Write(PID); + NetOut.Write(gFlags[Flag].State); + NetOut.Write(gFlags[Flag].CaptureTime); + NetOut.Write(gFlags[Flag].Obj.X); + NetOut.Write(gFlags[Flag].Obj.Y); + NetOut.Write(gFlags[Flag].Obj.Vel.X); + NetOut.Write(gFlags[Flag].Obj.Vel.Y); g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT); end; procedure MH_SEND_GameSettings(ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_GSET)); - e_Buffer_Write(@NetOut, gGameSettings.GameMode); - e_Buffer_Write(@NetOut, gGameSettings.GoalLimit); - e_Buffer_Write(@NetOut, gGameSettings.TimeLimit); - e_Buffer_Write(@NetOut, gGameSettings.MaxLives); - e_Buffer_Write(@NetOut, gGameSettings.Options); + NetOut.Write(Byte(NET_MSG_GSET)); + NetOut.Write(gGameSettings.GameMode); + NetOut.Write(gGameSettings.GoalLimit); + NetOut.Write(gGameSettings.TimeLimit); + NetOut.Write(gGameSettings.MaxLives); + NetOut.Write(gGameSettings.Options); g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT); end; @@ -953,15 +962,15 @@ begin P := g_Player_Get(PID); if P = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLR)); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, P.Name); + NetOut.Write(Byte(NET_MSG_PLR)); + NetOut.Write(PID); + NetOut.Write(P.Name); - e_Buffer_Write(@NetOut, P.FActualModelName); - e_Buffer_Write(@NetOut, P.FColor.R); - e_Buffer_Write(@NetOut, P.FColor.G); - e_Buffer_Write(@NetOut, P.FColor.B); - e_Buffer_Write(@NetOut, P.Team); + NetOut.Write(P.FActualModelName); + NetOut.Write(P.FColor.R); + NetOut.Write(P.FColor.G); + NetOut.Write(P.FColor.B); + NetOut.Write(P.Team); g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT) end; @@ -975,16 +984,16 @@ begin if Pl = nil then Exit; if Pl.FDummy then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRPOS)); - e_Buffer_Write(@NetOut, gTime); - e_Buffer_Write(@NetOut, PID); + NetOut.Write(Byte(NET_MSG_PLRPOS)); + NetOut.Write(gTime); + NetOut.Write(PID); kByte := 0; with Pl do begin - e_Buffer_Write(@NetOut, FPing); - e_Buffer_Write(@NetOut, FLoss); + NetOut.Write(FPing); + NetOut.Write(FLoss); if IsKeyPressed(KEY_CHAT) then kByte := NET_KEY_CHAT else @@ -997,14 +1006,14 @@ begin if JustTeleported then kByte := kByte or NET_KEY_FORCEDIR; end; - e_Buffer_Write(@NetOut, kByte); - if Direction = D_LEFT then e_Buffer_Write(@NetOut, Byte(0)) else e_Buffer_Write(@NetOut, Byte(1)); - e_Buffer_Write(@NetOut, GameX); - e_Buffer_Write(@NetOut, GameY); - e_Buffer_Write(@NetOut, GameVelX); - e_Buffer_Write(@NetOut, GameVelY); - e_Buffer_Write(@NetOut, GameAccelX); - e_Buffer_Write(@NetOut, GameAccelY); + NetOut.Write(kByte); + if Direction = TDirection.D_LEFT then NetOut.Write(Byte(0)) else NetOut.Write(Byte(1)); + NetOut.Write(GameX); + NetOut.Write(GameY); + NetOut.Write(GameVelX); + NetOut.Write(GameVelY); + NetOut.Write(GameAccelX); + NetOut.Write(GameAccelY); end; g_Net_Host_Send(ID, Reliable, NET_CHAN_PLAYERPOS); @@ -1018,48 +1027,49 @@ begin P := g_Player_Get(PID); if P = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRSTA)); - e_Buffer_Write(@NetOut, PID); + NetOut.Write(Byte(NET_MSG_PLRSTA)); + NetOut.Write(PID); with P do begin - e_Buffer_Write(@NetOut, Byte(Live)); - e_Buffer_Write(@NetOut, Byte(GodMode)); - e_Buffer_Write(@NetOut, Health); - e_Buffer_Write(@NetOut, Armor); - e_Buffer_Write(@NetOut, Air); - e_Buffer_Write(@NetOut, JetFuel); - e_Buffer_Write(@NetOut, Lives); - e_Buffer_Write(@NetOut, Team); + NetOut.Write(Byte(alive)); + NetOut.Write(Byte(GodMode)); + NetOut.Write(Health); + NetOut.Write(Armor); + NetOut.Write(Air); + NetOut.Write(JetFuel); + NetOut.Write(Lives); + NetOut.Write(Team); - for I := WEAPON_KASTET to WEAPON_SUPERPULEMET do - e_Buffer_Write(@NetOut, Byte(FWeapon[I])); + for I := WP_FIRST to WP_LAST do + NetOut.Write(Byte(FWeapon[I])); - for I := A_BULLETS to A_CELLS do - e_Buffer_Write(@NetOut, FAmmo[I]); + for I := A_BULLETS to A_HIGH do + NetOut.Write(FAmmo[I]); - for I := A_BULLETS to A_CELLS do - e_Buffer_Write(@NetOut, FMaxAmmo[I]); + for I := A_BULLETS to A_HIGH do + NetOut.Write(FMaxAmmo[I]); for I := MR_SUIT to MR_MAX do - e_Buffer_Write(@NetOut, LongWord(FMegaRulez[I])); + NetOut.Write(LongWord(FMegaRulez[I])); - e_Buffer_Write(@NetOut, Byte(R_ITEM_BACKPACK in FRulez)); - e_Buffer_Write(@NetOut, Byte(R_KEY_RED in FRulez)); - e_Buffer_Write(@NetOut, Byte(R_KEY_GREEN in FRulez)); - e_Buffer_Write(@NetOut, Byte(R_KEY_BLUE in FRulez)); - e_Buffer_Write(@NetOut, Byte(R_BERSERK in FRulez)); + NetOut.Write(Byte(R_ITEM_BACKPACK in FRulez)); + NetOut.Write(Byte(R_KEY_RED in FRulez)); + NetOut.Write(Byte(R_KEY_GREEN in FRulez)); + NetOut.Write(Byte(R_KEY_BLUE in FRulez)); + NetOut.Write(Byte(R_BERSERK in FRulez)); - e_Buffer_Write(@NetOut, Frags); - e_Buffer_Write(@NetOut, Death); + NetOut.Write(Frags); + NetOut.Write(Death); - e_Buffer_Write(@NetOut, CurrWeap); + NetOut.Write(CurrWeap); - e_Buffer_Write(@NetOut, Byte(FSpectator)); - e_Buffer_Write(@NetOut, Byte(FGhost)); - e_Buffer_Write(@NetOut, Byte(FPhysics)); - e_Buffer_Write(@NetOut, Byte(FNoRespawn)); - e_Buffer_Write(@NetOut, Byte(FJetpack)); + NetOut.Write(Byte(FSpectator)); + NetOut.Write(Byte(FGhost)); + NetOut.Write(Byte(FPhysics)); + NetOut.Write(Byte(FNoRespawn)); + NetOut.Write(Byte(FJetpack)); + NetOut.Write(FFireTime); end; g_Net_Host_Send(ID, True, NET_CHAN_PLAYER); @@ -1067,46 +1077,46 @@ end; procedure MH_SEND_PlayerDamage(PID: Word; Kind: Byte; Attacker, Value: Word; VX, VY: Integer; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRDMG)); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, Kind); - e_Buffer_Write(@NetOut, Attacker); - e_Buffer_Write(@NetOut, Value); - e_Buffer_Write(@NetOut, VX); - e_Buffer_Write(@NetOut, VY); + NetOut.Write(Byte(NET_MSG_PLRDMG)); + NetOut.Write(PID); + NetOut.Write(Kind); + NetOut.Write(Attacker); + NetOut.Write(Value); + NetOut.Write(VX); + NetOut.Write(VY); g_Net_Host_Send(ID, False, NET_CHAN_PLAYER); end; procedure MH_SEND_PlayerDeath(PID: Word; KillType, DeathType: Byte; Attacker: Word; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRDIE)); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, KillType); - e_Buffer_Write(@NetOut, DeathType); - e_Buffer_Write(@NetOut, Attacker); + NetOut.Write(Byte(NET_MSG_PLRDIE)); + NetOut.Write(PID); + NetOut.Write(KillType); + NetOut.Write(DeathType); + NetOut.Write(Attacker); g_Net_Host_Send(ID, True, NET_CHAN_PLAYER); end; procedure MH_SEND_PlayerFire(PID: Word; Weapon: Byte; X, Y, AX, AY: Integer; ShotID: Integer = -1; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRFIRE)); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, Weapon); - e_Buffer_Write(@NetOut, X); - e_Buffer_Write(@NetOut, Y); - e_Buffer_Write(@NetOut, AX); - e_Buffer_Write(@NetOut, AY); - e_Buffer_Write(@NetOut, ShotID); + NetOut.Write(Byte(NET_MSG_PLRFIRE)); + NetOut.Write(PID); + NetOut.Write(Weapon); + NetOut.Write(X); + NetOut.Write(Y); + NetOut.Write(AX); + NetOut.Write(AY); + NetOut.Write(ShotID); g_Net_Host_Send(ID, True, NET_CHAN_SHOTS); end; procedure MH_SEND_PlayerDelete(PID: Word; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRDEL)); - e_Buffer_Write(@NetOut, PID); + NetOut.Write(Byte(NET_MSG_PLRDEL)); + NetOut.Write(PID); g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT); end; @@ -1118,17 +1128,17 @@ begin Pl := g_Player_Get(PID); if Pl = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRSET)); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, Pl.Name); + NetOut.Write(Byte(NET_MSG_PLRSET)); + NetOut.Write(PID); + NetOut.Write(Pl.Name); if Mdl = '' then - e_Buffer_Write(@NetOut, Pl.Model.Name) + NetOut.Write(Pl.Model.Name) else - e_Buffer_Write(@NetOut, Mdl); - e_Buffer_Write(@NetOut, Pl.FColor.R); - e_Buffer_Write(@NetOut, Pl.FColor.G); - e_Buffer_Write(@NetOut, Pl.FColor.B); - e_Buffer_Write(@NetOut, Pl.Team); + NetOut.Write(Mdl); + NetOut.Write(Pl.FColor.R); + NetOut.Write(Pl.FColor.G); + NetOut.Write(Pl.FColor.B); + NetOut.Write(Pl.Team); g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT); end; @@ -1136,87 +1146,89 @@ end; // ITEM (SEND) procedure MH_SEND_ItemSpawn(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); -begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_ISPAWN)); - e_Buffer_Write(@NetOut, IID); - e_Buffer_Write(@NetOut, Byte(Quiet)); - e_Buffer_Write(@NetOut, gItems[IID].ItemType); - e_Buffer_Write(@NetOut, Byte(gItems[IID].Fall)); - e_Buffer_Write(@NetOut, Byte(gItems[IID].Respawnable)); - e_Buffer_Write(@NetOut, gItems[IID].Obj.X); - e_Buffer_Write(@NetOut, gItems[IID].Obj.Y); - e_Buffer_Write(@NetOut, gItems[IID].Obj.Vel.X); - e_Buffer_Write(@NetOut, gItems[IID].Obj.Vel.Y); +var + it: PItem; + tt: Byte; +begin + it := g_Items_ByIdx(IID); + + NetOut.Write(Byte(NET_MSG_ISPAWN)); + NetOut.Write(IID); + NetOut.Write(Byte(Quiet)); + tt := it.ItemType; + if it.dropped then tt := tt or $80; + NetOut.Write(tt); + NetOut.Write(Byte(it.Fall)); + NetOut.Write(Byte(it.Respawnable)); + NetOut.Write(it.Obj.X); + NetOut.Write(it.Obj.Y); + NetOut.Write(it.Obj.Vel.X); + NetOut.Write(it.Obj.Vel.Y); g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; procedure MH_SEND_ItemDestroy(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_IDEL)); - e_Buffer_Write(@NetOut, IID); - e_Buffer_Write(@NetOut, Byte(Quiet)); + NetOut.Write(Byte(NET_MSG_IDEL)); + NetOut.Write(IID); + NetOut.Write(Byte(Quiet)); g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; // PANEL -procedure MH_SEND_PanelTexture(PType: Word; PID: LongWord; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); var TP: TPanel; begin - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - TP := gWalls[PID]; - PANEL_FORE: - TP := gRenderForegrounds[PID]; - PANEL_BACK: - TP := gRenderBackgrounds[PID]; - PANEL_WATER: - TP := gWater[PID]; - PANEL_ACID1: - TP := gAcid1[PID]; - PANEL_ACID2: - TP := gAcid2[PID]; - PANEL_STEP: - TP := gSteps[PID]; - else - Exit; - end; + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; with TP do begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_PTEX)); - e_Buffer_Write(@NetOut, PType); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, FCurTexture); - e_Buffer_Write(@NetOut, FCurFrame); - e_Buffer_Write(@NetOut, FCurFrameCount); - e_Buffer_Write(@NetOut, AnimLoop); + NetOut.Write(Byte(NET_MSG_PTEX)); + NetOut.Write(LongWord(PGUID)); + NetOut.Write(FCurTexture); + NetOut.Write(FCurFrame); + NetOut.Write(FCurFrameCount); + NetOut.Write(AnimLoop); end; g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; -procedure MH_SEND_PanelState(PType: Word; PID: LongWord; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelState(PGUID: Integer; ID: Integer = NET_EVERYONE); var TP: TPanel; -begin - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - TP := gWalls[PID]; - PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - TP := gLifts[PID]; - else - Exit; - end; - - e_Buffer_Write(@NetOut, Byte(NET_MSG_PSTATE)); - e_Buffer_Write(@NetOut, PType); - e_Buffer_Write(@NetOut, PID); - e_Buffer_Write(@NetOut, Byte(TP.Enabled)); - e_Buffer_Write(@NetOut, TP.LiftType); + mpflags: Byte = 0; +begin + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; + + NetOut.Write(Byte(NET_MSG_PSTATE)); + NetOut.Write(LongWord(PGUID)); + NetOut.Write(Byte(TP.Enabled)); + NetOut.Write(TP.LiftType); + NetOut.Write(TP.X); + NetOut.Write(TP.Y); + NetOut.Write(Word(TP.Width)); + NetOut.Write(Word(TP.Height)); + // mplats + NetOut.Write(LongInt(TP.movingSpeedX)); + NetOut.Write(LongInt(TP.movingSpeedY)); + NetOut.Write(LongInt(TP.movingStartX)); + NetOut.Write(LongInt(TP.movingStartY)); + NetOut.Write(LongInt(TP.movingEndX)); + NetOut.Write(LongInt(TP.movingEndY)); + NetOut.Write(LongInt(TP.sizeSpeedX)); + NetOut.Write(LongInt(TP.sizeSpeedY)); + NetOut.Write(LongInt(TP.sizeEndX)); + NetOut.Write(LongInt(TP.sizeEndY)); + if TP.movingActive then mpflags := mpflags or 1; + if TP.moveOnce then mpflags := mpflags or 2; + NetOut.Write(Byte(mpflags)); g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; @@ -1228,22 +1240,22 @@ begin if gTriggers = nil then Exit; if T.Sound = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_TSOUND)); - e_Buffer_Write(@NetOut, T.ClientID); - e_Buffer_Write(@NetOut, Byte(T.Sound.IsPlaying)); - e_Buffer_Write(@NetOut, LongWord(T.Sound.GetPosition)); - e_Buffer_Write(@NetOut, T.SoundPlayCount); + NetOut.Write(Byte(NET_MSG_TSOUND)); + NetOut.Write(T.ClientID); + NetOut.Write(Byte(T.Sound.IsPlaying)); + NetOut.Write(LongWord(T.Sound.GetPosition)); + NetOut.Write(T.SoundPlayCount); g_Net_Host_Send(ID, True); end; procedure MH_SEND_TriggerMusic(ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_TMUSIC)); - e_Buffer_Write(@NetOut, gMusic.Name); - e_Buffer_Write(@NetOut, Byte(gMusic.IsPlaying)); - e_Buffer_Write(@NetOut, LongWord(gMusic.GetPosition)); - e_Buffer_Write(@NetOut, Byte(gMusic.SpecPause or gMusic.IsPaused)); + NetOut.Write(Byte(NET_MSG_TMUSIC)); + NetOut.Write(gMusic.Name); + NetOut.Write(Byte(gMusic.IsPlaying)); + NetOut.Write(LongWord(gMusic.GetPosition)); + NetOut.Write(Byte(gMusic.SpecPause or gMusic.IsPaused)); g_Net_Host_Send(ID, True); end; @@ -1254,28 +1266,28 @@ procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; with M do begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_MSPAWN)); - e_Buffer_Write(@NetOut, UID); - e_Buffer_Write(@NetOut, MonsterType); - e_Buffer_Write(@NetOut, MonsterState); - e_Buffer_Write(@NetOut, MonsterAnim); - e_Buffer_Write(@NetOut, MonsterTargetUID); - e_Buffer_Write(@NetOut, MonsterTargetTime); - e_Buffer_Write(@NetOut, MonsterBehaviour); - e_Buffer_Write(@NetOut, MonsterSleep); - e_Buffer_Write(@NetOut, MonsterHealth); - e_Buffer_Write(@NetOut, MonsterAmmo); - e_Buffer_Write(@NetOut, GameX); - e_Buffer_Write(@NetOut, GameY); - e_Buffer_Write(@NetOut, GameVelX); - e_Buffer_Write(@NetOut, GameVelY); - e_Buffer_Write(@NetOut, Byte(GameDirection)); + NetOut.Write(Byte(NET_MSG_MSPAWN)); + NetOut.Write(UID); + NetOut.Write(MonsterType); + NetOut.Write(MonsterState); + NetOut.Write(MonsterAnim); + NetOut.Write(MonsterTargetUID); + NetOut.Write(MonsterTargetTime); + NetOut.Write(MonsterBehaviour); + NetOut.Write(MonsterSleep); + NetOut.Write(MonsterHealth); + NetOut.Write(MonsterAmmo); + NetOut.Write(GameX); + NetOut.Write(GameY); + NetOut.Write(GameVelX); + NetOut.Write(GameVelY); + NetOut.Write(Byte(GameDirection)); end; g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); @@ -1285,19 +1297,19 @@ procedure MH_SEND_MonsterPos(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_MPOS)); - e_Buffer_Write(@NetOut, UID); + NetOut.Write(Byte(NET_MSG_MPOS)); + NetOut.Write(UID); with M do begin - e_Buffer_Write(@NetOut, GameX); - e_Buffer_Write(@NetOut, GameY); - e_Buffer_Write(@NetOut, GameVelX); - e_Buffer_Write(@NetOut, GameVelY); - e_Buffer_Write(@NetOut, Byte(GameDirection)); + NetOut.Write(GameX); + NetOut.Write(GameY); + NetOut.Write(GameVelX); + NetOut.Write(GameVelY); + NetOut.Write(Byte(GameDirection)); end; g_Net_Host_Send(ID, False, NET_CHAN_MONSTERPOS); @@ -1307,23 +1319,24 @@ procedure MH_SEND_MonsterState(UID: Word; ForcedAnim: Byte = 255; ID: Integer = var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_MSTATE)); - e_Buffer_Write(@NetOut, UID); + NetOut.Write(Byte(NET_MSG_MSTATE)); + NetOut.Write(UID); with M do begin - e_Buffer_Write(@NetOut, MonsterState); - e_Buffer_Write(@NetOut, ForcedAnim); - e_Buffer_Write(@NetOut, MonsterTargetUID); - e_Buffer_Write(@NetOut, MonsterTargetTime); - e_Buffer_Write(@NetOut, MonsterSleep); - e_Buffer_Write(@NetOut, MonsterHealth); - e_Buffer_Write(@NetOut, MonsterAmmo); - e_Buffer_Write(@NetOut, MonsterPain); - e_Buffer_Write(@NetOut, Byte(AnimIsReverse)); + NetOut.Write(MonsterState); + NetOut.Write(ForcedAnim); + NetOut.Write(MonsterTargetUID); + NetOut.Write(MonsterTargetTime); + NetOut.Write(MonsterSleep); + NetOut.Write(MonsterHealth); + NetOut.Write(MonsterAmmo); + NetOut.Write(MonsterPain); + NetOut.Write(Byte(AnimIsReverse)); + NetOut.Write(FFireTime); end; g_Net_Host_Send(ID, True, NET_CHAN_MONSTER); @@ -1331,12 +1344,12 @@ end; procedure MH_SEND_MonsterShot(UID: Word; X, Y, VX, VY: Integer; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_MSHOT)); - e_Buffer_Write(@NetOut, UID); - e_Buffer_Write(@NetOut, X); - e_Buffer_Write(@NetOut, Y); - e_Buffer_Write(@NetOut, VX); - e_Buffer_Write(@NetOut, VY); + NetOut.Write(Byte(NET_MSG_MSHOT)); + NetOut.Write(UID); + NetOut.Write(X); + NetOut.Write(Y); + NetOut.Write(VX); + NetOut.Write(VY); g_Net_Host_Send(ID, True, NET_CHAN_MONSTER); end; @@ -1345,11 +1358,11 @@ procedure MH_SEND_MonsterDelete(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; - e_Buffer_Write(@NetOut, Byte(NET_MSG_MDEL)); - e_Buffer_Write(@NetOut, UID); + NetOut.Write(Byte(NET_MSG_MDEL)); + NetOut.Write(UID); g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; @@ -1358,8 +1371,8 @@ end; procedure MH_SEND_TimeSync(Time: LongWord; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_TIME_SYNC)); - e_Buffer_Write(@NetOut, Time); + NetOut.Write(Byte(NET_MSG_TIME_SYNC)); + NetOut.Write(Time); g_Net_Host_Send(ID, False, NET_CHAN_SERVICE); end; @@ -1369,12 +1382,12 @@ procedure MH_SEND_VoteEvent(EvType: Byte; IntArg1: SmallInt = 0; IntArg2: SmallInt = 0; ID: Integer = NET_EVERYONE); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_VOTE_EVENT)); - e_Buffer_Write(@NetOut, EvType); - e_Buffer_Write(@NetOut, IntArg1); - e_Buffer_Write(@NetOut, IntArg2); - e_Buffer_Write(@NetOut, StrArg1); - e_Buffer_Write(@NetOut, StrArg2); + NetOut.Write(Byte(NET_MSG_VOTE_EVENT)); + NetOut.Write(EvType); + NetOut.Write(IntArg1); + NetOut.Write(IntArg2); + NetOut.Write(StrArg1); + NetOut.Write(StrArg2); g_Net_Host_Send(ID, True, NET_CHAN_IMPORTANT); end; @@ -1383,21 +1396,21 @@ end; // GAME -procedure MC_RECV_Chat(P: Pointer); +procedure MC_RECV_Chat(var M: TMsg); var Txt: string; Mode: Byte; begin - Txt := e_Raw_Read_String(P); - Mode := e_Raw_Read_Byte(P); + Txt := M.ReadString(); + Mode := M.ReadByte(); if Mode <> NET_CHAT_SYSTEM then begin if Mode = NET_CHAT_PLAYER then begin g_Console_Add(Txt, True); - e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end else if (Mode = NET_CHAT_TEAM) and (gPlayer1 <> nil) then begin @@ -1405,14 +1418,14 @@ begin g_Console_Add(b_Text_Format('\r[Team] ') + Txt, True); if gPlayer1.Team = TEAM_BLUE then g_Console_Add(b_Text_Format('\b[Team] ') + Txt, True); - e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end; end else g_Console_Add(Txt, True); end; -procedure MC_RECV_Effect(P: Pointer); +procedure MC_RECV_Effect(var M: TMsg); var Kind: Byte; X, Y: Integer; @@ -1421,10 +1434,10 @@ var ID: LongWord; begin if not gGameOn then Exit; - Kind := e_Raw_Read_Byte(P); - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - Ang := e_Raw_Read_SmallInt(P); + Kind := M.ReadByte(); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + Ang := M.ReadSmallInt(); case Kind of NET_GFX_SPARK: @@ -1516,33 +1529,40 @@ begin end; end; -procedure MC_RECV_Sound(P: Pointer); +procedure MC_RECV_Sound(var M: TMsg); var Name: string; X, Y: Integer; + Pos: Boolean; begin - Name := e_Raw_Read_String(P); - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - g_Sound_PlayExAt(Name, X, Y); + Name := M.ReadString(); + Pos := M.ReadByte() <> 0; + if Pos then + begin + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + g_Sound_PlayExAt(Name, X, Y); + end + else + g_Sound_PlayEx(Name); end; -procedure MC_RECV_CreateShot(P: Pointer); +procedure MC_RECV_CreateShot(var M: TMsg); var I, X, Y, XV, YV: Integer; Timeout: LongWord; Target, Spawner: Word; ShType: Byte; begin - I := e_Raw_Read_LongInt(P); - ShType := e_Raw_Read_Byte(P); - Target := e_Raw_Read_Word(P); - Spawner := e_Raw_Read_Word(P); - Timeout := e_Raw_Read_LongWord(P); - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - XV := e_Raw_Read_LongInt(P); - YV := e_Raw_Read_LongInt(P); + I := M.ReadLongInt(); + ShType := M.ReadByte(); + Target := M.ReadWord(); + Spawner := M.ReadWord(); + Timeout := M.ReadLongWord(); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + XV := M.ReadLongInt(); + YV := M.ReadLongInt(); I := g_Weapon_CreateShot(I, ShType, Spawner, Target, X, Y, XV, YV); if (Shots <> nil) and (I <= High(Shots)) then @@ -1552,15 +1572,15 @@ begin end; end; -procedure MC_RECV_UpdateShot(P: Pointer); +procedure MC_RECV_UpdateShot(var M: TMsg); var I, TX, TY, TXV, TYV: Integer; begin - I := e_Raw_Read_LongInt(P); - TX := e_Raw_Read_LongInt(P); - TY := e_Raw_Read_LongInt(P); - TXV := e_Raw_Read_LongInt(P); - TYV := e_Raw_Read_LongInt(P); + I := M.ReadLongInt(); + TX := M.ReadLongInt(); + TY := M.ReadLongInt(); + TXV := M.ReadLongInt(); + TYV := M.ReadLongInt(); if (Shots <> nil) and (I <= High(Shots)) then with (Shots[i]) do @@ -1572,46 +1592,46 @@ begin end; end; -procedure MC_RECV_DeleteShot(P: Pointer); +procedure MC_RECV_DeleteShot(var M: TMsg); var I, X, Y: Integer; L: Boolean; begin if not gGameOn then Exit; - I := e_Raw_Read_LongInt(P); - L := (e_Raw_Read_Byte(P) <> 0); - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); + I := M.ReadLongInt(); + L := (M.ReadByte() <> 0); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); g_Weapon_DestroyShot(I, X, Y, L); end; -procedure MC_RECV_GameStats(P: Pointer); +procedure MC_RECV_GameStats(var M: TMsg); begin if gGameSettings.GameMode in [GM_TDM, GM_CTF] then begin - gTeamStat[TEAM_RED].Goals := e_Raw_Read_SmallInt(P); - gTeamStat[TEAM_BLUE].Goals := e_Raw_Read_SmallInt(P); + gTeamStat[TEAM_RED].Goals := M.ReadSmallInt(); + gTeamStat[TEAM_BLUE].Goals := M.ReadSmallInt(); end else if gGameSettings.GameMode = GM_COOP then begin - gCoopMonstersKilled := e_Raw_Read_Word(P); - gCoopSecretsFound := e_Raw_Read_Word(P); + gCoopMonstersKilled := M.ReadWord(); + gCoopSecretsFound := M.ReadWord(); end; end; -procedure MC_RECV_CoopStats(P: Pointer); +procedure MC_RECV_CoopStats(var M: TMsg); begin - gTotalMonsters := e_Raw_Read_LongInt(P); - gSecretsCount := e_Raw_Read_LongInt(P); - gCoopTotalMonstersKilled := e_Raw_Read_Word(P); - gCoopTotalSecretsFound := e_Raw_Read_Word(P); - gCoopTotalMonsters := e_Raw_Read_Word(P); - gCoopTotalSecrets := e_Raw_Read_Word(P); + gTotalMonsters := M.ReadLongInt(); + gSecretsCount := M.ReadLongInt(); + gCoopTotalMonstersKilled := M.ReadWord(); + gCoopTotalSecretsFound := M.ReadWord(); + gCoopTotalMonsters := M.ReadWord(); + gCoopTotalSecrets := M.ReadWord(); end; -procedure MC_RECV_GameEvent(P: Pointer); +procedure MC_RECV_GameEvent(var M: TMsg); var EvType: Byte; EvNum: Integer; @@ -1625,16 +1645,16 @@ var cnt: Byte; begin FillChar(EvHash, Sizeof(EvHash), 0); - EvType := e_Raw_Read_Byte(P); - EvNum := e_Raw_Read_LongInt(P); - EvStr := e_Raw_Read_String(P); - gLastMap := e_Raw_Read_Byte(P) <> 0; + EvType := M.ReadByte(); + EvNum := M.ReadLongInt(); + EvStr := M.ReadString(); + gLastMap := M.ReadByte() <> 0; if gLastMap and (gGameSettings.GameMode = GM_COOP) then gStatsOff := True; gStatsPressed := True; - EvTime := e_Raw_Read_LongWord(P); - BHash := e_Raw_Read_Byte(P) <> 0; + EvTime := M.ReadLongWord(); + BHash := M.ReadByte() <> 0; if BHash then - EvHash := e_Raw_Read_MD5(P); + EvHash := M.ReadMD5(); gTime := EvTime; @@ -1651,7 +1671,7 @@ begin gWADHash := EvHash; if not g_Game_StartMap(EvStr, True) then begin - if Pos(':\', EvStr) = 0 then + 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])); @@ -1813,7 +1833,7 @@ begin end; end; -procedure MC_RECV_FlagEvent(P: Pointer); +procedure MC_RECV_FlagEvent(var M: TMsg); var PID: Word; Pl: TPlayer; @@ -1822,20 +1842,20 @@ var Quiet: Boolean; s, ts: string; begin - EvType := e_Raw_Read_Byte(P); - Fl := e_Raw_Read_Byte(P); + EvType := M.ReadByte(); + Fl := M.ReadByte(); if Fl = FLAG_NONE then Exit; - Quiet := (e_Raw_Read_Byte(P) <> 0); - PID := e_Raw_Read_Word(P); + Quiet := (M.ReadByte() <> 0); + PID := M.ReadWord(); - gFlags[Fl].State := e_Raw_Read_Byte(P); - gFlags[Fl].CaptureTime := e_Raw_Read_LongWord(P); - gFlags[Fl].Obj.X := e_Raw_Read_LongInt(P); - gFlags[Fl].Obj.Y := e_Raw_Read_LongInt(P); - gFlags[Fl].Obj.Vel.X := e_Raw_Read_LongInt(P); - gFlags[Fl].Obj.Vel.Y := e_Raw_Read_LongInt(P); + gFlags[Fl].State := M.ReadByte(); + gFlags[Fl].CaptureTime := M.ReadLongWord(); + gFlags[Fl].Obj.X := M.ReadLongInt(); + gFlags[Fl].Obj.Y := M.ReadLongInt(); + gFlags[Fl].Obj.Vel.X := M.ReadLongInt(); + gFlags[Fl].Obj.Vel.Y := M.ReadLongInt(); Pl := g_Player_Get(PID); if (Pl = nil) and @@ -1920,18 +1940,18 @@ begin end; end; -procedure MC_RECV_GameSettings(P: Pointer); +procedure MC_RECV_GameSettings(var M: TMsg); begin - gGameSettings.GameMode := e_Raw_Read_Byte(P); - gGameSettings.GoalLimit := e_Raw_Read_Word(P); - gGameSettings.TimeLimit := e_Raw_Read_Word(P); - gGameSettings.MaxLives := e_Raw_Read_Byte(P); - gGameSettings.Options := e_Raw_Read_LongWord(P); + gGameSettings.GameMode := M.ReadByte(); + gGameSettings.GoalLimit := M.ReadWord(); + gGameSettings.TimeLimit := M.ReadWord(); + gGameSettings.MaxLives := M.ReadByte(); + gGameSettings.Options := M.ReadLongWord(); end; // PLAYER -function MC_RECV_PlayerCreate(P: Pointer): Word; +function MC_RECV_PlayerCreate(var M: TMsg): Word; var PID, DID: Word; PName, Model: string; @@ -1939,15 +1959,15 @@ var T: Byte; Pl: TPlayer; begin - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); - PName := e_Raw_Read_String(P); - Model := e_Raw_Read_String(P); - Color.R := e_Raw_Read_Byte(P); - Color.G := e_Raw_Read_Byte(P); - Color.B := e_Raw_Read_Byte(P); - T := e_Raw_Read_Byte(P); + PName := M.ReadString(); + Model := M.ReadString(); + Color.R := M.ReadByte(); + Color.G := M.ReadByte(); + Color.B := M.ReadByte(); + T := M.ReadByte(); Result := 0; if (PID <> NetPlrUID1) and (PID <> NetPlrUID2) then @@ -1976,11 +1996,11 @@ begin end; g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True); - e_WriteLog('NET: Player ' + PName + ' [' + IntToStr(PID) + '] added.', MSG_NOTIFY); + e_WriteLog('NET: Player ' + PName + ' [' + IntToStr(PID) + '] added.', TMsgType.Notify); Result := PID; end; -function MC_RECV_PlayerPos(P: Pointer): Word; +function MC_RECV_PlayerPos(var M: TMsg): Word; var GT: LongWord; PID: Word; @@ -1991,7 +2011,7 @@ var begin Result := 0; - GT := e_Raw_Read_LongWord(P); + GT := M.ReadLongWord(); if GT < gTime - NET_MAX_DIFFTIME then begin gTime := GT; @@ -1999,7 +2019,7 @@ begin end; gTime := GT; - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); if Pl = nil then Exit; @@ -2008,13 +2028,13 @@ begin with Pl do begin - FPing := e_Raw_Read_Word(P); - FLoss := e_Raw_Read_Byte(P); - kByte := e_Raw_Read_Word(P); - Dir := e_Raw_Read_Byte(P); + FPing := M.ReadWord(); + FLoss := M.ReadByte(); + kByte := M.ReadWord(); + Dir := M.ReadByte(); - TmpX := e_Raw_Read_LongInt(P); - TmpY := e_Raw_Read_LongInt(P); + TmpX := M.ReadLongInt(); + TmpY := M.ReadLongInt(); ReleaseKeys; @@ -2032,16 +2052,16 @@ begin if ((Pl <> gPlayer1) and (Pl <> gPlayer2)) or LongBool(kByte and NET_KEY_FORCEDIR) then SetDirection(TDirection(Dir)); - GameVelX := e_Raw_Read_LongInt(P); - GameVelY := e_Raw_Read_LongInt(P); - GameAccelX := e_Raw_Read_LongInt(P); - GameAccelY := e_Raw_Read_LongInt(P); + GameVelX := M.ReadLongInt(); + GameVelY := M.ReadLongInt(); + GameAccelX := M.ReadLongInt(); + GameAccelY := M.ReadLongInt(); SetLerp(TmpX, TmpY); if NetForcePlayerUpdate then Update(); end; end; -function MC_RECV_PlayerStats(P: Pointer): Word; +function MC_RECV_PlayerStats(var M: TMsg): Word; var PID: Word; Pl: TPlayer; @@ -2049,7 +2069,7 @@ var OldJet: Boolean; NewTeam: Byte; begin - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); Result := 0; if Pl = nil then @@ -2057,45 +2077,45 @@ begin with Pl do begin - Live := (e_Raw_Read_Byte(P) <> 0); - GodMode := (e_Raw_Read_Byte(P) <> 0); - Health := e_Raw_Read_LongInt(P); - Armor := e_Raw_Read_LongInt(P); - Air := e_Raw_Read_LongInt(P); - JetFuel := e_Raw_Read_LongInt(P); - Lives := e_Raw_Read_Byte(P); - NewTeam := e_Raw_Read_Byte(P); + alive := (M.ReadByte() <> 0); + GodMode := (M.ReadByte() <> 0); + Health := M.ReadLongInt(); + Armor := M.ReadLongInt(); + Air := M.ReadLongInt(); + JetFuel := M.ReadLongInt(); + Lives := M.ReadByte(); + NewTeam := M.ReadByte(); - for I := WEAPON_KASTET to WEAPON_SUPERPULEMET do - FWeapon[I] := (e_Raw_Read_Byte(P) <> 0); + for I := WP_FIRST to WP_LAST do + FWeapon[I] := (M.ReadByte() <> 0); - for I := A_BULLETS to A_CELLS do - FAmmo[I] := e_Raw_Read_Word(P); + for I := A_BULLETS to A_HIGH do + FAmmo[I] := M.ReadWord(); - for I := A_BULLETS to A_CELLS do - FMaxAmmo[I] := e_Raw_Read_Word(P); + for I := A_BULLETS to A_HIGH do + FMaxAmmo[I] := M.ReadWord(); for I := MR_SUIT to MR_MAX do - FMegaRulez[I] := e_Raw_Read_LongWord(P); + FMegaRulez[I] := M.ReadLongWord(); FRulez := []; - if (e_Raw_Read_Byte(P) <> 0) then + if (M.ReadByte() <> 0) then FRulez := FRulez + [R_ITEM_BACKPACK]; - if (e_Raw_Read_Byte(P) <> 0) then + if (M.ReadByte() <> 0) then FRulez := FRulez + [R_KEY_RED]; - if (e_Raw_Read_Byte(P) <> 0) then + if (M.ReadByte() <> 0) then FRulez := FRulez + [R_KEY_GREEN]; - if (e_Raw_Read_Byte(P) <> 0) then + if (M.ReadByte() <> 0) then FRulez := FRulez + [R_KEY_BLUE]; - if (e_Raw_Read_Byte(P) <> 0) then + if (M.ReadByte() <> 0) then FRulez := FRulez + [R_BERSERK]; - Frags := e_Raw_Read_LongInt(P); - Death := e_Raw_Read_LongInt(P); + Frags := M.ReadLongInt(); + Death := M.ReadLongInt(); - SetWeapon(e_Raw_Read_Byte(P)); + SetWeapon(M.ReadByte()); - FSpectator := e_Raw_Read_Byte(P) <> 0; + FSpectator := M.ReadByte() <> 0; if FSpectator then begin if Pl = gPlayer1 then @@ -2116,11 +2136,12 @@ begin if (gPlayer2 = nil) and (gLMSPID2 > 0) then gPlayer2 := g_Player_Get(gLMSPID2); end; - FGhost := e_Raw_Read_Byte(P) <> 0; - FPhysics := e_Raw_Read_Byte(P) <> 0; - FNoRespawn := e_Raw_Read_Byte(P) <> 0; + FGhost := M.ReadByte() <> 0; + FPhysics := M.ReadByte() <> 0; + FNoRespawn := M.ReadByte() <> 0; OldJet := FJetpack; - FJetpack := e_Raw_Read_Byte(P) <> 0; + FJetpack := M.ReadByte() <> 0; + FFireTime := M.ReadLongInt(); if OldJet and not FJetpack then JetpackOff else if not OldJet and FJetpack then @@ -2132,7 +2153,7 @@ begin Result := PID; end; -function MC_RECV_PlayerDamage(P: Pointer): Word; +function MC_RECV_PlayerDamage(var M: TMsg): Word; var PID: Word; Pl: TPlayer; @@ -2142,15 +2163,15 @@ var begin Result := 0; if not gGameOn then Exit; - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); if Pl = nil then Exit; - Kind := e_Raw_Read_Byte(P); - Attacker := e_Raw_Read_Word(P); - Value := e_Raw_Read_Word(P); - VX := e_Raw_Read_Word(P); - VY := e_Raw_Read_Word(P); + Kind := M.ReadByte(); + Attacker := M.ReadWord(); + Value := M.ReadWord(); + VX := M.ReadWord(); + VY := M.ReadWord(); with Pl do Damage(Value, Attacker, VX, VY, Kind); @@ -2158,7 +2179,7 @@ begin Result := PID; end; -function MC_RECV_PlayerDeath(P: Pointer): Word; +function MC_RECV_PlayerDeath(var M: TMsg): Word; var PID: Word; Pl: TPlayer; @@ -2167,13 +2188,13 @@ var begin Result := 0; if not gGameOn then Exit; - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); if Pl = nil then Exit; - KillType := e_Raw_Read_Byte(P); - DeathType := e_Raw_Read_Byte(P); - Attacker := e_Raw_Read_Word(P); + KillType := M.ReadByte(); + DeathType := M.ReadByte(); + Attacker := M.ReadWord(); with Pl do begin @@ -2182,25 +2203,25 @@ begin end; end; -function MC_RECV_PlayerDelete(P: Pointer): Word; +function MC_RECV_PlayerDelete(var M: TMsg): Word; var PID: Word; Pl: TPlayer; begin - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); Result := 0; if Pl = nil then Exit; g_Console_Add(Format(_lc[I_PLAYER_LEAVE], [Pl.Name]), True); - e_WriteLog('NET: Player ' + Pl.Name + ' [' + IntToStr(PID) + '] removed.', MSG_NOTIFY); + e_WriteLog('NET: Player ' + Pl.Name + ' [' + IntToStr(PID) + '] removed.', TMsgType.Notify); g_Player_Remove(PID); Result := PID; end; -function MC_RECV_PlayerFire(P: Pointer): Word; +function MC_RECV_PlayerFire(var M: TMsg): Word; var PID: Word; Weap: Byte; @@ -2210,22 +2231,22 @@ var begin Result := 0; if not gGameOn then Exit; - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); if Pl = nil then Exit; - Weap := e_Raw_Read_Byte(P); - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - AX := e_Raw_Read_LongInt(P); - AY := e_Raw_Read_LongInt(P); - SHID := e_Raw_Read_LongInt(P); + Weap := M.ReadByte(); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + AX := M.ReadLongInt(); + AY := M.ReadLongInt(); + SHID := M.ReadLongInt(); with Pl do - if Live then NetFire(Weap, X, Y, AX, AY, SHID); + if alive then NetFire(Weap, X, Y, AX, AY, SHID); end; -procedure MC_RECV_PlayerSettings(P: Pointer); +procedure MC_RECV_PlayerSettings(var M: TMsg); var TmpName: string; TmpModel: string; @@ -2234,16 +2255,16 @@ var Pl: TPlayer; PID: Word; begin - PID := e_Raw_Read_Word(P); + PID := M.ReadWord(); Pl := g_Player_Get(PID); if Pl = nil then Exit; - TmpName := e_Raw_Read_String(P); - TmpModel := e_Raw_Read_String(P); - TmpColor.R := e_Raw_Read_Byte(P); - TmpColor.G := e_Raw_Read_Byte(P); - TmpColor.B := e_Raw_Read_Byte(P); - TmpTeam := e_Raw_Read_Byte(P); + TmpName := M.ReadString(); + TmpModel := M.ReadString(); + TmpColor.R := M.ReadByte(); + TmpColor.G := M.ReadByte(); + TmpColor.B := M.ReadByte(); + TmpTeam := M.ReadByte(); if (gGameSettings.GameMode in [GM_TDM, GM_CTF]) and (Pl.Team <> TmpTeam) then begin @@ -2267,7 +2288,7 @@ end; // ITEM -procedure MC_RECV_ItemSpawn(P: Pointer); +procedure MC_RECV_ItemSpawn(var M: TMsg); var ID: Word; AID: DWord; @@ -2275,21 +2296,25 @@ var T: Byte; Quiet, Fall{, Resp}: Boolean; Anim: TAnimation; + it: PItem; begin if not gGameOn then Exit; - ID := e_Raw_Read_Word(P); - Quiet := e_Raw_Read_Byte(P) <> 0; - T := e_Raw_Read_Byte(P); - Fall := e_Raw_Read_Byte(P) <> 0; - {Resp :=} e_Raw_Read_Byte(P); - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - VX := e_Raw_Read_LongInt(P); - VY := e_Raw_Read_LongInt(P); - - g_Items_Create(X, Y, T, Fall, False, False, ID); - gItems[ID].Obj.Vel.X := VX; - gItems[ID].Obj.Vel.Y := VY; + ID := M.ReadWord(); + Quiet := M.ReadByte() <> 0; + T := M.ReadByte(); + Fall := M.ReadByte() <> 0; + {Resp :=} M.ReadByte(); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + VX := M.ReadLongInt(); + VY := M.ReadLongInt(); + + g_Items_Create(X, Y, T and $7F, Fall, False, False, ID); + if ((T and $80) <> 0) then g_Items_SetDrop(ID); + + it := g_Items_ByIdx(ID); + it.Obj.Vel.X := VX; + it.Obj.Vel.Y := VY; if not Quiet then begin @@ -2297,143 +2322,121 @@ begin if g_Frames_Get(AID, 'FRAMES_ITEM_RESPAWN') then begin Anim := TAnimation.Create(AID, False, 4); - g_GFX_OnceAnim(X+(gItems[ID].Obj.Rect.Width div 2)-16, Y+(gItems[ID].Obj.Rect.Height div 2)-16, Anim); + g_GFX_OnceAnim(X+(it.Obj.Rect.Width div 2)-16, Y+(it.Obj.Rect.Height div 2)-16, Anim); Anim.Free(); end; end; end; -procedure MC_RECV_ItemDestroy(P: Pointer); +procedure MC_RECV_ItemDestroy(var M: TMsg); var ID: Word; Quiet: Boolean; begin if not gGameOn then Exit; - ID := e_Raw_Read_Word(P); - Quiet := e_Raw_Read_Byte(P) <> 0; - if gItems = nil then Exit; - if (ID > High(gItems)) then Exit; + ID := M.ReadWord(); + Quiet := M.ReadByte() <> 0; - if not Quiet then - if gSoundEffectsDF then - begin - if gItems[ID].ItemType in [ITEM_SPHERE_BLUE, ITEM_SPHERE_WHITE, ITEM_INVUL, - ITEM_INVIS, ITEM_MEDKIT_BLACK, ITEM_JETPACK] then - g_Sound_PlayExAt('SOUND_ITEM_GETRULEZ', - gItems[ID].Obj.X, gItems[ID].Obj.Y) - else - if gItems[ID].ItemType in [ITEM_WEAPON_SAW, ITEM_WEAPON_PISTOL, ITEM_WEAPON_SHOTGUN1, ITEM_WEAPON_SHOTGUN2, - ITEM_WEAPON_CHAINGUN, ITEM_WEAPON_ROCKETLAUNCHER, ITEM_WEAPON_PLASMA, - ITEM_WEAPON_BFG, ITEM_WEAPON_SUPERPULEMET, ITEM_AMMO_BACKPACK] then - g_Sound_PlayExAt('SOUND_ITEM_GETWEAPON', - gItems[ID].Obj.X, gItems[ID].Obj.Y) - else - g_Sound_PlayExAt('SOUND_ITEM_GETITEM', - gItems[ID].Obj.X, gItems[ID].Obj.Y); - end - else - begin - if gItems[ID].ItemType in [ITEM_SPHERE_BLUE, ITEM_SPHERE_WHITE, ITEM_SUIT, - ITEM_MEDKIT_BLACK, ITEM_INVUL, ITEM_INVIS, ITEM_JETPACK] then - g_Sound_PlayExAt('SOUND_ITEM_GETRULEZ', - gItems[ID].Obj.X, gItems[ID].Obj.Y) - else - if gItems[ID].ItemType in [ITEM_WEAPON_SAW, ITEM_WEAPON_PISTOL, ITEM_WEAPON_SHOTGUN1, ITEM_WEAPON_SHOTGUN2, - ITEM_WEAPON_CHAINGUN, ITEM_WEAPON_ROCKETLAUNCHER, ITEM_WEAPON_PLASMA, - ITEM_WEAPON_BFG, ITEM_WEAPON_SUPERPULEMET] then - g_Sound_PlayExAt('SOUND_ITEM_GETWEAPON', - gItems[ID].Obj.X, gItems[ID].Obj.Y) - else - g_Sound_PlayExAt('SOUND_ITEM_GETITEM', - gItems[ID].Obj.X, gItems[ID].Obj.Y); - end; + if not g_Items_ValidId(ID) then exit; + + if not Quiet then g_Items_EmitPickupSound(ID); g_Items_Remove(ID); end; // PANEL -procedure MC_RECV_PanelTexture(P: Pointer); +procedure MC_RECV_PanelTexture(var M: TMsg); var TP: TPanel; - PType: Word; - ID: LongWord; + PGUID: Integer; Tex, Fr: Integer; Loop, Cnt: Byte; begin if not gGameOn then Exit; - PType := e_Raw_Read_Word(P); - ID := e_Raw_Read_LongWord(P); - Tex := e_Raw_Read_LongInt(P); - Fr := e_Raw_Read_LongInt(P); - Cnt := e_Raw_Read_Byte(P); - Loop := e_Raw_Read_Byte(P); - - TP := nil; - - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - if gWalls <> nil then - TP := gWalls[ID]; - PANEL_FORE: - if gRenderForegrounds <> nil then - TP := gRenderForegrounds[ID]; - PANEL_BACK: - if gRenderBackgrounds <> nil then - TP := gRenderBackgrounds[ID]; - PANEL_WATER: - if gWater <> nil then - TP := gWater[ID]; - PANEL_ACID1: - if gAcid1 <> nil then - TP := gAcid1[ID]; - PANEL_ACID2: - if gAcid2 <> nil then - TP := gAcid2[ID]; - PANEL_STEP: - if gSteps <> nil then - TP := gSteps[ID]; - else - Exit; - end; - if TP <> nil then - if Loop = 0 then - begin // switch texture - TP.SetTexture(Tex, Loop); - TP.SetFrame(Fr, Cnt); - end else // looped or non-looped animation - TP.NextTexture(Loop); + PGUID := Integer(M.ReadLongWord()); + Tex := M.ReadLongInt(); + Fr := M.ReadLongInt(); + Cnt := M.ReadByte(); + Loop := M.ReadByte(); + + TP := g_Map_PanelByGUID(PGUID); + if (TP <> nil) then + begin + // switch texture + TP.SetTexture(Tex, Loop); + TP.SetFrame(Fr, Cnt); + end; end; -procedure MC_RECV_PanelState(P: Pointer); +procedure MC_RECV_PanelState(var M: TMsg); var - ID: LongWord; + PGUID: Integer; E: Boolean; Lift: Byte; - PType: Word; + X, Y, W, H: Integer; + TP: TPanel; + speedX, speedY, startX, startY, endX, endY: Integer; + sizeSpX, sizeSpY, sizeEX, sizeEY: Integer; + mpflags: Byte; begin if not gGameOn then Exit; - PType := e_Raw_Read_Word(P); - ID := e_Raw_Read_LongWord(P); - E := (e_Raw_Read_Byte(P) <> 0); - Lift := e_Raw_Read_Byte(P); - - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - if E then - g_Map_EnableWall(ID) - else - g_Map_DisableWall(ID); - PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - g_Map_SetLift(ID, Lift); - end; + PGUID := Integer(M.ReadLongWord()); + E := (M.ReadByte() <> 0); + Lift := M.ReadByte(); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + W := M.ReadWord(); + H := M.ReadWord(); + // mplats + speedX := M.ReadLongInt(); + speedY := M.ReadLongInt(); + startX := M.ReadLongInt(); + startY := M.ReadLongInt(); + endX := M.ReadLongInt(); + endY := M.ReadLongInt(); + sizeSpX := M.ReadLongInt(); + sizeSpY := M.ReadLongInt(); + sizeEX := M.ReadLongInt(); + sizeEY := M.ReadLongInt(); + mpflags := M.ReadByte(); // bit0: TP.movingActive; bit1: TP.moveOnce + + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; + + // update lifts state + if TP.isGLift then g_Map_SetLiftGUID(PGUID, Lift); + + // update enabled/disabled state for all panels + if E then g_Map_EnableWallGUID(PGUID) else g_Map_DisableWallGUID(PGUID); + + // update panel position, as it can be moved (mplat) + TP.X := X; + TP.Y := Y; + TP.Width := W; + TP.Height := H; + // update mplat state + TP.movingSpeedX := speedX; + TP.movingSpeedY := speedY; + TP.movingStartX := startX; + TP.movingStartY := startY; + TP.movingEndX := endX; + TP.movingEndY := endY; + TP.sizeSpeedX := sizeSpX; + TP.sizeSpeedY := sizeSpY; + TP.sizeEndX := sizeEX; + TP.sizeEndY := sizeEY; + TP.movingActive := ((mpflags and 1) <> 0); + TP.moveOnce := ((mpflags and 2) <> 0); + // notify panel of it's position/size change, so it can fix other internal structures + TP.positionChanged(); end; // TRIGGERS -procedure MC_RECV_TriggerSound(P: Pointer); +procedure MC_RECV_TriggerSound(var M: TMsg); var SPlaying: Boolean; SPos, SID: LongWord; @@ -2443,32 +2446,35 @@ begin if not gGameOn then Exit; if gTriggers = nil then Exit; - SID := e_Raw_Read_LongWord(P); - SPlaying := e_Raw_Read_Byte(P) <> 0; - SPos := e_Raw_Read_LongWord(P); - SCount := e_Raw_Read_LongInt(P); + SID := M.ReadLongWord(); + SPlaying := M.ReadByte() <> 0; + SPos := M.ReadLongWord(); + SCount := M.ReadLongInt(); for I := Low(gTriggers) to High(gTriggers) do if gTriggers[I].TriggerType = TRIGGER_SOUND then if gTriggers[I].ClientID = SID then with gTriggers[I] do begin - if SPlaying then + if Sound <> nil then begin - if Data.Local then - Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0) + if SPlaying then + begin + if tgcLocal then + Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), tgcVolume/255.0) + else + Sound.PlayPanVolume((tgcPan-127.0)/128.0, tgcVolume/255.0); + Sound.SetPosition(SPos); + end else - Sound.PlayPanVolume((Data.Pan-127.0)/128.0, Data.Volume/255.0); - Sound.SetPosition(SPos); - end - else - if Sound.IsPlaying then Sound.Stop; + if Sound.IsPlaying then Sound.Stop; + end; SoundPlayCount := SCount; end; end; -procedure MC_RECV_TriggerMusic(P: Pointer); +procedure MC_RECV_TriggerMusic(var M: TMsg); var MName: string; MPlaying: Boolean; @@ -2477,10 +2483,10 @@ var begin if not gGameOn then Exit; - MName := e_Raw_Read_String(P); - MPlaying := e_Raw_Read_Byte(P) <> 0; - MPos := e_Raw_Read_LongWord(P); - MPaused := e_Raw_Read_Byte(P) <> 0; + MName := M.ReadString(); + MPlaying := M.ReadByte() <> 0; + MPos := M.ReadLongWord(); + MPaused := M.ReadByte() <> 0; if MPlaying then begin @@ -2495,46 +2501,42 @@ end; // MONSTERS -procedure MC_RECV_MonsterSpawn(P: Pointer); +procedure MC_RECV_MonsterSpawn(var M: TMsg); var ID: Word; MType, MState, MDir, MAnim, MBehav: Byte; X, Y, VX, VY, MTargTime, MHealth, MAmmo, MSleep: Integer; MTarg: Word; - M: TMonster; + Mon: TMonster; begin - ID := e_Raw_Read_Word(P); - M := g_Monsters_Get(ID); - if M <> nil then + ID := M.ReadWord(); + Mon := g_Monsters_ByUID(ID); + if Mon <> nil then Exit; - MType := e_Raw_Read_Byte(P); - MState := e_Raw_Read_Byte(P); - MAnim := e_Raw_Read_Byte(P); - MTarg := e_Raw_Read_Word(P); - MTargTime := e_Raw_Read_LongInt(P); - MBehav := e_Raw_Read_Byte(P); - MSleep := e_Raw_Read_LongInt(P); - MHealth := e_Raw_Read_LongInt(P); - MAmmo := e_Raw_Read_LongInt(P); - - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - VX := e_Raw_Read_LongInt(P); - VY := e_Raw_Read_LongInt(P); - MDir := e_Raw_Read_Byte(P); + MType := M.ReadByte(); + MState := M.ReadByte(); + MAnim := M.ReadByte(); + MTarg := M.ReadWord(); + MTargTime := M.ReadLongInt(); + MBehav := M.ReadByte(); + MSleep := M.ReadLongInt(); + MHealth := M.ReadLongInt(); + MAmmo := M.ReadLongInt(); + + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + VX := M.ReadLongInt(); + VY := M.ReadLongInt(); + MDir := M.ReadByte(); g_Monsters_Create(MType, X, Y, TDirection(MDir), False, ID); - M := g_Monsters_Get(ID); - if M = nil then + Mon := g_Monsters_ByUID(ID); + if Mon = nil then Exit; - with M do + with Mon do begin - GameX := X; - GameY := Y; - GameVelX := VX; - GameVelY := VY; MonsterAnim := MAnim; MonsterTargetUID := MTarg; @@ -2545,125 +2547,126 @@ begin SetHealth(MHealth); SetState(MState); + + setPosition(X, Y); // this will call positionChanged(); + GameVelX := VX; + GameVelY := VY; end; end; -procedure MC_RECV_MonsterPos(P: Pointer); +procedure MC_RECV_MonsterPos(var M: TMsg); var - M: TMonster; + Mon: TMonster; ID: Word; + X, Y: Integer; begin - ID := e_Raw_Read_Word(P); - M := g_Monsters_Get(ID); - if M = nil then + ID := M.ReadWord(); + Mon := g_Monsters_ByUID(ID); + if Mon = nil then Exit; - with M do + with Mon do begin - GameX := e_Raw_Read_LongInt(P); - GameY := e_Raw_Read_LongInt(P); - GameVelX := e_Raw_Read_LongInt(P); - GameVelY := e_Raw_Read_LongInt(P); - GameDirection := TDirection(e_Raw_Read_Byte(P)); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + Mon.setPosition(X, Y); // this will call `positionChanged()` + GameVelX := M.ReadLongInt(); + GameVelY := M.ReadLongInt(); + GameDirection := TDirection(M.ReadByte()); end; end; -procedure MC_RECV_MonsterState(P: Pointer); +procedure MC_RECV_MonsterState(var M: TMsg); var ID: Integer; MState, MFAnm: Byte; - M: TMonster; + Mon: TMonster; AnimRevert: Boolean; begin - ID := e_Raw_Read_Word(P); - M := g_Monsters_Get(ID); - if M = nil then Exit; + ID := M.ReadWord(); + Mon := g_Monsters_ByUID(ID); + if Mon = nil then Exit; - MState := e_Raw_Read_Byte(P); - MFAnm := e_Raw_Read_Byte(P); + MState := M.ReadByte(); + MFAnm := M.ReadByte(); - with M do + with Mon do begin - MonsterTargetUID := e_Raw_Read_Word(P); - MonsterTargetTime := e_Raw_Read_LongInt(P); - MonsterSleep := e_Raw_Read_LongInt(P); - MonsterHealth := e_Raw_Read_LongInt(P); - MonsterAmmo := e_Raw_Read_LongInt(P); - MonsterPain := e_Raw_Read_LongInt(P); - AnimRevert := e_Raw_Read_Byte(P) <> 0; + MonsterTargetUID := M.ReadWord(); + MonsterTargetTime := M.ReadLongInt(); + MonsterSleep := M.ReadLongInt(); + MonsterHealth := M.ReadLongInt(); + MonsterAmmo := M.ReadLongInt(); + MonsterPain := M.ReadLongInt(); + AnimRevert := M.ReadByte() <> 0; + FFireTime := M.ReadLongInt(); RevertAnim(AnimRevert); if MonsterState <> MState then begin - if (MState = MONSTATE_GO) and (MonsterState = MONSTATE_SLEEP) then - WakeUpSound; - if (MState = MONSTATE_DIE) then - DieSound; - if (MState = MONSTATE_PAIN) then - MakeBloodSimple(Min(200, MonsterPain)); - if (MState = MONSTATE_ATTACK) then - kick(nil); - if (MState = MONSTATE_DEAD) then - SetDeadAnim; + if (MState = MONSTATE_GO) and (MonsterState = MONSTATE_SLEEP) then WakeUpSound(); + if (MState = MONSTATE_DIE) then DieSound(); + if (MState = MONSTATE_PAIN) then MakeBloodSimple(Min(200, MonsterPain)); + if (MState = MONSTATE_ATTACK) then kick(nil); + if (MState = MONSTATE_DEAD) then SetDeadAnim(); SetState(MState, MFAnm); end; end; end; -procedure MC_RECV_MonsterShot(P: Pointer); +procedure MC_RECV_MonsterShot(var M: TMsg); var ID: Integer; - M: TMonster; + Mon: TMonster; X, Y, VX, VY: Integer; begin - ID := e_Raw_Read_Word(P); + ID := M.ReadWord(); - M := g_Monsters_Get(ID); - if M = nil then Exit; + Mon := g_Monsters_ByUID(ID); + if Mon = nil then Exit; - X := e_Raw_Read_LongInt(P); - Y := e_Raw_Read_LongInt(P); - VX := e_Raw_Read_LongInt(P); - VY := e_Raw_Read_LongInt(P); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + VX := M.ReadLongInt(); + VY := M.ReadLongInt(); - M.ClientAttack(X, Y, VX, VY); + Mon.ClientAttack(X, Y, VX, VY); end; -procedure MC_RECV_MonsterDelete(P: Pointer); +procedure MC_RECV_MonsterDelete(var M: TMsg); var ID: Integer; - M: TMonster; + Mon: TMonster; begin - ID := e_Raw_Read_Word(P); - M := g_Monsters_Get(ID); - if M = nil then Exit; - - gMonsters[ID].SetState(5); - gMonsters[ID].MonsterRemoved := True; + ID := M.ReadWord(); + Mon := g_Monsters_ByUID(ID); + if Mon = nil then Exit; + Mon.SetState(5); + Mon.MonsterRemoved := True; end; -procedure MC_RECV_TimeSync(P: Pointer); +procedure MC_RECV_TimeSync(var M: TMsg); var Time: LongWord; begin - Time := e_Raw_Read_LongWord(P); + Time := M.ReadLongWord(); if gState = STATE_INTERCUSTOM then gServInterTime := Min(Time, 255); end; -procedure MC_RECV_VoteEvent(P: Pointer); +procedure MC_RECV_VoteEvent(var M: TMsg); var EvID: Byte; Str1, Str2: string; Int1, Int2: SmallInt; begin - EvID := e_Raw_Read_Byte(P); - Int1 := e_Raw_Read_SmallInt(P); - Int2 := e_Raw_Read_SmallInt(P); - Str1 := e_Raw_Read_String(P); - Str2 := e_Raw_Read_String(P); + EvID := M.ReadByte(); + Int1 := M.ReadSmallInt(); + Int2 := M.ReadSmallInt(); + Str1 := M.ReadString(); + Str2 := M.ReadString(); case EvID of NET_VE_STARTED: @@ -2683,34 +2686,44 @@ end; procedure MC_SEND_Info(Password: string); begin - e_Buffer_Clear(@NetOut); + NetOut.Clear(); - e_Buffer_Write(@NetOut, Byte(NET_MSG_INFO)); - e_Buffer_Write(@NetOut, GAME_VERSION); - e_Buffer_Write(@NetOut, Password); - e_Buffer_Write(@NetOut, gPlayer1Settings.Name); - e_Buffer_Write(@NetOut, gPlayer1Settings.Model); - e_Buffer_Write(@NetOut, gPlayer1Settings.Color.R); - e_Buffer_Write(@NetOut, gPlayer1Settings.Color.G); - e_Buffer_Write(@NetOut, gPlayer1Settings.Color.B); - e_Buffer_Write(@NetOut, gPlayer1Settings.Team); + NetOut.Write(Byte(NET_MSG_INFO)); + NetOut.Write(GAME_VERSION); + NetOut.Write(Password); + NetOut.Write(gPlayer1Settings.Name); + NetOut.Write(gPlayer1Settings.Model); + NetOut.Write(gPlayer1Settings.Color.R); + NetOut.Write(gPlayer1Settings.Color.G); + NetOut.Write(gPlayer1Settings.Color.B); + NetOut.Write(gPlayer1Settings.Team); g_Net_Client_Send(True, NET_CHAN_SERVICE); end; procedure MC_SEND_Chat(Txt: string; Mode: Byte); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_CHAT)); - e_Buffer_Write(@NetOut, Txt); - e_Buffer_Write(@NetOut, Mode); + NetOut.Write(Byte(NET_MSG_CHAT)); + NetOut.Write(Txt); + NetOut.Write(Mode); g_Net_Client_Send(True, NET_CHAN_CHAT); end; +function isKeyPressed (key1: Word; key2: Word): Boolean; +begin + if (key1 <> 0) and e_KeyPressed(key1) then begin result := true; exit; end; + if (key2 <> 0) and e_KeyPressed(key2) then begin result := true; exit; end; + result := false; +end; + procedure MC_SEND_PlayerPos(); var kByte: Word; Predict: Boolean; + strafeDir: Byte; + WeaponSelect: Word = 0; + I: Integer; begin if not gGameOn then Exit; if gPlayers = nil then Exit; @@ -2720,25 +2733,30 @@ begin Predict := NetPredictSelf; // and (not NetGotKeys); if (not gConsoleShow) and (not gChatShow) and (g_ActiveWindow = nil) then + begin + strafeDir := P1MoveButton shr 4; + P1MoveButton := P1MoveButton and $0F; with gGameControls.P1Control do begin - if e_KeyPressed(KeyLeft) and (not e_KeyPressed(KeyRight)) then - P1MoveButton := 1 - else - if (not e_KeyPressed(KeyLeft)) and e_KeyPressed(KeyRight) then - P1MoveButton := 2 - else - if (not e_KeyPressed(KeyLeft)) and (not e_KeyPressed(KeyRight)) then - P1MoveButton := 0; + if isKeyPressed(KeyLeft, KeyLeft2) and (not isKeyPressed(KeyRight, KeyRight2)) then P1MoveButton := 1 + else if (not isKeyPressed(KeyLeft, KeyLeft2)) and isKeyPressed(KeyRight, KeyRight2) then P1MoveButton := 2 + else if (not isKeyPressed(KeyLeft, KeyLeft2)) and (not isKeyPressed(KeyRight, KeyRight2)) then P1MoveButton := 0; - if (P1MoveButton = 2) and e_KeyPressed(KeyLeft) then - gPlayer1.SetDirection(D_LEFT) + // strafing + if isKeyPressed(KeyStrafe, KeyStrafe2) then + begin + // new strafe mechanics + 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); + end else - if (P1MoveButton = 1) and e_KeyPressed(KeyRight) then - gPlayer1.SetDirection(D_RIGHT) - else - if P1MoveButton <> 0 then - gPlayer1.SetDirection(TDirection(P1MoveButton-1)); + begin + if (P1MoveButton = 2) and isKeyPressed(KeyLeft, KeyLeft2) then gPlayer1.SetDirection(TDirection.D_LEFT) + else if (P1MoveButton = 1) and isKeyPressed(KeyRight, KeyRight2) then gPlayer1.SetDirection(TDirection.D_RIGHT) + else if P1MoveButton <> 0 then gPlayer1.SetDirection(TDirection(P1MoveButton-1)); + end; gPlayer1.ReleaseKeys; if P1MoveButton = 1 then @@ -2751,33 +2769,41 @@ begin kByte := kByte or NET_KEY_RIGHT; if Predict then gPlayer1.PressKey(KEY_RIGHT, 10000); end; - if e_KeyPressed(KeyUp) then + if isKeyPressed(KeyUp, KeyUp2) then begin kByte := kByte or NET_KEY_UP; gPlayer1.PressKey(KEY_UP, 10000); end; - if e_KeyPressed(KeyDown) then + if isKeyPressed(KeyDown, KeyDown2) then begin kByte := kByte or NET_KEY_DOWN; gPlayer1.PressKey(KEY_DOWN, 10000); end; - if e_KeyPressed(KeyJump) then + if isKeyPressed(KeyJump, KeyJump2) then begin kByte := kByte or NET_KEY_JUMP; // gPlayer1.PressKey(KEY_JUMP, 10000); // TODO: Make a prediction option end; - if e_KeyPressed(KeyFire) then kByte := kByte or NET_KEY_FIRE; - if e_KeyPressed(KeyOpen) then kByte := kByte or NET_KEY_OPEN; - if e_KeyPressed(KeyNextWeapon) then kByte := kByte or NET_KEY_NW; - if e_KeyPressed(KeyPrevWeapon) then kByte := kByte or NET_KEY_PW; - end + if isKeyPressed(KeyFire, KeyFire2) then kByte := kByte or NET_KEY_FIRE; + if isKeyPressed(KeyOpen, KeyOpen2) then kByte := kByte or NET_KEY_OPEN; + if isKeyPressed(KeyNextWeapon, KeyNextWeapon2) then kByte := kByte or NET_KEY_NW; + if isKeyPressed(KeyPrevWeapon, KeyPrevWeapon2) then kByte := kByte or NET_KEY_PW; + for I := 0 to High(KeyWeapon) do + if isKeyPressed(KeyWeapon[I], KeyWeapon2[I]) then + WeaponSelect := WeaponSelect or Word(1 shl I); + end; + // fix movebutton state + P1MoveButton := P1MoveButton or (strafeDir shl 4); + end else kByte := NET_KEY_CHAT; - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRPOS)); - e_Buffer_Write(@NetOut, gTime); - e_Buffer_Write(@NetOut, kByte); - e_Buffer_Write(@NetOut, Byte(gPlayer1.Direction)); + NetOut.Write(Byte(NET_MSG_PLRPOS)); + NetOut.Write(gTime); + NetOut.Write(kByte); + NetOut.Write(Byte(gPlayer1.Direction)); + NetOut.Write(WeaponSelect); + //e_WriteLog(Format('S:ws=%d', [WeaponSelect]), MSG_WARNING); g_Net_Client_Send(True, NET_CHAN_PLAYERPOS); //kBytePrev := kByte; @@ -2786,50 +2812,50 @@ end; procedure MC_SEND_Vote(Start: Boolean = False; Command: string = 'a'); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_VOTE_EVENT)); - e_Buffer_Write(@NetOut, Byte(Start)); - e_Buffer_Write(@NetOut, Command); + NetOut.Write(Byte(NET_MSG_VOTE_EVENT)); + NetOut.Write(Byte(Start)); + NetOut.Write(Command); g_Net_Client_Send(True, NET_CHAN_IMPORTANT); end; procedure MC_SEND_PlayerSettings(); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_PLRSET)); - e_Buffer_Write(@NetOut, gPlayer1Settings.Name); - e_Buffer_Write(@NetOut, gPlayer1Settings.Model); - e_Buffer_Write(@NetOut, gPlayer1Settings.Color.R); - e_Buffer_Write(@NetOut, gPlayer1Settings.Color.G); - e_Buffer_Write(@NetOut, gPlayer1Settings.Color.B); - e_Buffer_Write(@NetOut, gPlayer1Settings.Team); + NetOut.Write(Byte(NET_MSG_PLRSET)); + NetOut.Write(gPlayer1Settings.Name); + NetOut.Write(gPlayer1Settings.Model); + NetOut.Write(gPlayer1Settings.Color.R); + NetOut.Write(gPlayer1Settings.Color.G); + NetOut.Write(gPlayer1Settings.Color.B); + NetOut.Write(gPlayer1Settings.Team); g_Net_Client_Send(True, NET_CHAN_IMPORTANT); end; procedure MC_SEND_FullStateRequest(); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_REQFST)); + NetOut.Write(Byte(NET_MSG_REQFST)); g_Net_Client_Send(True, NET_CHAN_SERVICE); end; procedure MC_SEND_CheatRequest(Kind: Byte); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_CHEAT)); - e_Buffer_Write(@NetOut, Kind); + NetOut.Write(Byte(NET_MSG_CHEAT)); + NetOut.Write(Kind); g_Net_Client_Send(True, NET_CHAN_IMPORTANT); end; procedure MC_SEND_RCONPassword(Password: string); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_RCON_AUTH)); - e_Buffer_Write(@NetOut, Password); + NetOut.Write(Byte(NET_MSG_RCON_AUTH)); + NetOut.Write(Password); g_Net_Client_Send(True, NET_CHAN_SERVICE); end; procedure MC_SEND_RCONCommand(Cmd: string); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_RCON_CMD)); - e_Buffer_Write(@NetOut, Cmd); + NetOut.Write(Byte(NET_MSG_RCON_CMD)); + NetOut.Write(Cmd); g_Net_Client_Send(True, NET_CHAN_SERVICE); end; @@ -2841,15 +2867,15 @@ var FileStream : TStream; fname: string; begin - e_WriteLog(Format('NETWORK: looking for file "%s"', [FileName]), MSG_NOTIFY); + 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]), MSG_FATALERROR); + e_WriteLog(Format('NETWORK: file "%s" not found!', [FileName]), TMsgType.Fatal); SetLength(Result, 0); exit; end; - e_WriteLog(Format('NETWORK: found file "%s"', [fname]), MSG_NOTIFY); + e_WriteLog(Format('NETWORK: found file "%s"', [fname]), TMsgType.Notify); Result := nil; FileStream := openDiskFileRO(fname); try @@ -2970,28 +2996,28 @@ end; procedure MC_SEND_MapRequest(); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_MAP_REQUEST)); + NetOut.Write(Byte(NET_MSG_MAP_REQUEST)); g_Net_Client_Send(True, NET_CHAN_IMPORTANT); end; procedure MC_SEND_ResRequest(const resName: AnsiString); begin - e_Buffer_Write(@NetOut, Byte(NET_MSG_RES_REQUEST)); - e_Buffer_Write(@NetOut, resName); + 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; P: Pointer); +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), MSG_NOTIFY); + DecodeIPV4(C^.Peer.address.host), TMsgType.Notify); mapDataMsg := CreateMapDataMsg(MapsDir + gGameSettings.WAD, gExternalResources); - peer := NetClients[C.ID].Peer; + peer := NetClients[C^.ID].Peer; MapDataMsgToBytes(payload, mapDataMsg); g_Net_SendData(payload, peer, True, NET_CHAN_DOWNLOAD); @@ -3001,24 +3027,24 @@ begin mapDataMsg.ExternalResources := nil; end; -procedure MH_RECV_ResRequest(C: pTNetClient; P: Pointer); +procedure MH_RECV_ResRequest(C: pTNetClient; var M: TMsg); var payload: AByte; peer: pENetPeer; FileName: String; resDataMsg: TResDataMsg; begin - FileName := ExtractFileName(e_Raw_Read_String(P)); + FileName := ExtractFileName(M.ReadString()); e_WriteLog('NET: Received res request: ' + FileName + - ' from ' + DecodeIPV4(C.Peer.address.host), MSG_NOTIFY); + ' from ' + DecodeIPV4(C^.Peer.address.host), TMsgType.Notify); if not IsValidFilePath(FileName) then begin - e_WriteLog('Invalid filename: ' + FileName, MSG_WARNING); + e_WriteLog('Invalid filename: ' + FileName, TMsgType.Warning); exit; end; - peer := NetClients[C.ID].Peer; + peer := NetClients[C^.ID].Peer; if gExternalResources.IndexOf(FileName) > -1 then begin