fixed issue crashing connections and added system logger

This commit is contained in:
steev 2024-01-14 17:55:35 +01:00
parent 677552a617
commit 15cce52aea
16 changed files with 93 additions and 81 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"cSpell.ignoreWords": [
"posx"
]
}

View File

@ -9,13 +9,17 @@ class GameManager:
__state:str
__round:str
def __init__(self):
def __init__(self, logger):
self.__players = {}
self.__playingPlayer = None
self.__state = "waiting"
self.__round = "none"
self.logger = logger
pass
def getLogger(self):
return self.logger
# game round management
# this section manages the flow of rounds this should inherit itself
# =============================================================================

View File

@ -0,0 +1,18 @@
import logging
class Logger:
def __init__(self, filename):
logging.basicConfig(filename=filename,
filemode='a',
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
datefmt='%H:%M:%S',
level=logging.DEBUG)
def info(self, message):
print(message)
logging.info(message)
def error(self, message):
print(message)
logging.error(message)

View File

@ -13,15 +13,7 @@ class TCPEventHandler:
# handles passing of event data to the right functions
def handleTCPEvents(self, event, gameManager:GameManager, address):
pass
class UDPEventHandler:
__udpSocket:socket
def __init__(self, socket:socket, gameManager:GameManager):
self.__udpSocket = socket
def handleUDPEvents(self, event):
gameManager.getLogger().info(f"incommingevent {event}")
if event["event"] == "PlaceCard":
pass
elif event["event"] == "MoveCard":
@ -36,3 +28,4 @@ class UDPEventHandler:
pass
elif event["event"] == "ActivateMonsterCard":
pass
pass

View File

@ -1,4 +1,5 @@
import json
import signal
import socket
import sys
import threading
@ -9,56 +10,6 @@ from Classes.System.Network.EventHandler import UDPEventHandler, TCPEventHandler
from Classes.System.World import World
class NetworkManager:
#class UDP:
# __Addr:str
# __Port:str
# __BufferSize:int = 1024
# __udpSocket:socket
# __users:dict
# __eventHandler: UDPEventHandler
# __UDPClientThread:threading.Thread
# __gameManager:GameManager
#
# def __init__(self, Addr:str, Port:str, gameManager:GameManager):
# self.__Addr = Addr
# self.__Port = int(Port)
# self.__gameManager = gameManager
# self.__users = {}
# self.__eventHandler = {}
# self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#
# try:
# self.__udpSocket.bind((self.__Addr, self.__Port))
# except OSError as e:
# print(f"Error binding UDP socket: {e}")
#
# self.__UDPClientThread = threading.Thread(target=self.receive)
# self.__UDPClientThread.start()
#
# # handles incoming udp data
# def receive(self):
# while True:
# data, address = self.__udpSocket.recvfrom(self.__BufferSize)
# message = data.decode()
# messageJson = json.loads(message)
# user = messageJson.get("user")
#
# if user not in self.__users:
# self.__users[user] = address # Storing new user in dictionary
#
# # Process the message and handle accordingly
# self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld)
# print(f"Received message from {address}: {message}")
#
# def broadcast(self, payload:dict):
# for user_address in self.__users.values():
# self.__udpSocket.sendto(json.dumps(payload).encode(), user_address)
#
# def send(self, payload:dict, user:str):
# if user in self.__users:
# self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user])
#
class TCP:
__Addr:str
__Port:str
@ -70,40 +21,49 @@ class NetworkManager:
__gameManager:GameManager
def __init__(self, Addr:str, Port:str, gameManager:GameManager):
gameManager.getLogger().info("starting up network manager")
self.running = True
self.__Addr = Addr
self.__Port = int(Port)
self.__gameManager = gameManager
self.__eventHandler = {}
gameManager.getLogger().info("starting up tcp server")
self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__tcpSocket.bind((self.__Addr, self.__Port))
self.__tcpSocket.listen()
gameManager.getLogger().info("starting up thread for client socket accepting")
self.__TCPClientThread = threading.Thread(target=self.accept_connections)
self.__TCPClientThread.daemon = True
self.__TCPClientThread.start()
def accept_connections(self):
while self.running:
try:
client_tcp_socket, client_address = self.__tcpSocket.accept()
print(f"Connected with {client_address}")
self.__gameManager.getLogger().info(f"Connected with {client_address}")
self.__gameManager.getPlayers()[client_address] = client_tcp_socket
self.__eventHandler[client_address] = TCPEventHandler(client_tcp_socket)
client_handler_thread = threading.Thread(
target=self.receive,
args=(client_tcp_socket, client_address)
)
self.__gameManager.getLogger().info(f"starting client handler thread for client at address {client_address}")
client_handler_thread.daemon = True
client_handler_thread.start()
except Exception as e:
print(f"tcp socket failed to accept connection due to error: {e}")
self.__gameManager.getLogger().error(f"tcp socket failed to accept connection due to error: {e}")
pass
client_handler_thread.join()
def receive(self, client_socket, client_address):
while self.running:
try:
data = client_socket.recv(self.__BufferSize)
if not data:
print(f"Connection with {client_address} closed.")
self.__gameManager.getLogger().info(f"Connection with {client_address} closed.")
break
message = data.decode()
@ -114,21 +74,23 @@ class NetworkManager:
# if enough users for a round are connected the server has to start the game
if user not in self.__gameManager.getPlayers():
if messageJson["event"] == "login":
self.logger.__gameManager.getLogger().info("user logging in")
self.logger.__gameManager.getLogger().info("task passed off to gameManager")
self.__gameManager.addPlayers(Player(messageJson["username"], messageJson["deck"]), client_socket, client_address)
print(f"connected users {len(self.__gameManager.getPlayers())}")
self.__gameManager.getLogger().info(f"connected users {len(self.__gameManager.getPlayers())}")
self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address)
print(f"Received message from {client_address}: {message}")
self.__gameManager.getLogger().info(f"Received message from {client_address}: {message}")
except socket.error as e:
if e.errno == 10054:
print(f"Connection with {client_address} forcibly closed by remote host.")
self.__gameManager.getLogger().error(f"Connection with {client_address} forcibly closed by remote host.")
break
print(f"Socket error receiving data from {client_address}: {e}")
self.__gameManager.getLogger().error(f"Socket error receiving data from {client_address}: {e}")
except json.JSONDecodeError as e:
print(f"JSON decoding error receiving data from {client_address}: {e}")
self.__gameManager.getLogger().error(f"JSON decoding error receiving data from {client_address}: {e}")
except Exception as e:
print(f"Error receiving data from {client_address}: {e}")
self.__gameManager.getLogger().error(f"Error receiving data from {client_address}: {e}")
def broadcast(self, payload:dict):
for user in self.__gameManager.getPlayers().values():
@ -140,11 +102,19 @@ class NetworkManager:
if user in players and "socket" in players[user]:
players[user]["socket"].send(json.dumps(payload).encode())
else:
print(f"user '{user}' or socket was not found 'socket' failed to send data.")
self.__gameManager.getLogger().error(f"user '{user}' or socket was not found 'socket' failed to send data.")
def stop(self):
self.__TCPClientThread.join() # Wait for the thread to finish before exiting
tcp: TCP
# udp: UDP
def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager):
self.tcp = self.TCP(Addr, TCPPort, gameManager)
# self.udp = self.UDP(Addr, UDPPort, gameManager)
signal.signal(signal.SIGINT, self.handle_interrupt) # Register the signal handler
def handle_interrupt(self, signum, frame):
self.__gameManager.getLogger().info("Received keyboard interrupt. Stopping the server.")
self.tcp().stop()
sys.exit(0)

