61 lastcmd: PCmd = nil; |
61 lastcmd: PCmd = nil; |
62 |
62 |
63 SendEmptyPacketTicks: LongWord = 0; |
63 SendEmptyPacketTicks: LongWord = 0; |
64 |
64 |
65 |
65 |
66 function AddCmd(Time: Longword; str: shortstring): PCmd; |
66 function AddCmd(Time: Word; str: shortstring): PCmd; |
67 var Result: PCmd; |
67 var Result: PCmd; |
68 begin |
68 begin |
69 new(Result); |
69 new(Result); |
70 FillChar(Result^, sizeof(TCmd), 0); |
70 FillChar(Result^, sizeof(TCmd), 0); |
71 Result^.Time:= Time; |
71 Result^.loTime:= Time; |
72 Result^.str:= str; |
72 Result^.str:= str; |
73 if Result^.cmd <> 'F' then dec(Result^.len, 2); // cut timestamp |
73 if Result^.cmd <> 'F' then dec(Result^.len, 2); // cut timestamp |
74 if headcmd = nil then |
74 if headcmd = nil then |
75 begin |
75 begin |
76 headcmd:= Result; |
76 headcmd:= Result; |
119 var loTicks: Word; |
119 var loTicks: Word; |
120 begin |
120 begin |
121 case s[1] of |
121 case s[1] of |
122 '!': begin {$IFDEF DEBUGFILE}AddFileLog('Ping? Pong!');{$ENDIF}isPonged:= true; end; |
122 '!': begin {$IFDEF DEBUGFILE}AddFileLog('Ping? Pong!');{$ENDIF}isPonged:= true; end; |
123 '?': SendIPC('!'); |
123 '?': SendIPC('!'); |
124 '#': inc(hiTicks); |
|
125 'e': ParseCommand(copy(s, 2, Length(s) - 1), true); |
124 'e': ParseCommand(copy(s, 2, Length(s) - 1), true); |
126 'E': OutError(copy(s, 2, Length(s) - 1), true); |
125 'E': OutError(copy(s, 2, Length(s) - 1), true); |
127 'W': OutError(copy(s, 2, Length(s) - 1), false); |
126 'W': OutError(copy(s, 2, Length(s) - 1), false); |
128 'M': CheckLandDigest(s); |
127 'M': CheckLandDigest(s); |
129 'T': case s[2] of |
128 'T': case s[2] of |
132 'N': GameType:= gmtNet; |
131 'N': GameType:= gmtNet; |
133 'S': GameType:= gmtSave; |
132 'S': GameType:= gmtSave; |
134 else OutError(errmsgIncorrectUse + ' IPC "T" :' + s[2], true) end; |
133 else OutError(errmsgIncorrectUse + ' IPC "T" :' + s[2], true) end; |
135 else |
134 else |
136 loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]); |
135 loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]); |
137 AddCmd(hiTicks shl 16 + loTicks, s); |
136 AddCmd(loTicks, s); |
138 {$IFDEF DEBUGFILE}AddFileLog('IPC in: '+s[1]+' ticks '+inttostr(lastcmd^.Time));{$ENDIF} |
137 {$IFDEF DEBUGFILE}AddFileLog('IPC in: '+s[1]+' ticks '+inttostr(lastcmd^.loTime));{$ENDIF} |
139 end |
138 end |
140 end; |
139 end; |
141 |
140 |
142 procedure IPCCheckSock; |
141 procedure IPCCheckSock; |
143 const ss: string = ''; |
142 const ss: string = ''; |
263 s: shortstring; |
262 s: shortstring; |
264 begin |
263 begin |
265 tmpflag:= true; |
264 tmpflag:= true; |
266 |
265 |
267 while (headcmd <> nil) |
266 while (headcmd <> nil) |
268 and tmpflag |
267 and (tmpflag or (headcmd^.cmd = '#')) // '#' is the only cmd which can be sent within same tick after 'N' |
269 and ((GameTicks = headcmd^.Time) |
268 and ((GameTicks = hiTicks shl 16 + headcmd^.loTime) |
270 or (headcmd^.cmd = 's') |
269 or (headcmd^.cmd = 's') // for these commands time isn't specified |
271 or (headcmd^.cmd = 'b') |
270 or (headcmd^.cmd = '#') |
|
271 or (headcmd^.cmd = 'b') |
272 or (headcmd^.cmd = 'F')) do |
272 or (headcmd^.cmd = 'F')) do |
273 begin |
273 begin |
274 case headcmd^.cmd of |
274 case headcmd^.cmd of |
275 '+': ; // do nothing - it is just empty packet |
275 '+': ; // do nothing - it is just an empty packet |
|
276 '#': inc(hiTicks); |
276 'L': ParseCommand('+left', true); |
277 'L': ParseCommand('+left', true); |
277 'l': ParseCommand('-left', true); |
278 'l': ParseCommand('-left', true); |
278 'R': ParseCommand('+right', true); |
279 'R': ParseCommand('+right', true); |
279 'r': ParseCommand('-right', true); |
280 'r': ParseCommand('-right', true); |
280 'U': ParseCommand('+up', true); |
281 'U': ParseCommand('+up', true); |
300 WriteLnToConsole(s) |
301 WriteLnToConsole(s) |
301 end; |
302 end; |
302 'F': TeamGone(copy(headcmd^.str, 2, Pred(headcmd^.len))); |
303 'F': TeamGone(copy(headcmd^.str, 2, Pred(headcmd^.len))); |
303 'N': begin |
304 'N': begin |
304 tmpflag:= false; |
305 tmpflag:= false; |
305 {$IFDEF DEBUGFILE}AddFileLog('got cmd "N": time '+inttostr(headcmd^.Time)){$ENDIF} |
306 {$IFDEF DEBUGFILE}AddFileLog('got cmd "N": time '+inttostr(hiTicks shl 16 + headcmd^.loTime)){$ENDIF} |
306 end; |
307 end; |
307 'p': begin |
308 'p': begin |
308 TargetPoint.X:= SDLNet_Read16(@(headcmd^.X)); |
309 TargetPoint.X:= SDLNet_Read16(@(headcmd^.X)); |
309 TargetPoint.Y:= SDLNet_Read16(@(headcmd^.Y)); |
310 TargetPoint.Y:= SDLNet_Read16(@(headcmd^.Y)); |
310 ParseCommand('put', true) |
311 ParseCommand('put', true) |
311 end; |
312 end; |
312 'P': begin |
313 'P': begin |
313 // these are equations solved for CursorPoint |
314 // these are equations solved for CursorPoint |
314 // SDLNet_Read16(@(headcmd^.X)):= CursorPoint.X - WorldDx; |
315 // SDLNet_Read16(@(headcmd^.X)) == CursorPoint.X - WorldDx; |
315 // SDLNet_Read16(@(headcmd^.Y)):= cScreenHeight - CursorPoint.Y - WorldDy; |
316 // SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy; |
316 CursorPoint.X:= SDLNet_Read16(@(headcmd^.X)) + WorldDx; |
317 CursorPoint.X:= SDLNet_Read16(@(headcmd^.X)) + WorldDx; |
317 CursorPoint.Y:= cScreenHeight - SDLNet_Read16(@(headcmd^.Y)) - WorldDy; |
318 CursorPoint.Y:= cScreenHeight - SDLNet_Read16(@(headcmd^.Y)) - WorldDy; |
318 end; |
319 end; |
319 'w': ParseCommand('setweap ' + headcmd^.str[2], true); |
320 'w': ParseCommand('setweap ' + headcmd^.str[2], true); |
320 't': ParseCommand('taunt ' + headcmd^.str[2], true); |
321 't': ParseCommand('taunt ' + headcmd^.str[2], true); |
326 OutError('Unexpected protocol command: ' + headcmd^.cmd, True) |
327 OutError('Unexpected protocol command: ' + headcmd^.cmd, True) |
327 end; |
328 end; |
328 RemoveCmd |
329 RemoveCmd |
329 end; |
330 end; |
330 |
331 |
331 if (headcmd <> nil) and tmpflag then |
332 if (headcmd <> nil) and tmpflag and (not CurrentTeam^.hasGone) then |
332 TryDo(GameTicks < headcmd^.Time, |
333 TryDo(GameTicks < hiTicks shl 16 + headcmd^.loTime, |
333 'oops, queue error. in buffer: ' + headcmd^.cmd + |
334 'oops, queue error. in buffer: ' + headcmd^.cmd + |
334 ' (' + inttostr(GameTicks) + ' > ' + |
335 ' (' + inttostr(GameTicks) + ' > ' + |
335 inttostr(headcmd^.Time) + ')', |
336 inttostr(hiTicks shl 16 + headcmd^.loTime) + ')', |
336 true); |
337 true); |
337 |
338 |
338 isInLag:= (headcmd = nil) and tmpflag and (not CurrentTeam^.hasGone); |
339 isInLag:= (headcmd = nil) and tmpflag and (not CurrentTeam^.hasGone); |
339 |
340 |
340 if isInLag then fastUntilLag:= false |
341 if isInLag then fastUntilLag:= false |