--- a/hedgewars/uIO.pas Tue Nov 10 18:16:35 2015 +0100
+++ b/hedgewars/uIO.pas Tue Nov 10 20:43:13 2015 +0100
@@ -1,6 +1,6 @@
(*
* Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
*
* 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
@@ -13,7 +13,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*)
{$INCLUDE "options.inc"}
@@ -51,8 +51,7 @@
loTime: Word;
case byte of
1: (len: byte;
- cmd: Char;
- X, Y: LongInt);
+ cmd: Char);
2: (str: shortstring);
end;
@@ -77,7 +76,7 @@
FillChar(command^, sizeof(TCmd), 0);
command^.loTime:= Time;
command^.str:= str;
-if command^.cmd <> 'F' then dec(command^.len, 2); // cut timestamp
+if (command^.cmd <> 'F') and (command^.cmd <> 'G') then dec(command^.len, 2); // cut timestamp
if headcmd = nil then
begin
headcmd:= command;
@@ -119,9 +118,23 @@
WriteLnToConsole(msgOK)
end;
+procedure ParseChatCommand(command: shortstring; message: shortstring;
+ messageStartIndex: Byte);
+var
+ text: shortstring;
+begin
+ text:= copy(message, messageStartIndex,
+ Length(message) - messageStartIndex + 1);
+ ParseCommand(command + text, true);
+ WriteLnToConsole(text)
+end;
+
procedure ParseIPCCommand(s: shortstring);
var loTicks: Word;
+ isProcessed: boolean;
begin
+isProcessed := true;
+
case s[1] of
'!': begin AddFileLog('Ping? Pong!'); isPonged:= true; end;
'?': SendIPC(_S'!');
@@ -140,12 +153,27 @@
'V': begin
if s[2] = '.' then
ParseCommand('campvar ' + copy(s, 3, length(s) - 2), true);
- end
+ end;
+ 'I': ParseCommand('pause server', true);
+ 's': if gameType = gmtNet then
+ ParseChatCommand('chatmsg ', s, 2)
+ else
+ isProcessed:= false;
+ 'b': if gameType = gmtNet then
+ ParseChatCommand('chatmsg ' + #4, s, 2)
+ else
+ isProcessed:= false;
+ 'Y': ChatPasteBuffer:= copy(s, 2, Length(s) - 1);
else
- loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]);
- AddCmd(loTicks, s);
- AddFileLog('[IPC in] ' + sanitizeCharForLog(s[1]) + ' ticks ' + IntToStr(lastcmd^.loTime));
- end
+ isProcessed:= false;
+ end;
+
+ if (not isProcessed) then
+ begin
+ loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]);
+ AddCmd(loTicks, s);
+ AddFileLog('[IPC in] ' + sanitizeCharForLog(s[1]) + ' ticks ' + IntToStr(lastcmd^.loTime));
+ end
end;
procedure IPCCheckSock;
@@ -177,10 +205,10 @@
end;
procedure LoadRecordFromFile(fileName: shortstring);
-var f: file;
- ss: shortstring = '';
- i: LongInt;
- s: shortstring;
+var f : File;
+ ss : shortstring = '';
+ i : LongInt;
+ s : shortstring;
begin
// set RDNLY on file open
@@ -188,7 +216,6 @@
{$I-}
assign(f, fileName);
reset(f, 1);
-
tryDo(IOResult = 0, 'Error opening file ' + fileName, true);
i:= 0; // avoid compiler hints
@@ -202,7 +229,7 @@
while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do
begin
ParseIPCCommand(copy(ss, 2, byte(ss[1])));
- Delete(ss, 1, Succ(byte(ss[1])))
+ Delete(ss, 1, Succ(byte(ss[1])));
end
end
until i = 0;
@@ -221,7 +248,15 @@
function isSyncedCommand(c: char): boolean;
begin
- isSyncedCommand:= (c in ['+', '#', 'L', 'l', 'R', 'r', 'U', 'u', 'D', 'd', 'Z', 'z', 'A', 'a', 'S', 'j', 'J', ',', 'c', 'N', 'p', 'P', 'w', 't', '1', '2', '3', '4', '5']) or ((c >= #128) and (c <= char(128 + cMaxSlotIndex)))
+ case c of
+ '+', '#', 'L', 'l', 'R', 'r', 'U'
+ , 'u', 'D', 'd', 'Z', 'z', 'A', 'a'
+ , 'S', 'j', 'J', ',', 'c', 'N', 'p'
+ , 'P', 'w', 't', '1', '2', '3', '4'
+ , '5', 'f', 'g': isSyncedCommand:= true;
+ else
+ isSyncedCommand:= ((byte(c) >= 128) and (byte(c) <= 128 + cMaxSlotIndex))
+ end
end;
procedure flushBuffer();
@@ -240,20 +275,20 @@
begin
if s[0] > #251 then
s[0]:= #251;
-
+
SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
-
+
AddFileLog('[IPC out] '+ sanitizeCharForLog(s[1]));
inc(s[0], 2);
-
+
if isSyncedCommand(s[1]) then
begin
if sendBuffer.count + byte(s[0]) >= cSendBufferSize then
flushBuffer();
-
+
Move(s, sendBuffer.buf[sendBuffer.count], byte(s[0]) + 1);
inc(sendBuffer.count, byte(s[0]) + 1);
-
+
if (s[1] = 'N') or (s[1] = '#') then
flushBuffer();
end else
@@ -302,8 +337,8 @@
begin
if sendBuffer.count = 0 then
SendIPC(_S'+');
-
- flushBuffer()
+
+ flushBuffer()
end
end;
@@ -316,12 +351,13 @@
while (headcmd <> nil)
and (tmpflag or (headcmd^.cmd = '#')) // '#' is the only cmd which can be sent within same tick after 'N'
- and ((GameTicks = hiTicks shl 16 + headcmd^.loTime)
+ and ((GameTicks = LongWord(hiTicks shl 16 + headcmd^.loTime))
or (headcmd^.cmd = 's') // for these commands time is not specified
or (headcmd^.cmd = 'h') // seems the hedgewars protocol does not allow remote synced commands
or (headcmd^.cmd = '#') // must be synced for saves to work
or (headcmd^.cmd = 'b')
- or (headcmd^.cmd = 'F')) do
+ or (headcmd^.cmd = 'F')
+ or (headcmd^.cmd = 'G')) do
begin
case headcmd^.cmd of
'+': ; // do nothing - it is just an empty packet
@@ -349,26 +385,20 @@
s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
ParseCommand('gencmd ' + s, true);
end;
- 's': begin
- s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
- ParseCommand('chatmsg ' + s, true);
- WriteLnToConsole(s)
- end;
- 'b': begin
- s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
- ParseCommand('chatmsg ' + #4 + s, true);
- WriteLnToConsole(s)
- end;
-// TODO: deprecate 'F'
- 'F': ParseCommand('teamgone ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
+ 's': ParseChatCommand('chatmsg ', headcmd^.str, 2);
+ 'b': ParseChatCommand('chatmsg ' + #4, headcmd^.str, 2);
+ 'F': ParseCommand('teamgone u' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
+ 'G': ParseCommand('teamback u' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
+ 'f': ParseCommand('teamgone s' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
+ 'g': ParseCommand('teamback s' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
'N': begin
tmpflag:= false;
lastTurnChecksum:= SDLNet_Read32(@headcmd^.str[2]);
AddFileLog('got cmd "N": time '+IntToStr(hiTicks shl 16 + headcmd^.loTime))
end;
'p': begin
- x32:= SDLNet_Read32(@(headcmd^.X));
- y32:= SDLNet_Read32(@(headcmd^.Y));
+ x32:= SDLNet_Read32(@(headcmd^.str[2]));
+ y32:= SDLNet_Read32(@(headcmd^.str[6]));
doPut(x32, y32, false)
end;
'P': begin
@@ -377,8 +407,8 @@
// SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy;
if CurrentTeam^.ExtDriven then
begin
- TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.X))) + WorldDx;
- TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.Y))) - WorldDy;
+ TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.str[2]))) + WorldDx;
+ TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.str[6]))) - WorldDy;
if not bShowAmmoMenu and autoCameraOn then
CursorPoint:= TargetCursorPoint
end
@@ -388,7 +418,7 @@
'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
'1'..'5': ParseCommand('timer ' + headcmd^.cmd, true);
else
- if (headcmd^.cmd >= #128) and (headcmd^.cmd <= char(128 + cMaxSlotIndex)) then
+ if (byte(headcmd^.cmd) >= 128) and (byte(headcmd^.cmd) <= 128 + cMaxSlotIndex) then
ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
else
OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
@@ -397,7 +427,7 @@
end;
if (headcmd <> nil) and tmpflag and (not CurrentTeam^.hasGone) then
- TryDo(GameTicks < hiTicks shl 16 + headcmd^.loTime,
+ TryDo(GameTicks < LongWord(hiTicks shl 16) + headcmd^.loTime,
'oops, queue error. in buffer: ' + headcmd^.cmd +
' (' + IntToStr(GameTicks) + ' > ' +
IntToStr(hiTicks shl 16 + headcmd^.loTime) + ')',
@@ -405,7 +435,11 @@
isInLag:= (headcmd = nil) and tmpflag and (not CurrentTeam^.hasGone);
-if isInLag then fastUntilLag:= false
+if isInLag and fastUntilLag then
+begin
+ ParseCommand('spectate 0', true);
+ fastUntilLag:= false
+end;
end;
procedure chFatalError(var s: shortstring);
@@ -413,7 +447,11 @@
SendIPC('E' + s);
// TODO: should we try to clean more stuff here?
SDL_Quit;
- halt(2)
+
+ if IPCSock <> nil then
+ halt(HaltFatalError)
+ else
+ halt(HaltFatalErrorNoIPC);
end;
procedure doPut(putX, putY: LongInt; fromAI: boolean);
@@ -421,7 +459,7 @@
if CheckNoTeamOrHH or isPaused then
exit;
bShowFinger:= false;
-if not CurrentTeam^.ExtDriven and bShowAmmoMenu then
+if (not CurrentTeam^.ExtDriven) and bShowAmmoMenu then
begin
bSelected:= true;
exit
@@ -429,7 +467,7 @@
with CurrentHedgehog^.Gear^,
CurrentHedgehog^ do
- if (State and gstHHChooseTarget) <> 0 then
+ if (State and gstChooseTarget) <> 0 then
begin
isCursorVisible:= false;
if not CurrentTeam^.ExtDriven then
@@ -452,7 +490,7 @@
TargetPoint.Y:= putY
end;
AddFileLog('put: ' + inttostr(TargetPoint.X) + ', ' + inttostr(TargetPoint.Y));
- State:= State and (not gstHHChooseTarget);
+ State:= State and (not gstChooseTarget);
if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackingPut) <> 0 then
Message:= Message or (gmAttack and InputMask);
end
@@ -471,7 +509,7 @@
lastcmd:= nil;
isPonged:= false;
SocketString:= '';
-
+
hiTicks:= 0;
flushDelayTicks:= 0;
sendBuffer.count:= 0;
@@ -483,6 +521,7 @@
SDLNet_FreeSocketSet(fds);
SDLNet_TCP_Close(IPCSock);
SDLNet_Quit();
+
end;
end.