Merge pull request #412 from albertoxamin/test-save

Add some form of persistency during restarts
This commit is contained in:
Alberto Xamin 2023-01-23 10:36:27 +00:00 committed by GitHub
commit 9be6b0f387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 567 additions and 349 deletions

1
.gitignore vendored
View File

@ -141,3 +141,4 @@ frontend/package-lock.json
bang-workspace.code-workspace bang-workspace.code-workspace
.vscode/ .vscode/
backend/save/*

View File

@ -20,8 +20,11 @@ COPY --from=pybuilder /code /dist
# copy the frontend static files from the builder # copy the frontend static files from the builder
COPY --from=builder ./dist /dist/ COPY --from=builder ./dist /dist/
WORKDIR /dist WORKDIR /dist
# create dir for save
RUN mkdir save
EXPOSE 5001 EXPOSE 5001
ENV PATH=/root/.local/bin:${PATH} ENV PATH=/root/.local/bin:${PATH}
VOLUME /dist/save
ENTRYPOINT ["python", "/dist/server.py"] ENTRYPOINT ["python", "/dist/server.py"]

View File

@ -4,6 +4,7 @@ import bang.expansions.high_noon.card_events as ceh
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from enum import IntEnum from enum import IntEnum
import bang.roles as r import bang.roles as r
from globals import G
class Suit(IntEnum): class Suit(IntEnum):
DIAMONDS = 0 # ♦ DIAMONDS = 0 # ♦
@ -84,10 +85,10 @@ class Card(ABC):
player.equipment.append(self) player.equipment.append(self)
self.can_be_used_now = False self.can_be_used_now = False
if against: if against:
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_play_card_against|{player.name}|{self.name}|{against}') data=f'_play_card_against|{player.name}|{self.name}|{against}')
else: else:
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_play_card|{player.name}|{self.name}') data=f'_play_card|{player.name}|{self.name}')
return True return True
@ -154,7 +155,7 @@ class Prigione(Card):
return False return False
if against != None and not isinstance(player.game.get_player_named(against).role, r.Sheriff): if against != None and not isinstance(player.game.get_player_named(against).role, r.Sheriff):
self.can_be_used_now = False self.can_be_used_now = False
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_play_card_against|{player.name}|{self.name}|{against}') data=f'_play_card_against|{player.name}|{self.name}|{against}')
player.game.get_player_named(against).equipment.append(self) player.game.get_player_named(against).equipment.append(self)
player.game.get_player_named(against).notify_self() player.game.get_player_named(against).notify_self()
@ -268,7 +269,7 @@ class Birra(Card):
player.lives = min(player.lives+1, player.max_lives) player.lives = min(player.lives+1, player.max_lives)
return True return True
elif len(player.game.get_alive_players()) == 2 or player.lives == player.max_lives: elif len(player.game.get_alive_players()) == 2 or player.lives == player.max_lives:
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_spilled_beer|{player.name}|{self.name}') data=f'_spilled_beer|{player.name}|{self.name}')
return True return True
return False return False
@ -305,7 +306,7 @@ class Diligenza(Card):
# self.desc_eng = "Draw 2 cards from the deck." # self.desc_eng = "Draw 2 cards from the deck."
def play_card(self, player, against, _with=None): def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_diligenza|{player.name}|{self.name}') data=f'_diligenza|{player.name}|{self.name}')
for i in range(2): for i in range(2):
player.hand.append(player.game.deck.draw(True)) player.hand.append(player.game.deck.draw(True))
@ -382,7 +383,7 @@ class Mancato(Card):
return False return False
if player.game.check_event(ceh.Sermone): if player.game.check_event(ceh.Sermone):
return False return False
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_special_calamity|{player.name}|{self.name}|{against}') data=f'_special_calamity|{player.name}|{self.name}|{against}')
player.bang_used += 1 player.bang_used += 1
player.has_played_bang = True if not player.game.check_event(ceh.Sparatoria) else player.bang_used > 1 player.has_played_bang = True if not player.game.check_event(ceh.Sparatoria) else player.bang_used > 1
@ -421,7 +422,7 @@ class Saloon(Card):
self.alt_text = "👥🍺" self.alt_text = "👥🍺"
def play_card(self, player, against, _with=None): def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_saloon|{player.name}|{self.name}') data=f'_saloon|{player.name}|{self.name}')
for p in player.game.get_alive_players(): for p in player.game.get_alive_players():
p.lives = min(p.lives+1, p.max_lives) p.lives = min(p.lives+1, p.max_lives)
@ -438,7 +439,7 @@ class WellsFargo(Card):
self.alt_text = "🎴🎴🎴" self.alt_text = "🎴🎴🎴"
def play_card(self, player, against, _with=None): def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_wellsfargo|{player.name}|{self.name}') data=f'_wellsfargo|{player.name}|{self.name}')
for i in range(3): for i in range(3):
player.hand.append(player.game.deck.draw(True)) player.hand.append(player.game.deck.draw(True))

View File

@ -1,6 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from bang.expansions import * from bang.expansions import *
from typing import List from typing import List
from globals import G
class Character(ABC): class Character(ABC):
def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0, pick_mod: int = 0, desc: str = ''): def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0, pick_mod: int = 0, desc: str = ''):
@ -25,7 +26,7 @@ class Character(ABC):
import bang.expansions.high_noon.card_events as ceh import bang.expansions.high_noon.card_events as ceh
if player.game.check_event(ceh.Sbornia): if player.game.check_event(ceh.Sbornia):
return False return False
player.sio.emit('chat_message', room=player.game.name, data=f'_use_special|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_use_special|{player.name}|{self.name}')
return True return True
class BartCassidy(Character): class BartCassidy(Character):

View File

@ -1,5 +1,6 @@
from bang.cards import * from bang.cards import *
import bang.expansions.fistful_of_cards.card_events as ce import bang.expansions.fistful_of_cards.card_events as ce
from globals import G
class Binocolo(Mirino): class Binocolo(Mirino):
def __init__(self, suit, number): def __init__(self, suit, number):
@ -88,7 +89,7 @@ class Rissa(CatBalou):
player.event_type = 'rissa' player.event_type = 'rissa'
print(f'rissa targets: {player.rissa_targets}') print(f'rissa targets: {player.rissa_targets}')
super().play_card(player, against=player.rissa_targets.pop(0).name) super().play_card(player, against=player.rissa_targets.pop(0).name)
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}')
return True return True
return False return False
@ -123,7 +124,7 @@ class Tequila(Card):
def play_card(self, player, against, _with=None): def play_card(self, player, against, _with=None):
if against != None and _with != None: if against != None and _with != None:
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card_for|{player.name}|{self.name}|{against}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_for|{player.name}|{self.name}|{against}')
player.game.deck.scrap(_with) player.game.deck.scrap(_with)
player.game.get_player_named(against).lives = min(player.game.get_player_named(against).lives+1, player.game.get_player_named(against).max_lives) player.game.get_player_named(against).lives = min(player.game.get_player_named(against).lives+1, player.game.get_player_named(against).max_lives)
player.game.get_player_named(against).notify_self() player.game.get_player_named(against).notify_self()
@ -322,7 +323,7 @@ class CanCan(CatBalou):
def play_card(self, player, against, _with=None): def play_card(self, player, against, _with=None):
if self.can_be_used_now: if self.can_be_used_now:
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{player.name}|{self.name}|{against}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{player.name}|{self.name}|{against}')
return super().play_card(player, against) return super().play_card(player, against)
else: else:
if not self.is_duplicate_card(player) and not player.game.check_event(ce.IlGiudice): if not self.is_duplicate_card(player) and not player.game.check_event(ce.IlGiudice):

View File

@ -1,6 +1,7 @@
from bang.cards import * from bang.cards import *
import bang.roles as r import bang.roles as r
import bang.players as pl import bang.players as pl
from globals import G
class ShopCardKind(IntEnum): class ShopCardKind(IntEnum):
BROWN = 0 # Se lequipaggiamento ha il bordo marrone, applicane subito leffetto e poi scartalo. BROWN = 0 # Se lequipaggiamento ha il bordo marrone, applicane subito leffetto e poi scartalo.
@ -16,14 +17,14 @@ class ShopCard(Card):
def play_card(self, player, against, _with=None): def play_card(self, player, against, _with=None):
if self.kind == ShopCardKind.BROWN: if self.kind == ShopCardKind.BROWN:
player.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}')
return True return True
elif self.kind == ShopCardKind.BLACK: # equip it elif self.kind == ShopCardKind.BLACK: # equip it
if not self.is_duplicate_card(player): if not self.is_duplicate_card(player):
self.reset_card() self.reset_card()
self.can_be_used_now = True self.can_be_used_now = True
player.gold_rush_equipment.append(self) player.gold_rush_equipment.append(self)
player.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}')
return True return True
else: else:
return False return False
@ -102,7 +103,7 @@ class Rum(ShopCard):
num = 5 if player.character.check(player.game, c.LuckyDuke) else 4 num = 5 if player.character.check(player.game, c.LuckyDuke) else 4
for i in range(num): for i in range(num):
c = player.game.deck.pick_and_scrap() c = player.game.deck.pick_and_scrap()
player.sio.emit('chat_message', room=player.game.name, data=f'_flipped|{player.name}|{c.name}|{c.num_suit()}') G.sio.emit('chat_message', room=player.game.name, data=f'_flipped|{player.name}|{c.name}|{c.num_suit()}')
suits.add(c.suit) suits.add(c.suit)
player.lives = min(player.lives+len(suits), player.max_lives) player.lives = min(player.lives+len(suits), player.max_lives)
return super().play_card(player, against, _with) return super().play_card(player, against, _with)
@ -113,7 +114,7 @@ class UnionPacific(ShopCard):
self.icon = '🚆️' self.icon = '🚆️'
def play_card(self, player, against=None, _with=None): def play_card(self, player, against=None, _with=None):
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_UnionPacific|{player.name}|{self.name}') data=f'_UnionPacific|{player.name}|{self.name}')
for i in range(4): for i in range(4):
player.hand.append(player.game.deck.draw(True)) player.hand.append(player.game.deck.draw(True))
@ -162,7 +163,7 @@ class Ricercato(ShopCard):
self.can_target_self = True self.can_target_self = True
def play_card(self, player, against=None, _with=None): def play_card(self, player, against=None, _with=None):
player.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}')
player.available_cards = [{ player.available_cards = [{
'name': p.name, 'name': p.name,
'icon': p.role.icon if(player.game.initial_players == 3) else '🤠', 'icon': p.role.icon if(player.game.initial_players == 3) else '🤠',
@ -187,7 +188,7 @@ class Setaccio(ShopCard):
return super().play_card(player, against, _with) return super().play_card(player, against, _with)
else: else:
if player.gold_nuggets >= 1 and player.setaccio_count < 2: if player.gold_nuggets >= 1 and player.setaccio_count < 2:
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}')
player.gold_nuggets -= 1 player.gold_nuggets -= 1
player.setaccio_count += 1 player.setaccio_count += 1
player.hand.append(player.game.deck.draw(True)) player.hand.append(player.game.deck.draw(True))
@ -224,7 +225,7 @@ class Zaino(ShopCard):
return super().play_card(player, against, _with) return super().play_card(player, against, _with)
else: else:
if player.gold_nuggets >= 2: if player.gold_nuggets >= 2:
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}')
player.gold_nuggets -= 2 player.gold_nuggets -= 2
player.lives = min(player.lives + 1, player.max_lives) player.lives = min(player.lives + 1, player.max_lives)
player.notify_self() player.notify_self()

View File

@ -3,6 +3,7 @@ import bang.roles as r
import bang.players as pl import bang.players as pl
from bang.cards import Card, Suit, Bang, Mancato from bang.cards import Card, Suit, Bang, Mancato
import bang.expansions.fistful_of_cards.card_events as ce import bang.expansions.fistful_of_cards.card_events as ce
from globals import G
class Fantasma(Card): class Fantasma(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
@ -46,7 +47,7 @@ class SerpenteASonagli(Card):
return False return False
if against != None: if against != None:
self.can_be_used_now = False self.can_be_used_now = False
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_play_card_against|{player.name}|{self.name}|{against}') data=f'_play_card_against|{player.name}|{self.name}|{against}')
player.game.get_player_named(against).equipment.append(self) player.game.get_player_named(against).equipment.append(self)
player.game.get_player_named(against).notify_self() player.game.get_player_named(against).notify_self()
@ -69,7 +70,7 @@ class Taglia(Card):
return False return False
if against != None: if against != None:
self.can_be_used_now = False self.can_be_used_now = False
player.sio.emit('chat_message', room=player.game.name, G.sio.emit('chat_message', room=player.game.name,
data=f'_play_card_against|{player.name}|{self.name}|{against}') data=f'_play_card_against|{player.name}|{self.name}|{against}')
player.game.get_player_named(against).equipment.append(self) player.game.get_player_named(against).equipment.append(self)
player.game.get_player_named(against).notify_self() player.game.get_player_named(against).notify_self()

View File

@ -14,7 +14,10 @@ import bang.expansions.fistful_of_cards.card_events as ce
import bang.expansions.high_noon.card_events as ceh import bang.expansions.high_noon.card_events as ceh
import bang.expansions.gold_rush.shop_cards as grc import bang.expansions.gold_rush.shop_cards as grc
import bang.expansions.gold_rush.characters as grch import bang.expansions.gold_rush.characters as grch
import bang.expansions.the_valley_of_shadows.cards as tvosc
from metrics import Metrics from metrics import Metrics
from globals import G
debug_commands = [ debug_commands = [
{'cmd':'/debug', 'help':'Toggles the debug mode'}, {'cmd':'/debug', 'help':'Toggles the debug mode'},
@ -45,9 +48,8 @@ debug_commands = [
] ]
class Game: class Game:
def __init__(self, name, sio:socketio): def __init__(self, name):
super().__init__() super().__init__()
self.sio = sio
self.name = name self.name = name
self.players: List[pl.Player] = [] self.players: List[pl.Player] = []
self.spectators: List[pl.Player] = [] self.spectators: List[pl.Player] = []
@ -81,6 +83,7 @@ class Game:
self.rng = random.Random() self.rng = random.Random()
self.rpc_log = [] self.rpc_log = []
self.is_replay = False self.is_replay = False
self.replay_speed = 1
def shuffle_players(self): def shuffle_players(self):
if not self.started: if not self.started:
@ -117,13 +120,14 @@ class Game:
self.notify_room() self.notify_room()
def replay(self, log, speed=1.0, fast_forward = -1): def replay(self, log, speed=1.0, fast_forward = -1):
from tests.dummy_socket import DummySocket
self.players = [] self.players = []
self.is_hidden = True self.is_hidden = True
self.is_replay = True self.is_replay = True
self.replay_speed = speed self.replay_speed = speed
for i in range(len(log)-1): for i in range(len(log)-1):
print('replay:', i, 'of', len(log)-3, '->', log[i]) print('replay:', i, 'of', len(log)-3, '->', log[i])
if len(self.spectators) == 0:
break
if (log[i] == "@@@"): if (log[i] == "@@@"):
eventlet.sleep(10) eventlet.sleep(10)
if self.is_replay: if self.is_replay:
@ -134,7 +138,7 @@ class Game:
self.expansions = json.loads(cmd[4].replace("'",'"')) self.expansions = json.loads(cmd[4].replace("'",'"'))
pnames = json.loads(cmd[3].replace("'",'"')) pnames = json.loads(cmd[3].replace("'",'"'))
for p in pnames: for p in pnames:
self.add_player(pl.Player(p, p, DummySocket(self.sio), bot=False)) self.add_player(pl.Player(p, 'a', bot=False))
continue continue
if cmd[1] == 'start_game': if cmd[1] == 'start_game':
self.start_game(int(cmd[2])) self.start_game(int(cmd[2]))
@ -173,7 +177,7 @@ class Game:
if i == fast_forward: if i == fast_forward:
self.replay_speed = 1.0 self.replay_speed = 1.0
self.notify_room() self.notify_room()
eventlet.sleep(max(self.replay_speed, 0.1)) eventlet.sleep(max(self.replay_speed, 0.001))
eventlet.sleep(6) eventlet.sleep(6)
if self.is_replay: if self.is_replay:
self.reset() self.reset()
@ -181,7 +185,7 @@ class Game:
def notify_room(self, sid=None): def notify_room(self, sid=None):
if any((p.character == None for p in self.players)) or sid: if any((p.character == None for p in self.players)) or sid:
self.sio.emit('room', room=self.name if not sid else sid, data={ G.sio.emit('room', room=self.name if not sid else sid, data={
'name': self.name, 'name': self.name,
'started': self.started, 'started': self.started,
'players': [{'name':p.name, 'ready': p.character != None, 'is_bot': p.is_bot, 'avatar': p.avatar} for p in self.players], 'players': [{'name':p.name, 'ready': p.character != None, 'is_bot': p.is_bot, 'avatar': p.avatar} for p in self.players],
@ -192,12 +196,12 @@ class Game:
'available_expansions': self.available_expansions, 'available_expansions': self.available_expansions,
'is_replay': self.is_replay, 'is_replay': self.is_replay,
}) })
self.sio.emit('debug', room=self.name, data=self.debug) G.sio.emit('debug', room=self.name, data=self.debug)
if self.debug: if self.debug:
self.sio.emit('commands', room=self.name, data=[x for x in debug_commands if 'admin' not in x]) G.sio.emit('commands', room=self.name, data=[x for x in debug_commands if 'admin' not in x])
else: else:
self.sio.emit('commands', room=self.name, data=[{'cmd':'/debug', 'help':'Toggles the debug mode'}]) G.sio.emit('commands', room=self.name, data=[{'cmd':'/debug', 'help':'Toggles the debug mode'}])
self.sio.emit('spectators', room=self.name, data=len(self.spectators)) G.sio.emit('spectators', room=self.name, data=len(self.spectators))
def toggle_expansion(self, expansion_name): def toggle_expansion(self, expansion_name):
if not self.started: if not self.started:
@ -217,7 +221,7 @@ class Game:
self.notify_room() self.notify_room()
def feature_flags(self): def feature_flags(self):
if 'the_valley_of_shadows' not in self.expansions: if 'the_valley_of_shadows' not in self.expansions and 'the_valley_of_shadows' not in self.available_expansions :
self.available_expansions.append('the_valley_of_shadows') self.available_expansions.append('the_valley_of_shadows')
self.notify_room() self.notify_room()
@ -235,7 +239,7 @@ class Game:
self.players.append(player) self.players.append(player)
print(f'{self.name}: Added player {player.name} to game') print(f'{self.name}: Added player {player.name} to game')
self.notify_room() self.notify_room()
self.sio.emit('chat_message', room=self.name, data=f'_joined|{player.name}') G.sio.emit('chat_message', room=self.name, data=f'_joined|{player.name}')
def set_private(self): def set_private(self):
if not self.is_changing_pwd: if not self.is_changing_pwd:
@ -254,7 +258,7 @@ class Game:
if not any((p.character == None for p in self.players)): if not any((p.character == None for p in self.players)):
for i in range(len(self.players)): for i in range(len(self.players)):
print(self.name, self.players[i].name, self.players[i].character) print(self.name, self.players[i].name, self.players[i].character)
self.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}') G.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}')
self.players[i].prepare() self.players[i].prepare()
for k in range(self.players[i].max_lives): for k in range(self.players[i].max_lives):
self.players[i].hand.append(self.deck.draw()) self.players[i].hand.append(self.deck.draw())
@ -265,7 +269,7 @@ class Game:
for x in current_roles: for x in current_roles:
if (x not in cr): if (x not in cr):
cr += '|' +x + '|' + str(current_roles.count(x)) cr += '|' +x + '|' + str(current_roles.count(x))
self.sio.emit('chat_message', room=self.name, data=f'_allroles{cr}') G.sio.emit('chat_message', room=self.name, data=f'_allroles{cr}')
self.play_turn() self.play_turn()
def choose_characters(self): def choose_characters(self):
@ -286,8 +290,8 @@ class Game:
self.rpc_log = [f';players;{len(self.players)};{[p.name for p in self.players]};{self.expansions}', f';start_game;{SEED}'] self.rpc_log = [f';players;{len(self.players)};{[p.name for p in self.players]};{self.expansions}', f';start_game;{SEED}']
self.rng = random.Random(SEED) self.rng = random.Random(SEED)
self.players_map = {c.name: i for i, c in enumerate(self.players)} self.players_map = {c.name: i for i, c in enumerate(self.players)}
self.sio.emit('chat_message', room=self.name, data=f'_starting') G.sio.emit('chat_message', room=self.name, data=f'_starting')
self.sio.emit('start', room=self.name) G.sio.emit('start', room=self.name)
self.started = True self.started = True
self.someone_won = False self.someone_won = False
self.attack_in_progress = False self.attack_in_progress = False
@ -319,7 +323,7 @@ class Game:
self.players[i].set_role(available_roles[i]) self.players[i].set_role(available_roles[i])
if isinstance(available_roles[i], roles.Sheriff) or (len(available_roles) == 3 and isinstance(available_roles[i], roles.Vice)): if isinstance(available_roles[i], roles.Sheriff) or (len(available_roles) == 3 and isinstance(available_roles[i], roles.Vice)):
if isinstance(available_roles[i], roles.Sheriff): if isinstance(available_roles[i], roles.Sheriff):
self.sio.emit('chat_message', room=self.name, data=f'_sheriff|{self.players[i].name}') G.sio.emit('chat_message', room=self.name, data=f'_sheriff|{self.players[i].name}')
self.turn = i self.turn = i
self.players[i].notify_self() self.players[i].notify_self()
self.notify_event_card() self.notify_event_card()
@ -420,13 +424,13 @@ class Game:
self.players[self.turn].pending_action = pl.PendingAction.CHOOSE self.players[self.turn].pending_action = pl.PendingAction.CHOOSE
self.players[self.turn].choose_text = 'choose_card_to_get' self.players[self.turn].choose_text = 'choose_card_to_get'
self.players[self.turn].available_cards = self.available_cards self.players[self.turn].available_cards = self.available_cards
self.sio.emit('emporio', room=self.name, data=json.dumps( G.sio.emit('emporio', room=self.name, data=json.dumps(
{'name':self.players[self.turn].name,'cards': self.available_cards}, default=lambda o: o.__dict__)) {'name':self.players[self.turn].name,'cards': self.available_cards}, default=lambda o: o.__dict__))
self.players[self.turn].notify_self() self.players[self.turn].notify_self()
def respond_emporio(self, player, i): def respond_emporio(self, player, i):
card = self.available_cards.pop(i) card = self.available_cards.pop(i)
player.sio.emit('chat_message', room=self.name, data=f'_choose_emporio|{player.name}|{card.name}') G.sio.emit('chat_message', room=self.name, data=f'_choose_emporio|{player.name}|{card.name}')
player.hand.append(card) player.hand.append(card)
player.available_cards = [] player.available_cards = []
player.pending_action = pl.PendingAction.WAIT player.pending_action = pl.PendingAction.WAIT
@ -436,18 +440,18 @@ class Game:
if len(self.available_cards) == 1: if len(self.available_cards) == 1:
nextPlayer.hand.append(self.available_cards.pop()) nextPlayer.hand.append(self.available_cards.pop())
nextPlayer.notify_self() nextPlayer.notify_self()
self.sio.emit('emporio', room=self.name, data='{"name":"","cards":[]}') G.sio.emit('emporio', room=self.name, data='{"name":"","cards":[]}')
self.players[self.turn].pending_action = pl.PendingAction.PLAY self.players[self.turn].pending_action = pl.PendingAction.PLAY
self.players[self.turn].notify_self() self.players[self.turn].notify_self()
elif nextPlayer == self.players[self.turn]: elif nextPlayer == self.players[self.turn]:
self.sio.emit('emporio', room=self.name, data='{"name":"","cards":[]}') G.sio.emit('emporio', room=self.name, data='{"name":"","cards":[]}')
self.players[self.turn].pending_action = pl.PendingAction.PLAY self.players[self.turn].pending_action = pl.PendingAction.PLAY
self.players[self.turn].notify_self() self.players[self.turn].notify_self()
else: else:
nextPlayer.pending_action = pl.PendingAction.CHOOSE nextPlayer.pending_action = pl.PendingAction.CHOOSE
nextPlayer.choose_text = 'choose_card_to_get' nextPlayer.choose_text = 'choose_card_to_get'
nextPlayer.available_cards = self.available_cards nextPlayer.available_cards = self.available_cards
self.sio.emit('emporio', room=self.name, data=json.dumps( G.sio.emit('emporio', room=self.name, data=json.dumps(
{'name':nextPlayer.name,'cards': self.available_cards}, default=lambda o: o.__dict__)) {'name':nextPlayer.name,'cards': self.available_cards}, default=lambda o: o.__dict__))
nextPlayer.notify_self() nextPlayer.notify_self()
@ -533,15 +537,15 @@ class Game:
if p.win_status and not (isinstance(p.role, roles.Renegade) and p.is_dead): if p.win_status and not (isinstance(p.role, roles.Renegade) and p.is_dead):
if not self.someone_won: if not self.someone_won:
self.someone_won = True self.someone_won = True
self.sio.emit('chat_message', room=self.name, data=f'_won|{p.name}|{p.role.name}') G.sio.emit('chat_message', room=self.name, data=f'_won|{p.name}|{p.role.name}')
if not self.is_replay: if not self.is_replay:
Metrics.send_metric('player_win', points=[1], tags=[f"char:{p.character.name}", f"role:{p.role.name}"]) Metrics.send_metric('player_win', points=[1], tags=[f"char:{p.character.name}", f"role:{p.role.name}"])
p.notify_self() p.notify_self()
if hasattr(self.sio, 'is_fake'): if hasattr(G.sio, 'is_fake'):
print('announces_winners(): Running for tests, you will have to call reset manually!') print('announces_winners(): Running for tests, you will have to call reset manually!')
return return
for i in range(5): for i in range(5):
self.sio.emit('chat_message', room=self.name, data=f'_lobby_reset|{5-i}') G.sio.emit('chat_message', room=self.name, data=f'_lobby_reset|{5-i}')
eventlet.sleep(1) eventlet.sleep(1)
return self.reset() return self.reset()
@ -563,6 +567,11 @@ class Game:
pl.lives = 2 pl.lives = 2
pl.hand.append(self.deck.draw()) pl.hand.append(self.deck.draw())
pl.hand.append(self.deck.draw()) pl.hand.append(self.deck.draw())
if any((True for c in pl.equipment if isinstance(c, tvosc.Fantasma))):
for c in pl.equipment:
if isinstance(c, tvosc.Fantasma):
self.deck.scrap(pl.equipment.pop(c))
break
pl.notify_self() pl.notify_self()
elif self.check_event(ceh.CittaFantasma) or self.players[self.turn].is_ghost: elif self.check_event(ceh.CittaFantasma) or self.players[self.turn].is_ghost:
print(f'{self.name}: {self.players[self.turn]} is dead, event ghost') print(f'{self.name}: {self.players[self.turn]} is dead, event ghost')
@ -575,7 +584,7 @@ class Game:
self.deck.flip_event() self.deck.flip_event()
if len(self.deck.event_cards) > 0 and self.deck.event_cards[0] != None: if len(self.deck.event_cards) > 0 and self.deck.event_cards[0] != None:
print(f'{self.name}: flip new event {self.deck.event_cards[0].name}') print(f'{self.name}: flip new event {self.deck.event_cards[0].name}')
self.sio.emit('chat_message', room=self.name, data={'color': f'orange','text':f'_flip_event|{self.deck.event_cards[0].name}'}) G.sio.emit('chat_message', room=self.name, data={'color': f'orange','text':f'_flip_event|{self.deck.event_cards[0].name}'})
if self.check_event(ce.DeadMan): if self.check_event(ce.DeadMan):
self.did_resuscitate_deadman = False self.did_resuscitate_deadman = False
elif self.check_event(ce.RouletteRussa): elif self.check_event(ce.RouletteRussa):
@ -592,7 +601,7 @@ class Game:
for p in hurt_players: for p in hurt_players:
if p.lives != p.max_lives: if p.lives != p.max_lives:
p.lives += 1 p.lives += 1
self.sio.emit('chat_message', room=self.name, data=f'_doctor_heal|{p.name}') G.sio.emit('chat_message', room=self.name, data=f'_doctor_heal|{p.name}')
p.notify_self() p.notify_self()
elif self.check_event(ceh.IDalton): elif self.check_event(ceh.IDalton):
self.waiting_for = 0 self.waiting_for = 0
@ -633,29 +642,29 @@ class Game:
if len(self.deck.event_cards) > 0: if len(self.deck.event_cards) > 0:
room = self.name if sid == None else sid room = self.name if sid == None else sid
if self.deck.event_cards[0] != None: if self.deck.event_cards[0] != None:
self.sio.emit('event_card', room=room, data=self.deck.event_cards[0].__dict__) G.sio.emit('event_card', room=room, data=self.deck.event_cards[0].__dict__)
else: else:
self.sio.emit('event_card', room=room, data=None) G.sio.emit('event_card', room=room, data=None)
def notify_gold_rush_shop(self, sid=None): def notify_gold_rush_shop(self, sid=None):
if 'gold_rush' in self.expansions and self.deck and self.deck.shop_cards and len(self.deck.shop_cards) > 0: if 'gold_rush' in self.expansions and self.deck and self.deck.shop_cards and len(self.deck.shop_cards) > 0:
room = self.name if sid == None else sid room = self.name if sid == None else sid
print(f'{self.name}: gold_rush_shop room={room}, data={self.deck.shop_cards}') print(f'{self.name}: gold_rush_shop room={room}, data={self.deck.shop_cards}')
self.sio.emit('gold_rush_shop', room=room, data=json.dumps(self.deck.shop_cards, default=lambda o: o.__dict__)) G.sio.emit('gold_rush_shop', room=room, data=json.dumps(self.deck.shop_cards, default=lambda o: o.__dict__))
def notify_scrap_pile(self, sid=None): def notify_scrap_pile(self, sid=None):
print(f'{self.name}: scrap') print(f'{self.name}: scrap')
room = self.name if sid == None else sid room = self.name if sid == None else sid
if self.deck.peek_scrap_pile(): if self.deck.peek_scrap_pile():
self.sio.emit('scrap', room=room, data=self.deck.peek_scrap_pile().__dict__) G.sio.emit('scrap', room=room, data=self.deck.peek_scrap_pile().__dict__)
else: else:
self.sio.emit('scrap', room=room, data=None) G.sio.emit('scrap', room=room, data=None)
def handle_disconnect(self, player: pl.Player): def handle_disconnect(self, player: pl.Player):
print(f'{self.name}: player {player.name} left the game') print(f'{self.name}: player {player.name} left the game')
if player in self.spectators: if player in self.spectators:
self.spectators.remove(player) self.spectators.remove(player)
self.sio.emit('spectators', room=self.name, data=len(self.spectators)) G.sio.emit('spectators', room=self.name, data=len(self.spectators))
return False return False
if player.is_bot and not self.started: if player.is_bot and not self.started:
player.game = None player.game = None
@ -675,7 +684,7 @@ class Game:
player.was_player = False player.was_player = False
if len(player.available_characters) > 0: if len(player.available_characters) > 0:
player.set_available_character(player.available_characters) player.set_available_character(player.available_characters)
player.bot_spin() G.sio.start_background_task(player.bot_spin)
else: else:
self.player_death(player=player, disconnected=True) self.player_death(player=player, disconnected=True)
# else: # else:
@ -735,9 +744,20 @@ class Game:
# if not disconnected: # if not disconnected:
# self.dead_players.append(corpse) # self.dead_players.append(corpse)
self.notify_room() self.notify_room()
self.sio.emit('chat_message', room=self.name, data=f'_died|{player.name}') G.sio.emit('chat_message', room=self.name, data=f'_died|{player.name}')
if self.started: if self.started:
self.sio.emit('chat_message', room=self.name, data=f'_died_role|{player.name}|{player.role.name}') G.sio.emit('chat_message', room=self.name, data=f'_died_role|{player.name}|{player.role.name}')
if not isinstance(player.role, roles.Sheriff) and not self.initial_players == 3:
G.sio.emit('notify_dead_role', room=self.name, data={
'name': player.name,
'lives': 0,
'max_lives': player.max_lives,
'is_ghost': player.is_ghost,
'is_bot': player.is_bot,
'icon': '🤠',
'avatar': player.avatar,
'role': player.role.__dict__,
})
for p in self.players: for p in self.players:
if not p.is_bot: if not p.is_bot:
p.notify_self() p.notify_self()
@ -835,7 +855,7 @@ class Game:
return [p for p in self.players if p.is_dead and (include_ghosts or not p.is_ghost)] return [p for p in self.players if p.is_dead and (include_ghosts or not p.is_ghost)]
def notify_all(self): def notify_all(self):
if self.started: if self.started and self.replay_speed > 0:
data = [{ data = [{
'name': p.name, 'name': p.name,
'ncards': len(p.hand), 'ncards': len(p.hand),
@ -854,4 +874,4 @@ class Game:
'is_ghost': p.is_ghost, 'is_ghost': p.is_ghost,
'is_bot': p.is_bot, 'is_bot': p.is_bot,
} for p in self.get_alive_players()] } for p in self.get_alive_players()]
self.sio.emit('players_update', room=self.name, data=data) G.sio.emit('players_update', room=self.name, data=data)

View File

@ -13,9 +13,10 @@ import bang.expansions.high_noon.card_events as ceh
import bang.expansions.gold_rush.shop_cards as grc import bang.expansions.gold_rush.shop_cards as grc
import bang.expansions.gold_rush.characters as grch import bang.expansions.gold_rush.characters as grch
import bang.expansions.the_valley_of_shadows.cards as tvosc import bang.expansions.the_valley_of_shadows.cards as tvosc
import eventlet
from typing import List from typing import List
from metrics import Metrics from metrics import Metrics
from globals import G
import sys
robot_pictures = [ robot_pictures = [
'https://i.imgur.com/40rAFIb.jpg', 'https://i.imgur.com/40rAFIb.jpg',
@ -63,25 +64,24 @@ class Player:
else: else:
self.avatar = f'https://cdn.discordapp.com/avatars/{res["id"]}/{res["avatar"]}.png' self.avatar = f'https://cdn.discordapp.com/avatars/{res["id"]}/{res["avatar"]}.png'
if self.game: if self.game:
self.sio.emit('chat_message', room=self.game.name, data=f'_change_username|{self.name}|{res["username"]}') G.sio.emit('chat_message', room=self.game.name, data=f'_change_username|{self.name}|{res["username"]}')
self.name = res['username'] self.name = res['username']
self.discord_id = res['id'] self.discord_id = res['id']
if self.is_admin(): if self.is_admin():
if self.game: self.game.feature_flags() if self.game: self.game.feature_flags()
self.sio.emit('chat_message', room=self.sid, data={'color':'green', 'text':'(you are admin)'}) G.sio.emit('chat_message', room=self.sid, data={'color':'green', 'text':'(you are admin)'})
if self.game: if self.game:
self.game.notify_room() self.game.notify_room()
self.sio.emit('me', data=self.name, room=self.sid) G.sio.emit('me', data=self.name, room=self.sid)
else: else:
print('error getting avatar', r.status_code, r.text) print('error getting avatar', r.status_code, r.text)
print(r) print(r)
def __init__(self, name, sid, sio, bot=False, discord_token=None): def __init__(self, name, sid, bot=False, discord_token=None):
import bang.game as g import bang.game as g
super().__init__() super().__init__()
self.name = name self.name = name
self.sid = sid self.sid = sid
self.sio = sio
self.is_bot = bot self.is_bot = bot
self.discord_token = discord_token self.discord_token = discord_token
self.discord_id = None self.discord_id = None
@ -89,7 +89,7 @@ class Player:
if self.is_bot: if self.is_bot:
self.avatar = robot_pictures[randrange(len(robot_pictures))] self.avatar = robot_pictures[randrange(len(robot_pictures))]
if self.discord_token: if self.discord_token:
sio.start_background_task(self.get_avatar) G.sio.start_background_task(self.get_avatar)
self.game: g = None self.game: g = None
self.reset() self.reset()
@ -150,12 +150,13 @@ class Player:
print(f'I {self.name} joined {self.game}') print(f'I {self.name} joined {self.game}')
def disconnect(self): def disconnect(self):
if self.is_admin() and self.game.debug and self.game.started and getattr(sys, 'gettrace', None)(): return False
return self.game.handle_disconnect(self) return self.game.handle_disconnect(self)
def set_role(self, role: r.Role): def set_role(self, role: r.Role):
self.role = role self.role = role
print(f'{self.name}: I am a {role.name}, my goal is "{role.goal}"') print(f'{self.name}: I am a {role.name}, my goal is "{role.goal}"')
self.sio.emit('role', room=self.sid, data=json.dumps( G.sio.emit('role', room=self.sid, data=json.dumps(
role, default=lambda o: o.__dict__)) role, default=lambda o: o.__dict__))
def set_character(self, character: str): def set_character(self, character: str):
@ -174,14 +175,14 @@ class Player:
self.real_character = self.character self.real_character = self.character
self.available_characters = [] self.available_characters = []
print(f'{self.name}: I chose character {self.character.name}') print(f'{self.name}: I chose character {self.character.name}')
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_did_choose_character|{self.name}') data=f'_did_choose_character|{self.name}')
self.game.notify_character_selection() self.game.notify_character_selection()
elif self.real_character and isinstance(self.real_character, chd.VeraCuster): elif self.real_character and isinstance(self.real_character, chd.VeraCuster):
self.character = next( self.character = next(
x for x in self.available_characters if x.name == character) x for x in self.available_characters if x.name == character)
self.available_characters = [] self.available_characters = []
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_did_choose_character|{self.name}') data=f'_did_choose_character|{self.name}')
self.pending_action = PendingAction.DRAW self.pending_action = PendingAction.DRAW
self.notify_self() self.notify_self()
@ -199,7 +200,7 @@ class Player:
self.available_characters = available self.available_characters = available
print(f'{self.name}: I have to choose between {available}') print(f'{self.name}: I have to choose between {available}')
if not self.is_bot: if not self.is_bot:
self.sio.emit('characters', room=self.sid, data=json.dumps( G.sio.emit('characters', room=self.sid, data=json.dumps(
available, default=lambda o: o.__dict__)) available, default=lambda o: o.__dict__))
else: else:
char_name = available[randrange(0, len(available))].name char_name = available[randrange(0, len(available))].name
@ -217,7 +218,7 @@ class Player:
'message':message 'message':message
} }
print('notifying card') print('notifying card')
self.sio.emit('notify_card', room=self.sid, data=mess) G.sio.emit('notify_card', room=self.sid, data=mess)
def notify_self(self): def notify_self(self):
if any((True for c in self.equipment if isinstance(c, tvosc.Fantasma))): if any((True for c in self.equipment if isinstance(c, tvosc.Fantasma))):
@ -272,7 +273,6 @@ class Player:
ser = self.__dict__.copy() ser = self.__dict__.copy()
ser.pop('game') ser.pop('game')
ser.pop('sio')
ser.pop('sid') ser.pop('sid')
ser.pop('on_pick_cb') ser.pop('on_pick_cb')
ser.pop('discord_token') ser.pop('discord_token')
@ -292,16 +292,16 @@ class Player:
self.pending_action = PendingAction.WAIT self.pending_action = PendingAction.WAIT
ser['hand'] = [] ser['hand'] = []
ser['equipment'] = [] ser['equipment'] = []
self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__)) G.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__))
self.game.player_death(self) self.game.player_death(self)
if self.game and self.game.started: # falso quando un bot viene eliminato dalla partita if self.game and self.game.started: # falso quando un bot viene eliminato dalla partita
self.sio.emit('self_vis', room=self.sid, data=json.dumps(self.game.get_visible_players(self), default=lambda o: o.__dict__)) G.sio.emit('self_vis', room=self.sid, data=json.dumps(self.game.get_visible_players(self), default=lambda o: o.__dict__))
self.game.notify_all() self.game.notify_all()
self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__)) G.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__))
def bot_spin(self): def bot_spin(self):
while self.is_bot and self.game != None and not self.game.shutting_down: while self.is_bot and self.game != None and not self.game.shutting_down:
eventlet.sleep(max(0.2, uniform(self.game.bot_speed/2-0.1, self.game.bot_speed))) G.sio.sleep(max(0.2, uniform(self.game.bot_speed/2-0.1, self.game.bot_speed)))
if self.lives > 0 or self.is_ghost: if self.lives > 0 or self.is_ghost:
self.bot_logic() self.bot_logic()
@ -441,7 +441,7 @@ class Player:
self.is_playing_ranch = False self.is_playing_ranch = False
self.can_play_vendetta = can_play_vendetta self.can_play_vendetta = can_play_vendetta
if not again: if not again:
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_turn|{self.name}') data=f'_turn|{self.name}')
print(f'{self.name}: I was notified that it is my turn') print(f'{self.name}: I was notified that it is my turn')
self.was_shot = False self.was_shot = False
@ -461,7 +461,7 @@ class Player:
self.hand.append(self.game.deck.draw(True)) self.hand.append(self.game.deck.draw(True))
if self.character.check(self.game, chars.BartCassidy) and self.lives > 0: if self.character.check(self.game, chars.BartCassidy) and self.lives > 0:
self.hand.append(self.game.deck.draw(True)) self.hand.append(self.game.deck.draw(True))
self.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}')
self.heal_if_needed() self.heal_if_needed()
if self.lives <= 0: if self.lives <= 0:
return self.notify_self() return self.notify_self()
@ -557,11 +557,11 @@ class Player:
for i in range(num): for i in range(num):
if i == 0 and pile == 'scrap' and self.character.check(self.game, chars.PedroRamirez): if i == 0 and pile == 'scrap' and self.character.check(self.game, chars.PedroRamirez):
self.hand.append(self.game.deck.draw_from_scrap_pile()) self.hand.append(self.game.deck.draw_from_scrap_pile())
self.sio.emit('chat_message', room=self.game.name, data=f'_draw_from_scrap|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_draw_from_scrap|{self.name}')
elif i == 0 and type(pile) == str and pile != self.name and pile in self.game.players_map and self.character.check(self.game, chars.JesseJones) and len(self.game.get_player_named(pile).hand) > 0: elif i == 0 and type(pile) == str and pile != self.name and pile in self.game.players_map and self.character.check(self.game, chars.JesseJones) and len(self.game.get_player_named(pile).hand) > 0:
self.hand.append(self.game.get_player_named(pile).hand.pop( randrange(0, len(self.game.get_player_named(pile).hand)))) self.hand.append(self.game.get_player_named(pile).hand.pop( randrange(0, len(self.game.get_player_named(pile).hand))))
self.game.get_player_named(pile).notify_self() self.game.get_player_named(pile).notify_self()
self.sio.emit('chat_message', room=self.game.name, data=f'_draw_from_player|{self.name}|{pile}') G.sio.emit('chat_message', room=self.game.name, data=f'_draw_from_player|{self.name}|{pile}')
elif i == 1: elif i == 1:
card: cs.Card = self.game.deck.draw() card: cs.Card = self.game.deck.draw()
if (self.character.check(self.game, chars.BlackJack) or self.game.check_event(ce.LeggeDelWest)): if (self.character.check(self.game, chars.BlackJack) or self.game.check_event(ce.LeggeDelWest)):
@ -602,7 +602,7 @@ class Player:
pickable_cards -= 1 pickable_cards -= 1
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
if picked.check_suit(self.game, [cs.Suit.SPADES]) and 2 <= picked.number <= 9 and pickable_cards == 0: if picked.check_suit(self.game, [cs.Suit.SPADES]) and 2 <= picked.number <= 9 and pickable_cards == 0:
self.lives -= 3 self.lives -= 3
@ -616,12 +616,12 @@ class Player:
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
self.attacker = None self.attacker = None
self.game.deck.scrap(self.equipment.pop(i), True) self.game.deck.scrap(self.equipment.pop(i), True)
self.sio.emit('chat_message', room=self.game.name, data=f'_explode|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_explode|{self.name}')
self.heal_if_needed() self.heal_if_needed()
if self.character.check(self.game, chars.BartCassidy) and self.lives > 0: if self.character.check(self.game, chars.BartCassidy) and self.lives > 0:
for i in range(3): for i in range(3):
self.hand.append(self.game.deck.draw(True)) self.hand.append(self.game.deck.draw(True))
self.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}')
print(f'{self.name} Boom, -3 hp') print(f'{self.name} Boom, -3 hp')
break break
else: else:
@ -637,16 +637,16 @@ class Player:
pickable_cards -= 1 pickable_cards -= 1
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
if not picked.check_suit(self.game, [cs.Suit.HEARTS]) and pickable_cards == 0: if not picked.check_suit(self.game, [cs.Suit.HEARTS]) and pickable_cards == 0:
self.game.deck.scrap(self.equipment.pop(i), True) self.game.deck.scrap(self.equipment.pop(i), True)
self.sio.emit('chat_message', room=self.game.name, data=f'_prison_turn|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_prison_turn|{self.name}')
self.end_turn(forced=True) self.end_turn(forced=True)
return return
elif pickable_cards == 0: elif pickable_cards == 0:
self.game.deck.scrap(self.equipment.pop(i), True) self.game.deck.scrap(self.equipment.pop(i), True)
self.sio.emit('chat_message', room=self.game.name, data=f'_prison_free|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_prison_free|{self.name}')
break break
break break
for i in range(len(self.equipment)): for i in range(len(self.equipment)):
@ -655,13 +655,13 @@ class Player:
pickable_cards -= 1 pickable_cards -= 1
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
if not picked.check_suit(self.game, [cs.Suit.SPADES]): if not picked.check_suit(self.game, [cs.Suit.SPADES]):
break break
elif pickable_cards == 0: elif pickable_cards == 0:
self.lives -= 1 self.lives -= 1
self.sio.emit('chat_message', room=self.game.name, data=f'_snake_bit|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_snake_bit|{self.name}')
break break
if any((isinstance(c, cs.Prigione) for c in self.equipment)): if any((isinstance(c, cs.Prigione) for c in self.equipment)):
self.notify_self() #TODO perchè solo le prigioni? e multiple dinamiti come si comportano con veracuster? self.notify_self() #TODO perchè solo le prigioni? e multiple dinamiti come si comportano con veracuster?
@ -725,7 +725,7 @@ class Player:
self.hand.insert(hand_index, card) self.hand.insert(hand_index, card)
if withCard: if withCard:
self.hand.insert(_with, withCard) self.hand.insert(_with, withCard)
self.sio.emit('cant_play_card', room=self.sid) G.sio.emit('cant_play_card', room=self.sid)
elif (card.usable_next_turn and card.can_be_used_now) or (isinstance(card, grc.ShopCard) and card.kind == grc.ShopCardKind.BLACK): elif (card.usable_next_turn and card.can_be_used_now) or (isinstance(card, grc.ShopCard) and card.kind == grc.ShopCardKind.BLACK):
if did_play_card: if did_play_card:
self.game.deck.scrap(card, True) self.game.deck.scrap(card, True)
@ -773,7 +773,7 @@ class Player:
self.notify_self() self.notify_self()
elif self.choose_text == 'choose_ricercato': elif self.choose_text == 'choose_ricercato':
player = self.game.get_player_named(self.available_cards[card_index]['name']) player = self.game.get_player_named(self.available_cards[card_index]['name'])
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Ricercato|{player.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Ricercato|{player.name}')
if any((isinstance(c, grc.Ricercato) for c in player.gold_rush_equipment)): if any((isinstance(c, grc.Ricercato) for c in player.gold_rush_equipment)):
self.game.deck.shop_deck.append(grc.Ricercato()) self.game.deck.shop_deck.append(grc.Ricercato())
else: else:
@ -793,20 +793,20 @@ class Player:
self.notify_self() self.notify_self()
elif self.choose_text == 'choose_bicchierino': elif self.choose_text == 'choose_bicchierino':
player = self.game.get_player_named(self.available_cards[card_index]['name']) player = self.game.get_player_named(self.available_cards[card_index]['name'])
self.sio.emit('chat_message', room=self.game.name, data=f'_play_card_for|{self.name}|{"Bicchierino"}|{player.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_play_card_for|{self.name}|{"Bicchierino"}|{player.name}')
player.lives = min(player.lives+1, player.max_lives) player.lives = min(player.lives+1, player.max_lives)
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif self.choose_text == 'choose_birra_function': elif self.choose_text == 'choose_birra_function':
if card_index == 0: if card_index == 0:
self.gold_nuggets += 1 self.gold_nuggets += 1
self.sio.emit('chat_message', room=self.game.name, data=f'_get_nugget|{self.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_get_nugget|{self.name}')
else: else:
cs.Birra(1,1).play_card(self, skipChecks=True) cs.Birra(1,1).play_card(self, skipChecks=True)
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif self.choose_text == 'choose_bottiglia': elif self.choose_text == 'choose_bottiglia':
self.sio.emit('chat_message', room=self.game.name, data=f'_play_card|{self.name}|{"Bottiglia"}') G.sio.emit('chat_message', room=self.game.name, data=f'_play_card|{self.name}|{"Bottiglia"}')
if isinstance(self.available_cards[card_index], cs.Birra): if isinstance(self.available_cards[card_index], cs.Birra):
self.lives = min(self.lives+1, self.max_lives) self.lives = min(self.lives+1, self.max_lives)
else: else:
@ -814,7 +814,7 @@ class Player:
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif self.choose_text == 'choose_complice': elif self.choose_text == 'choose_complice':
self.sio.emit('chat_message', room=self.game.name, data=f'_play_card|{self.name}|{"Bottiglia"}') G.sio.emit('chat_message', room=self.game.name, data=f'_play_card|{self.name}|{"Bottiglia"}')
self.hand.append(self.available_cards[card_index]) self.hand.append(self.available_cards[card_index])
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
@ -835,7 +835,7 @@ class Player:
player = self.game.get_player_named(self.choose_text.split('|')[1]) player = self.game.get_player_named(self.choose_text.split('|')[1])
player.gold_rush_equipment.remove(self.available_cards[card_index]) player.gold_rush_equipment.remove(self.available_cards[card_index])
self.game.deck.shop_deck.append(self.available_cards[card_index]) self.game.deck.shop_deck.append(self.available_cards[card_index])
self.sio.emit('chat_message', room=self.game.name, data=f'_gold_rush_pay_discard|{self.name}|{player.name}|{self.available_cards[card_index].name}') G.sio.emit('chat_message', room=self.game.name, data=f'_gold_rush_pay_discard|{self.name}|{player.name}|{self.available_cards[card_index].name}')
player.notify_self() player.notify_self()
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
@ -845,7 +845,7 @@ class Player:
player.equipment.append(self.game.deck.scrap_pile.pop(-1)) player.equipment.append(self.game.deck.scrap_pile.pop(-1))
player.notify_self() player.notify_self()
self.game.notify_all() self.game.notify_all()
self.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Fantasma|{player.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Fantasma|{player.name}')
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif 'choose_sventagliata' in self.choose_text: elif 'choose_sventagliata' in self.choose_text:
@ -854,8 +854,8 @@ class Player:
player = self.game.get_player_named(self.available_cards[card_index]['name']) player = self.game.get_player_named(self.available_cards[card_index]['name'])
player.game.attack(self, og, card_name='Sventagliata') player.game.attack(self, og, card_name='Sventagliata')
player.game.attack(self, player.name, card_name='Sventagliata') player.game.attack(self, player.name, card_name='Sventagliata')
self.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Sventagliata|{og}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Sventagliata|{og}')
self.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Sventagliata|{player.name}') G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Sventagliata|{player.name}')
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif 'choose_tornado' in self.choose_text: elif 'choose_tornado' in self.choose_text:
@ -899,11 +899,11 @@ class Player:
self.real_character = self.character self.real_character = self.character
self.max_lives = self.character.max_lives + self.role.health_mod self.max_lives = self.character.max_lives + self.role.health_mod
self.lives = 2 self.lives = 2
self.sio.emit('chat_message', room=self.game.name, data=f'_choose_character|{self.name}|{self.character.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_choose_character|{self.name}|{self.character.name}')
self.play_turn(again = True) self.play_turn(again = True)
elif self.game.check_event(ceh.Manette) and self.choose_text == 'choose_manette': elif self.game.check_event(ceh.Manette) and self.choose_text == 'choose_manette':
self.committed_suit_manette = cs.Suit(card_index) self.committed_suit_manette = cs.Suit(card_index)
self.sio.emit('chat_message', room=self.game.name, data=f'_choose_manette|{self.name}|{"♦♣♥♠"[card_index]}') G.sio.emit('chat_message', room=self.game.name, data=f'_choose_manette|{self.name}|{"♦♣♥♠"[card_index]}')
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif self.is_giving_life and self.game.check_event(ce.FratelliDiSangue): elif self.is_giving_life and self.game.check_event(ce.FratelliDiSangue):
@ -918,7 +918,7 @@ class Player:
if any((isinstance(c, grc.Stivali) for c in self.gold_rush_equipment)): if any((isinstance(c, grc.Stivali) for c in self.gold_rush_equipment)):
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
player.notify_self() player.notify_self()
self.sio.emit('chat_message', room=self.game.name, data=f'_fratelli_sangue|{self.name}|{player.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_fratelli_sangue|{self.name}|{player.name}')
except: pass except: pass
self.play_turn(again = True) self.play_turn(again = True)
elif self.is_using_checchino and self.game.check_event(ce.Cecchino): elif self.is_using_checchino and self.game.check_event(ce.Cecchino):
@ -975,15 +975,15 @@ class Player:
elif self.is_drawing and self.game.check_event(ce.Peyote): elif self.is_drawing and self.game.check_event(ce.Peyote):
self.is_drawing = False self.is_drawing = False
card = self.game.deck.draw() card = self.game.deck.draw()
self.sio.emit('chat_message', room=self.game.name, data=f"_guess|{self.name}|{self.available_cards[card_index]['icon']}") G.sio.emit('chat_message', room=self.game.name, data=f"_guess|{self.name}|{self.available_cards[card_index]['icon']}")
self.available_cards = [] self.available_cards = []
if card_index == card.suit%2: if card_index == card.suit%2:
self.hand.append(card) self.hand.append(card)
self.sio.emit('chat_message', room=self.game.name, data=f"_guess_right|{self.name}") G.sio.emit('chat_message', room=self.game.name, data=f"_guess_right|{self.name}")
self.pending_action = PendingAction.DRAW self.pending_action = PendingAction.DRAW
else: else:
self.game.deck.scrap(card) self.game.deck.scrap(card)
self.sio.emit('chat_message', room=self.game.name, data=f"_guess_wrong|{self.name}") G.sio.emit('chat_message', room=self.game.name, data=f"_guess_wrong|{self.name}")
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
# specifico per personaggio # specifico per personaggio
@ -1051,7 +1051,7 @@ class Player:
pickable_cards -= 1 pickable_cards -= 1
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
if picked.check_suit(self.game, [cs.Suit.HEARTS]): if picked.check_suit(self.game, [cs.Suit.HEARTS]):
self.mancato_needed -= 1 self.mancato_needed -= 1
@ -1081,7 +1081,7 @@ class Player:
pickable_cards -= 1 pickable_cards -= 1
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
if picked.check_suit(self.game, [cs.Suit.HEARTS]): if picked.check_suit(self.game, [cs.Suit.HEARTS]):
self.mancato_needed -= 1 self.mancato_needed -= 1
@ -1213,34 +1213,34 @@ class Player:
self.lives += 1 if not self.character.check(self.game, chd.TequilaJoe) else 2 self.lives += 1 if not self.character.check(self.game, chd.TequilaJoe) else 2
self.lives = min(self.lives, self.max_lives) self.lives = min(self.lives, self.max_lives)
self.game.deck.scrap(self.hand.pop(i), True) self.game.deck.scrap(self.hand.pop(i), True)
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_beer_save|{self.name}') data=f'_beer_save|{self.name}')
break break
def take_damage_response(self): def take_damage_response(self):
self.lives -= 1 self.lives -= 1
self.sio.emit('hurt', room=self.sid, data=f'') G.sio.emit('hurt', room=self.sid, data=f'')
if self.lives > 0: if self.lives > 0:
if self.character.check(self.game, chars.BartCassidy): if self.character.check(self.game, chars.BartCassidy):
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_special_bart_cassidy|{self.name}') data=f'_special_bart_cassidy|{self.name}')
self.hand.append(self.game.deck.draw(True)) self.hand.append(self.game.deck.draw(True))
elif self.character.check(self.game, chars.ElGringo) and self.attacker and self.attacker in self.game.get_alive_players() and len(self.attacker.hand) > 0: elif self.character.check(self.game, chars.ElGringo) and self.attacker and self.attacker in self.game.get_alive_players() and len(self.attacker.hand) > 0:
self.hand.append(self.attacker.hand.pop(randrange(0, len(self.attacker.hand)))) self.hand.append(self.attacker.hand.pop(randrange(0, len(self.attacker.hand))))
self.hand[-1].reset_card() self.hand[-1].reset_card()
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_special_el_gringo|{self.name}|{self.attacker.name}') data=f'_special_el_gringo|{self.name}|{self.attacker.name}')
self.attacker.notify_self() self.attacker.notify_self()
if isinstance(self.attacker, Player) and not self.game.check_event(ce.Lazo): if isinstance(self.attacker, Player) and not self.game.check_event(ce.Lazo):
if any((isinstance(c, tvosc.Taglia) for c in self.equipment)): if any((isinstance(c, tvosc.Taglia) for c in self.equipment)):
self.attacker.hand.append(self.game.deck.draw(True)) self.attacker.hand.append(self.game.deck.draw(True))
self.sio.emit('chat_message', room=self.game.name, G.sio.emit('chat_message', room=self.game.name,
data=f'_taglia_reward|{self.name}|{self.attacker.name}') data=f'_taglia_reward|{self.name}|{self.attacker.name}')
self.attacker.notify_self() self.attacker.notify_self()
if len(self.hand) > 0 and any((isinstance(cd, tvosc.Shotgun) for cd in self.attacker.equipment)): if len(self.hand) > 0 and any((isinstance(cd, tvosc.Shotgun) for cd in self.attacker.equipment)):
c = self.hand.pop(randrange(0, len(self.hand))) c = self.hand.pop(randrange(0, len(self.hand)))
self.game.deck.scrap(c, True) self.game.deck.scrap(c, True)
self.sio.emit('chat_message', room=self.game.name, data=f'_shotgun_scrap|{self.name}|{c.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_shotgun_scrap|{self.name}|{c.name}')
if self.attacker and 'gold_rush' in self.game.expansions: if self.attacker and 'gold_rush' in self.game.expansions:
if (isinstance(self.attacker, Player)): if (isinstance(self.attacker, Player)):
self.attacker.gold_nuggets += 1 self.attacker.gold_nuggets += 1
@ -1285,7 +1285,7 @@ class Player:
self.hand.append(self.game.deck.draw(True)) self.hand.append(self.game.deck.draw(True))
card.use_card(self) card.use_card(self)
print(f'{self.game.name}: {self.name} responded with {card.name}') print(f'{self.game.name}: {self.name} responded with {card.name}')
self.sio.emit('chat_message', room=self.game.name, data=f'_respond|{self.name}|{card.name}') G.sio.emit('chat_message', room=self.game.name, data=f'_respond|{self.name}|{card.name}')
self.game.deck.scrap(card, True) self.game.deck.scrap(card, True)
self.notify_self() self.notify_self()
self.mancato_needed -= 1 self.mancato_needed -= 1
@ -1448,14 +1448,14 @@ class Player:
##Vendetta## ##Vendetta##
if not forced and self.game.check_event(ce.Vendetta) and self.can_play_vendetta: if not forced and self.game.check_event(ce.Vendetta) and self.can_play_vendetta:
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
self.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') G.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
if picked.check_suit(self.game, [cs.Suit.HEARTS]): if picked.check_suit(self.game, [cs.Suit.HEARTS]):
self.play_turn(can_play_vendetta=False) self.play_turn(can_play_vendetta=False)
return return
##Don Bell## ##Don Bell##
if not forced and self.character.check(self.game, grch.DonBell) and self.can_play_again_don_bell: if not forced and self.character.check(self.game, grch.DonBell) and self.can_play_again_don_bell:
picked: cs.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
self.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') G.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}')
self.can_play_again_don_bell = False self.can_play_again_don_bell = False
if picked.check_suit(self.game, [cs.Suit.HEARTS, cs.Suit.DIAMONDS]): if picked.check_suit(self.game, [cs.Suit.HEARTS, cs.Suit.DIAMONDS]):
self.play_turn(can_play_vendetta=False) self.play_turn(can_play_vendetta=False)

6
backend/globals.py Normal file
View File

@ -0,0 +1,6 @@
class G:
sio = None
def __init__(self):
pass

View File

@ -20,10 +20,16 @@ sys.setrecursionlimit(10**6) # this should prevents bots from stopping
import logging import logging
logging.basicConfig(filename='out.log', level='ERROR') logging.basicConfig(filename='out.log', level='ERROR')
from functools import wraps from functools import wraps
from globals import G
Metrics.init() Metrics.init()
sio = socketio.Server(cors_allowed_origins="*") sio = socketio.Server(cors_allowed_origins="*")
G.sio = sio
import faulthandler
faulthandler.enable()
static_files={ static_files={
'/': {'content_type': 'text/html', 'filename': 'index.html'}, '/': {'content_type': 'text/html', 'filename': 'index.html'},
@ -54,20 +60,24 @@ def send_to_debug(error):
if g.debug or any((p.is_admin() for p in g.players)): if g.debug or any((p.is_admin() for p in g.players)):
sio.emit('chat_message', room=g.name, data={'color': f'red','text':json.dumps({'ERROR':error}), 'type':'json'}) sio.emit('chat_message', room=g.name, data={'color': f'red','text':json.dumps({'ERROR':error}), 'type':'json'})
save_lock = False
def bang_handler(func): def bang_handler(func):
@wraps(func) @wraps(func)
def wrapper_func(*args, **kwargs): def wrapper_func(*args, **kwargs):
global save_lock
save_lock = True
try: try:
func(*args, **kwargs) func(*args, **kwargs)
except Exception as e: except Exception as e:
logging.exception(e) logging.exception(e)
print(traceback.format_exc()) print(traceback.format_exc())
send_to_debug(traceback.format_exc()) send_to_debug(traceback.format_exc())
save_lock = False
return wrapper_func return wrapper_func
def advertise_lobbies(): def advertise_lobbies():
sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10 and not g.is_hidden]) sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10 and not g.is_hidden])
sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started and not g.is_hidden]) sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started and not g.is_hidden and len(g.players) > 0])
Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)]) Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)])
Metrics.send_metric('online_players', points=[online_players]) Metrics.send_metric('online_players', points=[online_players])
@ -114,7 +124,7 @@ def set_username(sid, username):
ses = sio.get_session(sid) ses = sio.get_session(sid)
if not isinstance(ses, Player): if not isinstance(ses, Player):
dt = username["discord_token"] if 'discord_token' in username else None dt = username["discord_token"] if 'discord_token' in username else None
sio.save_session(sid, Player(username["name"], sid, sio, discord_token=dt)) sio.save_session(sid, Player(username["name"], sid, discord_token=dt))
print(f'{sid} is now {username}') print(f'{sid} is now {username}')
advertise_lobbies() advertise_lobbies()
elif ses.game == None or not ses.game.started: elif ses.game == None or not ses.game.started:
@ -138,7 +148,7 @@ def get_me(sid, room):
sio.get_session(sid).game.notify_room() sio.get_session(sid).game.notify_room()
else: else:
dt = room["discord_token"] if 'discord_token' in room else None dt = room["discord_token"] if 'discord_token' in room else None
sio.save_session(sid, Player('player', sid, sio, discord_token=dt)) sio.save_session(sid, Player('player', sid, discord_token=dt))
if 'replay' in room and room['replay'] != None: if 'replay' in room and room['replay'] != None:
create_room(sid, room['replay']) create_room(sid, room['replay'])
sid = sio.get_session(sid) sid = sio.get_session(sid)
@ -153,16 +163,16 @@ def get_me(sid, room):
if 'ffw' not in room: if 'ffw' not in room:
sid.game.replay(log) sid.game.replay(log)
else: else:
sid.game.replay(log, speed=0.1, fast_forward=int(room['ffw'])) sid.game.replay(log, speed=0, fast_forward=int(room['ffw']))
return return
de_games = [g for g in games if g.name == room['name']] de_games = [g for g in games if g.name == room['name']]
if len(de_games) == 1 and not de_games[0].started: if len(de_games) == 1 and not de_games[0].started:
join_room(sid, room) join_room(sid, room)
elif len(de_games) == 1 and de_games[0].started: elif len(de_games) == 1 and de_games[0].started:
print('room exists') print('room exists')
if room['username'] != None and any((p.name == room['username'] for p in de_games[0].players if (p.is_bot or (dt != None and p.discord_token == dt)))): if room['username'] != None and any((p.name == room['username'] for p in de_games[0].players if (p.is_bot or (dt != None and p.discord_token == dt) or p.sid == None))):
print('getting inside the bot') print('getting inside the bot')
bot = [p for p in de_games[0].players if p.is_bot and p.name == room['username'] ][0] bot = [p for p in de_games[0].players if (p.is_bot or (dt != None and p.discord_token == dt) or p.sid == None) and p.name == room['username']][0]
bot.sid = sid bot.sid = sid
bot.is_bot = False bot.is_bot = False
sio.enter_room(sid, de_games[0].name) sio.enter_room(sid, de_games[0].name)
@ -193,7 +203,7 @@ def get_me(sid, room):
sio.emit('me', data={'error':'Wrong password/Cannot connect'}, room=sid) sio.emit('me', data={'error':'Wrong password/Cannot connect'}, room=sid)
else: else:
sio.emit('me', data=sio.get_session(sid).name, room=sid) sio.emit('me', data=sio.get_session(sid).name, room=sid)
if room['username'] == None or any((p.name == room['username'] for p in sio.get_session(sid).game.players)): if room['username'] == None or any((p.name == room['username'] for p in sio.get_session(sid).game.players if not ((dt != None and p.discord_token == dt) or p.sid == None))):
sio.emit('change_username', room=sid) sio.emit('change_username', room=sid)
else: else:
sio.emit('chat_message', room=sio.get_session(sid).game.name, data=f"_change_username|{sio.get_session(sid).name}|{room['username']}") sio.emit('chat_message', room=sio.get_session(sid).game.name, data=f"_change_username|{sio.get_session(sid).name}|{room['username']}")
@ -225,7 +235,7 @@ def create_room(sid, room_name):
room_name += f'_{random.randint(0,100)}' room_name += f'_{random.randint(0,100)}'
sio.leave_room(sid, 'lobby') sio.leave_room(sid, 'lobby')
sio.enter_room(sid, room_name) sio.enter_room(sid, room_name)
g = Game(room_name, sio) g = Game(room_name)
g.add_player(sio.get_session(sid)) g.add_player(sio.get_session(sid))
if room_name in blacklist: if room_name in blacklist:
g.is_hidden = True g.is_hidden = True
@ -289,7 +299,8 @@ Sockets for the status page
@sio.event @sio.event
@bang_handler @bang_handler
def get_all_rooms(sid, deploy_key): def get_all_rooms(sid, deploy_key):
if ('DEPLOY_KEY' in os.environ and deploy_key == os.environ['DEPLOY_KEY']) or sio.get_session(sid).is_admin(): ses = sio.get_session(sid)
if ('DEPLOY_KEY' in os.environ and deploy_key == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
sio.emit('all_rooms', room=sid, data=[{ sio.emit('all_rooms', room=sid, data=[{
'name': g.name, 'name': g.name,
'hidden': g.is_hidden, 'hidden': g.is_hidden,
@ -306,13 +317,25 @@ def get_all_rooms(sid, deploy_key):
@sio.event @sio.event
@bang_handler @bang_handler
def kick(sid, data): def kick(sid, data):
if ('DEPLOY_KEY' in os.environ and data['key'] == os.environ['DEPLOY_KEY']) or sio.get_session(sid).is_admin(): ses = sio.get_session(sid)
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
sio.emit('kicked', room=data['sid']) sio.emit('kicked', room=data['sid'])
@sio.event
@bang_handler
def reset(sid, data):
global games
ses = sio.get_session(sid)
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
for g in games:
sio.emit('kicked', room=g.name)
games = []
@sio.event @sio.event
@bang_handler @bang_handler
def hide_toogle(sid, data): def hide_toogle(sid, data):
if ('DEPLOY_KEY' in os.environ and data['key'] == os.environ['DEPLOY_KEY']) or sio.get_session(sid).is_admin(): ses = sio.get_session(sid)
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
game = [g for g in games if g.name==data['room']] game = [g for g in games if g.name==data['room']]
if len(games) > 0: if len(games) > 0:
game[0].is_hidden = not game[0].is_hidden game[0].is_hidden = not game[0].is_hidden
@ -436,14 +459,14 @@ def chat_message(sid, msg, pl=None):
if '/addbot' in msg and not ses.game.started: if '/addbot' in msg and not ses.game.started:
if len(msg.split()) > 1: if len(msg.split()) > 1:
# for _ in range(int(msg.split()[1])): # for _ in range(int(msg.split()[1])):
# ses.game.add_player(Player(f'AI_{random.randint(0,1000)}', 'bot', sio, bot=True)) # ses.game.add_player(Player(f'AI_{random.randint(0,1000)}', 'bot', bot=True))
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'Only 1 bot at the time'}) sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'Only 1 bot at the time'})
else: else:
bot = Player(f'AI_{random.randint(0,10)}', 'bot', sio, bot=True) bot = Player(f'AI_{random.randint(0,10)}', 'bot', bot=True)
while any((p for p in ses.game.players if p.name == bot.name)): while any((p for p in ses.game.players if p.name == bot.name)):
bot = Player(f'AI_{random.randint(0,10)}', 'bot', sio, bot=True) bot = Player(f'AI_{random.randint(0,10)}', 'bot', bot=True)
ses.game.add_player(bot) ses.game.add_player(bot)
bot.bot_spin() sio.start_background_task(bot.bot_spin)
return return
if '/replay' in msg and not '/replayspeed' in msg and not '/replaypov' in msg: if '/replay' in msg and not '/replayspeed' in msg and not '/replaypov' in msg:
_cmd = msg.split() _cmd = msg.split()
@ -456,7 +479,7 @@ def chat_message(sid, msg, pl=None):
ses.game.replay(log) ses.game.replay(log)
if len(_cmd) == 3: if len(_cmd) == 3:
line = int(_cmd[2]) line = int(_cmd[2])
ses.game.replay(log, speed=0.1, fast_forward=line) ses.game.replay(log, speed=0, fast_forward=line)
return return
if '/replayspeed' in msg: if '/replayspeed' in msg:
_cmd = msg.split() _cmd = msg.split()
@ -469,11 +492,8 @@ def chat_message(sid, msg, pl=None):
name = ' '.join(_cmd[1:]) name = ' '.join(_cmd[1:])
for p in ses.game.players: for p in ses.game.players:
if p.sid == ses.sid: if p.sid == ses.sid:
from tests.dummy_socket import DummySocket
p.sio = DummySocket()
p.sid = '' p.sid = ''
pl = ses.game.get_player_named(name) pl = ses.game.get_player_named(name)
pl.sio = sio
pl.sid = ses.sid pl.sid = ses.sid
pl.set_role(pl.role) pl.set_role(pl.role)
pl.notify_self() pl.notify_self()
@ -666,7 +686,7 @@ def chat_message(sid, msg, pl=None):
ses.is_bot = not ses.is_bot ses.is_bot = not ses.is_bot
if (ses.is_bot): if (ses.is_bot):
ses.was_player = True ses.was_player = True
ses.bot_spin() sio.start_background_task(ses.bot_spin)
elif '/arcadekick' in msg and ses.game.started: elif '/arcadekick' in msg and ses.game.started:
if not any((p.pending_action != PendingAction.WAIT for p in ses.game.players)): if not any((p.pending_action != PendingAction.WAIT for p in ses.game.players)):
sio.emit('chat_message', room=ses.game.name, data={'color': f'','text':f'KICKING THE ARCADE CABINET'}) sio.emit('chat_message', room=ses.game.name, data={'color': f'','text':f'KICKING THE ARCADE CABINET'})
@ -763,11 +783,12 @@ def discord_auth(sid, data):
if res.status_code == 200: if res.status_code == 200:
sio.emit('discord_auth_succ', room=sid, data=res.json()) sio.emit('discord_auth_succ', room=sid, data=res.json())
def pool_metrics(): def pool_metrics():
while True:
sio.sleep(60) sio.sleep(60)
Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)]) Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)])
Metrics.send_metric('online_players', points=[online_players]) Metrics.send_metric('online_players', points=[online_players])
pool_metrics()
import urllib.parse import urllib.parse
class CustomProxyFix(object): class CustomProxyFix(object):
@ -790,7 +811,30 @@ class CustomProxyFix(object):
discord_ci = '1059452581027532880' discord_ci = '1059452581027532880'
discord_cs = 'Mc8ZlMQhayzi1eOqWFtGHs3L0iXCzaEu' discord_cs = 'Mc8ZlMQhayzi1eOqWFtGHs3L0iXCzaEu'
import pickle
def save_games():
global save_lock
while True:
sio.sleep(2)
if not save_lock:
if not os.path.exists("save"):
os.mkdir("save")
with open('./save/games.pickle', 'wb') as f:
pickle.dump([g for g in games if g.started and not g.is_replay and not g.is_hidden], f)
if __name__ == '__main__': if __name__ == '__main__':
if os.path.exists('./save/games.pickle'):
try:
with open('./save/games.pickle', 'rb') as file:
games = pickle.load(file)
for g in games:
for p in g.players:
if p.sid != 'bot':
sio.start_background_task(p.disconnect)
else:
sio.start_background_task(p.bot_spin)
except:
pass
sio.start_background_task(save_games)
sio.start_background_task(pool_metrics) sio.start_background_task(pool_metrics)
eventlet.wsgi.server(eventlet.listen(('', 5001)), CustomProxyFix(app)) eventlet.wsgi.server(eventlet.listen(('', 5001)), CustomProxyFix(app))

View File

@ -0,0 +1,3 @@
from tests.dummy_socket import DummySocket
from globals import G
G.sio = DummySocket()

View File

@ -1,16 +1,15 @@
from random import randint from random import randint
from bang.characters import Character from bang.characters import Character
from bang.cards import * from bang.cards import *
from tests.dummy_socket import DummySocket
from bang.deck import Deck from bang.deck import Deck
from bang.game import Game from bang.game import Game
from bang.players import Player, PendingAction from bang.players import Player, PendingAction
# test card Barile # test card Barile
def test_barile(): def test_barile():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -43,9 +42,9 @@ def test_barile():
#test card Volcanic #test card Volcanic
def test_volcanic(): def test_volcanic():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -67,9 +66,9 @@ def test_volcanic():
# test card Dinamite # test card Dinamite
def test_dinamite(): def test_dinamite():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -103,9 +102,9 @@ def test_dinamite():
# test mirino # test mirino
def test_mirino(): def test_mirino():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(4)] ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -121,9 +120,9 @@ def test_mirino():
# test mustang # test mustang
def test_mustang(): def test_mustang():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -139,9 +138,9 @@ def test_mustang():
# test Prigione # test Prigione
def test_prigione(): def test_prigione():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(4)] ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -171,9 +170,9 @@ def test_prigione():
# test all weapons ranges # test all weapons ranges
def test_all_weapons(): def test_all_weapons():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(4)] ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -195,9 +194,9 @@ def test_all_weapons():
# test bang # test bang
def test_bang(): def test_bang():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -214,9 +213,9 @@ def test_bang():
# test birra # test birra
def test_birra_2p(): def test_birra_2p():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -231,9 +230,9 @@ def test_birra_2p():
# test birra # test birra
def test_birra_3p(): def test_birra_3p():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -262,9 +261,9 @@ def test_birra_3p():
# test CatBalou # test CatBalou
def test_catbalou(): def test_catbalou():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -282,9 +281,9 @@ def test_catbalou():
# test Diligenza # test Diligenza
def test_diligenza(): def test_diligenza():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(4)] ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -298,9 +297,9 @@ def test_diligenza():
# test Duello # test Duello
def test_duello(): def test_duello():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -326,9 +325,9 @@ def test_duello():
# test Emporio # test Emporio
def test_emporio(): def test_emporio():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(7)] ps = [Player(f'p{i}', f'p{i}') for i in range(7)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -352,9 +351,9 @@ def test_emporio():
# test Gatling # test Gatling
def test_gatling(): def test_gatling():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(7)] ps = [Player(f'p{i}', f'p{i}') for i in range(7)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -386,9 +385,9 @@ def test_gatling():
# test Indiani # test Indiani
def test_indiani(): def test_indiani():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(7)] ps = [Player(f'p{i}', f'p{i}') for i in range(7)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -420,9 +419,9 @@ def test_indiani():
# test Mancato # test Mancato
def test_mancato(): def test_mancato():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -442,9 +441,9 @@ def test_mancato():
# test Panico # test Panico
def test_panico(): def test_panico():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -461,9 +460,9 @@ def test_panico():
# test Saloon # test Saloon
def test_saloon(): def test_saloon():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(8)] ps = [Player(f'p{i}', f'p{i}') for i in range(8)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -480,9 +479,9 @@ def test_saloon():
# test WellsFargo # test WellsFargo
def test_wells_fargo(): def test_wells_fargo():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(4)] ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()

View File

@ -1,15 +1,14 @@
from random import randint from random import randint
from bang.characters import * from bang.characters import *
from tests.dummy_socket import DummySocket
from bang.deck import Deck from bang.deck import Deck
from bang.game import Game from bang.game import Game
from bang.players import Player, PendingAction from bang.players import Player, PendingAction
from bang.cards import * from bang.cards import *
def test_bartcassidy(): def test_bartcassidy():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -29,9 +28,9 @@ def test_bartcassidy():
assert len(g.players[(g.turn+1)%2].hand) == 1 assert len(g.players[(g.turn+1)%2].hand) == 1
def test_blackjack(): def test_blackjack():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(1)] ps = [Player(f'p{i}', f'p{i}') for i in range(1)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -62,9 +61,9 @@ def test_blackjack():
g.players[g.turn].end_turn() g.players[g.turn].end_turn()
def test_calamityjanet(): def test_calamityjanet():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -89,9 +88,9 @@ def test_calamityjanet():
assert g.players[(g.turn+1)%2].lives == 1 assert g.players[(g.turn+1)%2].lives == 1
def test_ElGringo(): def test_ElGringo():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -112,9 +111,9 @@ def test_ElGringo():
assert len(g.players[g.turn].hand) == 0 assert len(g.players[g.turn].hand) == 0
def test_JesseJones(): def test_JesseJones():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -133,9 +132,9 @@ def test_JesseJones():
assert len(g.players[g.turn].hand) == 2 assert len(g.players[g.turn].hand) == 2
def test_Jourdonnais(): def test_Jourdonnais():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -153,9 +152,9 @@ def test_Jourdonnais():
assert g.players[(g.turn+1)%2].pending_action == PendingAction.PICK assert g.players[(g.turn+1)%2].pending_action == PendingAction.PICK
def test_KitCarlson(): def test_KitCarlson():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -176,9 +175,9 @@ def test_KitCarlson():
assert g.players[g.turn].pending_action == PendingAction.PLAY assert g.players[g.turn].pending_action == PendingAction.PLAY
def test_LuckyDuke(): def test_LuckyDuke():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -198,9 +197,9 @@ def test_LuckyDuke():
assert g.players[g.turn].pending_action == PendingAction.DRAW assert g.players[g.turn].pending_action == PendingAction.DRAW
def test_PaulRegret(): def test_PaulRegret():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -214,9 +213,9 @@ def test_PaulRegret():
assert pls[0]['dist'] > g.players[0].get_sight() assert pls[0]['dist'] > g.players[0].get_sight()
def test_PedroRamirez(): def test_PedroRamirez():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -237,9 +236,9 @@ def test_PedroRamirez():
assert isinstance(g.players[g.turn].hand[0], Bang) assert isinstance(g.players[g.turn].hand[0], Bang)
def test_RoseDoolan(): def test_RoseDoolan():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -256,9 +255,9 @@ def test_RoseDoolan():
assert pls[0]['dist'] <= g.players[1].get_sight() assert pls[0]['dist'] <= g.players[1].get_sight()
def test_SidKetchum(): def test_SidKetchum():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -278,9 +277,9 @@ def test_SidKetchum():
assert g.players[g.turn].lives == 2 assert g.players[g.turn].lives == 2
def test_SlabTheKiller(): def test_SlabTheKiller():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -301,9 +300,9 @@ def test_SlabTheKiller():
assert g.players[(g.turn+1)%2].lives == 3 assert g.players[(g.turn+1)%2].lives == 3
def test_SuzyLafayette(): def test_SuzyLafayette():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -318,9 +317,9 @@ def test_SuzyLafayette():
g.players[g.turn].end_turn() g.players[g.turn].end_turn()
def test_VultureSam(): def test_VultureSam():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -341,9 +340,9 @@ def test_VultureSam():
return return
def test_WillyTheKid(): def test_WillyTheKid():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()

View File

@ -3,7 +3,7 @@ from bang.deck import Deck
from bang.game import Game from bang.game import Game
def test_card_flip(): def test_card_flip():
g = Game('test', DummySocket()) g = Game('test')
g.deck = Deck(g) g.deck = Deck(g)
l = len(g.deck.cards) l = len(g.deck.cards)
assert g.deck.pick_and_scrap() != None assert g.deck.pick_and_scrap() != None
@ -11,7 +11,7 @@ def test_card_flip():
assert len(g.deck.scrap_pile) == 1 assert len(g.deck.scrap_pile) == 1
def test_draw(): def test_draw():
g = Game('test', DummySocket()) g = Game('test')
g.deck = Deck(g) g.deck = Deck(g)
l = len(g.deck.cards) l = len(g.deck.cards)
assert g.deck.draw(True) != None assert g.deck.draw(True) != None
@ -19,7 +19,7 @@ def test_draw():
assert len(g.deck.scrap_pile) == 0 assert len(g.deck.scrap_pile) == 0
def test_reshuffle(): def test_reshuffle():
g = Game('test', DummySocket()) g = Game('test')
g.deck = Deck(g) g.deck = Deck(g)
l = len(g.deck.cards) l = len(g.deck.cards)
for i in range(80): for i in range(80):
@ -28,7 +28,7 @@ def test_reshuffle():
assert len(g.deck.scrap_pile) == 1 assert len(g.deck.scrap_pile) == 1
def test_draw_from_scrap(): def test_draw_from_scrap():
g = Game('test', DummySocket()) g = Game('test')
g.deck = Deck(g) g.deck = Deck(g)
l = len(g.deck.cards) l = len(g.deck.cards)
assert g.deck.pick_and_scrap() != None assert g.deck.pick_and_scrap() != None

View File

@ -1,4 +1,3 @@
from tests.dummy_socket import DummySocket
from bang.deck import Deck from bang.deck import Deck
from bang.game import Game from bang.game import Game
from bang.players import Player, PendingAction from bang.players import Player, PendingAction
@ -7,13 +6,13 @@ from bang.cards import *
# test that game can start # test that game can start
def test_game_start(): def test_game_start():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
p1 = Player('p1', 'p1', sio) p1 = Player('p1', 'p1')
g.add_player(p1) g.add_player(p1)
p2 = Player('p2', 'p2', sio) p2 = Player('p2', 'p2')
g.add_player(p2) g.add_player(p2)
p3 = Player('p3', 'p3', sio) p3 = Player('p3', 'p3')
g.add_player(p3) g.add_player(p3)
assert p1.role == None assert p1.role == None
assert p2.role == None assert p2.role == None
@ -37,20 +36,20 @@ def test_game_start():
# test that dodge_city is added to games with more than 8 players # test that dodge_city is added to games with more than 8 players
def test_dodge_city(): def test_dodge_city():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
for i in range(9): for i in range(9):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
assert 'dodge_city' in g.expansions assert 'dodge_city' in g.expansions
# test that a game with 2 players has only renegade as role # test that a game with 2 players has only renegade as role
def test_renegade_only(): def test_renegade_only():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
p1 = Player('p1', 'p1', sio) p1 = Player('p1', 'p1')
g.add_player(p1) g.add_player(p1)
p2 = Player('p2', 'p2', sio) p2 = Player('p2', 'p2')
g.add_player(p2) g.add_player(p2)
g.start_game() g.start_game()
assert isinstance(g.players[0].role, Renegade) assert isinstance(g.players[0].role, Renegade)
@ -58,10 +57,10 @@ def test_renegade_only():
# test that a game with 3 player has Renegade, Vice and Outlaw as roles # test that a game with 3 player has Renegade, Vice and Outlaw as roles
def test_renegade_vice_outlaw(): def test_renegade_vice_outlaw():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
for i in range(3): for i in range(3):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
roles = {p.role.name for p in g.players} roles = {p.role.name for p in g.players}
@ -69,10 +68,10 @@ def test_renegade_vice_outlaw():
# test that a game with 4 players has all roles except the deputy # test that a game with 4 players has all roles except the deputy
def test_4_players_roles(): def test_4_players_roles():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
for i in range(4): for i in range(4):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
roles = {p.role.name for p in g.players} roles = {p.role.name for p in g.players}
@ -80,10 +79,10 @@ def test_4_players_roles():
# test that a game with 5 players has all roles # test that a game with 5 players has all roles
def test_5_players_roles(): def test_5_players_roles():
sio = DummySocket()
g = Game('test', sio) g = Game('test')
for i in range(5): for i in range(5):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
roles = {p.role.name for p in g.players} roles = {p.role.name for p in g.players}

View File

@ -1,5 +1,4 @@
from bang.characters import Character from bang.characters import Character
from tests.dummy_socket import DummySocket
from bang.deck import Deck from bang.deck import Deck
from bang.game import Game from bang.game import Game
from bang.players import Player, PendingAction from bang.players import Player, PendingAction
@ -8,10 +7,9 @@ from bang.cards import *
# test that a game with 3 player the deputy kills renegade and wins # test that a game with 3 player the deputy kills renegade and wins
def test_3p_deputy_win(): def test_3p_deputy_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(3): for i in range(3):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:
@ -33,10 +31,9 @@ def test_3p_deputy_win():
# test that a game with 3 player the renegade kills the outlaw and wins # test that a game with 3 player the renegade kills the outlaw and wins
def test_3p_renegade_win(): def test_3p_renegade_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(3): for i in range(3):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:
@ -60,10 +57,9 @@ def test_3p_renegade_win():
# test that a game with 3 player the outlaw kills the deputy and wins # test that a game with 3 player the outlaw kills the deputy and wins
def test_3p_outlaw_win(): def test_3p_outlaw_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(3): for i in range(3):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:
@ -87,10 +83,9 @@ def test_3p_outlaw_win():
# test that a game with 4 player the outlaw kills the sheriff and win # test that a game with 4 player the outlaw kills the sheriff and win
def test_4p_outlaw_win(): def test_4p_outlaw_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(4): for i in range(4):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:
@ -116,10 +111,9 @@ def test_4p_outlaw_win():
# test that a game with 5 player the renegade kills all the other players and wins # test that a game with 5 player the renegade kills all the other players and wins
def test_5p_renegade_gatling_win(): def test_5p_renegade_gatling_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(5): for i in range(5):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:
@ -148,10 +142,9 @@ def test_5p_renegade_gatling_win():
# test that a game with 5 player the renegade kills all the other players and wins # test that a game with 5 player the renegade kills all the other players and wins
def test_5p_renegade_indiani_win(): def test_5p_renegade_indiani_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(5): for i in range(5):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:
@ -180,10 +173,9 @@ def test_5p_renegade_indiani_win():
# test that a game with 5 player the renegade kills the sheriff but it isn't the last alive player and the outlaws wins # test that a game with 5 player the renegade kills the sheriff but it isn't the last alive player and the outlaws wins
def test_5p_outlaw_death_win(): def test_5p_outlaw_death_win():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
for i in range(5): for i in range(5):
p = Player(f'p{i}', f'p{i}', sio) p = Player(f'p{i}', f'p{i}')
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
for p in g.players: for p in g.players:

View File

@ -1,7 +1,6 @@
from random import randint from random import randint
from bang.characters import Character from bang.characters import Character
from bang.expansions.the_valley_of_shadows.cards import * from bang.expansions.the_valley_of_shadows.cards import *
from tests.dummy_socket import DummySocket
from bang.deck import Deck from bang.deck import Deck
from bang.game import Game from bang.game import Game
from bang.players import Player, PendingAction from bang.players import Player, PendingAction
@ -9,9 +8,8 @@ import bang.cards as cs
# test UltimoGiro # test UltimoGiro
def test_ultimo_giro(): def test_ultimo_giro():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -28,9 +26,8 @@ def test_ultimo_giro():
# test Tomahawk # test Tomahawk
def test_tomahawk(): def test_tomahawk():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(6)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(6)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -48,9 +45,8 @@ def test_tomahawk():
# test Fantasma # test Fantasma
def test_fantasma(): def test_fantasma():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -73,9 +69,8 @@ def test_fantasma():
# test SerpenteASonagli # test SerpenteASonagli
def test_serpente_a_sonagli(): def test_serpente_a_sonagli():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -107,10 +102,9 @@ def test_serpente_a_sonagli():
# test RitornoDiFiamma # test RitornoDiFiamma
def test_ritorno_di_fiamma(): def test_ritorno_di_fiamma():
sio = DummySocket() g = Game('test')
g = Game('test', sio)
g.expansions = ['the_valley_of_shadows'] g.expansions = ['the_valley_of_shadows']
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -144,9 +138,8 @@ def test_ritorno_di_fiamma():
# test RitornoDiFiamma with gatling # test RitornoDiFiamma with gatling
def test_ritorno_di_fiamma_gatling(): def test_ritorno_di_fiamma_gatling():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
g.expansions = ['the_valley_of_shadows'] g.expansions = ['the_valley_of_shadows']
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
@ -177,9 +170,8 @@ def test_ritorno_di_fiamma_gatling():
# test Taglia # test Taglia
def test_taglia(): def test_taglia():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -201,9 +193,8 @@ def test_taglia():
# test Bandidos # test Bandidos
def test_bandidos(): def test_bandidos():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -233,9 +224,8 @@ def test_bandidos():
# test Poker # test Poker
def test_poker(): def test_poker():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()
@ -265,9 +255,8 @@ def test_poker():
# test Tornado # test Tornado
def test_tornado(): def test_tornado():
sio = DummySocket() g = Game('test')
g = Game('test', sio) ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)]
for p in ps: for p in ps:
g.add_player(p) g.add_player(p)
g.start_game() g.start_game()

View File

@ -0,0 +1,153 @@
<template>
<div id="overlay" class="center-stuff">
<h1>{{text}}</h1>
<div>
<Card v-if="playerCard" :card="playerCard" />
<Card v-if="playerRole" :card="playerRole" class="back"/>
</div>
</div>
</template>
<script>
import Card from '@/components/Card.vue'
export default {
name: 'DeadRoleNotification',
components: {
Card,
},
props: {
playerCard: Object,
playerRole: Object
},
data: () => ({
}),
computed: {
},
methods: {
},
mounted() {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#overlay {
position: fixed; /* Sit on top of the page content */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.7); /* Black background with opacity */
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
/* display: flex; */
color: white;
justify-content: center;
text-align: center;
}
#overlay>div {
margin:auto;
position: relative;
top:35%;
text-align: center;
width: 72pt;
transform: scale(1.5);
}
.card {
width: 72pt;
min-width:72pt;
height: 120pt;
position: absolute;
}
.card.avatarred{
animation: slide-in-fwd-bottom 2s ease, puff-out-center 1s ease 2s, make-invisible 10s step-start 3s;
}
.card.back {
animation: make-visible 3s step-end, wobble-ver-left 2s ease 3s;
}
@keyframes make-invisible {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes make-visible {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes wobble-ver-left {
0% {
transform:translateY(0) rotate(0);
transform-origin:50% 50%;
}
15% {
transform:translateY(-30px) rotate(-6deg);
}
30% {
transform:translateY(15px) rotate(6deg);
}
45% {
transform:translateY(-15px) rotate(-3.6deg);
}
60% {
transform:translateY(9px) rotate(2.4deg);
}
75% {
transform:translateY(-6px) rotate(-1.2deg);
}
100% {
transform:translateY(0) rotate(0);
transform-origin:50% 50%;
}
}
@keyframes slide-in-fwd-bottom {
0% {
transform:translateZ(-1400px) translateY(800px);
opacity:0;
}
100% {
transform:translateZ(0) translateY(0);
opacity:1;
}
}
@keyframes puff-out-center {
0% {
transform:scale(1);
filter:blur(0);
opacity:1;
}
100% {
transform:scale(2);
filter:blur(4px);
opacity:0;
}
}
.button {
background-color: #0000;
color: white;
border: 2px solid white;
transition-duration: 0.2s;
width: 100pt;
height: 24pt;
border-radius: 12pt;
cursor: pointer;
}
.button:hover {
background-color: white; /* Green */
color: black;
}
</style>

View File

@ -90,9 +90,12 @@
<transition name="bounce"> <transition name="bounce">
<div v-if="displayAdminStatus" id="admin-status"> <div v-if="displayAdminStatus" id="admin-status">
<input type="button" @click="displayAdminStatus = false" value="close"/> <input type="button" @click="displayAdminStatus = false" value="close"/>
<Status deploy_key="ok"/> <Status deploy_key="ok" :onpage="false"/>
</div> </div>
</transition> </transition>
<transition name="bounce">
<DeadRoleNotification v-if="deadRoleData" :playerCard="deadRoleData" :playerRole="deadRoleData.role"/>
</transition>
</div> </div>
</template> </template>
@ -107,6 +110,7 @@ import Deck from './Deck.vue'
import TinyHand from './TinyHand.vue' import TinyHand from './TinyHand.vue'
import FullScreenInput from './FullScreenInput.vue' import FullScreenInput from './FullScreenInput.vue'
import Status from './Status.vue' import Status from './Status.vue'
import DeadRoleNotification from './DeadRoleNotification.vue'
export default { export default {
name: 'Lobby', name: 'Lobby',
@ -119,7 +123,8 @@ export default {
TinyHand, TinyHand,
PrettyCheck, PrettyCheck,
FullScreenInput, FullScreenInput,
Status Status,
DeadRoleNotification
}, },
data: () => ({ data: () => ({
username: '', username: '',
@ -147,6 +152,7 @@ export default {
displayAdminStatus: false, displayAdminStatus: false,
is_replay: false, is_replay: false,
turn: -1, turn: -1,
deadRoleData: null,
}), }),
sockets: { sockets: {
room(data) { room(data) {
@ -174,6 +180,12 @@ export default {
} }
}) })
}, },
notify_dead_role(data) {
this.deadRoleData = data
setTimeout(() => {
this.deadRoleData = null
}, 4000);
},
debug(data) { debug(data) {
this.debug_mode = data; this.debug_mode = data;
}, },
@ -191,28 +203,10 @@ export default {
this.$router.push('/') this.$router.push('/')
} }
this.username = username this.username = username
// this.$socket.emit('get_cards', 'dodge_city')
}, },
mount_status() { mount_status() {
this.displayAdminStatus = true this.displayAdminStatus = true
}, },
// cards_info(data) {
// data = JSON.parse(data)
// let bigthing = {}
// let bigthing_eng = {}
// data.forEach(x => {
// bigthing[x.name] = {
// name:x.name,
// desc:x.desc,
// }
// bigthing_eng[x.name] = {
// name:x.name,
// desc:x.desc_eng,
// }
// })
// console.log(JSON.stringify(bigthing))
// console.log(JSON.stringify(bigthing_eng))
// },
change_username() { change_username() {
this.hasToSetUsername = true this.hasToSetUsername = true
}, },
@ -333,6 +327,7 @@ export default {
icon: icon, icon: icon,
is_character: true, is_character: true,
avatar: player.avatar, avatar: player.avatar,
is_player: true
} }
}, },
startGame() { startGame() {

View File

@ -92,6 +92,7 @@ export default {
icon: '🤠', icon: '🤠',
is_character: true, is_character: true,
avatar: this.discordPic, avatar: this.discordPic,
is_player: true
} }
}, },
version() { version() {

View File

@ -245,6 +245,7 @@ export default {
icon: this.noStar ? player.icon : player.is_sheriff ? '⭐' : '🤠', icon: this.noStar ? player.icon : player.is_sheriff ? '⭐' : '🤠',
avatar: player.avatar, avatar: player.avatar,
is_character: true, is_character: true,
is_player: true
}}) }})
return vis return vis
}, },
@ -267,6 +268,7 @@ export default {
alt_text: Array(player.lives+1).join('❤️')+Array(player.max_lives-player.lives+1).join('💀'), alt_text: Array(player.lives+1).join('❤️')+Array(player.max_lives-player.lives+1).join('💀'),
avatar: player.avatar, avatar: player.avatar,
is_character: true, is_character: true,
is_player: true
}}) }})
if (this.card_against && this.card_against.can_target_self) { if (this.card_against && this.card_against.can_target_self) {
vis.push({ vis.push({
@ -274,6 +276,7 @@ export default {
number: 0, number: 0,
icon: this.$t('you'), icon: this.$t('you'),
is_character: true, is_character: true,
is_player: true
}) })
} }
return vis return vis

View File

@ -3,6 +3,7 @@
<h1 id="status">PewPew! Server Status</h1> <h1 id="status">PewPew! Server Status</h1>
<h2>Rooms {{rooms.length}}</h2> <h2>Rooms {{rooms.length}}</h2>
<button @click="refresh">reload</button> <button @click="refresh">reload</button>
<button @click="reset">RESET</button>
<ul> <ul>
<li v-for="r in rooms" :key="r"> <li v-for="r in rooms" :key="r">
<p style="margin:0"><b>name:</b> {{r.name}}</p> <p style="margin:0"><b>name:</b> {{r.name}}</p>
@ -37,7 +38,7 @@ export default {
props: { props: {
onpage: { onpage: {
type: Boolean, type: Boolean,
default: false default: true
} }
}, },
data:()=>({ data:()=>({
@ -60,6 +61,11 @@ export default {
refresh(){ refresh(){
this.$socket.emit('get_all_rooms', this.deploy_key) this.$socket.emit('get_all_rooms', this.deploy_key)
}, },
reset(){
if (confirm('ARE YOU SURE? KICK EVERYONE AND RESET LOBBIES?'))
this.$socket.emit('reset', {'key':this.deploy_key})
this.refresh();
},
hide(room_name){ hide(room_name){
this.$socket.emit('hide_toogle', {'key':this.deploy_key, 'room':room_name}) this.$socket.emit('hide_toogle', {'key':this.deploy_key, 'room':room_name})
setTimeout((()=>{ setTimeout((()=>{