Skip to content

Commit

Permalink
Merge branch 'main' into paco/game-logs-2
Browse files Browse the repository at this point in the history
  • Loading branch information
PacoSchatz authored Mar 11, 2024
2 parents 18da4a1 + 9a82836 commit 46d5d45
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 32 deletions.
10 changes: 9 additions & 1 deletion comprl/client/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ def run(self, token: str, host: str = "localhost", port: int = 65335) -> None:
super().run(token)
networking.connect_agent(self, host, port)

def on_error(self, msg):
def on_error(self, msg: str):
"""Called if an error occurred on the server side."""
print(f"Error: {msg}")

def on_message(self, msg: str):
"""Called if a message is sent from the server."""
print(f"Info: {msg}")

def on_disconnect(self):
"""Called when the agent disconnects from the server."""
print("Error: Agent disconnected from the server.")
18 changes: 15 additions & 3 deletions comprl/client/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_step(self, obv: list[float]) -> list[float]:
"""
raise NotImplementedError("step function not implemented")

def on_end_game(self, result, stats) -> None:
def on_end_game(self, result: bool, stats: list[float]) -> None:
"""
Called when a game ends.
Expand All @@ -70,11 +70,23 @@ def on_end_game(self, result, stats) -> None:
"""
pass

def on_error(self, msg):
def on_error(self, msg: str):
"""
Called when an error occurs.
Args:
msg: The error message.
msg (str): The error message.
"""
pass

def on_message(self, msg: str):
"""Called when a message is sent from the server.
Args:
msg (str): The message
"""
pass

def on_disconnect(self):
"""Called when the agent disconnects from the server."""
pass
22 changes: 20 additions & 2 deletions comprl/client/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from twisted.internet import reactor
from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol

from comprl.shared.commands import Ready, StartGame, EndGame, Step, Auth, Error
from comprl.shared.commands import Ready, StartGame, EndGame, Step, Auth, Error, Message

from .interfaces import IAgent

Expand Down Expand Up @@ -46,6 +46,7 @@ def connectionLost(self, reason):
log.debug(f"Disconnected from the server. Reason: {reason}")
if reactor.running:
reactor.stop()
self.agent.on_disconnect()
return super().connectionLost(reason)

@Auth.responder
Expand Down Expand Up @@ -108,7 +109,14 @@ def step(self, obv: list[float]):
dict: A dictionary containing the action that should be executed.
Example: {"action": 1}
"""
return {"action": self.agent.get_step(obv)}
action = self.agent.get_step(obv)
if isinstance(action, list) and all(isinstance(x, float) for x in action):
return {"action": action}
else:
raise Exception(
"Tried to send an action with wrong type. "
"Only actions of type list[float] can be send."
)

@Error.responder
def on_error(self, msg):
Expand All @@ -120,6 +128,16 @@ def on_error(self, msg):
self.agent.on_error(msg=str(msg, encoding="utf-8"))
return {}

@Message.responder
def on_message(self, msg):
"""Called if a message from the server is sent.
Args:
msg (object): The message.
"""
self.agent.on_message(msg=str(msg, encoding="utf-8"))
return {}


def connect_agent(agent: IAgent, host: str = "localhost", port: int = 65335):
"""Connects the client to the server.
Expand Down
8 changes: 8 additions & 0 deletions comprl/server/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def on_connect(self, player: IPlayer):
def __auth(token):
if self.player_manager.auth(player.id, token):
self.matchmaking.try_match(player.id)
player.notify_info(msg="Authentication successful")
else:
player.disconnect("Authentication failed")

Expand All @@ -64,6 +65,13 @@ def on_timeout(self, player: IPlayer, failure, timeout):
log.debug(f"Player {player.id} had timeout after {timeout}s")
player.disconnect(reason=f"Timeout after {timeout}s")

def on_remote_error(self, player: IPlayer, error: Exception):
"""gets called when there is an error in deferred"""
if player.is_connected:
log.error(f"Connected player caused remote error \n {error}")
else:
log.debug("Disconnected player caused remote error")

def on_update(self):
"""gets called every update cycle"""
self.matchmaking.update()
Expand Down
18 changes: 18 additions & 0 deletions comprl/server/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class IPlayer(abc.ABC):
def __init__(self) -> None:
self.id: PlayerID = IDGenerator.generate_player_id()
self.user_id: Optional[int] = None
self.is_connected = True

@abc.abstractmethod
def authenticate(self, result_callback):
Expand Down Expand Up @@ -77,6 +78,11 @@ def notify_error(self, error: str):
"""notifies the player of an error"""
...

@abc.abstractmethod
def notify_info(self, msg: str):
"""notifies the player of an information"""
...


class IGame(abc.ABC):
"""
Expand Down Expand Up @@ -155,6 +161,8 @@ def _end(self, reason="unknown"):
callback(self)

for player in self.players.values():
if player.id == self.disconnected_player_id:
continue
player.notify_end(
self._player_won(player.id), self._player_stats(player.id)
)
Expand Down Expand Up @@ -336,6 +344,16 @@ def on_timeout(self, player: IPlayer, failure, timeout):
"""
...

@abc.abstractmethod
def on_remote_error(self, player: IPlayer, error):
"""
Gets called when an error in deferred occurs.
Args:
player (IPlayer): The player that caused the error.
error (Exception): Error that occurred
"""
...

@abc.abstractmethod
def on_update(self):
"""
Expand Down
8 changes: 7 additions & 1 deletion comprl/server/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,13 @@ def try_match(self, player_id: PlayerID) -> None:

if player is not None:
# FIXME: we might wan't to kick the player
player.is_ready(lambda res: self.match(player_id) if res else None)

def __match(ready: bool):
if ready:
player.notify_info(msg="Waiting in queue")
self.match(player_id)

player.is_ready(result_callback=__match)

def match(self, player_id: PlayerID) -> None:
"""
Expand Down
Loading

0 comments on commit 46d5d45

Please sign in to comment.