added auto kick from lobby after 30 seconds of not doing a status_check

This commit is contained in:
2023-04-29 16:08:57 -07:00
parent cc91060ded
commit 23716a7bc7
3 changed files with 183 additions and 115 deletions

View File

@@ -2,6 +2,7 @@ import wx
import socket import socket
from constants import * from constants import *
import json import json
import pprint
class ClientVCKO(wx.App): class ClientVCKO(wx.App):
@@ -18,6 +19,7 @@ class ClientVCKO(wx.App):
self.lobby_frame = LobbyFrame(self) self.lobby_frame = LobbyFrame(self)
self.game_frame = GameFrame(self) self.game_frame = GameFrame(self)
self.last_lobby_state = "" self.last_lobby_state = ""
self.last_game_state = ""
self.debug_frame.set_connection_status() self.debug_frame.set_connection_status()
return True return True
@@ -45,6 +47,12 @@ class ClientVCKO(wx.App):
self.in_game = True self.in_game = True
self.in_lobby = False self.in_lobby = False
self.lobby_frame.enter_game() self.lobby_frame.enter_game()
elif full_command[1] == "state":
json_response = ' '.join(full_command[2:])
new_game_state = json.loads(json_response)
if new_game_state == self.last_game_state:
return
self.last_game_state = new_game_state
def update_lobby_status(self): def update_lobby_status(self):
return self.in_lobby return self.in_lobby
@@ -55,21 +63,52 @@ class GameFrame(wx.Frame):
super().__init__(parent=None, title='VCK Online', size=Constants.default_window_size) super().__init__(parent=None, title='VCK Online', size=Constants.default_window_size)
self.app = app self.app = app
self.panel = wx.Panel(self) self.panel = wx.Panel(self)
# Create a static box sizer with padding
vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, label=""), wx.VERTICAL)
vbox.AddSpacer(10) # Add a bit of padding at the top
# Wrap the list control widget inside a scrolled window
sw = wx.ScrolledWindow(vbox.GetStaticBox(), style=wx.VSCROLL)
sw.SetScrollbars(1, 1, 1, 1) # Show the scrollbars
self.game_state_list = wx.ListCtrl(sw, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
sw.SetSizer(wx.BoxSizer(wx.VERTICAL))
sw.GetSizer().Add(self.game_state_list, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
vbox.Add(sw, proportion=1, flag=wx.EXPAND | wx.ALL, border=10) # Add the scrolled window to the sizer
vbox.AddSpacer(10) # Add a bit of padding at the bottom
# Set the sizer for the panel
self.panel.SetSizer(vbox)
self.SetMinSize(Constants.minimum_window_size) self.SetMinSize(Constants.minimum_window_size)
self.last_lobby_state = [] self.last_pretty_game_state = ""
self.timer_interval = 500
self.timer = wx.Timer(self) self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.get_game_status, self.timer) self.Bind(wx.EVT_TIMER, self.get_game_status, self.timer)
self.timer.Start(500) self.timer.Start(self.timer_interval)
def get_game_status(self, event=None): def get_game_status(self, event=None):
if connection_check() and self.app.in_game: if connection_check() and self.app.in_game:
self.app.parse_response(send(f"game get_status {self.app.game_id}")) self.app.parse_response(send(f"game get_status {self.app.game_id}"))
if self.app.lobby == self.last_lobby_state: new_pretty_game_state = pprint.pformat(self.app.last_game_state)
# If the current lobby state is the same as the last one, don't update the list control if self.last_pretty_game_state == new_pretty_game_state:
# If the current game state is the same as the last one, don't update the list control
if self.timer_interval < 9500:
self.timer_interval += 500
self.timer.Start(self.timer_interval)
return return
self.game_state_list.ClearAll()
# Save the new lobby state self.game_state_list.InsertColumn(0, "Game State")
self.last_lobby_state = self.app.lobby for idx, state in enumerate(new_pretty_game_state.split('\n')):
self.game_state_list.InsertItem(idx, state.strip())
self.game_state_list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
# Save the new game state
self.last_pretty_game_state = new_pretty_game_state
self.timer_interval = 500
else:
self.timer.Stop()
class LobbyFrame(wx.Frame): class LobbyFrame(wx.Frame):
@@ -99,9 +138,10 @@ class LobbyFrame(wx.Frame):
self.Bind(wx.EVT_SIZE, self.on_size) self.Bind(wx.EVT_SIZE, self.on_size)
self.Bind(wx.EVT_CLOSE, self.on_close) self.Bind(wx.EVT_CLOSE, self.on_close)
self.timer_interval = 500
self.timer = wx.Timer(self) self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.get_lobby_status, self.timer) self.Bind(wx.EVT_TIMER, self.get_lobby_status, self.timer)
self.timer.Start(500) self.timer.Start(self.timer_interval)
def on_size(self, event): def on_size(self, event):
# Calculate the width of each column based on the width of the list control # Calculate the width of each column based on the width of the list control
@@ -116,6 +156,9 @@ class LobbyFrame(wx.Frame):
self.app.parse_response(send(f"lobby get_status {self.app.player_id}")) self.app.parse_response(send(f"lobby get_status {self.app.player_id}"))
if self.app.lobby == self.last_lobby_state: 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 # If the current lobby state is the same as the last one, don't update the list control
if self.timer_interval < 9500:
self.timer_interval += 500
self.timer.Start(self.timer_interval)
return return
self.list_ctrl.DeleteAllItems() self.list_ctrl.DeleteAllItems()
for index, player in enumerate(self.app.lobby): for index, player in enumerate(self.app.lobby):
@@ -266,7 +309,6 @@ def connection_check():
def _send(msg, input_socket): def _send(msg, input_socket):
message = msg.encode(Constants.text_format) message = msg.encode(Constants.text_format)
msg_length = len(message) msg_length = len(message)
print(msg_length)
send_length = str(msg_length).encode(Constants.text_format) send_length = str(msg_length).encode(Constants.text_format)
send_length += b' ' * (Constants.header_size - len(send_length)) send_length += b' ' * (Constants.header_size - len(send_length))
input_socket.send(send_length) input_socket.send(send_length)

