diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas
index e838a9b7fff87f34eaceee923c3dc387feb14fe1..244b2ebd716ef55a21674fbd4b375f9c2324aad8 100644 (file)
--- a/src/game/g_netmsg.pas
+++ b/src/game/g_netmsg.pas
-(* Copyright (C) DooM 2D:Forever Developers
+(* 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.
+ * 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
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
-{$MODE DELPHI}
+{$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;
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;
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;
NET_EV_LMS_DRAW = 16;
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;
NET_CHEAT_SUICIDE = 1;
NET_CHEAT_SPECTATE = 2;
+ NET_CHEAT_READY = 3;
NET_MAX_DIFFTIME = 5000 div 36;
// 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_ProcessFirstSpawn (C: pTNetClient);
+
+procedure MH_RECV_Info(C: pTNetClient; var M: TMsg);
+procedure MH_RECV_Chat(C: pTNetClient; var M: TMsg);
+procedure MH_RECV_FullStateRequest(C: pTNetClient; var M: TMsg);
+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_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);
@@ -168,8 +174,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);
// 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);
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
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
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;
//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 //
// GAME
-procedure MH_RECV_Chat(C: pTNetClient; P: Pointer);
+procedure MH_RECV_Chat(C: pTNetClient; var M: TMsg);
var
Txt: string;
Mode: Byte;
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
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;
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
end;
C^.Player := PID;
+ C^.WaitForFirstSpawn := false;
g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True);
e_WriteLog('NET: Client ' + PName + ' [' + IntToStr(C^.ID) +
- '] connected. Assigned player #' + IntToStr(PID) + '.', MSG_NOTIFY);
+ '] connected. Assigned player #' + IntToStr(PID) + '.', TMsgType.Notify);
MH_SEND_Info(C^.ID);
FNoRespawn := True;
Spectate;
FWantsInGame := True; // TODO: look into this later
+ C^.WaitForFirstSpawn := true;
end
else
- Respawn(gGameSettings.GameType = GT_SINGLE);
+ begin
+ e_LogWritefln('*** client #%u (cid #%u) authenticated...', [C.ID, C.Player]);
+ //e_LogWritefln('spawning player with pid #%u...', [PID]);
+ //Respawn(gGameSettings.GameType = GT_SINGLE);
+ //k8: no, do not spawn a player yet, wait for a 'i am ready' packet
+ Lives := 0;
+ Spectate;
+ FNoRespawn := True;
+ FWantsInGame := false; // TODO: look into this later
+ C^.WaitForFirstSpawn := true;
+ end;
end;
- for I := Low(NetClients) to High(NetClients) do
+ //if not C^.WaitForFirstSpawn then
begin
- if NetClients[I].ID = C^.ID then Continue;
- MH_SEND_PlayerCreate(PID, NetClients[I].ID);
- MH_SEND_PlayerPos(True, PID, NetClients[I].ID);
- MH_SEND_PlayerStats(PID, NetClients[I].ID);
+ for I := Low(NetClients) to High(NetClients) do
+ begin
+ if NetClients[I].ID = C^.ID then Continue;
+ MH_SEND_PlayerCreate(PID, NetClients[I].ID);
+ MH_SEND_PlayerPos(True, PID, NetClients[I].ID);
+ MH_SEND_PlayerStats(PID, NetClients[I].ID);
+ end;
end;
if gState in [STATE_INTERCUSTOM, STATE_FOLD] then
if NetUseMaster then g_Net_Slist_Update;
end;
-procedure MH_RECV_FullStateRequest(C: pTNetClient; P: Pointer);
+
+procedure MH_ProcessFirstSpawn (C: pTNetClient);
+var
+ plr: TPlayer;
+begin
+ if not C.WaitForFirstSpawn then exit;
+ plr := g_Player_Get(C^.Player);
+ if not assigned(plr) then exit;
+ e_LogWritefln('*** client #%u (cid #%u) first spawn', [C.ID, C.Player]);
+ C.WaitForFirstSpawn := false;
+ plr.FNoRespawn := false;
+ plr.FWantsInGame := true; // TODO: look into this later
+ plr.Respawn(False);
+end;
+
+
+procedure MH_RECV_FullStateRequest(C: pTNetClient; var M: TMsg);
begin
+ //e_LogWritefln('*** client #%u (cid #%u) full state request', [C.ID, C.Player]);
if gGameOn then
+ begin
MH_SEND_Everything((C^.State = NET_STATE_AUTH), C^.ID)
+ end
else
+ begin
C^.RequestedFullUpdate := True;
+ end;
end;
// PLAYER
-function MH_RECV_PlayerPos(C: pTNetClient; P: Pointer): Word;
+function MH_RECV_PlayerPos(C: pTNetClient; var M: TMsg): Word;
var
Dir, i: Byte;
WeaponSelect: Word;
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
with Pl do
begin
NetTime := GT;
- kByte := e_Raw_Read_Word(P);
- Dir := e_Raw_Read_Byte(P);
- WeaponSelect := e_Raw_Read_Word(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;
// 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;
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:
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;
-procedure MH_RECV_PlayerSettings(C: pTNetClient; P: Pointer);
+procedure MH_RECV_PlayerSettings(C: pTNetClient; var M: TMsg);
var
TmpName: string;
TmpModel: string;
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;
// 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
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
// 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;
// GAME (SEND)
-procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_EVERYONE);
+procedure MH_SEND_Everything(CreatePlayers: Boolean {= False}; ID: Integer {= NET_EVERYONE});
+
+ function sendItemRespawn (it: PItem): Boolean;
+ begin
+ 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 (ID >= 0) and (ID < length(NetClients)) then
+ begin
+ e_LogWritefln('*** client #%u (cid #%u) will get everything', [ID, NetClients[ID].Player]);
+ MH_ProcessFirstSpawn(@NetClients[ID]);
+ end;
+
if gPlayers <> nil then
+ begin
for I := Low(gPlayers) to High(gPlayers) do
+ begin
if gPlayers[I] <> nil then
begin
if CreatePlayers then MH_SEND_PlayerCreate(gPlayers[I].UID, ID);
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
- begin
- if (GetTextureCount > 1) then
- MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID);
- if Moved then
- MH_SEND_PanelState(PanelType, I, ID);
- end;
- if gRenderBackgrounds <> nil then
- for I := Low(gRenderBackgrounds) to High(gRenderBackgrounds) do
- if gRenderBackgrounds[I] <> nil then
- with gRenderBackgrounds[I] do
- begin
- if (GetTextureCount > 1) then
- MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID);
- if Moved then
- MH_SEND_PanelState(PanelType, I, ID);
- end;
- 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);
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
+ e_LogWritefln('*** client #%u (cid #%u) WARMUP', [ID, NetClients[ID].Player]);
MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000, 'N', ID);
+ end;
+
+ g_Net_Flush();
end;
procedure MH_SEND_Info(ID: Byte);
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;
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;
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;
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
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
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; Pos: Boolean = True; ID: Integer = NET_EVERYONE);
begin
- e_Buffer_Write(@NetOut, Byte(NET_MSG_SND));
- e_Buffer_Write(@NetOut, Name);
+ NetOut.Write(Byte(NET_MSG_SND));
+ NetOut.Write(Name);
if Pos then
begin
- e_Buffer_Write(@NetOut, Byte(1));
- e_Buffer_Write(@NetOut, X);
- e_Buffer_Write(@NetOut, Y);
+ NetOut.Write(Byte(1));
+ NetOut.Write(X);
+ NetOut.Write(Y);
end
else
- e_Buffer_Write(@NetOut, Byte(0));
+ NetOut.Write(Byte(0));
g_Net_Host_Send(ID, False, NET_CHAN_GAME);
end;
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;
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);
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;
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;
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
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);
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 := WP_FIRST to WP_LAST do
- e_Buffer_Write(@NetOut, Byte(FWeapon[I]));
+ 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]));
-
- 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));
-
- e_Buffer_Write(@NetOut, Frags);
- e_Buffer_Write(@NetOut, Death);
-
- e_Buffer_Write(@NetOut, 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(LongWord(FMegaRulez[I]));
+
+ 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));
+
+ NetOut.Write(Frags);
+ NetOut.Write(Death);
+
+ NetOut.Write(CurrWeap);
+
+ NetOut.Write(Byte(FSpectator));
+ NetOut.Write(Byte(FGhost));
+ NetOut.Write(Byte(FPhysics));
+ NetOut.Write(Byte(FNoRespawn));
+ NetOut.Write(Byte(FJetpack));
+ NetOut.Write(FFireTime);
+ NetOut.Write(Byte(FFlaming));
end;
g_Net_Host_Send(ID, True, NET_CHAN_PLAYER);
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;
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;
// 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];
- PANEL_BACK:
- begin
- TP := gRenderBackgrounds[PID];
- TP.Moved := True;
- end;
- PANEL_FORE:
- begin
- TP := gRenderForegrounds[PID];
- TP.Moved := True;
- end;
- 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);
- e_Buffer_Write(@NetOut, TP.X);
- e_Buffer_Write(@NetOut, TP.Y);
+ 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;
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;
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);
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);
@@ -1361,23 +1415,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);
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;
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;
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;
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;
// 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
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;
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:
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);
- Pos := e_Raw_Read_Byte(P) <> 0;
+ Name := M.ReadString();
+ Pos := M.ReadByte() <> 0;
if Pos then
begin
- X := e_Raw_Read_LongInt(P);
- Y := e_Raw_Read_LongInt(P);
+ 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
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
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;
i1, i2: TStrings_Locale;
pln: String;
cnt: Byte;
+ goodCmd: Boolean = true;
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;
+ 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 Pos(':\', EvStr) = 0 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:
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);
pl.Touch();
end;
+ NET_EV_SECRET:
+ begin
+ pl := g_Player_Get(EvNum);
+ if pl <> nil then
+ begin
+ g_Console_Add(Format(_lc[I_PLAYER_SECRET], [pl.Name]), True);
+ g_Sound_PlayEx('SOUND_GAME_SECRET');
+ end;
+ end;
+
+ NET_EV_INTER_READY:
+ begin
+ pl := g_Player_Get(EvNum);
+ if pl <> nil then pl.FReady := (EvStr = 'Y');
+ end;
end;
end;
-procedure MC_RECV_FlagEvent(P: Pointer);
+procedure MC_RECV_FlagEvent(var M: TMsg);
var
PID: Word;
Pl: TPlayer;
EvType: Byte;
- Fl: Byte;
+ Fl, a: Byte;
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
s := _lc[I_PLAYER_FLAG_BLUE];
g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144);
+
+ if ((Pl = gPlayer1) or (Pl = gPlayer2)
+ or ((gPlayer1 <> nil) and (gPlayer1.Team = Pl.Team))
+ or ((gPlayer2 <> nil) and (gPlayer2.Team = Pl.Team))) then
+ a := 0
+ else
+ a := 1;
+
+ if not sound_ret_flag[a].IsPlaying() then
+ sound_ret_flag[a].Play();
end;
FLAG_STATE_CAPTURED:
g_Console_Add(Format(_lc[I_PLAYER_FLAG_GET], [Pl.Name, s]), True);
g_Game_Message(Format(_lc[I_MESSAGE_FLAG_GET], [AnsiUpperCase(s)]), 144);
+
+ if ((Pl = gPlayer1) or (Pl = gPlayer2)
+ or ((gPlayer1 <> nil) and (gPlayer1.Team = Pl.Team))
+ or ((gPlayer2 <> nil) and (gPlayer2.Team = Pl.Team))) then
+ a := 0
+ else
+ a := 1;
+
+ if not sound_get_flag[a].IsPlaying() then
+ sound_get_flag[a].Play();
end;
FLAG_STATE_DROPPED:
g_Console_Add(Format(_lc[I_PLAYER_FLAG_DROP], [Pl.Name, s]), True);
g_Game_Message(Format(_lc[I_MESSAGE_FLAG_DROP], [AnsiUpperCase(s)]), 144);
+
+ if ((Pl = gPlayer1) or (Pl = gPlayer2)
+ or ((gPlayer1 <> nil) and (gPlayer1.Team = Pl.Team))
+ or ((gPlayer2 <> nil) and (gPlayer2.Team = Pl.Team))) then
+ a := 0
+ else
+ a := 1;
+
+ if not sound_lost_flag[a].IsPlaying() then
+ sound_lost_flag[a].Play();
end;
FLAG_STATE_SCORED:
Insert('.', ts, Length(ts) + 1 - 3);
g_Console_Add(Format(_lc[I_PLAYER_FLAG_CAPTURE], [Pl.Name, s, ts]), True);
g_Game_Message(Format(_lc[I_MESSAGE_FLAG_CAPTURE], [AnsiUpperCase(s)]), 144);
+
+ if ((Pl = gPlayer1) or (Pl = gPlayer2)
+ or ((gPlayer1 <> nil) and (gPlayer1.Team = Pl.Team))
+ or ((gPlayer2 <> nil) and (gPlayer2.Team = Pl.Team))) then
+ a := 0
+ else
+ a := 1;
+
+ if not sound_cap_flag[a].IsPlaying() then
+ sound_cap_flag[a].Play();
end;
FLAG_STATE_RETURNED:
s := _lc[I_PLAYER_FLAG_BLUE];
g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144);
+
+ if ((Pl = gPlayer1) or (Pl = gPlayer2)
+ or ((gPlayer1 <> nil) and (gPlayer1.Team = Pl.Team))
+ or ((gPlayer2 <> nil) and (gPlayer2.Team = Pl.Team))) then
+ a := 0
+ else
+ a := 1;
+
+ if not sound_ret_flag[a].IsPlaying() then
+ sound_ret_flag[a].Play();
end;
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;
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
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;
begin
Result := 0;
- GT := e_Raw_Read_LongWord(P);
+ GT := M.ReadLongWord();
if GT < gTime - NET_MAX_DIFFTIME then
begin
gTime := GT;
end;
gTime := GT;
- PID := e_Raw_Read_Word(P);
+ PID := M.ReadWord();
Pl := g_Player_Get(PID);
if Pl = nil then Exit;
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;
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;
- I: Integer;
- OldJet: Boolean;
+ I, OldFire: Integer;
+ OldJet, Flam: Boolean;
NewTeam: Byte;
begin
- PID := e_Raw_Read_Word(P);
+ PID := M.ReadWord();
Pl := g_Player_Get(PID);
Result := 0;
if Pl = nil then
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 := WP_FIRST to WP_LAST do
- FWeapon[I] := (e_Raw_Read_Byte(P) <> 0);
+ 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
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;
+ OldFire := FFireTime;
+ FFireTime := M.ReadLongInt();
+ if (OldFire <= 0) and (FFireTime > 0) then
+ g_Sound_PlayExAt('SOUND_IGNITE', Obj.X, Obj.Y);
+ Flam := M.ReadByte() <> 0;
if OldJet and not FJetpack then
JetpackOff
else if not OldJet and FJetpack then
JetpackOn;
+ if FFlaming and not Flam then
+ FlamerOff;
if Team <> NewTeam then
Pl.ChangeTeam(NewTeam);
end;
Result := PID;
end;
-function MC_RECV_PlayerDamage(P: Pointer): Word;
+function MC_RECV_PlayerDamage(var M: TMsg): Word;
var
PID: Word;
Pl: TPlayer;
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);
Result := PID;
end;
-function MC_RECV_PlayerDeath(P: Pointer): Word;
+function MC_RECV_PlayerDeath(var M: TMsg): Word;
var
PID: Word;
Pl: TPlayer;
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
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;
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;
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
// ITEM
-procedure MC_RECV_ItemSpawn(P: Pointer);
+procedure MC_RECV_ItemSpawn(var M: TMsg);
var
ID: Word;
AID: DWord;
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
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: Integer;
+ 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);
- X := e_Raw_Read_LongInt(P);
- Y := e_Raw_Read_LongInt(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);
-
- PANEL_BACK:
- begin
- gRenderBackgrounds[ID].X := X;
- gRenderBackgrounds[ID].Y := Y;
- end;
- PANEL_FORE:
- begin
- gRenderForegrounds[ID].X := X;
- gRenderForegrounds[ID].Y := Y;
- end;
- 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;
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;
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;
+ 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
// 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;
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;
+ ID, OldFire: 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;
+ OldFire := FFireTime;
+ FFireTime := M.ReadLongInt();
+ if (OldFire <= 0) and (FFireTime > 0) then
+ g_Sound_PlayExAt('SOUND_IGNITE', Obj.X, Obj.Y);
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:
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;
+ i: Integer;
begin
if not gGameOn then Exit;
if gPlayers = nil then Exit;
begin
strafeDir := P1MoveButton shr 4;
P1MoveButton := P1MoveButton and $0F;
- with gGameControls.P1Control do
+
+ if gPlayerAction[0, ACTION_MOVELEFT] and (not gPlayerAction[0, ACTION_MOVERIGHT]) then
+ P1MoveButton := 1
+ else if (not gPlayerAction[0, ACTION_MOVELEFT]) and gPlayerAction[0, ACTION_MOVERIGHT] then
+ P1MoveButton := 2
+ else if (not gPlayerAction[0, ACTION_MOVELEFT]) and (not gPlayerAction[0, ACTION_MOVERIGHT]) then
+ P1MoveButton := 0;
+
+ // strafing
+ if gPlayerAction[0, ACTION_STRAFE] then
begin
- 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;
+ // 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
+ 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
+ gPlayer1.SetDirection(TDirection.D_RIGHT)
+ else if P1MoveButton <> 0 then
+ gPlayer1.SetDirection(TDirection(P1MoveButton-1));
+ end;
- // 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(D_LEFT)
- else if (strafeDir = 1) then gPlayer1.SetDirection(D_RIGHT);
- end
- else
- begin
- if (P1MoveButton = 2) and isKeyPressed(KeyLeft, KeyLeft2) then gPlayer1.SetDirection(D_LEFT)
- else if (P1MoveButton = 1) and isKeyPressed(KeyRight, KeyRight2) then gPlayer1.SetDirection(D_RIGHT)
- else if P1MoveButton <> 0 then gPlayer1.SetDirection(TDirection(P1MoveButton-1));
- end;
+ gPlayer1.ReleaseKeys;
+ if P1MoveButton = 1 then
+ begin
+ kByte := kByte or NET_KEY_LEFT;
+ if Predict then gPlayer1.PressKey(KEY_LEFT, 10000);
+ end;
+ if P1MoveButton = 2 then
+ begin
+ kByte := kByte or NET_KEY_RIGHT;
+ if Predict then gPlayer1.PressKey(KEY_RIGHT, 10000);
+ end;
+ if gPlayerAction[0, ACTION_LOOKUP] then
+ begin
+ kByte := kByte or NET_KEY_UP;
+ gPlayer1.PressKey(KEY_UP, 10000);
+ end;
+ if gPlayerAction[0, ACTION_LOOKDOWN] then
+ begin
+ kByte := kByte or NET_KEY_DOWN;
+ gPlayer1.PressKey(KEY_DOWN, 10000);
+ end;
+ if gPlayerAction[0, ACTION_JUMP] then
+ begin
+ kByte := kByte or NET_KEY_JUMP;
+ // gPlayer1.PressKey(KEY_JUMP, 10000); // TODO: Make a prediction option
+ end;
+ if gPlayerAction[0, ACTION_ATTACK] then kByte := kByte or NET_KEY_FIRE;
+ if gPlayerAction[0, ACTION_ACTIVATE] then kByte := kByte or NET_KEY_OPEN;
+ if gPlayerAction[0, ACTION_WEAPNEXT] then kByte := kByte or NET_KEY_NW;
+ if gPlayerAction[0, ACTION_WEAPPREV] then kByte := kByte or NET_KEY_PW;
- gPlayer1.ReleaseKeys;
- if P1MoveButton = 1 then
- begin
- kByte := kByte or NET_KEY_LEFT;
- if Predict then gPlayer1.PressKey(KEY_LEFT, 10000);
- end;
- if P1MoveButton = 2 then
- begin
- kByte := kByte or NET_KEY_RIGHT;
- if Predict then gPlayer1.PressKey(KEY_RIGHT, 10000);
- end;
- if isKeyPressed(KeyUp, KeyUp2) then
- begin
- kByte := kByte or NET_KEY_UP;
- gPlayer1.PressKey(KEY_UP, 10000);
- end;
- if isKeyPressed(KeyDown, KeyDown2) then
- begin
- kByte := kByte or NET_KEY_DOWN;
- gPlayer1.PressKey(KEY_DOWN, 10000);
- end;
- if isKeyPressed(KeyJump, KeyJump2) then
+ gPlayerAction[0, ACTION_WEAPNEXT] := False; // HACK, remove after readyweaon&pendinweapon implementation
+ gPlayerAction[0, ACTION_WEAPPREV] := False; // HACK, remove after readyweaon&pendinweapon implementation
+
+ for i := WP_FIRST to WP_LAST do
+ begin
+ if gSelectWeapon[0, i] then
begin
- kByte := kByte or NET_KEY_JUMP;
- // gPlayer1.PressKey(KEY_JUMP, 10000); // TODO: Make a prediction option
- 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);
+ WeaponSelect := WeaponSelect or Word(1 shl i);
+ gSelectWeapon[0, i] := False
+ end
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));
- e_Buffer_Write(@NetOut, WeaponSelect);
+ 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);
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;
-// 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]), MSG_NOTIFY);
- fname := findDiskWad(FileName);
- if length(fname) = 0 then
- begin
- e_WriteLog(Format('NETWORK: file "%s" not found!', [FileName]), MSG_FATALERROR);
- SetLength(Result, 0);
- exit;
- end;
- e_WriteLog(Format('NETWORK: found file "%s"', [fname]), MSG_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
- e_Buffer_Write(@NetOut, 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);
- g_Net_Client_Send(True, NET_CHAN_IMPORTANT);
-end;
-
-procedure MH_RECV_MapRequest(C: pTNetClient; P: Pointer);
-var
- payload: AByte;
- peer: pENetPeer;
- mapDataMsg: TMapDataMsg;
-begin
- e_WriteLog('NET: Received map request from ' +
- DecodeIPV4(C.Peer.address.host), MSG_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; P: Pointer);
-var
- payload: AByte;
- peer: pENetPeer;
- FileName: String;
- resDataMsg: TResDataMsg;
-begin
- FileName := ExtractFileName(e_Raw_Read_String(P));
- e_WriteLog('NET: Received res request: ' + FileName +
- ' from ' + DecodeIPV4(C.Peer.address.host), MSG_NOTIFY);
-
- if not IsValidFilePath(FileName) then
- begin
- e_WriteLog('Invalid filename: ' + FileName, MSG_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.