moved game management into own class serverside

This commit is contained in:
steev 2024-01-07 22:27:43 +01:00
parent d9b367dd42
commit 8f90633b16
14 changed files with 176 additions and 45 deletions

View File

@ -4,10 +4,11 @@ import random
class Player: class Player:
__id:int __id:int
__hp:int __hp:int
__mana:int
__name:str __name:str
__handCards:list __handCards:list
def __init__(self, name:str, hp:int=1000): def __init__(self, name:str, hp:int=1000, mana:int=0):
self.__hp = hp self.__hp = hp
self.__name = name self.__name = name
self.__handCards = [] self.__handCards = []
@ -28,6 +29,13 @@ class Player:
def getHand(self) -> list: def getHand(self) -> list:
return self.__handCards return self.__handCards
def getMana(self) -> int:
return self.__mana
def addMana(self, amount) -> int:
self.__mana + amount
return self.__mana
def AddToHand(self, card) -> list: def AddToHand(self, card) -> list:
self.__handCards.append(card) self.__handCards.append(card)
return self.__handCards return self.__handCards

View File

@ -0,0 +1,89 @@
import socket
from Classes.Game.Player import Player
class GameManager:
__players:dict
__playingPlayer:Player
__state:str
__round:str
def __init__(self):
self.__players = {}
self.__playingPlayer = None
self.__state = "waiting"
self.__round = "none"
pass
# game round management
# this section manages the flow of rounds this should inherit itself
# =============================================================================
# this function iterates all
def progressRound(self):
# phases
# - playerPrep => playing player switches, gets a mana point and gets verified
if self.__playingPlayer != None:
for player in self.__players:
if self.__playingPlayer != player:
self.__playingPlayer = player
else:
self.__playingPlayer = next(iter(self.__players))
# - playerDraw => player draws a card
# - playerPlay => player can place cards and active effects
# - playerEnd => player ends his turn and the code reiterates with the remaining player
pass
# game state management
# this section mostly only used by the networking and event handling classes
# other parts should never need to interface with this unless really required
# =============================================================================
def startGame(self):
self.__state = "running"
print("game starts")
for userAddr in self.__users.keys():
try:
user = self.__serverWorld.getPlayers[userAddr]
user.addMana(1000)
user.adjustHP(1000)
payload = {
"event":"startgame",
"mana": user.getMana(),
"hp": user.getHP()
}
self.send(payload, userAddr)
except Exception as e:
print(f"failed to start game due to error: {e}")
break
# handles notifying all players that the game starts
pass
def stopGame(self):
# handles notifying all players that the game stops
# handles stoping the game itself and notifies server to stop itself
pass
# player management
# the network manager will create a player instance
# =============================================================
# gets all player known to the game manager and returns them
def getPlayers(self) -> dict:
return self.__players
# creates a player and handles counting all players and if conditions met starting the game
# returns the new dict in which the new player now is added
def addPlayers(self, player:Player, socket:socket, clientAddr) -> dict:
self.__players[clientAddr] = {
player: player,
socket:socket
}
# counts participating players and starts the game if enough have joined
if len(self.__players) == 2:
self.startGame()
return self.__players

View File

@ -1,4 +1,8 @@
import socket import socket
from Classes.Game.Player import Player
from Classes.System.GameManager import GameManager
from Classes.System.World import World
class TCPEventHandler: class TCPEventHandler:
@ -8,13 +12,13 @@ class TCPEventHandler:
self.__tcpSocket = socket self.__tcpSocket = socket
# handles passing of event data to the right functions # handles passing of event data to the right functions
def handleTCPEvents(self, event): def handleTCPEvents(self, event, gameManager:GameManager, address):
pass pass
class UDPEventHandler: class UDPEventHandler:
__udpSocket:socket __udpSocket:socket
def __init__(self, socket:socket): def __init__(self, socket:socket, gameManager:GameManager):
self.__udpSocket = socket self.__udpSocket = socket
def handleUDPEvents(self, event): def handleUDPEvents(self, event):

View File

