84 lines
3.2 KiB
Python
84 lines
3.2 KiB
Python
import socket
|
|
from queue import Queue
|
|
from typing import TYPE_CHECKING
|
|
|
|
import pyglet.clock
|
|
|
|
from source.core.enums import BombState
|
|
from source.core.error import PositionAlreadyShot, InvalidBombPosition
|
|
from source.gui import scene
|
|
from source.network.SocketType import SocketType
|
|
from source.network.packet.Bomb import Bomb
|
|
from source.network.packet.PacketBombState import PacketBombState
|
|
from source.utils import StoppableThread
|
|
|
|
if TYPE_CHECKING:
|
|
from source.gui.window import Window
|
|
|
|
|
|
class Client(StoppableThread):
|
|
def __init__(self, window: "Window", username: str, ip_address: str, port: int = 52321, **kw):
|
|
super().__init__(**kw)
|
|
|
|
self.window = window
|
|
self.username = username
|
|
self.ip_address = ip_address
|
|
self.port = port
|
|
|
|
def run(self) -> None:
|
|
print("[Client] Thread démarré")
|
|
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as connection:
|
|
connection.connect((self.ip_address, self.port))
|
|
connection.settimeout(5) # défini le timeout à 5 secondes
|
|
|
|
print(f"[Client] Connecté avec {connection}")
|
|
|
|
def create_game_scene(dt: float, queue: Queue):
|
|
game_scene = self.window.set_scene(scene.Game, connection=connection)
|
|
queue.put(game_scene)
|
|
|
|
queue = Queue()
|
|
pyglet.clock.schedule_once(create_game_scene, 0, queue)
|
|
game_scene = queue.get()
|
|
|
|
while True:
|
|
data = None
|
|
|
|
try: data = connection.recv(1)
|
|
except socket.timeout: pass
|
|
|
|
if not data:
|
|
if self._stop: return # vérifie si le thread n'est pas censé s'arrêter
|
|
continue
|
|
|
|
socket_type = SocketType(int.from_bytes(data, "big"))
|
|
|
|
match socket_type:
|
|
case SocketType.CHAT: print(connection.recv(1024).decode())
|
|
case SocketType.BOAT_PLACED: print("adversaire à posé ses bateaux")
|
|
case SocketType.BOMB:
|
|
bomb = Bomb.from_bytes(connection.recv(2))
|
|
|
|
try: bomb_state = game_scene.grid_ally.board.bomb((bomb.x, bomb.y))
|
|
except (InvalidBombPosition, PositionAlreadyShot): pass # TODO: gérer les erreurs
|
|
|
|
connection.send(SocketType.BOMB_STATE.value.to_bytes(1, "big"))
|
|
|
|
packet_bomb_state = PacketBombState(
|
|
x=bomb.x,
|
|
y=bomb.y,
|
|
bomb_state=bomb_state
|
|
)
|
|
connection.send(packet_bomb_state.to_bytes())
|
|
|
|
case SocketType.BOMB_STATE:
|
|
packet_bomb_state = PacketBombState.from_bytes(connection.recv(3))
|
|
|
|
touched = packet_bomb_state.bomb_state in [BombState.TOUCHED, BombState.SUNKEN, BombState.WON]
|
|
|
|
pyglet.clock.schedule_once(
|
|
lambda dt: game_scene.grid_enemy.place_bomb((packet_bomb_state.x, packet_bomb_state.y),
|
|
touched),
|
|
0
|
|
)
|