added auto kick from lobby after 30 seconds of not doing a status_check
This commit is contained in:
60
client.py
60
client.py
@@ -2,6 +2,7 @@ import wx
|
||||
import socket
|
||||
from constants import *
|
||||
import json
|
||||
import pprint
|
||||
|
||||
|
||||
class ClientVCKO(wx.App):
|
||||
@@ -18,6 +19,7 @@ class ClientVCKO(wx.App):
|
||||
self.lobby_frame = LobbyFrame(self)
|
||||
self.game_frame = GameFrame(self)
|
||||
self.last_lobby_state = ""
|
||||
self.last_game_state = ""
|
||||
self.debug_frame.set_connection_status()
|
||||
return True
|
||||
|
||||
@@ -45,6 +47,12 @@ class ClientVCKO(wx.App):
|
||||
self.in_game = True
|
||||
self.in_lobby = False
|
||||
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):
|
||||
return self.in_lobby
|
||||
@@ -55,21 +63,52 @@ class GameFrame(wx.Frame):
|
||||
super().__init__(parent=None, title='VCK Online', size=Constants.default_window_size)
|
||||
self.app = app
|
||||
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.last_lobby_state = []
|
||||
self.last_pretty_game_state = ""
|
||||
self.timer_interval = 500
|
||||
self.timer = wx.Timer(self)
|
||||
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):
|
||||
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
|
||||
new_pretty_game_state = pprint.pformat(self.app.last_game_state)
|
||||
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
|
||||
|
||||
# Save the new lobby state
|
||||
self.last_lobby_state = self.app.lobby
|
||||
self.game_state_list.ClearAll()
|
||||
self.game_state_list.InsertColumn(0, "Game State")
|
||||
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):
|
||||
@@ -99,9 +138,10 @@ class LobbyFrame(wx.Frame):
|
||||
self.Bind(wx.EVT_SIZE, self.on_size)
|
||||
self.Bind(wx.EVT_CLOSE, self.on_close)
|
||||
|
||||
self.timer_interval = 500
|
||||
self.timer = wx.Timer(self)
|
||||
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):
|
||||
# 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}"))
|
||||
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 self.timer_interval < 9500:
|
||||
self.timer_interval += 500
|
||||
self.timer.Start(self.timer_interval)
|
||||
return
|
||||
self.list_ctrl.DeleteAllItems()
|
||||
for index, player in enumerate(self.app.lobby):
|
||||
@@ -266,7 +309,6 @@ def connection_check():
|
||||
def _send(msg, input_socket):
|
||||
message = msg.encode(Constants.text_format)
|
||||
msg_length = len(message)
|
||||
print(msg_length)
|
||||
send_length = str(msg_length).encode(Constants.text_format)
|
||||
send_length += b' ' * (Constants.header_size - len(send_length))
|
||||
input_socket.send(send_length)
|
||||
|
||||
224
common.py
224
common.py
@@ -14,6 +14,13 @@ class Card:
|
||||
self.is_visible = 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):
|
||||
self.is_visible = toggle
|
||||
|
||||
@@ -74,6 +81,25 @@ class Starter(Card):
|
||||
self.specialPayoutOffTurn = special_payout_off_turn
|
||||
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):
|
||||
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.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):
|
||||
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.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):
|
||||
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.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):
|
||||
self.strength_cost = self.strength_cost + added_strength
|
||||
|
||||
@@ -178,6 +269,27 @@ class Duke(Card):
|
||||
self.titan_multiplier = titan_mult
|
||||
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:
|
||||
def __init__(self, game_id, player_list_from_lobby, preset="shuffled", number_of_dukes=2):
|
||||
@@ -511,13 +623,7 @@ class Game:
|
||||
|
||||
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):
|
||||
if isinstance(obj, Player):
|
||||
return {
|
||||
'player_id': obj.player_id,
|
||||
'name': obj.name,
|
||||
@@ -536,107 +642,15 @@ class GameObjectEncoder(JSONEncoder):
|
||||
'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,
|
||||
}
|
||||
return obj.to_dict()
|
||||
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,
|
||||
}
|
||||
return obj.to_dict()
|
||||
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,
|
||||
}
|
||||
return obj.to_dict()
|
||||
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,
|
||||
}
|
||||
return obj.to_dict()
|
||||
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
|
||||
}
|
||||
return obj.to_dict()
|
||||
elif isinstance(obj, Game):
|
||||
return {
|
||||
"game_id": obj.game_id,
|
||||
@@ -644,9 +658,9 @@ class GameObjectEncoder(JSONEncoder):
|
||||
"preset": obj.preset,
|
||||
"number_of_dukes": obj.number_of_dukes,
|
||||
"player_list": obj.player_list,
|
||||
"monster_grid": obj.monster_grid,
|
||||
"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,
|
||||
|
||||
14
server.py
14
server.py
@@ -15,6 +15,16 @@ class ServerVCKO:
|
||||
self.lobby = []
|
||||
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):
|
||||
print(f"Connection from: {addr}")
|
||||
connected = True
|
||||
@@ -49,6 +59,7 @@ class ServerVCKO:
|
||||
found = False
|
||||
for player in self.lobby:
|
||||
if full_command[2] == player.player_id:
|
||||
player.last_active_time = time.time() # update last active time
|
||||
self.send_lobby_state(conn)
|
||||
found = True
|
||||
for player in self.gamers:
|
||||
@@ -80,7 +91,8 @@ class ServerVCKO:
|
||||
players_to_remove.append(player)
|
||||
for player in players_to_remove:
|
||||
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
|
||||
print(f"size of game dict: {len(self.game_dict)}")
|
||||
message = f"game joined {new_game_id}"
|
||||
|
||||
Reference in New Issue
Block a user