annotate pytouhou/network.py @ 487:711c75115675

Various netplay-related fixes.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sat, 28 Sep 2013 20:11:41 +0200
parents c099802e2435
children d1f0bb0b7a17
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
1 import socket
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
2 from struct import Struct
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
3 from select import select
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
4 from time import time
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
5
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
6 from pytouhou.utils.helpers import get_logger
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
7
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
8 logger = get_logger(__name__)
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
9
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
10 MSG_STRUCT = Struct('!HHH')
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
11
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
12 class Network(object):
479
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
13 def __init__(self, port=8080, dest=None, selected_player=0):
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
14 self.frame = 0
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
15 self.keystate = 0
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
16 self.old_keystate = 0
485
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
17 self.remote_keystate = 0
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
18
479
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
19 self.selected_player = selected_player
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
20
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
21 self.remote_addr = dest
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
22 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
23 self.sock.bind(('', port))
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
24
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
25
484
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
26 def read_message(self):
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
27 message = None
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
28
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
29 start_time = time()
483
216107767b8a Remove useless checksum, and wait as long as possible for valid packets (do not stop waiting on invalid packets)
Thibaut Girka <thib@sitedethib.com>
parents: 482
diff changeset
30 delta = 1./60.
216107767b8a Remove useless checksum, and wait as long as possible for valid packets (do not stop waiting on invalid packets)
Thibaut Girka <thib@sitedethib.com>
parents: 482
diff changeset
31
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
32 rlist, _, _ = select([self.sock], [], [], delta)
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
33 while rlist:
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
34 msg, addr = rlist[0].recvfrom(MSG_STRUCT.size)
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
35 # Check whether the message comes from the right address
484
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
36 if self.frame == 0 or addr == self.remote_addr:
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
37 self.remote_addr = addr
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
38
483
216107767b8a Remove useless checksum, and wait as long as possible for valid packets (do not stop waiting on invalid packets)
Thibaut Girka <thib@sitedethib.com>
parents: 482
diff changeset
39 frame, keystate, old_keystate = MSG_STRUCT.unpack(msg)
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
40
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
41 # Check for well-formedness
483
216107767b8a Remove useless checksum, and wait as long as possible for valid packets (do not stop waiting on invalid packets)
Thibaut Girka <thib@sitedethib.com>
parents: 482
diff changeset
42 if frame in (self.frame, self.frame + 1):
484
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
43 message = (frame, keystate, old_keystate)
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
44 else:
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
45 logger.error('Mismatch, got a message from %s, waiting for %s.', self.remote_addr, addr)
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
46
484
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
47 # If no valid message has been read, wait for one as long as possible
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
48 # else, read as much as we can without blocking.
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
49 delta = 0 if message else max(0, 1./60. - (time() - start_time))
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
50 rlist, _, _ = select(rlist, [], [], delta)
483
216107767b8a Remove useless checksum, and wait as long as possible for valid packets (do not stop waiting on invalid packets)
Thibaut Girka <thib@sitedethib.com>
parents: 482
diff changeset
51
484
699c8e8c7738 Don't stick with the remote user unless the game has started, avoid skipping to prevent desynchro
Thibaut Girka <thib@sitedethib.com>
parents: 483
diff changeset
52 return message
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
53
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
54
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
55 def send_message(self):
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
56 if self.remote_addr is not None:
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
57 self.sock.sendto(MSG_STRUCT.pack(self.frame, self.keystate, self.old_keystate), self.remote_addr)
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
58
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
59
479
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
60 def run_game_iter(self, game, keystate, other_keystate):
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
61 keystates = [other_keystate, other_keystate]
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
62 keystates[self.selected_player] = keystate
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
63 game.run_iter(keystates)
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
64
1de67f332f00 Fix several synchro issues
Thibaut Girka <thib@sitedethib.com>
parents: 478
diff changeset
65
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
66 def run_iter(self, game, keystate):
485
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
67 if game.frame % 3 == 0:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
68 # Phase 1: Update game with old data
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
69 self.run_game_iter(game, self.keystate, self.remote_keystate)
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
70 elif game.frame % 3 == 1:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
71 # Phase 2: Update data, send new data, update game with old data
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
72 self.old_keystate, self.keystate = self.keystate, keystate
485
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
73 self.frame = game.frame // 3
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
74 self.send_message()
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
75 self.run_game_iter(game, self.old_keystate, self.remote_keystate)
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
76 elif game.frame % 3 == 2:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
77 # Phase 3: Send new data, get remote data, update game with new data
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
78 self.send_message()
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
79 # Follow one valid update
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
80 message = self.read_message()
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
81 if message:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
82 frame, keystate, old_keystate = message
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
83 if frame == self.frame:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
84 self.remote_keystate = keystate
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
85 elif frame == self.frame + 1:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
86 self.remote_keystate = old_keystate
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
87 else:
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
88 raise Exception #TODO
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
89 self.run_game_iter(game, self.keystate, self.remote_keystate)
c099802e2435 Improve network latency by increasing game latency to 3 frames.
Thibaut Girka <thib@sitedethib.com>
parents: 484
diff changeset
90 elif game.frame > 2:
487
711c75115675 Various netplay-related fixes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 485
diff changeset
91 logger.warn('Message not received in time, dropping frame.')
480
d666856acb52 Hopefully improve performance
Thibaut Girka <thib@sitedethib.com>
parents: 479
diff changeset
92
475
9d4d52793eca Experimental netplay! Yay!
Thibaut Girka <thib@sitedethib.com>
parents:
diff changeset
93