Some network & other fixes

pull/3/head
kaqu 2020-12-08 12:59:24 +01:00
parent eba911af01
commit b6fc2e001f
10 changed files with 85 additions and 39 deletions

3
.vscode/launch.json vendored
View File

@ -10,7 +10,8 @@
"request": "launch",
"program": "${file}",
//"args": ["--sizeable", "--server"],
"args": ["--sizeable", "--player", "1", "127.0.0.1"],
"args": ["--sizeable", "--player", "1", "localhost"],
//"args": ["--sizeable", "--viewer", "127.0.0.1"],
"console": "integratedTerminal"
}
]

View File

@ -92,11 +92,14 @@ Then to run a headless game server instance use
To connect player #1, use
./pp_player1.sh
./pp_player1.sh <remote_host_ip_or_name>
where <remote_host_ip_or_name> may be "127.0.0.1" or localhost or any other internet
host.
To connect player #2, use
./pp_player2.sh
./pp_player2.sh <remote_host_ip_or_name>
If you want to access a remote game server, edit the IP address within
the cl1.sh or cl2.sh file respectively.
@ -107,7 +110,7 @@ To achieve this, substitute --sizeable by --fullscreen in both files.
Finally, you may also connect one pure view client as
./pp_viewer.sh
./pp_viewer.sh <remote_host_ip_or_name>
### 2.3 Scoring ###
A game is won by the player who first reaches 10 points.

View File

@ -32,6 +32,15 @@ class PongGame:
[vs.Thread(i, self) for i in range(3)] # Spawn player listeners & streams
print("Game server started & listening ...")
def reinit(self):
"""Reinit game stats & settings"""
print("Match reset, ready for next round ...")
self.state = pgc.STATE_START
self.delay = 0
self.p1_game = 0
self.p2_game = 0
self.playsound = pgc.NOSOUND # Play the provided sound & reset locally
def game_fsm(self, player1, player2):
"""Game engine state machine"""
@ -164,16 +173,16 @@ class PongGame:
def pong_game(self, ball, player1, player2):
if (pgv.bIsServer == True) or (pgv.bIsLocal == True):
if (pgv.bIsServer == True) or (pgv.bIsLocal == True): # Game engine runs locally or on server only!
if self.game_fsm(player1, player2) == False: # Exit
return False
# 1. Retrieve user entries
if pgv.bIsServer == True:
bChanged = player1.eval_socket(player2)
else:
bChanged = player1.eval_gamepad()
bChanged = player2.eval_gamepad()
bChanged = player1.eval_socket(player2) # Either from network inputs
else:
bChanged = player1.eval_gamepad() # Or from actual USB gamepad inputs
bChanged = player2.eval_gamepad()
if (pgv.bIsServer == True) or (pgv.bIsLocal == True):
if self.state == pgc.STATE_PLAY: # Actually playing?
@ -195,7 +204,11 @@ class PongGame:
player1.score = player1.score + 1
ball.reinit(-(8 + (random() - 0.5) * 4), (random() - 0.5) * 10)
self.playsound = pgc.PLAYERMISSSOUND
else: # This is a remote player or a viewer ...
if self.state == pgc.STATE_EXIT: # If we're on exit, terminate!
if self.delay <= 10: # But permit some exit sound play ...
return False
return True

View File

@ -55,7 +55,8 @@ class PongPlayer:
if (player_index == 1) and (bThisIsTheServer): # Is this THE server? (But init. only once!)
UDP_PACKET_SIZE = struct.calcsize(pgc.UDP_TRANSFER_FORMAT) # Size of receiver buffer
serverUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP Receiver
serverUDP.bind(("127.0.0.1", pgc.PANDEMIC_PONG_PORT)) # Localhost
#serverUDP.bind(("127.0.0.1", pgc.PANDEMIC_PONG_PORT)) # Localhost
serverUDP.bind(("localhost", pgc.PANDEMIC_PONG_PORT)) # Localhost
serverUDP.setblocking(False) # Do not block ...
self.state = pgc.BTN_STATE_NONE # Button mask (as listed above)

View File

@ -231,6 +231,7 @@ class pongWindow(QMainWindow):
if self.game.pong_game(self.ball, self.player1, self.player2) == False:
# Quit gracefully
print("Player exiting ...")
self.player2.exit()
self.player1.exit()
sys.exit(0)

View File

