can now join game and begin polling gamestate
This commit is contained in:
16
client.py
16
client.py
@@ -57,6 +57,20 @@ class GameFrame(wx.Frame):
|
|||||||
self.app = app
|
self.app = app
|
||||||
self.panel = wx.Panel(self)
|
self.panel = wx.Panel(self)
|
||||||
self.SetMinSize(Constants.minimum_window_size)
|
self.SetMinSize(Constants.minimum_window_size)
|
||||||
|
self.last_lobby_state = []
|
||||||
|
self.timer = wx.Timer(self)
|
||||||
|
self.Bind(wx.EVT_TIMER, self.get_game_status, self.timer)
|
||||||
|
self.timer.Start(500)
|
||||||
|
|
||||||
|
def get_game_status(self, event=None):
|
||||||
|
if connection_check() and self.app.in_game:
|
||||||
|
self.app.parse_response(send(f"game get_status {self.app.game_id}"))
|
||||||
|
if self.app.lobby == self.last_lobby_state:
|
||||||
|
# If the current lobby state is the same as the last one, don't update the list control
|
||||||
|
return
|
||||||
|
|
||||||
|
# Save the new lobby state
|
||||||
|
self.last_lobby_state = self.app.lobby
|
||||||
|
|
||||||
|
|
||||||
class LobbyFrame(wx.Frame):
|
class LobbyFrame(wx.Frame):
|
||||||
@@ -116,7 +130,7 @@ class LobbyFrame(wx.Frame):
|
|||||||
# Save the new lobby state
|
# Save the new lobby state
|
||||||
self.last_lobby_state = self.app.lobby
|
self.last_lobby_state = self.app.lobby
|
||||||
|
|
||||||
def highlight_current_player(self):
|
def highlight_current_player(self, event=None):
|
||||||
if self.current_player_index is not None:
|
if self.current_player_index is not None:
|
||||||
self.list_ctrl.Select(self.current_player_index)
|
self.list_ctrl.Select(self.current_player_index)
|
||||||
else:
|
else:
|
||||||
|
|||||||
174
common.py
174
common.py
@@ -1,6 +1,9 @@
|
|||||||
|
import json
|
||||||
|
from json import JSONEncoder
|
||||||
|
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
import random
|
import random
|
||||||
from typing import List
|
from typing import List, Dict
|
||||||
import shortuuid
|
import shortuuid
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@@ -19,9 +22,9 @@ class Card:
|
|||||||
|
|
||||||
|
|
||||||
class Player:
|
class Player:
|
||||||
def __init__(self, player_id):
|
def __init__(self, player_id, name):
|
||||||
self.player_id = player_id
|
self.player_id = player_id
|
||||||
# self.name = name
|
self.name = name
|
||||||
self.owned_starters = []
|
self.owned_starters = []
|
||||||
self.owned_citizens = []
|
self.owned_citizens = []
|
||||||
self.owned_domains = []
|
self.owned_domains = []
|
||||||
@@ -177,9 +180,9 @@ class Duke(Card):
|
|||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self, player_count, preset="shuffled", number_of_dukes=2):
|
def __init__(self, game_id, player_list_from_lobby, preset="shuffled", number_of_dukes=2):
|
||||||
self.game_id = uuid.uuid4()
|
self.game_id = game_id
|
||||||
self.player_count = player_count
|
self.player_count = len(player_list_from_lobby)
|
||||||
self.preset = preset
|
self.preset = preset
|
||||||
self.number_of_dukes = number_of_dukes
|
self.number_of_dukes = number_of_dukes
|
||||||
self.player_list = []
|
self.player_list = []
|
||||||
@@ -394,9 +397,8 @@ class Game:
|
|||||||
stack[:] = [monster for monster in stack if not monster.is_extra]
|
stack[:] = [monster for monster in stack if not monster.is_extra]
|
||||||
# end remove extra cards
|
# end remove extra cards
|
||||||
# create players and determine order
|
# create players and determine order
|
||||||
for x in range(0, self.player_count):
|
for player in player_list_from_lobby:
|
||||||
my_player = Player(shortuuid.uuid())
|
my_player = Player(player.player_id, player.name)
|
||||||
my_player.name = f"Player {(x + 1)}"
|
|
||||||
self.player_list.append(my_player)
|
self.player_list.append(my_player)
|
||||||
random.shuffle(self.player_list)
|
random.shuffle(self.player_list)
|
||||||
self.player_list[0].is_first = True
|
self.player_list[0].is_first = True
|
||||||
@@ -505,3 +507,157 @@ class Game:
|
|||||||
def end_check(self):
|
def end_check(self):
|
||||||
if self.exhausted_count <= (self.player_count * 2):
|
if self.exhausted_count <= (self.player_count * 2):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class GameObjectEncoder(JSONEncoder):
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, Card):
|
||||||
|
return {
|
||||||
|
"name": obj.name,
|
||||||
|
"is_visible": obj.is_visible,
|
||||||
|
"is_accessible": obj.is_accessible,
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Player):
|
||||||
|
return {
|
||||||
|
'player_id': obj.player_id,
|
||||||
|
'name': obj.name,
|
||||||
|
'owned_starters': [starter.starter_id for starter in obj.owned_starters],
|
||||||
|
'owned_citizens': [citizen.citizen_id for citizen in obj.owned_citizens],
|
||||||
|
'owned_domains': [domain.domain_id for domain in obj.owned_domains],
|
||||||
|
'owned_dukes': [duke.duke_id for duke in obj.owned_dukes],
|
||||||
|
'owned_monsters': [monster.monster_id for monster in obj.owned_monsters],
|
||||||
|
'gold_score': obj.gold_score,
|
||||||
|
'strength_score': obj.strength_score,
|
||||||
|
'magic_score': obj.magic_score,
|
||||||
|
'is_first': obj.is_first,
|
||||||
|
'shadow_count': obj.shadow_count,
|
||||||
|
'holy_count': obj.holy_count,
|
||||||
|
'soldier_count': obj.soldier_count,
|
||||||
|
'worker_count': obj.worker_count
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Duke):
|
||||||
|
return {
|
||||||
|
**super().default(obj),
|
||||||
|
"duke_id": obj.duke_id,
|
||||||
|
"gold_multiplier": obj.gold_multiplier,
|
||||||
|
"strength_multiplier": obj.strength_multiplier,
|
||||||
|
"magic_multiplier": obj.magic_multiplier,
|
||||||
|
"shadow_multiplier": obj.shadow_multiplier,
|
||||||
|
"holy_multiplier": obj.holy_multiplier,
|
||||||
|
"soldier_multiplier": obj.soldier_multiplier,
|
||||||
|
"worker_multiplier": obj.worker_multiplier,
|
||||||
|
"monster_multiplier": obj.monster_multiplier,
|
||||||
|
"citizen_multiplier": obj.citizen_multiplier,
|
||||||
|
"domain_multiplier": obj.domain_multiplier,
|
||||||
|
"boss_multiplier": obj.boss_multiplier,
|
||||||
|
"minion_multiplier": obj.minion_multiplier,
|
||||||
|
"beast_multiplier": obj.beast_multiplier,
|
||||||
|
"titan_multiplier": obj.titan_multiplier,
|
||||||
|
"expansion": obj.expansion,
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Monster):
|
||||||
|
return {
|
||||||
|
**super().default(obj),
|
||||||
|
"monster_id": obj.monster_id,
|
||||||
|
"name": obj.name,
|
||||||
|
"area": obj.area,
|
||||||
|
"monster_type": obj.monster_type,
|
||||||
|
"order": obj.order,
|
||||||
|
"strength_cost": obj.strength_cost,
|
||||||
|
"magic_cost": obj.magic_cost,
|
||||||
|
"vp_reward": obj.vp_reward,
|
||||||
|
"gold_reward": obj.gold_reward,
|
||||||
|
"strength_reward": obj.strength_reward,
|
||||||
|
"magic_reward": obj.magic_reward,
|
||||||
|
"has_special_reward": obj.has_special_reward,
|
||||||
|
"special_reward": obj.special_reward,
|
||||||
|
"has_special_cost": obj.has_special_cost,
|
||||||
|
"special_cost": obj.special_cost,
|
||||||
|
"is_extra": obj.is_extra,
|
||||||
|
"expansion": obj.expansion,
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Starter):
|
||||||
|
return {
|
||||||
|
**super().default(obj),
|
||||||
|
"starter_id": obj.starter_id,
|
||||||
|
"name": obj.name,
|
||||||
|
"roll_match1": obj.rollMatch1,
|
||||||
|
"roll_match2": obj.rollMatch2,
|
||||||
|
"gold_payout_on_turn": obj.goldPayoutOnTurn,
|
||||||
|
"gold_payout_off_turn": obj.goldPayoutOffTurn,
|
||||||
|
"strength_payout_on_turn": obj.strengthPayoutOnTurn,
|
||||||
|
"strength_payout_off_turn": obj.strengthPayoutOffTurn,
|
||||||
|
"magic_payout_on_turn": obj.magicPayoutOnTurn,
|
||||||
|
"magic_payout_off_turn": obj.magicPayoutOffTurn,
|
||||||
|
"has_special_payout_on_turn": obj.hasSpecialPayoutOnTurn,
|
||||||
|
"has_special_payout_off_turn": obj.hasSpecialPayoutOffTurn,
|
||||||
|
"special_payout_on_turn": obj.specialPayoutOnTurn,
|
||||||
|
"special_payout_off_turn": obj.specialPayoutOffTurn,
|
||||||
|
"expansion": obj.expansion,
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Citizen):
|
||||||
|
return {
|
||||||
|
**super().default(obj),
|
||||||
|
"citizen_id": obj.citizen_id,
|
||||||
|
"name": obj.name,
|
||||||
|
"gold_cost": obj.gold_cost,
|
||||||
|
"roll_match1": obj.roll_match1,
|
||||||
|
"roll_match2": obj.roll_match2,
|
||||||
|
"shadow_count": obj.shadow_count,
|
||||||
|
"holy_count": obj.holy_count,
|
||||||
|
"soldier_count": obj.soldier_count,
|
||||||
|
"worker_count": obj.worker_count,
|
||||||
|
"gold_payout_on_turn": obj.gold_payout_on_turn,
|
||||||
|
"gold_payout_off_turn": obj.gold_payout_off_turn,
|
||||||
|
"strength_payout_on_turn": obj.strength_payout_on_turn,
|
||||||
|
"strength_payout_off_turn": obj.strength_payout_off_turn,
|
||||||
|
"magic_payout_on_turn": obj.magic_payout_on_turn,
|
||||||
|
"magic_payout_off_turn": obj.magic_payout_off_turn,
|
||||||
|
"has_special_payout_on_turn": obj.has_special_payout_on_turn,
|
||||||
|
"has_special_payout_off_turn": obj.has_special_payout_off_turn,
|
||||||
|
"special_payout_on_turn": obj.special_payout_on_turn,
|
||||||
|
"special_payout_off_turn": obj.special_payout_off_turn,
|
||||||
|
"special_citizen": obj.special_citizen,
|
||||||
|
"expansion": obj.expansion,
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Domain):
|
||||||
|
return {
|
||||||
|
'domain_id': obj.domain_id,
|
||||||
|
'name': obj.name,
|
||||||
|
'gold_cost': obj.gold_cost,
|
||||||
|
'shadow_count': obj.shadow_count,
|
||||||
|
'holy_count': obj.holy_count,
|
||||||
|
'soldier_count': obj.soldier_count,
|
||||||
|
'worker_count': obj.worker_count,
|
||||||
|
'vp_reward': obj.vp_reward,
|
||||||
|
'has_activation_effect': obj.has_activation_effect,
|
||||||
|
'has_passive_effect': obj.has_passive_effect,
|
||||||
|
'passive_effect': obj.passive_effect,
|
||||||
|
'activation_effect': obj.activation_effect,
|
||||||
|
'text': obj.text,
|
||||||
|
'expansion': obj.expansion
|
||||||
|
}
|
||||||
|
elif isinstance(obj, Game):
|
||||||
|
return {
|
||||||
|
"game_id": obj.game_id,
|
||||||
|
"player_count": obj.player_count,
|
||||||
|
"preset": obj.preset,
|
||||||
|
"number_of_dukes": obj.number_of_dukes,
|
||||||
|
"player_list": obj.player_list,
|
||||||
|
"citizen_grid": obj.citizen_grid,
|
||||||
|
"domain_grid": obj.domain_grid,
|
||||||
|
"monster_grid": obj.monster_grid,
|
||||||
|
"duke_stack": obj.duke_stack,
|
||||||
|
"domain_stack": obj.domain_stack,
|
||||||
|
"citizen_stack": obj.citizen_stack,
|
||||||
|
"monster_stack": obj.monster_stack,
|
||||||
|
"starter_stack": obj.starter_stack,
|
||||||
|
"graveyard": obj.graveyard,
|
||||||
|
"die_one": obj.die_one,
|
||||||
|
"die_two": obj.die_two,
|
||||||
|
"die_sum": obj.die_sum,
|
||||||
|
"exhausted_count": obj.exhausted_count
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return super().default(obj)
|
||||||
|
|
||||||
|
|||||||
30
server.py
30
server.py
@@ -11,7 +11,7 @@ class ServerVCKO:
|
|||||||
self.host = socket.gethostname()
|
self.host = socket.gethostname()
|
||||||
self.server_socket = socket.socket()
|
self.server_socket = socket.socket()
|
||||||
self.server_socket.bind((self.host, Constants.port))
|
self.server_socket.bind((self.host, Constants.port))
|
||||||
self.game_list = []
|
self.game_dict = {}
|
||||||
self.lobby = []
|
self.lobby = []
|
||||||
self.gamers = []
|
self.gamers = []
|
||||||
|
|
||||||
@@ -24,13 +24,13 @@ class ServerVCKO:
|
|||||||
msg_length = int(msg_length)
|
msg_length = int(msg_length)
|
||||||
msg = conn.recv(msg_length).decode(Constants.text_format)
|
msg = conn.recv(msg_length).decode(Constants.text_format)
|
||||||
first_word = msg.split()[0]
|
first_word = msg.split()[0]
|
||||||
|
full_command = msg.split()
|
||||||
match first_word:
|
match first_word:
|
||||||
case "connection_check":
|
case "connection_check":
|
||||||
connected = False
|
connected = False
|
||||||
conn.send("received".encode(Constants.text_format))
|
conn.send("received".encode(Constants.text_format))
|
||||||
case "lobby":
|
case "lobby":
|
||||||
connected = False
|
connected = False
|
||||||
full_command = msg.split()
|
|
||||||
if full_command[1] == "join" and len(full_command) > 2:
|
if full_command[1] == "join" and len(full_command) > 2:
|
||||||
joining_player_name = ' '.join(full_command[2:])
|
joining_player_name = ' '.join(full_command[2:])
|
||||||
joining_player_id = shortuuid.uuid()
|
joining_player_id = shortuuid.uuid()
|
||||||
@@ -80,6 +80,9 @@ class ServerVCKO:
|
|||||||
players_to_remove.append(player)
|
players_to_remove.append(player)
|
||||||
for player in players_to_remove:
|
for player in players_to_remove:
|
||||||
self.lobby.remove(player)
|
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}"
|
message = f"game joined {new_game_id}"
|
||||||
conn.send(message.encode(Constants.text_format))
|
conn.send(message.encode(Constants.text_format))
|
||||||
else:
|
else:
|
||||||
@@ -91,6 +94,20 @@ class ServerVCKO:
|
|||||||
self.send_lobby_state(conn)
|
self.send_lobby_state(conn)
|
||||||
else:
|
else:
|
||||||
conn.send("invalid message".encode(Constants.text_format))
|
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 _:
|
case _:
|
||||||
connected = False
|
connected = False
|
||||||
conn.send("invalid message".encode(Constants.text_format))
|
conn.send("invalid message".encode(Constants.text_format))
|
||||||
@@ -118,6 +135,15 @@ class ServerVCKO:
|
|||||||
response = f"lobby state {json.dumps(lobby_data)}"
|
response = f"lobby state {json.dumps(lobby_data)}"
|
||||||
conn.send(response.encode(Constants.text_format))
|
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:
|
class LobbyMember:
|
||||||
def __init__(self, player_name, player_id):
|
def __init__(self, player_name, player_id):
|
||||||
|
|||||||
Reference in New Issue
Block a user