diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas
index 36c0aa15e5e293f5a64713e87706577d27149864..910a480a78d25b4073593853012ef1a7d8e6a5b4 100644 (file)
--- a/src/game/g_netmsg.pas
+++ b/src/game/g_netmsg.pas
// HOST MESSAGES
+procedure MH_MalformedPacket(C: pTNetClient);
procedure MH_ProcessFirstSpawn (C: pTNetClient);
procedure MH_RECV_Info(C: pTNetClient; var M: TMsg);
// GAME
+procedure MH_MalformedPacket(C: pTNetClient);
+begin
+ g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_MSG_HOST_REJECT] +
+ _lc[I_NET_DISC_PROTOCOL]);
+ enet_peer_disconnect(C^.Peer, NET_DISC_PROTOCOL);
+end;
+
procedure MH_RECV_Chat(C: pTNetClient; var M: TMsg);
var
Txt: string;
Mode: Byte;
PID: Word;
Pl: TPlayer;
+ Err: Boolean;
begin
PID := C^.Player;
Pl := g_Player_Get(PID);
- Txt := M.ReadString();
- Mode := M.ReadByte();
+ Err := False;
+ try
+ Txt := M.ReadString();
+ Mode := M.ReadByte();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
+
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
var
Ver, PName, Model, Pw: string;
R, G, B, T: Byte;
+ WeapSwitch: Byte;
+ TmpPrefArray: Array [WP_FIRST .. WP_LAST + 1] of Byte;
+ SwitchEmpty: Byte;
+ SkipF: Byte;
PID: Word;
Color: TRGB;
I: Integer;
-begin
- Ver := M.ReadString();
- Pw := M.ReadString();
- PName := M.ReadString();
- Model := M.ReadString();
- R := M.ReadByte();
- G := M.ReadByte();
- B := M.ReadByte();
- T := M.ReadByte();
+ Err: Boolean;
+begin
+ Err := False;
+ try
+ Ver := M.ReadString();
+ Pw := M.ReadString();
+ PName := M.ReadString();
+ Model := M.ReadString();
+ R := M.ReadByte();
+ G := M.ReadByte();
+ B := M.ReadByte();
+ T := M.ReadByte();
+ WeapSwitch := M.ReadByte();
+ if (WeapSwitch = 2) then
+ for I := WP_FIRST to WP_LAST + 1 do
+ TmpPrefArray[I] := M.ReadByte();
+ SwitchEmpty := M.ReadByte();
+ SkipF := M.ReadByte();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
if Ver <> GAME_VERSION then
begin
Exit;
end;
+ if (C^.Player <> 0) then
+ begin
+ // already received info
+ g_Net_Penalize(C, 'client info spam');
+ Exit;
+ end;
+
Color.R := R;
Color.B := B;
Color.G := G;
with g_Player_Get(PID) do
begin
Name := PName;
+ WeapSwitchMode := WeapSwitch;
+ if (WeapSwitch = 2) then
+ SetWeaponPrefs(TmpPrefArray);
+ SwitchToEmpty := SwitchEmpty;
+ SkipFist := SkipF;
Reset(True);
end;
C^.Player := PID;
C^.WaitForFirstSpawn := false;
+ C^.AuthTime := 0;
g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True);
e_WriteLog('NET: Client ' + PName + ' [' + IntToStr(C^.ID) +
kByte: Word;
Pl: TPlayer;
GT: LongWord;
+ Err: Boolean;
begin
Result := 0;
+ Err := False;
if not gGameOn then Exit;
- GT := M.ReadLongWord();
+ try
+ GT := M.ReadLongWord();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
+
PID := C^.Player;
Pl := g_Player_Get(PID);
if Pl = nil then
with Pl do
begin
NetTime := GT;
- kByte := M.ReadWord();
- Dir := M.ReadByte();
- WeaponAct := M.ReadByte();
- WeaponSelect := M.ReadWord();
+ try
+ kByte := M.ReadWord();
+ Dir := M.ReadByte();
+ WeaponAct := M.ReadByte();
+ WeaponSelect := M.ReadWord();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
+
//e_WriteLog(Format('R:ws=%d', [WeaponSelect]), MSG_WARNING);
if Direction <> TDirection(Dir) then
JustTeleported := False;
var
CheatKind: Byte;
Pl: TPlayer;
+ Err: Boolean;
begin
+ Err := False;
Pl := g_Player_Get(C^.Player);
if Pl = nil then Exit;
- CheatKind := M.ReadByte();
+ try
+ CheatKind := M.ReadByte();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
case CheatKind of
NET_CHEAT_SUICIDE:
TmpModel: string;
TmpColor: TRGB;
TmpTeam: Byte;
+ TmpWeapSwitch: Byte;
+ TmpPrefArray: Array [WP_FIRST .. WP_LAST + 1] of Byte;
+ TmpSwEmpty: Byte;
+ TmpSkipF: Byte;
+ I: Integer;
Pl: TPlayer;
-begin
- TmpName := M.ReadString();
- TmpModel := M.ReadString();
- TmpColor.R := M.ReadByte();
- TmpColor.G := M.ReadByte();
- TmpColor.B := M.ReadByte();
- TmpTeam := M.ReadByte();
+ Err: Boolean;
+begin
+ Err := False;
+ try
+ TmpName := M.ReadString();
+ TmpModel := M.ReadString();
+ TmpColor.R := M.ReadByte();
+ TmpColor.G := M.ReadByte();
+ TmpColor.B := M.ReadByte();
+ TmpTeam := M.ReadByte();
+ TmpWeapSwitch := M.ReadByte();
+ if (TmpWeapSwitch = 2) then
+ for I := WP_FIRST to WP_LAST + 1 do
+ TmpPrefArray[I] := M.ReadByte();
+ TmpSwEmpty := M.ReadByte();
+ TmpSkipF := M.ReadByte();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
Pl := g_Player_Get(C^.Player);
if Pl = nil then Exit;
if TmpModel <> Pl.Model.Name then
Pl.SetModel(TmpModel);
+ if (TmpWeapSwitch <> Pl.WeapSwitchMode) then
+ Pl.WeapSwitchMode := TmpWeapSwitch;
+
+ if (TmpWeapSwitch = 2) then
+ Pl.SetWeaponPrefs(TmpPrefArray);
+
+ if (TmpSwEmpty <> Pl.SwitchToEmpty) then
+ Pl.SwitchToEmpty := TmpSwEmpty;
+
+ if (TmpSkipF <> Pl.SkipFist) then
+ Pl.SkipFist := TmpSkipF;
+
MH_SEND_PlayerSettings(Pl.UID, TmpModel);
end;
procedure MH_RECV_RCONPassword(C: pTNetClient; var M: TMsg);
var
Pwd: string;
+ Err: Boolean;
begin
- Pwd := M.ReadString();
+ Err := False;
+ try
+ Pwd := M.ReadString();
+ except
+ Err := True;
+ end;
+ if Err then begin MH_MalformedPacket(C); Exit; end;
if not NetAllowRCON then Exit;
if Pwd = NetRCONPassword then
begin
procedure MH_RECV_RCONCommand(C: pTNetClient; var M: TMsg);
var
Cmd: string;
+ Err: Boolean;
begin
- Cmd := M.ReadString();
+ Err := False;
+ try
+ Cmd := M.ReadString();
+ except
+ Err := True;
+ end;
+ if Err then begin MH_MalformedPacket(C); Exit; end;
if not NetAllowRCON then Exit;
if not C^.RCONAuth then
begin
Name, Command: string;
Need: Integer;
Pl: TPlayer;
-begin
- Start := M.ReadByte() <> 0;
- Command := M.ReadString();
+ Err: Boolean;
+begin
+ Err := False;
+ try
+ Start := M.ReadByte() <> 0;
+ Command := M.ReadString();
+ except
+ Err := True;
+ end;
+
+ if Err then begin MH_MalformedPacket(C); Exit; end;
Pl := g_Player_Get(C^.Player);
if Pl = nil then Exit;
TmpModel: string;
TmpColor: TRGB;
TmpTeam: Byte;
+ i: Integer;
Pl: TPlayer;
PID: Word;
begin
// CLIENT SEND
procedure MC_SEND_Info(Password: string);
+var i: Integer;
begin
NetOut.Clear();
NetOut.Write(gPlayer1Settings.Color.G);
NetOut.Write(gPlayer1Settings.Color.B);
NetOut.Write(gPlayer1Settings.Team);
+ NetOut.Write(gPlayer1Settings.WeaponSwitch);
+ if (gPlayer1Settings.WeaponSwitch = 2) then
+ for i := WP_FIRST to WP_LAST + 1 do
+ NetOut.Write(gPlayer1Settings.WeaponPreferences[i]);
+ NetOut.Write(gPlayer1Settings.SwitchToEmpty);
+ NetOut.Write(gPlayer1Settings.SkipFist);
g_Net_Client_Send(True, NET_CHAN_SERVICE);
end;
end;
procedure MC_SEND_PlayerSettings();
+var i: Integer;
begin
NetOut.Write(Byte(NET_MSG_PLRSET));
NetOut.Write(gPlayer1Settings.Name);
NetOut.Write(gPlayer1Settings.Color.G);
NetOut.Write(gPlayer1Settings.Color.B);
NetOut.Write(gPlayer1Settings.Team);
+ NetOut.Write(gPlayer1Settings.WeaponSwitch);
+ if (gPlayer1Settings.WeaponSwitch = 2) then
+ for i := WP_FIRST to WP_LAST + 1 do
+ NetOut.Write(gPlayer1Settings.WeaponPreferences[i]);
+ NetOut.Write(gPlayer1Settings.SwitchToEmpty);
+ NetOut.Write(gPlayer1Settings.SkipFist);
g_Net_Client_Send(True, NET_CHAN_IMPORTANT);
end;