@ -1,8 +1,11 @@
import json import json
import socket import socket
import threading import threading
from Classes.Game.Player import Player
from Classes.System.GameManager import GameManager
from Classes.System.Network.EventHandler import UDPEventHandler, TCPEventHandler from Classes.System.Network.EventHandler import UDPEventHandler, TCPEventHandler
from Classes.System.World import World
class NetworkManager: class NetworkManager:
@ -11,24 +14,28 @@ class NetworkManager:
__Port:str __Port:str
__BufferSize:int = 1024 __BufferSize:int = 1024
__udpSocket:socket __udpSocket:socket
__users:list __users:dict
__eventHandler: UDPEventHandler __eventHandler: UDPEventHandler
__UDPClientThread:threading.Thread __UDPClientThread:threading.Thread
__gameManager:GameManager
def __init__(self, Addr:str, Port:str):
def __init__(self, Addr:str, Port:str, gameManager:GameManager):
self.__Addr = Addr self.__Addr = Addr
self.__Port = int(Port) self.__Port = int(Port)
self.__gameManager = gameManager
self.__users = {} self.__users = {}
self.__eventHandler = {} self.__eventHandler = {}
self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.__udpSocket.bind((self.__Addr, self.__Port))
try:
# Starten eines Threads für das Empfangen von UDP-Daten 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 = threading.Thread(target=self.receive)
self.__UDPClientThread.start() self.__UDPClientThread.start()
# handles incomming udp data # handles incoming udp data
def receive(self): def receive(self):
while True: while True:
data, address = self.__udpSocket.recvfrom(self.__BufferSize) data, address = self.__udpSocket.recvfrom(self.__BufferSize)
@ -40,7 +47,7 @@ class NetworkManager:
self.__users[user] = address # Storing new user in dictionary self.__users[user] = address # Storing new user in dictionary
# Process the message and handle accordingly # Process the message and handle accordingly
self.__eventHandler.handleUDPEvents(messageJson) self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld)
print(f"Received message from {address}: {message}") print(f"Received message from {address}: {message}")
def broadcast(self, payload:dict): def broadcast(self, payload:dict):
@ -56,15 +63,14 @@ class NetworkManager:
__Port:str __Port:str
__BufferSize:int = 1024 __BufferSize:int = 1024
__tcpSocket:socket __tcpSocket:socket
__users:list __eventHandler: dict
__eventHandler: TCPEventHandler
__TCPClientThread:threading.Thread __TCPClientThread:threading.Thread
__gameManager:GameManager
def __init__(self, Addr:str, Port:str): def __init__(self, Addr:str, Port:str, gameManager:GameManager):
self.__Addr = Addr self.__Addr = Addr
self.__Port = int(Port) self.__Port = int(Port)
self.__gameManager = gameManager
self.__users = {}
self.__eventHandler = {} self.__eventHandler = {}
self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__tcpSocket.bind((self.__Addr, self.__Port)) self.__tcpSocket.bind((self.__Addr, self.__Port))
@ -95,16 +101,20 @@ class NetworkManager:
data = client_socket.recv(self.__BufferSize) data = client_socket.recv(self.__BufferSize)
if not data: if not data:
print(f"Connection with {client_address} closed.") print(f"Connection with {client_address} closed.")
break # Verbindung geschlossen, Schleife beenden break
message = data.decode() message = data.decode()
messageJson = json.loads(message) messageJson = json.loads(message)
user = messageJson.get("user") user = messageJson.get("user")
# creates a user and counts how many currently are connected to the server
# if enough users for a round are connected the server has to start the game
if user not in self.__users: if user not in self.__users:
self.__users[user] = client_address if messageJson["event"] == "login":
self.__gameManager.addPlayers(Player(messageJson["username"]), self.__tcpSocket, client_address)
print(f"connected users {len(self.__users)}")
self.__eventHandler[client_address].handleTCPEvents(messageJson) self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address)
print(f"Received message from {client_address}: {message}") print(f"Received message from {client_address}: {message}")
except socket.error as e: except socket.error as e:
@ -118,16 +128,20 @@ class NetworkManager:
print(f"Error receiving data from {client_address}: {e}") print(f"Error receiving data from {client_address}: {e}")
def broadcast(self, payload:dict): def broadcast(self, payload:dict):
for user_socket in self.__users.values(): for user in self.__gameManager.getPlayers().values():
user_socket.send(json.dumps(payload).encode()) user["socket"].send(json.dumps(payload).encode())
def send(self, payload:dict, user:str): def send(self, payload: dict, user: str):
if user in self.__users: players = self.__gameManager.getPlayers()
self.__users[user].send(json.dumps(payload).encode())
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.")
tcp: TCP tcp: TCP
udp: UDP udp: UDP
def __init__(self, Addr:str, TCPPort:str, UDPPort:str): def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager):
self.tcp = self.TCP(Addr, TCPPort) self.tcp = self.TCP(Addr, TCPPort, gameManager)
self.udp = self.UDP(Addr, UDPPort) self.udp = self.UDP(Addr, UDPPort, gameManager)

View File

@ -1,12 +1,6 @@
import json import json
from Classes.Objects.Player import Player
class Player: class Player:
__users:list
def __init__(self):
self.__users = []
def createUser(self, user:json): def createUser(self, user:json):
self.__users.append(user) self.__users.append(user)
@ -23,12 +17,7 @@ class Player:
def getUsers(self) -> list: def getUsers(self) -> list:
return self.__users return self.__users
def getUser(self, user:int) -> (any | None): def getUser(self, user:int):
for user in self.__users: for user in self.__users:
if int(user["id"]) == user: if int(user["id"]) == user:
return user
def getUser(self, user:str) -> (any | None):
for user in self.__users:
if user["name"] == user:
return user return user

View File

@ -1,25 +1,32 @@
import json import json
import socket import socket
import threading import threading
from Classes.System.GameManager import GameManager
from Classes.System.Network.NetworkManger import NetworkManager from Classes.System.Network.NetworkManger import NetworkManager
from Classes.System.PlayerManager import Player
from Classes.System.World import World
class Server: class Server:
__address:str __address:str
__tcpPort:str __tcpPort:str
__udpPort:str __udpPort:str
__world:World
__gameManager:GameManager
networkManager:NetworkManager networkManager:NetworkManager
def __init__(self, address:str, tcpPort:str, udpPort:str): def __init__(self, address:str, tcpPort:str, udpPort:str):
self.__address = address self.__address = address
self.__tcpPort = tcpPort self.__tcpPort = tcpPort
self.__udpPort = udpPort self.__udpPort = udpPort
self.__world = World()
self.__gameManager = GameManager()
self.startServer() self.startServer(self.__gameManager)
# handles starting the server and assigning socket values to the local reference # handles starting the server and assigning socket values to the local reference
def startServer(self): def startServer(self, gameManager:GameManager):
self.__networkManager = NetworkManager(self.__address, self.__tcpPort, self.__udpPort) self.__networkManager = NetworkManager(self.__address, self.__tcpPort, self.__udpPort, gameManager)

View File

@ -0,0 +1,20 @@
import socket
from Classes.Game.Player import Player
class World:
__players:dict
def __init__(self):
self.__players = {}
def getPlayers(self) -> list:
return self.__players
def addPlayers(self, player:Player, socket:socket, clientAddr) -> list:
self.__players[clientAddr] = {
player: player,
socket:socket
}
return self.__players