hedgewars/uIO.pas
changeset 2948 3f21a9dc93d0
parent 2905 f3c79f7193a9
child 2969 79024988792e
equal deleted inserted replaced
2947:803b277e4894 2948:3f21a9dc93d0
    53                 cmd: Char;
    53                 cmd: Char;
    54                 X, Y: SmallInt);
    54                 X, Y: SmallInt);
    55             2: (str: shortstring);
    55             2: (str: shortstring);
    56             end;
    56             end;
    57 
    57 
    58 var	IPCSock: PTCPSocket;
    58 var IPCSock: PTCPSocket;
    59 	fds: PSDLNet_SocketSet;
    59     fds: PSDLNet_SocketSet;
    60 	isPonged: boolean;
    60     isPonged: boolean;
    61 
    61 
    62 	headcmd: PCmd;
    62     headcmd: PCmd;
    63 	lastcmd: PCmd;
    63     lastcmd: PCmd;
    64 
    64 
    65 	SendEmptyPacketTicks: LongWord;
    65     SendEmptyPacketTicks: LongWord;
    66 
    66 
    67 
    67 
    68 function AddCmd(Time: Word; str: shortstring): PCmd;
    68 function AddCmd(Time: Word; str: shortstring): PCmd;
    69 var command: PCmd;
    69 var command: PCmd;
    70 begin
    70 begin
   110 WriteLnToConsole(msgOK)
   110 WriteLnToConsole(msgOK)
   111 end;
   111 end;
   112 
   112 
   113 procedure CloseIPC;
   113 procedure CloseIPC;
   114 begin
   114 begin
   115 	SDLNet_FreeSocketSet(fds);
   115     SDLNet_FreeSocketSet(fds);
   116 	SDLNet_TCP_Close(IPCSock);
   116     SDLNet_TCP_Close(IPCSock);
   117 	SDLNet_Quit();
   117     SDLNet_Quit();
   118 end;
   118 end;
   119 
   119 
   120 procedure ParseIPCCommand(s: shortstring);
   120 procedure ParseIPCCommand(s: shortstring);
   121 var loTicks: Word;
   121 var loTicks: Word;
   122 begin
   122 begin
   141 end;
   141 end;
   142 
   142 
   143 procedure IPCCheckSock;
   143 procedure IPCCheckSock;
   144 const ss: shortstring = '';
   144 const ss: shortstring = '';
   145 var i: LongInt;
   145 var i: LongInt;
   146 	buf: array[0..255] of byte;
   146     buf: array[0..255] of byte;
   147 	s: shortstring absolute buf;
   147     s: shortstring absolute buf;
   148 begin
   148 begin
   149 if IPCSock = nil then
   149 if IPCSock = nil then
   150    exit;
   150    exit;
   151 
   151 
   152 fds^.numsockets:= 0;
   152 fds^.numsockets:= 0;
   153 SDLNet_AddSocket(fds, IPCSock);
   153 SDLNet_AddSocket(fds, IPCSock);
   154 
   154 
   155 while SDLNet_CheckSockets(fds, 0) > 0 do
   155 while SDLNet_CheckSockets(fds, 0) > 0 do
   156 	begin
   156     begin
   157 	i:= SDLNet_TCP_Recv(IPCSock, @buf[1], 255 - Length(ss));
   157     i:= SDLNet_TCP_Recv(IPCSock, @buf[1], 255 - Length(ss));
   158 	if i > 0 then
   158     if i > 0 then
   159 		begin
   159         begin
   160 		buf[0]:= i;
   160         buf[0]:= i;
   161 		ss:= ss + s;
   161         ss:= ss + s;
   162 		while (Length(ss) > 1) and (Length(ss) > byte(ss[1])) do
   162         while (Length(ss) > 1) and (Length(ss) > byte(ss[1])) do
   163 			begin
   163             begin
   164 			ParseIPCCommand(copy(ss, 2, byte(ss[1])));
   164             ParseIPCCommand(copy(ss, 2, byte(ss[1])));
   165 			Delete(ss, 1, Succ(byte(ss[1])))
   165             Delete(ss, 1, Succ(byte(ss[1])))
   166 			end
   166             end
   167 		end else OutError('IPC connection lost', true)
   167         end else OutError('IPC connection lost', true)
   168 	end;
   168     end;
   169 end;
   169 end;
   170 
   170 
   171 procedure LoadRecordFromFile(fileName: shortstring);
   171 procedure LoadRecordFromFile(fileName: shortstring);
   172 var f: file;
   172 var f: file;
   173 	ss: shortstring = '';
   173     ss: shortstring = '';
   174 	i: LongInt;
   174     i: LongInt;
   175 	buf: array[0..255] of byte;
   175     buf: array[0..255] of byte;
   176 	s: shortstring absolute buf;
   176     s: shortstring absolute buf;
   177 begin
   177 begin
   178 
   178 
   179 // set RDNLY on file open
   179 // set RDNLY on file open
   180 filemode:= 0;
   180 filemode:= 0;
   181 
   181 
   182 assign(f, fileName);
   182 assign(f, fileName);
   183 reset(f, 1);
   183 reset(f, 1);
   184 
   184 
   185 repeat
   185 repeat
   186 	BlockRead(f, buf[1], 255 - Length(ss), i);
   186     BlockRead(f, buf[1], 255 - Length(ss), i);
   187 	if i > 0 then
   187     if i > 0 then
   188 		begin
   188         begin
   189 		buf[0]:= i;
   189         buf[0]:= i;
   190 		ss:= ss + s;
   190         ss:= ss + s;
   191 		while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do
   191         while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do
   192 			begin
   192             begin
   193 			ParseIPCCommand(copy(ss, 2, byte(ss[1])));
   193             ParseIPCCommand(copy(ss, 2, byte(ss[1])));
   194 			Delete(ss, 1, Succ(byte(ss[1])))
   194             Delete(ss, 1, Succ(byte(ss[1])))
   195 			end
   195             end
   196 		end
   196         end
   197 until i = 0;
   197 until i = 0;
   198 
   198 
   199 close(f)
   199 close(f)
   200 end;
   200 end;
   201 
   201 
   202 procedure SendIPC(s: shortstring);
   202 procedure SendIPC(s: shortstring);
   203 begin
   203 begin
   204 if IPCSock <> nil then
   204 if IPCSock <> nil then
   205 	begin
   205     begin
   206 	SendEmptyPacketTicks:= 0;
   206     SendEmptyPacketTicks:= 0;
   207 	if s[0]>#251 then s[0]:= #251;
   207     if s[0]>#251 then s[0]:= #251;
   208 	SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
   208     SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]);
   209 	{$IFDEF DEBUGFILE}AddFileLog('IPC send: '+ s[1]);{$ENDIF}
   209     {$IFDEF DEBUGFILE}AddFileLog('IPC send: '+ s[1]);{$ENDIF}
   210 	inc(s[0], 2);
   210     inc(s[0], 2);
   211 	SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0])))
   211     SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0])))
   212 	end
   212     end
   213 end;
   213 end;
   214 
   214 
   215 procedure SendIPCRaw(p: pointer; len: Longword);
   215 procedure SendIPCRaw(p: pointer; len: Longword);
   216 begin
   216 begin
   217 if IPCSock <> nil then
   217 if IPCSock <> nil then
   254 
   254 
   255 procedure SendKeepAliveMessage(Lag: Longword);
   255 procedure SendKeepAliveMessage(Lag: Longword);
   256 begin
   256 begin
   257 inc(SendEmptyPacketTicks, Lag);
   257 inc(SendEmptyPacketTicks, Lag);
   258 if (SendEmptyPacketTicks >= cSendEmptyPacketTime) then
   258 if (SendEmptyPacketTicks >= cSendEmptyPacketTime) then
   259 	SendIPC('+')
   259     SendIPC('+')
   260 end;
   260 end;
   261 
   261 
   262 procedure NetGetNextCmd;
   262 procedure NetGetNextCmd;
   263 var tmpflag: boolean;
   263 var tmpflag: boolean;
   264 	s: shortstring;
   264     s: shortstring;
   265 	x16, y16: SmallInt;
   265     x16, y16: SmallInt;
   266 begin
   266 begin
   267 tmpflag:= true;
   267 tmpflag:= true;
   268 
   268 
   269 while (headcmd <> nil)
   269 while (headcmd <> nil)
   270 	and (tmpflag or (headcmd^.cmd = '#')) // '#' is the only cmd which can be sent within same tick after 'N'
   270     and (tmpflag or (headcmd^.cmd = '#')) // '#' is the only cmd which can be sent within same tick after 'N'
   271 	and ((GameTicks = hiTicks shl 16 + headcmd^.loTime)
   271     and ((GameTicks = hiTicks shl 16 + headcmd^.loTime)
   272 		or (headcmd^.cmd = 's') // for these commands time is not specified
   272         or (headcmd^.cmd = 's') // for these commands time is not specified
   273 		or (headcmd^.cmd = '#')
   273         or (headcmd^.cmd = '#')
   274  		or (headcmd^.cmd = 'b')
   274         or (headcmd^.cmd = 'b')
   275 		or (headcmd^.cmd = 'F')) do
   275         or (headcmd^.cmd = 'F')) do
   276 	begin
   276     begin
   277 	case headcmd^.cmd of
   277     case headcmd^.cmd of
   278 		'+': ; // do nothing - it is just an empty packet
   278         '+': ; // do nothing - it is just an empty packet
   279 		'#': inc(hiTicks);
   279         '#': inc(hiTicks);
   280 		'L': ParseCommand('+left', true);
   280         'L': ParseCommand('+left', true);
   281 		'l': ParseCommand('-left', true);
   281         'l': ParseCommand('-left', true);
   282 		'R': ParseCommand('+right', true);
   282         'R': ParseCommand('+right', true);
   283 		'r': ParseCommand('-right', true);
   283         'r': ParseCommand('-right', true);
   284 		'U': ParseCommand('+up', true);
   284         'U': ParseCommand('+up', true);
   285 		'u': ParseCommand('-up', true);
   285         'u': ParseCommand('-up', true);
   286 		'D': ParseCommand('+down', true);
   286         'D': ParseCommand('+down', true);
   287 		'd': ParseCommand('-down', true);
   287         'd': ParseCommand('-down', true);
   288 		'Z': ParseCommand('+precise', true);
   288         'Z': ParseCommand('+precise', true);
   289 		'z': ParseCommand('-precise', true);
   289         'z': ParseCommand('-precise', true);
   290 		'A': ParseCommand('+attack', true);
   290         'A': ParseCommand('+attack', true);
   291 		'a': ParseCommand('-attack', true);
   291         'a': ParseCommand('-attack', true);
   292 		'S': ParseCommand('switch', true);
   292         'S': ParseCommand('switch', true);
   293 		'j': ParseCommand('ljump', true);
   293         'j': ParseCommand('ljump', true);
   294 		'J': ParseCommand('hjump', true);
   294         'J': ParseCommand('hjump', true);
   295 		',': ParseCommand('skip', true);
   295         ',': ParseCommand('skip', true);
   296 		's': begin
   296         's': begin
   297 			s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
   297             s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
   298 			AddChatString(s);
   298             AddChatString(s);
   299 			WriteLnToConsole(s)
   299             WriteLnToConsole(s)
   300 			end;
   300             end;
   301 		'b': begin
   301         'b': begin
   302 			s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
   302             s:= copy(headcmd^.str, 2, Pred(headcmd^.len));
   303 			AddChatString(#4 + s);
   303             AddChatString(#4 + s);
   304 			WriteLnToConsole(s)
   304             WriteLnToConsole(s)
   305 			end;
   305             end;
   306 		'F': TeamGone(copy(headcmd^.str, 2, Pred(headcmd^.len)));
   306         'F': TeamGone(copy(headcmd^.str, 2, Pred(headcmd^.len)));
   307 		'N': begin
   307         'N': begin
   308 			tmpflag:= false;
   308             tmpflag:= false;
   309 			{$IFDEF DEBUGFILE}AddFileLog('got cmd "N": time '+inttostr(hiTicks shl 16 + headcmd^.loTime)){$ENDIF}
   309             {$IFDEF DEBUGFILE}AddFileLog('got cmd "N": time '+inttostr(hiTicks shl 16 + headcmd^.loTime)){$ENDIF}
   310 			end;
   310             end;
   311 		'p': begin
   311         'p': begin
   312 			x16:= SDLNet_Read16(@(headcmd^.X));
   312             x16:= SDLNet_Read16(@(headcmd^.X));
   313 			y16:= SDLNet_Read16(@(headcmd^.Y));
   313             y16:= SDLNet_Read16(@(headcmd^.Y));
   314 			doPut(x16, y16, false)
   314             doPut(x16, y16, false)
   315 			end;
   315             end;
   316 		'P': begin
   316         'P': begin
   317 			// these are equations solved for CursorPoint
   317             // these are equations solved for CursorPoint
   318 			// SDLNet_Read16(@(headcmd^.X)) == CursorPoint.X - WorldDx;
   318             // SDLNet_Read16(@(headcmd^.X)) == CursorPoint.X - WorldDx;
   319 			// SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy;
   319             // SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy;
   320 			CursorPoint.X:= SmallInt(SDLNet_Read16(@(headcmd^.X))) + WorldDx;
   320             CursorPoint.X:= SmallInt(SDLNet_Read16(@(headcmd^.X))) + WorldDx;
   321 			CursorPoint.Y:= cScreenHeight - SmallInt(SDLNet_Read16(@(headcmd^.Y))) - WorldDy;
   321             CursorPoint.Y:= cScreenHeight - SmallInt(SDLNet_Read16(@(headcmd^.Y))) - WorldDy;
   322 			end;
   322             end;
   323 		'w': ParseCommand('setweap ' + headcmd^.str[2], true);
   323         'w': ParseCommand('setweap ' + headcmd^.str[2], true);
   324 		't': ParseCommand('taunt ' + headcmd^.str[2], true);
   324         't': ParseCommand('taunt ' + headcmd^.str[2], true);
   325 		'g': ParseCommand('newgrave', true);
   325         'g': ParseCommand('newgrave', true);
   326 		'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
   326         'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
   327 		'1'..'5': ParseCommand('timer ' + headcmd^.cmd, true);
   327         '1'..'5': ParseCommand('timer ' + headcmd^.cmd, true);
   328 		#128..char(128 + cMaxSlotIndex): ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
   328         #128..char(128 + cMaxSlotIndex): ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
   329 		else
   329         else
   330 			OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
   330             OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
   331 		end;
   331         end;
   332 	RemoveCmd
   332     RemoveCmd
   333 	end;
   333     end;
   334 
   334 
   335 if (headcmd <> nil) and tmpflag and (not CurrentTeam^.hasGone) then
   335 if (headcmd <> nil) and tmpflag and (not CurrentTeam^.hasGone) then
   336 	TryDo(GameTicks < hiTicks shl 16 + headcmd^.loTime,
   336     TryDo(GameTicks < hiTicks shl 16 + headcmd^.loTime,
   337 			'oops, queue error. in buffer: ' + headcmd^.cmd +
   337             'oops, queue error. in buffer: ' + headcmd^.cmd +
   338 			' (' + inttostr(GameTicks) + ' > ' +
   338             ' (' + inttostr(GameTicks) + ' > ' +
   339 			inttostr(hiTicks shl 16 + headcmd^.loTime) + ')',
   339             inttostr(hiTicks shl 16 + headcmd^.loTime) + ')',
   340 			true);
   340             true);
   341 
   341 
   342 isInLag:= (headcmd = nil) and tmpflag and (not CurrentTeam^.hasGone);
   342 isInLag:= (headcmd = nil) and tmpflag and (not CurrentTeam^.hasGone);
   343 
   343 
   344 if isInLag then fastUntilLag:= false
   344 if isInLag then fastUntilLag:= false
   345 end;
   345 end;
   346 
   346 
   347 procedure init_uIO;
   347 procedure init_uIO;
   348 begin
   348 begin
   349 	IPCSock:= nil;
   349     IPCSock:= nil;
   350 
   350 
   351 	headcmd:= nil;
   351     headcmd:= nil;
   352 	lastcmd:= nil;
   352     lastcmd:= nil;
   353 	isPonged:= false;	// was const
   353     isPonged:= false;   // was const
   354 
   354 
   355 	hiTicks:= 0;
   355     hiTicks:= 0;
   356 	SendEmptyPacketTicks:= 0;
   356     SendEmptyPacketTicks:= 0;
   357 	ipcPort:= 0;
   357     ipcPort:= 0;
   358 end;
   358 end;
   359 
   359 
   360 procedure free_uIO;
   360 procedure free_uIO;
   361 begin
   361 begin
   362 
   362