From ce829b62b12b55908343d7cd37f3c6b87e516e12 Mon Sep 17 00:00:00 2001 From: KylerO Date: Wed, 16 Apr 2025 11:11:22 -0600 Subject: [PATCH] Finished most of networking --- client.py | 82 +++++++++++++++++++++++++++++++++--------------------- library.py | 39 +++++++++++++++----------- server.py | 53 +++++++++++++++++++++++++---------- 3 files changed, 111 insertions(+), 63 deletions(-) diff --git a/client.py b/client.py index fccce24..cd19349 100644 --- a/client.py +++ b/client.py @@ -3,8 +3,9 @@ # Apr 2025 from __future__ import annotations -import network_utilities import socket +import select +import network_utilities class Game: @@ -17,44 +18,46 @@ class Game: self.__server = server def start_game(self): - data = network_utilities.pack_varint(1) + data = network_utilities.pack_varint(2) self.__server.send(data) def start_round(self, difficulty: int): - data = network_utilities.pack_varint(2) + data = network_utilities.pack_varint(3) data += network_utilities.pack_varint(difficulty) self.__server.send(data) def guess_reference(self, url: str): - data = network_utilities.pack_varint(3) + data = network_utilities.pack_varint(4) data += network_utilities.pack_string(url) self.__server.send(data) def end_game(self): - data = network_utilities.pack_varint(4) + data = network_utilities.pack_varint(5) self.__server.send(data) def update(self): - packet_id = network_utilities.unpack_varint(self.__server) - if packet_id == 1: - name = network_utilities.unpack_string(self.__server) - self.__player.player_joined(name) - elif packet_id == 2: - text = network_utilities.unpack_string(self.__server) - self.__player.new_verse(text) - elif packet_id == 3: - self.__player.guess_incorrect() - elif packet_id == 4: - self.__player.guess_correct() - elif packet_id == 5: - points = network_utilities.unpack_varint(self.__server) - url = network_utilities.unpack_string(self.__server) - player = network_utilities.unpack_string(self.__server) - self.__player.verse_guessed(points, url, player) - elif packet_id == 6: - players = network_utilities.unpack_string_array(self.__server) - scores = network_utilities.unpack_varint_array(self.__server) - self.__player.game_over(players, scores) + ready_to_read, _, _ = select.select([self.__server], [], [], 0) + if ready_to_read: + packet_id = network_utilities.unpack_varint(self.__server) + if packet_id == 1: + name = network_utilities.unpack_string(self.__server) + self.__player.player_joined(name) + elif packet_id == 2: + text = network_utilities.unpack_string(self.__server) + self.__player.new_verse(text) + elif packet_id == 3: + self.__player.guess_incorrect() + elif packet_id == 4: + self.__player.guess_correct() + elif packet_id == 5: + points = network_utilities.unpack_varint(self.__server) + url = network_utilities.unpack_string(self.__server) + player = network_utilities.unpack_string(self.__server) + self.__player.verse_guessed(points, url, player) + elif packet_id == 6: + players = network_utilities.unpack_string_array(self.__server) + scores = network_utilities.unpack_varint_array(self.__server) + self.__player.game_over(players, scores) class Player: @@ -80,7 +83,12 @@ class Player: def score(self) -> int: return self.__score def join_game(self, host: str = 'localhost', port: int = 7788): - pass + conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + conn.connect((host, port)) + data = network_utilities.pack_varint(1) + data += network_utilities.pack_string(self.name) + conn.send(data) + self.__game = Game(self, conn) def start_game(self): if self.__game is not None: @@ -99,20 +107,30 @@ class Player: self.__game.end_game() def player_joined(self, name: str): - pass + if self.__game is not None: + pass def new_verse(self, text: str): - pass + if self.__game is not None: + pass def guess_incorrect(self): - pass + if self.__game is not None: + pass def guess_correct(self): - pass + if self.__game is not None: + pass def verse_guessed(self, points: int, url: str, player: str): - pass + if self.__game is not None: + pass def game_over(self, players: list[str], scores: list[int]): - pass + if self.__game is not None: + pass + + def update(self): + if self.__game is not None: + self.__game.update() diff --git a/library.py b/library.py index c164c32..38daec0 100644 --- a/library.py +++ b/library.py @@ -3,13 +3,12 @@ # Apr 2025 from __future__ import annotations -from typing import TYPE_CHECKING import json import random import socket - -if TYPE_CHECKING: - from server import Game +import select +import network_utilities +from server import Game class Library: @@ -34,23 +33,31 @@ class Library: with self.__socket as s: s.bind((self.__host, self.__port)) s.listen(1) + s.setblocking(False) while True: - conn, _ = s.accept() - ... + ready_to_read, _, _ = select.select([s], [], [], 0) + for game in self.__games[:]: + if not game.finished: game.update() + else: self.__games.remove(game) + if ready_to_read: + conn, _ = s.accept() + conn.setblocking(False) + if network_utilities.unpack_varint(conn) == 1: + name = network_utilities.unpack_string(conn) + self.join_game(name, conn) except KeyboardInterrupt: print("KeyboardInterrupt\nExiting...") return - def join_game(self, name: str, game_num: int = -1): - if game_num == -1: - for i, game in enumerate(self.__games): - if not game.active: - game_num = i - break - else: - self.__games.append(Game()) - game_num = len(self.__games) - 1 - self.__games[game_num].add_player(name) + def join_game(self, name: str, conn: socket.socket): + for i, game in enumerate(self.__games): + if not game.active: + game_num = i + break + else: + self.__games.append(Game(self)) + game_num = len(self.__games) - 1 + self.__games[game_num].add_player(name, conn) def get_verse(self, difficulty: int, game: Game): url = self.__select_verse(difficulty) diff --git a/server.py b/server.py index 7709ee3..1223251 100644 --- a/server.py +++ b/server.py @@ -4,6 +4,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +import select +import datetime import network_utilities if TYPE_CHECKING: @@ -20,6 +22,7 @@ class Game: __total_scores: list[int] __active: bool __finished: bool + __created: datetime.datetime def __init__(self, library: Library): self.__library = library @@ -29,6 +32,7 @@ class Game: self.__total_scores = [] self.__active = False self.__finished = False + self.__created = datetime.datetime.now() @property def active(self) -> bool: return self.__active @@ -36,9 +40,9 @@ class Game: @property def finished(self) -> bool: return self.__finished - def add_player(self, name: str, socket: socket): + def add_player(self, name: str, conn: socket): if not self.__active: - self.__clients.append(Player(name, self, socket)) + self.__clients.append(Player(name, self, conn)) self.__total_scores.append(0) for player in self.__clients: player.player_joined(name) @@ -69,6 +73,21 @@ class Game: def end_game(self): self.__finished = True + for player in self.__clients: + player.game_over( + [i.name for i in self.__clients], self.__total_scores) + + def update(self): + if not self.__active and ( + datetime.datetime.now() - self.__created >= + datetime.timedelta(minutes=10) + ) or ( + datetime.datetime.now() - self.__created >= + datetime.timedelta(1) + ): self.__finished = True + if not self.__finished: + for player in self.__clients: + player.update() class Player: @@ -77,10 +96,10 @@ class Player: __game: Game __client: socket - def __init__(self, name: str, game: Game, socket: socket): + def __init__(self, name: str, game: Game, conn: socket): self.__name = name self.__game = game - self.__client = socket + self.__client = conn @property def name(self) -> str: return self.__name @@ -115,16 +134,20 @@ class Player: data += network_utilities.pack_string_array(players) data += network_utilities.pack_varint_array(scores) self.__client.send(data) + self.__client.close() def update(self): - packet_id = network_utilities.unpack_varint(self.__client) - if packet_id == 1: - self.__game.start_game() - elif packet_id == 2: - difficulty = network_utilities.unpack_varint(self.__client) - self.__game.start_round(difficulty) - elif packet_id == 3: - url = network_utilities.unpack_string(self.__client) - self.__game.guess_reference(url, self) - elif packet_id == 4: - self.__game.end_game() + ready_to_read, _, _ = select.select([self.__client], [], [], 0) + if ready_to_read: + packet_id = network_utilities.unpack_varint(self.__client) + if packet_id == 2: + self.__game.start_game() + elif packet_id == 3: + difficulty = network_utilities.unpack_varint(self.__client) + self.__game.start_round(difficulty) + elif packet_id == 4: + url = network_utilities.unpack_string(self.__client) + self.__game.guess_reference(url, self) + elif packet_id == 5: + self.__game.end_game() +