475
|
1 import socket
|
|
2 import struct
|
|
3 from select import select
|
|
4
|
|
5 MSG_STRUCT = struct.Struct('!IHHB')
|
|
6
|
|
7 class Network(object):
|
|
8 def __init__(self, port=8080, dest=None):
|
|
9 self.frame = 0
|
|
10 self.keystate = 0
|
|
11 self.old_keystate = 0
|
|
12
|
|
13 self.remote_addr = dest
|
|
14 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
|
15 self.sock.setblocking(0)
|
|
16 self.sock.bind(('', port))
|
|
17
|
|
18
|
|
19 def read_messages(self):
|
|
20 messages = []
|
|
21
|
|
22 rlist, wlist, xlist = select([self.sock], [], [], 0)
|
|
23 while rlist:
|
|
24 msg, addr = rlist[0].recvfrom(MSG_STRUCT.size)
|
|
25 # Check whether the message comes from the right address
|
|
26 if self.remote_addr is None or addr == self.remote_addr:
|
|
27 self.remote_addr = addr
|
|
28
|
|
29 frame, keystate, old_keystate, checksum = MSG_STRUCT.unpack(msg)
|
|
30
|
|
31 # Check for well-formedness
|
|
32 if checksum == sum(ord(c) for c in msg[:-1]) & 0xFF:
|
|
33 messages.append((frame, keystate, old_keystate, checksum))
|
|
34 else:
|
|
35 print('Mismatch', self.remote_addr, addr)
|
|
36
|
|
37 rlist, wlist, xlist = select(rlist, [], [], 0)
|
|
38
|
|
39 return messages
|
|
40
|
|
41
|
|
42 def send_message(self):
|
|
43 frame, keystate, old_keystate = self.frame, self.keystate, self.old_keystate
|
|
44 if self.remote_addr is not None:
|
|
45 checksum = frame + (frame >> 8) + (frame >> 16) + (frame >> 24)
|
|
46 checksum += keystate + (keystate >> 8)
|
|
47 checksum += old_keystate + (old_keystate >> 8)
|
|
48 checksum &= 0xFF
|
|
49 self.sock.sendto(MSG_STRUCT.pack(frame, keystate, old_keystate, checksum), self.remote_addr)
|
|
50
|
|
51
|
|
52 def run_iter(self, game, keystate):
|
|
53 if self.frame < game.frame:
|
|
54 self.old_keystate, self.keystate = self.keystate, keystate
|
|
55 self.frame = game.frame
|
|
56
|
|
57 for frame, keystate, old_keystate, checksum in self.read_messages():
|
|
58 if frame == game.frame:
|
|
59 game.run_iter([self.keystate, keystate])
|
|
60 elif frame == game.frame + 1:
|
|
61 print('Skipped')
|
|
62 game.run_iter([self.keystate, old_keystate])
|
|
63 game.run_iter([self.keystate, keystate])
|
|
64
|
|
65 self.send_message()
|
|
66
|