View File

@ -6,6 +6,7 @@ from Classes.System.GameManager import GameManager
from Classes.System.Network.NetworkManger import NetworkManager
from Classes.System.PlayerManager import Player
from Classes.System.World import World
from Classes.System.Logger import Logger
class Server:
@ -17,16 +18,23 @@ class Server:
networkManager:NetworkManager
def __init__(self, address:str, tcpPort:str, udpPort:str):
def __init__(self, address:str, tcpPort:str, udpPort:str, logger:Logger):
self.__address = address
self.__tcpPort = tcpPort
self.__udpPort = udpPort
self.__world = World()
self.__gameManager = GameManager()
self.logger = logger
self.logger.info("starting up game manager")
self.__gameManager = GameManager(logger)
self.logger.info("preparing to start server")
self.startServer(self.__gameManager)
# handles starting the server and assigning socket values to the local reference
def startServer(self, gameManager:GameManager):
self.logger.info("starting up network manager")
self.__networkManager = NetworkManager(self.__address, self.__tcpPort, self.__udpPort, gameManager)
def getNetworkManager(self) -> NetworkManager:
return self.__networkManager

View File

@ -1,7 +1,18 @@
import logging
import os
import random
import string
import sys
from Classes.System.Server import Server
from Classes.System.Logger import Logger
def get_random_string(length) -> str:
# choose from all lowercase letter
letters = string.ascii_lowercase
result_str = ''.join(random.choice(letters) for i in range(length))
print("Random string of length", length, "is:", result_str)
return result_str
def main():
# retrieves host data from environment
@ -9,9 +20,11 @@ def main():
TCPPORT = "54322"
UDPPORT = "54323"
Server(HOST, TCPPORT, UDPPORT)
logger = Logger("log/"+get_random_string(8)+".log")
logger.info("starting up server")
server = Server(HOST, TCPPORT, UDPPORT, logging)
server.getNetworkManager().tcp.stop()
sys.exit(0)
if __name__ == "__main__":
main()

View File

@ -13,7 +13,8 @@ def PlaceCard(tcpClient, card):
"event":"placecard",
"card": card.getID(),
"type": card.getType(),
"pos": card.getPos(),
"posx": card.getPos().x,
"posy": card.getPos().y,
}
tcpClient.send(payload)
@ -27,7 +28,7 @@ def CardPlaced(world:World, card:int, type:str, owner:str, pos:pygame.Vector2, i
world.spawnSpellCard(f"Assets/Cards/{card}/", pos, inputHandler, owner)
pass
elif type == "TrapCard":
world.spawmTrapCard(f"Assets/Cards/{card}/", pos, inputHandler, owner)
world.spawnTrapCard(f"Assets/Cards/{card}/", pos, inputHandler, owner)
pass
pass

View File

@ -117,7 +117,7 @@ class App:
if event.button == 1: # Wenn linke Maustaste losgelassen wird
for card in self.__world.getCards():
card.setDragging(False)
card.setState("placed")
# card.setState("placed")
# TODO: send place card event to server
# resets the currently selected card in order to prevent it getting moved
try: