Files
basegame-vcko/server.py

166 lines
7.8 KiB
Python
Executable File

import socket
import time
import threading
from common import *
from constants import *
import json
class ServerVCKO:
def __init__(self):
self.host = socket.gethostname()
self.server_socket = socket.socket()
self.server_socket.bind((self.host, Constants.port))
self.game_dict = {}
self.lobby = []
self.gamers = []
def handle_client(self, conn, addr):
print(f"Connection from: {addr}")
connected = True
while connected:
msg_length = conn.recv(Constants.header_size).decode(Constants.text_format)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(Constants.text_format)
first_word = msg.split()[0]
full_command = msg.split()
match first_word:
case "connection_check":
connected = False
conn.send("received".encode(Constants.text_format))
case "lobby":
connected = False
if full_command[1] == "join" and len(full_command) > 2:
joining_player_name = ' '.join(full_command[2:])
joining_player_id = shortuuid.uuid()
joining_player = LobbyMember(joining_player_name, joining_player_id)
self.lobby.append(joining_player)
message = f"lobby joined {joining_player_id}"
conn.send(message.encode(Constants.text_format))
elif full_command[1] == "leave" and len(full_command) > 2:
temp_lobby = []
for player in self.lobby:
if player.player_id != full_command[2]:
temp_lobby.append(player)
self.lobby = temp_lobby
self.send_lobby_state(conn)
elif full_command[1] == "get_status" and len(full_command) == 3:
found = False
for player in self.lobby:
if full_command[2] == player.player_id:
self.send_lobby_state(conn)
found = True
for player in self.gamers:
if full_command[2] == player.player_id:
message = f"game joined {player.game_id}"
conn.send(message.encode(Constants.text_format))
found = True
# this only runs if we somehow receive an invalid player id
if not found:
message = f"Unable to find any player with player id: {full_command[2]}"
conn.send(message.encode(Constants.text_format))
elif full_command[1] == "ready" and len(full_command) > 2:
ready_check = 0
for player in self.lobby:
if player.player_id == full_command[2]:
player.is_ready = True
if player.is_ready:
ready_check += 1
print(f"ready check: {ready_check}")
if ready_check == len(self.lobby):
new_game_id = str(uuid.uuid4())
for player in self.lobby:
print(f"lobby player: {player.name}")
players_to_remove = []
for player in self.lobby:
if player.is_ready:
new_gamer = GameMember(player.player_id, player.name, new_game_id)
self.gamers.append(new_gamer)
players_to_remove.append(player)
for player in players_to_remove:
self.lobby.remove(player)
new_game = Game(new_game_id, self.gamers)
self.game_dict[new_game.game_id] = new_game
print(f"size of game dict: {len(self.game_dict)}")
message = f"game joined {new_game_id}"
conn.send(message.encode(Constants.text_format))
else:
self.send_lobby_state(conn)
elif full_command[1] == "unready" and len(full_command) > 2:
for player in self.lobby:
if player.player_id == full_command[2]:
player.is_ready = False
self.send_lobby_state(conn)
else:
conn.send("invalid message".encode(Constants.text_format))
case "game":
connected = False
if full_command[1] == "get_status" and len(full_command) == 3:
print(full_command[2])
print(len(self.game_dict))
for game in self.game_dict:
print(f"game id: {game}")
game_id = full_command[2]
game = self.game_dict.get(game_id)
if not game:
message = "game state error: game not found"
conn.send(message.encode(Constants.text_format))
else:
self.send_game_state(conn, full_command[2])
case _:
connected = False
conn.send("invalid message".encode(Constants.text_format))
print(f"[{addr}] {msg}")
conn.close()
def start(self):
self.server_socket.listen()
print(f"server is listening on {socket.gethostbyname(self.host)}")
while True:
conn, addr = self.server_socket.accept()
thread = threading.Thread(target=self.handle_client, args=(conn, addr))
thread.start()
print(f"\nActive threads: {threading.active_count() - 1}")
def send_lobby_state(self, conn):
lobby_data = []
for lobby_member in self.lobby:
player_dict = {
"name": lobby_member.name,
"player_id": lobby_member.player_id,
"is_ready": lobby_member.is_ready
}
lobby_data.append(player_dict)
response = f"lobby state {json.dumps(lobby_data)}"
conn.send(response.encode(Constants.text_format))
def send_game_state(self, conn, game_id):
game = self.game_dict.get(game_id)
if not game:
response = "game state error: game not found"
else:
game_json = json.dumps(game, cls=GameObjectEncoder)
response = f"game state {game_json}"
conn.send(response.encode(Constants.text_format))
class LobbyMember:
def __init__(self, player_name, player_id):
self.name = player_name
self.player_id = player_id
self.is_ready = False
class GameMember:
def __init__(self, player_id, player_name, game_id):
self.name = player_name
self.player_id = player_id
self.game_id = game_id
if __name__ == '__main__':
print("server starting")
server = ServerVCKO()
server.start()