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:
__id:int
__hp:int
__mana:int
__name:str
__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.__name = name
self.__handCards = []
@ -28,6 +29,13 @@ class Player:
def getHand(self) -> list:
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:
self.__handCards.append(card)
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
from Classes.Game.Player import Player
from Classes.System.GameManager import GameManager
from Classes.System.World import World
class TCPEventHandler:
@ -8,13 +12,13 @@ class TCPEventHandler:
self.__tcpSocket = socket
# handles passing of event data to the right functions
def handleTCPEvents(self, event):
def handleTCPEvents(self, event, gameManager:GameManager, address):
pass
class UDPEventHandler:
__udpSocket:socket
def __init__(self, socket:socket):
def __init__(self, socket:socket, gameManager:GameManager):
self.__udpSocket = socket
def handleUDPEvents(self, event):

View File

@ -1,8 +1,11 @@
import json
import socket
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.World import World
class NetworkManager:
@ -11,24 +14,28 @@ class NetworkManager:
__Port:str
__BufferSize:int = 1024
__udpSocket:socket
__users:list
__users:dict
__eventHandler: UDPEventHandler
__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.__Port = int(Port)
self.__gameManager = gameManager
self.__users = {}
self.__eventHandler = {}
self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.__udpSocket.bind((self.__Addr, self.__Port))
# Starten eines Threads für das Empfangen von UDP-Daten
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 incomming udp data
# handles incoming udp data
def receive(self):
while True:
data, address = self.__udpSocket.recvfrom(self.__BufferSize)
@ -40,7 +47,7 @@ class NetworkManager:
self.__users[user] = address # Storing new user in dictionary
# Process the message and handle accordingly
self.__eventHandler.handleUDPEvents(messageJson)
self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld)
print(f"Received message from {address}: {message}")
def broadcast(self, payload:dict):
@ -56,15 +63,14 @@ class NetworkManager:
__Port:str
__BufferSize:int = 1024
__tcpSocket:socket
__users:list
__eventHandler: TCPEventHandler
__eventHandler: dict
__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.__Port = int(Port)
self.__users = {}
self.__gameManager = gameManager
self.__eventHandler = {}
self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__tcpSocket.bind((self.__Addr, self.__Port))
@ -95,16 +101,20 @@ class NetworkManager:
data = client_socket.recv(self.__BufferSize)
if not data:
print(f"Connection with {client_address} closed.")
break # Verbindung geschlossen, Schleife beenden
break
message = data.decode()
messageJson = json.loads(message)
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:
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}")
except socket.error as e:
@ -118,16 +128,20 @@ class NetworkManager:
print(f"Error receiving data from {client_address}: {e}")
def broadcast(self, payload:dict):
for user_socket in self.__users.values():
user_socket.send(json.dumps(payload).encode())
for user in self.__gameManager.getPlayers().values():
user["socket"].send(json.dumps(payload).encode())
def send(self, payload:dict, user:str):
if user in self.__users:
self.__users[user].send(json.dumps(payload).encode())
def send(self, payload: dict, user: str):
players = self.__gameManager.getPlayers()
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
udp: UDP
def __init__(self, Addr:str, TCPPort:str, UDPPort:str):
self.tcp = self.TCP(Addr, TCPPort)
self.udp = self.UDP(Addr, UDPPort)
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)

View File

@ -1,11 +1,5 @@
import json
from Classes.Objects.Player import Player
class Player:
__users:list
def __init__(self):
self.__users = []
def createUser(self, user:json):
self.__users.append(user)
@ -23,12 +17,7 @@ class Player:
def getUsers(self) -> list:
return self.__users
def getUser(self, user:int) -> (any | None):
def getUser(self, user:int):
for user in self.__users:
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

View File

@ -1,14 +1,19 @@
import json
import socket
import threading
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
class Server:
__address:str
__tcpPort:str
__udpPort:str
__world:World
__gameManager:GameManager
networkManager:NetworkManager
@ -16,10 +21,12 @@ class Server:
self.__address = address
self.__tcpPort = tcpPort
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
def startServer(self):
self.__networkManager = NetworkManager(self.__address, self.__tcpPort, self.__udpPort)
def startServer(self, gameManager:GameManager):
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