@ -56,9 +56,10 @@ def init_server_socket():
class ViewServer:
"""View server (one only instantiated)"""
def __init__(self):
self.tcpClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcpClientSocket.connect((socket.gethostname(), pgc.PANDEMIC_PONG_PORT))
def __init__(self, player_server):
self.player_server = player_server
self.tcpClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcpClientSocket.connect((self.player_server, pgc.PANDEMIC_PONG_PORT))
self.tcpClientSocket.send("GET / HTTP/1.1\r\n\r\n".encode()) # Initiate streaming on server
# Will return:
# HTTP/1.0 200 OK
@ -67,22 +68,30 @@ class ViewServer:
# Date: Mon, 30 Nov 2020 09:59:52 GMT
# Content-type: application/octet-stream
# <CR/LF><CR/LF><CR/LF>
msg = self.tcpClientSocket.recv(130).decode() # Skip server header
print("Searching stream packet start ... ", end="")
msg = self.tcpClientSocket.recv(120).decode() # Skip server header
print("Searching stream packet start ... ")
self.tcpClientSocket.setblocking(False) # Do not block ...
iCount = 0
iCountRec = 0
iCountErr = 0
while True: # Hunting ffa0 (little endian: a0, ff!)
data = self.tcpClientSocket.recv(1)
if data == b'\xa0':
data = self.tcpClientSocket.recv(1)
if data == b'\xff':
break
iCount += 1 # Count retries
if iCount > TCP_PACKET_SIZE: # Somethin's wrong here ...
raise BlockingIOError # Well, some error ...
try:
data = self.tcpClientSocket.recv(1)
if data == b'\xa0':
data = self.tcpClientSocket.recv(1)
if data == b'\xff':
break
iCountRec += 1 # Count retries
if iCountRec > TCP_PACKET_SIZE: # Somethin's wrong here ...
print(" Giving up, no data synchronization marker ...")
raise BlockingIOError # Well, some error ...
except BlockingIOError: # Always on empty receives ...
iCountErr += 1 # Count <no data> ...
if iCountErr > 8191:
print(" Giving up, no data from server received ...")
raise BlockingIOError
data = self.tcpClientSocket.recv(TCP_PACKET_SIZE-2) # Skip complete packet
print("detected! Receiving stream ...")
print("Detected after {} empty packets, {} bytes skipped!\nReceiving stream now ...".format(iCountErr, iCountRec))
def receive_data(self):
"""Client receiver function"""

View File

@ -87,7 +87,7 @@ if __name__ == '__main__':
game = PongGame(pgv.bIsServer)
ball = PongObject(pgc.GAMEAREA_MAX_X/2, pgc.GAMEAREA_MAX_Y/2, 20, 20, 8.0, 2.5)
if player_index == 0: # Local or viewer or server?
if pgv.bIsServer == True: # Server & viewer version, no gamepads locally avail.
if (pgv.bIsServer == True) or (pgv.bIsViewer == True): # Server & viewer version, no gamepads locally avail.
player1 = PongPlayer(None, True, 1, "", 10, pgc.GAMEAREA_MAX_Y/2-50, 20, 160)
player2 = PongPlayer(None, True, 2, "", pgc.GAMEAREA_MAX_X-40, pgc.GAMEAREA_MAX_Y/2-50, 20, 160)
else: # Local version (both gamepads assumed locally connected)
@ -107,8 +107,8 @@ if __name__ == '__main__':
vs.init_send_structures(game, player1, player2, ball)
# 3 View clients permissible
if (player_index > 0) or (pgv.bIsViewer): # i.e. NOT local only
viewserver = vs.ViewServer() # Create a view server
if (player_index > 0) or (pgv.bIsViewer == True): # i.e. NOT local only
viewserver = vs.ViewServer(player_server) # Create a view server
else: # Local
viewserver = None
@ -131,11 +131,11 @@ if __name__ == '__main__':
else: # Headless server-side game loop
while True:
try:
if game.pong_game(ball, player1, player2) == False:
break # Regular game exit
if game.pong_game(ball, player1, player2) == False: # Player game ended
game.reinit() # Re-init on server
time.sleep(0.025) # Yield to other threads ...
except KeyboardInterrupt:
print("Server stopped by user.")
print("\rPandemic Pong Server stopped by user.")
break
# Quit gracefully

View File

@ -1,2 +1,8 @@
# Client, player #1
./pandemic_pong.py --sizeable --player 1 127.0.0.1
# Pandemic Pong Player #1
if [ -z $1 ]; then
echo "usage: ./pp_player1.sh <gameserver>"
exit
fi
./pandemic_pong.py --sizeable --player 1 $1
echo "Pandemic Pong player #1 client terminated."

View File

@ -1,2 +1,8 @@
# Client, player #2
./pandemic_pong.py --sizeable --player 2 127.0.0.1
# Pandemic Pong Player #2
if [ -z $1 ]; then
echo "usage: ./pp_player2.sh <gameserver>"
exit
fi
./pandemic_pong.py --sizeable --player 2 $1
echo "Pandemic Pong player #2 client terminated."

View File

@ -1,2 +1,8 @@
# View client only
./pandemic_pong.py --sizeable --viewer 127.0.0.1
# Pandemic Pong Viewer
if [ -z $1 ]; then
echo "usage: ./pp_viewer.sh <gameserver>"
exit
fi
./pandemic_pong.py --sizeable --viewer $1
echo "Pandemic Pong View Client terminated."