hedgewars/uIO.pas
changeset 10015 4feced261c68
parent 9998 736015b847e3
parent 9974 fb84e878111d
child 10108 c68cf030eded
equal deleted inserted replaced
10014:56d2f2d5aad8 10015:4feced261c68
    49      TCmd = packed record
    49      TCmd = packed record
    50             Next: PCmd;
    50             Next: PCmd;
    51             loTime: Word;
    51             loTime: Word;
    52             case byte of
    52             case byte of
    53             1: (len: byte;
    53             1: (len: byte;
    54                 cmd: Char;
    54                 cmd: Char);
    55                 X, Y: LongInt);
       
    56             2: (str: shortstring);
    55             2: (str: shortstring);
    57             end;
    56             end;
    58 
    57 
    59 var IPCSock: PTCPSocket;
    58 var IPCSock: PTCPSocket;
    60     fds: PSDLNet_SocketSet;
    59     fds: PSDLNet_SocketSet;
   120 end;
   119 end;
   121 
   120 
   122 procedure ParseIPCCommand(s: shortstring);
   121 procedure ParseIPCCommand(s: shortstring);
   123 var loTicks: Word;
   122 var loTicks: Word;
   124 begin
   123 begin
       
   124 
   125 case s[1] of
   125 case s[1] of
   126      '!': begin AddFileLog('Ping? Pong!'); isPonged:= true; end;
   126      '!': begin AddFileLog('Ping? Pong!'); isPonged:= true; end;
   127      '?': SendIPC(_S'!');
   127      '?': SendIPC(_S'!');
   128      'e': ParseCommand(copy(s, 2, Length(s) - 1), true);
   128      'e': ParseCommand(copy(s, 2, Length(s) - 1), true);
   129      'E': OutError(copy(s, 2, Length(s) - 1), true);
   129      'E': OutError(copy(s, 2, Length(s) - 1), true);
   175         OutError('IPC connection lost', true)
   175         OutError('IPC connection lost', true)
   176     end;
   176     end;
   177 end;
   177 end;
   178 
   178 
   179 procedure LoadRecordFromFile(fileName: shortstring);
   179 procedure LoadRecordFromFile(fileName: shortstring);
   180 var f: file;
   180 var f  : File;
   181     ss: shortstring = '';
   181     ss : shortstring = '';
   182     i: LongInt;
   182     i  : LongInt;
   183     s: shortstring;
   183     s  : shortstring;
   184 begin
   184 begin
   185 
   185 
   186 // set RDNLY on file open
   186 // set RDNLY on file open
   187 filemode:= 0;
   187 filemode:= 0;
   188 {$I-}
   188 {$I-}
   189 assign(f, fileName);
   189 assign(f, fileName);
   190 reset(f, 1);
   190 reset(f, 1);
   191 
       
   192 tryDo(IOResult = 0, 'Error opening file ' + fileName, true);
   191 tryDo(IOResult = 0, 'Error opening file ' + fileName, true);
   193 
   192 
   194 i:= 0; // avoid compiler hints
   193 i:= 0; // avoid compiler hints
   195 s[0]:= #0;
   194 s[0]:= #0;
   196 repeat
   195 repeat
   197     BlockRead(f, s[1], 255 - Length(ss), i);
   196     BlockRead(f, s[1], 255 - Length(ss), i);
   198     if i > 0 then
   197     if i > 0 then
   199         begin
   198     begin
   200         s[0]:= char(i);
   199         s[0]:= char(i);
   201         ss:= ss + s;
   200         ss:= ss + s;
   202         while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do
   201         while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do
   203             begin
   202             begin
   204             ParseIPCCommand(copy(ss, 2, byte(ss[1])));
   203             ParseIPCCommand(copy(ss, 2, byte(ss[1])));
   205             Delete(ss, 1, Succ(byte(ss[1])))
   204             Delete(ss, 1, Succ(byte(ss[1])));
   206             end
   205             end
   207         end
   206         end
   208 until i = 0;
   207 until i = 0;
   209 
   208 
   210 close(f)
   209 close(f)
   219 SendIPCRaw(@buf[0], length(buf) + 1)
   218 SendIPCRaw(@buf[0], length(buf) + 1)
   220 end;
   219 end;
   221 
   220 
   222 function isSyncedCommand(c: char): boolean;
   221 function isSyncedCommand(c: char): boolean;
   223 begin
   222 begin
   224     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)))
   223     case c of
       
   224         '+', '#', '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': isSyncedCommand:= true;
       
   225     else
       
   226         isSyncedCommand:= ((c >= #128) and (c <= char(128 + cMaxSlotIndex)))
       
   227     end
   225 end;
   228 end;
   226 
   229 
   227 procedure flushBuffer();
   230 procedure flushBuffer();
   228 begin
   231 begin
   229     if IPCSock <> nil then
   232     if IPCSock <> nil then
   238 begin
   241 begin
   239 if IPCSock <> nil then
   242 if IPCSock <> nil then
   240     begin
   243     begin
   241     if s[0] > #251 then
   244     if s[0] > #251 then
   242         s[0]:= #251;
   245         s[0]:= #251;
   243         
   246 
   244     SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
   247     SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
   245     
   248 
   246     AddFileLog('[IPC out] '+ sanitizeCharForLog(s[1]));
   249     AddFileLog('[IPC out] '+ sanitizeCharForLog(s[1]));
   247     inc(s[0], 2);
   250     inc(s[0], 2);
   248     
   251 
   249     if isSyncedCommand(s[1]) then
   252     if isSyncedCommand(s[1]) then
   250         begin
   253         begin
   251         if sendBuffer.count + byte(s[0]) >= cSendBufferSize then
   254         if sendBuffer.count + byte(s[0]) >= cSendBufferSize then
   252             flushBuffer();
   255             flushBuffer();
   253             
   256 
   254         Move(s, sendBuffer.buf[sendBuffer.count], byte(s[0]) + 1);
   257         Move(s, sendBuffer.buf[sendBuffer.count], byte(s[0]) + 1);
   255         inc(sendBuffer.count, byte(s[0]) + 1);
   258         inc(sendBuffer.count, byte(s[0]) + 1);
   256         
   259 
   257         if (s[1] = 'N') or (s[1] = '#') then
   260         if (s[1] = 'N') or (s[1] = '#') then
   258             flushBuffer();
   261             flushBuffer();
   259         end else
   262         end else
   260         SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0])))
   263         SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0])))
   261     end
   264     end
   300 inc(flushDelayTicks, Lag);
   303 inc(flushDelayTicks, Lag);
   301 if (flushDelayTicks >= cSendEmptyPacketTime) then
   304 if (flushDelayTicks >= cSendEmptyPacketTime) then
   302     begin
   305     begin
   303     if sendBuffer.count = 0 then
   306     if sendBuffer.count = 0 then
   304         SendIPC(_S'+');
   307         SendIPC(_S'+');
   305         
   308 
   306      flushBuffer()    
   309      flushBuffer()
   307     end
   310     end
   308 end;
   311 end;
   309 
   312 
   310 procedure NetGetNextCmd;
   313 procedure NetGetNextCmd;
   311 var tmpflag: boolean;
   314 var tmpflag: boolean;
   365             tmpflag:= false;
   368             tmpflag:= false;
   366             lastTurnChecksum:= SDLNet_Read32(@headcmd^.str[2]);
   369             lastTurnChecksum:= SDLNet_Read32(@headcmd^.str[2]);
   367             AddFileLog('got cmd "N": time '+IntToStr(hiTicks shl 16 + headcmd^.loTime))
   370             AddFileLog('got cmd "N": time '+IntToStr(hiTicks shl 16 + headcmd^.loTime))
   368              end;
   371              end;
   369         'p': begin
   372         'p': begin
   370             x32:= SDLNet_Read32(@(headcmd^.X));
   373             x32:= SDLNet_Read32(@(headcmd^.str[2]));
   371             y32:= SDLNet_Read32(@(headcmd^.Y));
   374             y32:= SDLNet_Read32(@(headcmd^.str[6]));
   372             doPut(x32, y32, false)
   375             doPut(x32, y32, false)
   373              end;
   376              end;
   374         'P': begin
   377         'P': begin
   375             // these are equations solved for CursorPoint
   378             // these are equations solved for CursorPoint
   376             // SDLNet_Read16(@(headcmd^.X)) == CursorPoint.X - WorldDx;
   379             // SDLNet_Read16(@(headcmd^.X)) == CursorPoint.X - WorldDx;
   377             // SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy;
   380             // SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy;
   378             if CurrentTeam^.ExtDriven then
   381             if CurrentTeam^.ExtDriven then
   379                begin
   382                begin
   380                TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.X))) + WorldDx;
   383                TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.str[2]))) + WorldDx;
   381                TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.Y))) - WorldDy;
   384                TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.str[6]))) - WorldDy;
   382                if not bShowAmmoMenu and autoCameraOn then
   385                if not bShowAmmoMenu and autoCameraOn then
   383                     CursorPoint:= TargetCursorPoint
   386                     CursorPoint:= TargetCursorPoint
   384                end
   387                end
   385              end;
   388              end;
   386         'w': ParseCommand('setweap ' + headcmd^.str[2], true);
   389         'w': ParseCommand('setweap ' + headcmd^.str[2], true);
   387         't': ParseCommand('taunt ' + headcmd^.str[2], true);
   390         't': ParseCommand('taunt ' + headcmd^.str[2], true);
   388         'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
   391         'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
   389         '1'..'5': ParseCommand('timer ' + headcmd^.cmd, true);
   392         '1'..'5': ParseCommand('timer ' + headcmd^.cmd, true);
   390         else
   393         else
   391             if (headcmd^.cmd >= #128) and (headcmd^.cmd <= char(128 + cMaxSlotIndex)) then
   394             if (byte(headcmd^.cmd) >= 128) and (byte(headcmd^.cmd) <= 128 + cMaxSlotIndex) then
   392                 ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
   395                 ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
   393                 else
   396                 else
   394                 OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
   397                 OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
   395         end;
   398         end;
   396     RemoveCmd
   399     RemoveCmd
   419 procedure doPut(putX, putY: LongInt; fromAI: boolean);
   422 procedure doPut(putX, putY: LongInt; fromAI: boolean);
   420 begin
   423 begin
   421 if CheckNoTeamOrHH or isPaused then
   424 if CheckNoTeamOrHH or isPaused then
   422     exit;
   425     exit;
   423 bShowFinger:= false;
   426 bShowFinger:= false;
   424 if not CurrentTeam^.ExtDriven and bShowAmmoMenu then
   427 if (not CurrentTeam^.ExtDriven) and bShowAmmoMenu then
   425     begin
   428     begin
   426     bSelected:= true;
   429     bSelected:= true;
   427     exit
   430     exit
   428     end;
   431     end;
   429 
   432 
   469 
   472 
   470     headcmd:= nil;
   473     headcmd:= nil;
   471     lastcmd:= nil;
   474     lastcmd:= nil;
   472     isPonged:= false;
   475     isPonged:= false;
   473     SocketString:= '';
   476     SocketString:= '';
   474     
   477 
   475     hiTicks:= 0;
   478     hiTicks:= 0;
   476     flushDelayTicks:= 0;
   479     flushDelayTicks:= 0;
   477     sendBuffer.count:= 0;
   480     sendBuffer.count:= 0;
   478 end;
   481 end;
   479 
   482 
   481 begin
   484 begin
   482     while headcmd <> nil do RemoveCmd;
   485     while headcmd <> nil do RemoveCmd;
   483     SDLNet_FreeSocketSet(fds);
   486     SDLNet_FreeSocketSet(fds);
   484     SDLNet_TCP_Close(IPCSock);
   487     SDLNet_TCP_Close(IPCSock);
   485     SDLNet_Quit();
   488     SDLNet_Quit();
       
   489 
   486 end;
   490 end;
   487 
   491 
   488 end.
   492 end.