224
common.py
View File

@@ -14,6 +14,13 @@ class Card:
self.is_visible = False self.is_visible = False
self.is_accessible = False self.is_accessible = False
def to_dict(self):
return {
"name": self.name,
"is_visible": self.is_visible,
"is_accessible": self.is_accessible,
}
def toggle_visibility(self, toggle: bool = True): def toggle_visibility(self, toggle: bool = True):
self.is_visible = toggle self.is_visible = toggle
@@ -74,6 +81,25 @@ class Starter(Card):
self.specialPayoutOffTurn = special_payout_off_turn self.specialPayoutOffTurn = special_payout_off_turn
self.expansion = expansion self.expansion = expansion
def to_dict(self):
return {
"starter_id": self.starter_id,
"name": self.name,
"roll_match1": self.rollMatch1,
"roll_match2": self.rollMatch2,
"gold_payout_on_turn": self.goldPayoutOnTurn,
"gold_payout_off_turn": self.goldPayoutOffTurn,
"strength_payout_on_turn": self.strengthPayoutOnTurn,
"strength_payout_off_turn": self.strengthPayoutOffTurn,
"magic_payout_on_turn": self.magicPayoutOnTurn,
"magic_payout_off_turn": self.magicPayoutOffTurn,
"has_special_payout_on_turn": self.hasSpecialPayoutOnTurn,
"has_special_payout_off_turn": self.hasSpecialPayoutOffTurn,
"special_payout_on_turn": self.specialPayoutOnTurn,
"special_payout_off_turn": self.specialPayoutOffTurn,
"expansion": self.expansion
}
class Citizen(Card): class Citizen(Card):
def __init__(self, citizen_id, name, gold_cost, roll_match1, roll_match2, shadow_count, holy_count, soldier_count, def __init__(self, citizen_id, name, gold_cost, roll_match1, roll_match2, shadow_count, holy_count, soldier_count,
@@ -104,6 +130,30 @@ class Citizen(Card):
self.special_citizen = special_citizen self.special_citizen = special_citizen
self.expansion = expansion self.expansion = expansion
def to_dict(self):
base_dict = super().to_dict()
return {**base_dict,
"citizen_id": self.citizen_id,
"gold_cost": self.gold_cost,
"roll_match1": self.roll_match1,
"roll_match2": self.roll_match2,
"shadow_count": self.shadow_count,
"holy_count": self.holy_count,
"soldier_count": self.soldier_count,
"worker_count": self.worker_count,
"gold_payout_on_turn": self.gold_payout_on_turn,
"gold_payout_off_turn": self.gold_payout_off_turn,
"strength_payout_on_turn": self.strength_payout_on_turn,
"strength_payout_off_turn": self.strength_payout_off_turn,
"magic_payout_on_turn": self.magic_payout_on_turn,
"magic_payout_off_turn": self.magic_payout_off_turn,
"has_special_payout_on_turn": self.has_special_payout_on_turn,
"has_special_payout_off_turn": self.has_special_payout_off_turn,
"special_payout_on_turn": self.special_payout_on_turn,
"special_payout_off_turn": self.special_payout_off_turn,
"special_citizen": self.special_citizen,
"expansion": self.expansion}
class Domain(Card): class Domain(Card):
def __init__(self, domain_id, name, gold_cost, shadow_count, holy_count, soldier_count, worker_count, vp_reward, def __init__(self, domain_id, name, gold_cost, shadow_count, holy_count, soldier_count, worker_count, vp_reward,
@@ -124,6 +174,25 @@ class Domain(Card):
self.text = text self.text = text
self.expansion = expansion self.expansion = expansion
def to_dict(self):
return {
**super().to_dict(),
"domain_id": self.domain_id,
"name": self.name,
"gold_cost": self.gold_cost,
"shadow_count": self.shadow_count,
"holy_count": self.holy_count,
"soldier_count": self.soldier_count,
"worker_count": self.worker_count,
"vp_reward": self.vp_reward,
"has_activation_effect": self.has_activation_effect,
"has_passive_effect": self.has_passive_effect,
"passive_effect": self.passive_effect,
"activation_effect": self.activation_effect,
"text": self.text,
"expansion": self.expansion
}
class Monster(Card): class Monster(Card):
def __init__(self, monster_id, name, area, monster_type, order, strength_cost, magic_cost, vp_reward, gold_reward, def __init__(self, monster_id, name, area, monster_type, order, strength_cost, magic_cost, vp_reward, gold_reward,
@@ -148,6 +217,28 @@ class Monster(Card):
self.is_extra = is_extra self.is_extra = is_extra
self.expansion = expansion self.expansion = expansion
def to_dict(self):
card_dict = super().to_dict()
monster_dict = {
"monster_id": self.monster_id,
"area": self.area,
"monster_type": self.monster_type,
"order": self.order,
"strength_cost": self.strength_cost,
"magic_cost": self.magic_cost,
"vp_reward": self.vp_reward,
"gold_reward": self.gold_reward,
"strength_reward": self.strength_reward,
"magic_reward": self.magic_reward,
"has_special_reward": self.has_special_reward,
"special_reward": self.special_reward,
"has_special_cost": self.has_special_cost,
"special_cost": self.special_cost,
"is_extra": self.is_extra,
"expansion": self.expansion,
}
return {**card_dict, **monster_dict}
def add_strength_cost(self, added_strength): def add_strength_cost(self, added_strength):
self.strength_cost = self.strength_cost + added_strength self.strength_cost = self.strength_cost + added_strength
@@ -178,6 +269,27 @@ class Duke(Card):
self.titan_multiplier = titan_mult self.titan_multiplier = titan_mult
self.expansion = expansion self.expansion = expansion
def to_dict(self):
return {
**super().to_dict(),
"duke_id": self.duke_id,
"gold_multiplier": self.gold_multiplier,
"strength_multiplier": self.strength_multiplier,
"magic_multiplier": self.magic_multiplier,
"shadow_multiplier": self.shadow_multiplier,
"holy_multiplier": self.holy_multiplier,
"soldier_multiplier": self.soldier_multiplier,
"worker_multiplier": self.worker_multiplier,
"monster_multiplier": self.monster_multiplier,
"citizen_multiplier": self.citizen_multiplier,
"domain_multiplier": self.domain_multiplier,
"boss_multiplier": self.boss_multiplier,
"minion_multiplier": self.minion_multiplier,
"beast_multiplier": self.beast_multiplier,
"titan_multiplier": self.titan_multiplier,
"expansion": self.expansion
}
class Game: class Game:
def __init__(self, game_id, player_list_from_lobby, preset="shuffled", number_of_dukes=2): def __init__(self, game_id, player_list_from_lobby, preset="shuffled", number_of_dukes=2):
@@ -511,13 +623,7 @@ class Game:
class GameObjectEncoder(JSONEncoder): class GameObjectEncoder(JSONEncoder):
def default(self, obj): def default(self, obj):
if isinstance(obj, Card): if isinstance(obj, Player):
return {
"name": obj.name,
"is_visible": obj.is_visible,
"is_accessible": obj.is_accessible,
}
elif isinstance(obj, Player):
return { return {
'player_id': obj.player_id, 'player_id': obj.player_id,
'name': obj.name, 'name': obj.name,
@@ -536,107 +642,15 @@ class GameObjectEncoder(JSONEncoder):
'worker_count': obj.worker_count 'worker_count': obj.worker_count
} }
elif isinstance(obj, Duke): elif isinstance(obj, Duke):
return { return obj.to_dict()
**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): elif isinstance(obj, Monster):
return { return obj.to_dict()
**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): elif isinstance(obj, Starter):
return { return obj.to_dict()
**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): elif isinstance(obj, Citizen):
return { return obj.to_dict()
**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): elif isinstance(obj, Domain):
return { return obj.to_dict()
'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): elif isinstance(obj, Game):
return { return {
"game_id": obj.game_id, "game_id": obj.game_id,
@@ -644,9 +658,9 @@ class GameObjectEncoder(JSONEncoder):
"preset": obj.preset, "preset": obj.preset,
"number_of_dukes": obj.number_of_dukes, "number_of_dukes": obj.number_of_dukes,
"player_list": obj.player_list, "player_list": obj.player_list,
"monster_grid": obj.monster_grid,
"citizen_grid": obj.citizen_grid, "citizen_grid": obj.citizen_grid,
"domain_grid": obj.domain_grid, "domain_grid": obj.domain_grid,
"monster_grid": obj.monster_grid,
"duke_stack": obj.duke_stack, "duke_stack": obj.duke_stack,
"domain_stack": obj.domain_stack, "domain_stack": obj.domain_stack,
"citizen_stack": obj.citizen_stack, "citizen_stack": obj.citizen_stack,

View File

@@ -15,6 +15,16 @@ class ServerVCKO:
self.lobby = [] self.lobby = []
self.gamers = [] self.gamers = []
# Start the thread to remove inactive players
self.inactive_player_thread = threading.Thread(target=self.remove_inactive_players, daemon=True)
self.inactive_player_thread.start()
def remove_inactive_players(self):
while True:
current_time = time.time()
self.lobby = [player for player in self.lobby if current_time - player.last_active_time <= 60]
time.sleep(10) # check for inactive players every 10 seconds
def handle_client(self, conn, addr): def handle_client(self, conn, addr):
print(f"Connection from: {addr}") print(f"Connection from: {addr}")
connected = True connected = True
@@ -49,6 +59,7 @@ class ServerVCKO:
found = False found = False
for player in self.lobby: for player in self.lobby:
if full_command[2] == player.player_id: if full_command[2] == player.player_id:
player.last_active_time = time.time() # update last active time
self.send_lobby_state(conn) self.send_lobby_state(conn)
found = True found = True
for player in self.gamers: for player in self.gamers:
@@ -80,7 +91,8 @@ 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) # START GAME
new_game = Game(new_game_id, self.gamers, "base1", 2)
self.game_dict[new_game.game_id] = new_game self.game_dict[new_game.game_id] = new_game
print(f"size of game dict: {len(self.game_dict)}") print(f"size of game dict: {len(self.game_dict)}")
message = f"game joined {new_game_id}" message = f"game joined {new_game_id}"