@ -10,7 +10,10 @@ from bang.players import Player
|
||||
sio = socketio.Server(cors_allowed_origins="*")
|
||||
app = socketio.WSGIApp(sio, static_files={
|
||||
'/': {'content_type': 'text/html', 'filename': 'index.html'},
|
||||
'/game': {'content_type': 'text/html', 'filename': 'index.html'},
|
||||
'/favicon.ico': {'filename': 'favicon.ico'},
|
||||
'/img/icons': './img/icons',
|
||||
'/manifest.json': {'filename': 'manifest.json'},
|
||||
'/css': './css',
|
||||
'/js': './js',
|
||||
})
|
||||
@ -23,27 +26,51 @@ def advertise_lobbies():
|
||||
|
||||
@sio.event
|
||||
def connect(sid, environ):
|
||||
global online_players
|
||||
online_players += 1
|
||||
print('connect ', sid)
|
||||
sio.enter_room(sid, 'lobby')
|
||||
sio.emit('players', room='lobby', data=online_players)
|
||||
|
||||
@sio.event
|
||||
def set_username(sid, username):
|
||||
global online_players
|
||||
online_players += 1
|
||||
if not isinstance(sio.get_session(sid), Player):
|
||||
sio.save_session(sid, Player(username, sid, sio))
|
||||
print(f'{sid} is now {username}')
|
||||
advertise_lobbies()
|
||||
elif sio.get_session(sid).game == None or not sio.get_session(sid).game.started:
|
||||
print(f'{sid} changed username to {username}')
|
||||
if len([p for p in sio.get_session(sid).game.players if p.name == username]) > 0:
|
||||
sio.get_session(sid).name = f'{username}_{random.randint(0,100)}'
|
||||
else:
|
||||
sio.get_session(sid).name = username
|
||||
sio.emit('me', data=sio.get_session(sid).name, room=sid)
|
||||
sio.get_session(sid).game.notify_room()
|
||||
|
||||
@sio.event
|
||||
def my_message(sid, data):
|
||||
print('message ', data)
|
||||
def get_me(sid, room):
|
||||
if isinstance(sio.get_session(sid), Player):
|
||||
sio.emit('me', data=sio.get_session(sid).name, room=sid)
|
||||
if sio.get_session(sid).game:
|
||||
sio.get_session(sid).game.notify_room()
|
||||
else:
|
||||
sio.save_session(sid, Player('player', sid, sio))
|
||||
de_games = [g for g in games if g.name == room['name']]
|
||||
if len(de_games) == 1 and not de_games[0].started:
|
||||
join_room(sid, room)
|
||||
else:
|
||||
create_room(sid, room['name'])
|
||||
if sio.get_session(sid).game == None:
|
||||
sio.emit('me', data={'error':'Wrong password/Cannot connect'}, room=sid)
|
||||
else:
|
||||
sio.emit('me', data=sio.get_session(sid).name, room=sid)
|
||||
sio.emit('change_username', room=sid)
|
||||
|
||||
@sio.event
|
||||
def disconnect(sid):
|
||||
global online_players
|
||||
if sio.get_session(sid):
|
||||
online_players -= 1
|
||||
if sio.get_session(sid):
|
||||
sio.emit('players', room='lobby', data=online_players)
|
||||
if sio.get_session(sid).game and sio.get_session(sid).disconnect():
|
||||
sio.close_room(sio.get_session(sid).game.name)
|
||||
@ -85,6 +112,7 @@ def join_room(sid, room):
|
||||
sio.enter_room(sid, room_name)
|
||||
while len([p for p in games[i].players if p.name == sio.get_session(sid).name]):
|
||||
sio.get_session(sid).name += f'_{random.randint(0,100)}'
|
||||
sio.emit('me', data=sio.get_session(sid).name, room=sid)
|
||||
games[i].add_player(sio.get_session(sid))
|
||||
advertise_lobbies()
|
||||
|
||||
|
@ -80,6 +80,7 @@ class Barile(Card):
|
||||
super().__init__(suit, 'Barile', number, is_equipment=True)
|
||||
self.icon = '🛢'
|
||||
self.desc = "Quando sei bersagliato da un Bang puoi estrarre la prima carta dalla cima del mazzo, se la carta estratta è del seme Cuori allora vale come un Mancato"
|
||||
self.desc_eng = "When someone plays a Bang against you. You can flip the first card from the deck, if the suit is Hearts then it counts as a Missed card"
|
||||
|
||||
|
||||
class Dinamite(Card):
|
||||
@ -87,6 +88,7 @@ class Dinamite(Card):
|
||||
super().__init__(suit, 'Dinamite', number, is_equipment=True)
|
||||
self.icon = '🧨'
|
||||
self.desc = "Giocando la Dinamite, posizionala davanti a te, resterà innocua per un intero giro. All'inizio del prossimo turno prima di pescare e prima di una eventuale estrazione (es. Prigione), estrai una carta dalla cima del mazzo. Se esce una carta tra il 2 il 9 di picche (compresi) allora la dinamite esplode: perdi 3 vite e scarta la carta, altrimenti passa la dinamite al giocatore successivo, il quale estrarà a sua volta dopo che tu avrai passato il tuo turno"
|
||||
self.desc_eng = "When playing Dynamite, place it in front of you, it will remain harmless for a whole round. At the beginning of the next turn before drawing and before any card flip (eg Prison), flip a card from the top of the deck. If a card is between 2 and 9 of spades (inclusive) then the dynamite explodes: you lose 3 lives and discard the card, otherwise pass the dynamite to the next player, who will draw in turn after you have ended your turn"
|
||||
|
||||
|
||||
class Mirino(Card):
|
||||
@ -94,6 +96,7 @@ class Mirino(Card):
|
||||
super().__init__(suit, 'Mirino', number, is_equipment=True, sight_mod=1)
|
||||
self.icon = '🔎'
|
||||
self.desc = "Tu vedi gli altri giocatori a distanza -1"
|
||||
self.desc_eng = "You see the other players at distance -1"
|
||||
|
||||
|
||||
class Mustang(Card):
|
||||
@ -101,6 +104,7 @@ class Mustang(Card):
|
||||
super().__init__(suit, 'Mustang', number, is_equipment=True, vis_mod=1)
|
||||
self.icon = '🐎'
|
||||
self.desc = "Gli altri giocatori ti vedono a distanza +1"
|
||||
self.desc_eng = "The other players see you at distance +1"
|
||||
|
||||
|
||||
class Prigione(Card):
|
||||
@ -108,6 +112,7 @@ class Prigione(Card):
|
||||
super().__init__(suit, 'Prigione', number, is_equipment=True)
|
||||
self.icon = '⛓'
|
||||
self.desc = "Equipaggia questa carta a un altro giocatore, tranne lo Sceriffo. Il giocatore scelto all'inizio del suo turno, prima di pescare dovrà estrarre: se esce Cuori scarta questa carta e gioca normalmente il turno, altrimenti scarta questa carta e salta il turno"
|
||||
self.desc_eng = "Equip this card to another player, except the Sheriff. The player chosen at the beginning of his turn, must flip a card before drawing: if it's Hearts, discard this card and play the turn normally, otherwise discard this card and skip the turn"
|
||||
self.need_target = True
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
@ -124,6 +129,7 @@ class Remington(Card):
|
||||
is_equipment=True, is_weapon=True, range=3)
|
||||
self.icon = '🔫'
|
||||
self.desc = "Puoi sparare a un giocatore che sia distante 3 o meno"
|
||||
self.desc_eng = "You can shoot another player at distance 3 or less"
|
||||
|
||||
|
||||
class RevCarabine(Card):
|
||||
@ -132,6 +138,7 @@ class RevCarabine(Card):
|
||||
is_equipment=True, is_weapon=True, range=4)
|
||||
self.icon = '🔫'
|
||||
self.desc = "Puoi sparare a un giocatore che sia distante 4 o meno"
|
||||
self.desc_eng = "You can shoot another player at distance 4 or less"
|
||||
|
||||
|
||||
class Schofield(Card):
|
||||
@ -140,6 +147,7 @@ class Schofield(Card):
|
||||
is_equipment=True, is_weapon=True, range=2)
|
||||
self.icon = '🔫'
|
||||
self.desc = "Puoi sparare a un giocatore che sia distante 2 o meno"
|
||||
self.desc_eng = "You can shoot another player at distance 2 or less"
|
||||
|
||||
|
||||
class Volcanic(Card):
|
||||
@ -148,6 +156,7 @@ class Volcanic(Card):
|
||||
is_equipment=True, is_weapon=True, range=1)
|
||||
self.icon = '🔫'
|
||||
self.desc = "Puoi sparare a un giocatore che sia distante 1 o meno, tuttavia puoi giocare quanti bang vuoi"
|
||||
self.desc_eng = "You can shoot another player at distance 1 or less, however you no longer have the limit of 1 Bang"
|
||||
|
||||
|
||||
class Winchester(Card):
|
||||
@ -156,6 +165,7 @@ class Winchester(Card):
|
||||
is_equipment=True, is_weapon=True, range=5)
|
||||
self.icon = '🔫'
|
||||
self.desc = "Puoi sparare a un giocatore che sia distante 5 o meno"
|
||||
self.desc_eng = "You can shoot another player at distance 5 or less"
|
||||
|
||||
|
||||
class Bang(Card):
|
||||
@ -163,6 +173,7 @@ class Bang(Card):
|
||||
super().__init__(suit, 'Bang!', number)
|
||||
self.icon = '💥'
|
||||
self.desc = "Spara a un giocatore a distanza raggiungibile. Se non hai armi la distanza di default è 1"
|
||||
self.desc_eng = "Shoot a player in sight. If you do not have weapons, your is sight is 1"
|
||||
self.need_target = True
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
@ -173,7 +184,7 @@ class Bang(Card):
|
||||
super().play_card(player, against=against)
|
||||
player.has_played_bang = not isinstance(
|
||||
player.character, chars.WillyTheKid)
|
||||
player.game.attack(player, against)
|
||||
player.game.attack(player, against, double=isinstance(player.character, chars.SlabTheKiller))
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -183,11 +194,15 @@ class Birra(Card):
|
||||
super().__init__(suit, 'Birra', number)
|
||||
self.icon = '🍺'
|
||||
self.desc = "Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori"
|
||||
self.desc_eng = "Play this card to regain a life point. You cannot heal more than your character's maximum limit. If you are about to lose your last life point, you can also play this card on your opponent's turn. Beer no longer takes effect if there are only two players"
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
if len(player.game.players) != 2:
|
||||
super().play_card(player, against=against)
|
||||
player.lives = min(player.lives+1, player.max_lives)
|
||||
import bang.expansions.dodge_city.characters as chd
|
||||
if isinstance(player.character, chd.TequilaJoe):
|
||||
player.lives = min(player.lives+1, player.max_lives)
|
||||
return True
|
||||
elif len(player.game.players) == 2:
|
||||
player.sio.emit('chat_message', room=player.game.name,
|
||||
@ -201,6 +216,7 @@ class CatBalou(Card):
|
||||
super().__init__(suit, 'Cat Balou', number)
|
||||
self.icon = '💃'
|
||||
self.desc = "Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
|
||||
self.desc_eng = "Choose and discard a card from any other player."
|
||||
self.need_target = True
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
@ -221,9 +237,9 @@ class Diligenza(Card):
|
||||
super().__init__(suit, 'Diligenza', number)
|
||||
self.icon = '🚡'
|
||||
self.desc = "Pesca 2 carte dalla cima del mazzo"
|
||||
self.desc_eng = "Draw 2 cards from the deck."
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
super().play_card(player, against=against)
|
||||
player.sio.emit('chat_message', room=player.game.name,
|
||||
data=f'{player.name} ha giocato {self.name} e ha pescato 2 carte.')
|
||||
for i in range(2):
|
||||
@ -237,6 +253,7 @@ class Duello(Card):
|
||||
self.need_target = True
|
||||
self.icon = '⚔️'
|
||||
self.desc = "Gioca questa carta contro un qualsiasi giocatore. A turno, cominciando dal tuo avversario, potete scartare una carta Bang!, il primo giocatore che non lo fa perde 1 vita"
|
||||
self.desc_eng = "Play this card against any player. In turn, starting with your opponent, you can discard a Bang! Card, the first player who does not do so loses 1 life."
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
if against != None:
|
||||
@ -250,7 +267,8 @@ class Emporio(Card):
|
||||
def __init__(self, suit, number):
|
||||
super().__init__(suit, 'Emporio', number)
|
||||
self.icon = '🏪'
|
||||
self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano"
|
||||
self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori vivi, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano"
|
||||
self.desc_eng = "Put on the table N cards from the deck, where N is the number of alive players, in turn, starting with you, choose a card and add it to your hand"
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
super().play_card(player, against=against)
|
||||
@ -263,6 +281,7 @@ class Gatling(Card):
|
||||
super().__init__(suit, 'Gatling', number)
|
||||
self.icon = '🛰'
|
||||
self.desc = "Spara a tutti gli altri giocatori"
|
||||
self.desc_eng = "Shoot all the other players"
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
super().play_card(player, against=against)
|
||||
@ -275,6 +294,7 @@ class Indiani(Card):
|
||||
super().__init__(suit, 'Indiani!', number)
|
||||
self.icon = '🏹'
|
||||
self.desc = "Tutti gli altri giocatori devono scartare un Bang! o perdere una vita"
|
||||
self.desc_eng = "All the other players must discard a Bang! or lose 1 Health Point"
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
super().play_card(player, against=against)
|
||||
@ -286,7 +306,8 @@ class Mancato(Card):
|
||||
def __init__(self, suit, number):
|
||||
super().__init__(suit, 'Mancato!', number)
|
||||
self.icon = '😅'
|
||||
self.desc = "Usa questa carta per annullare un Bang!"
|
||||
self.desc = "Usa questa carta per annullare un bang"
|
||||
self.desc_eng = "Use this card to cancel the effect of a bang"
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
import bang.characters as chars
|
||||
@ -305,6 +326,7 @@ class Panico(Card):
|
||||
self.icon = '😱'
|
||||
self.need_target = True
|
||||
self.desc = "Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
|
||||
self.desc_eng = "Steal a card from a player at distance 1"
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0:
|
||||
@ -322,6 +344,7 @@ class Saloon(Card):
|
||||
def __init__(self, suit, number):
|
||||
super().__init__(suit, 'Saloon', number)
|
||||
self.desc = "Tutti i giocatori recuperano un punto vita compreso chi gioca la carta"
|
||||
self.desc_eng = "Everyone heals 1 Health point"
|
||||
self.icon = '🍻'
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
@ -337,6 +360,7 @@ class WellsFargo(Card):
|
||||
def __init__(self, suit, number):
|
||||
super().__init__(suit, 'WellsFargo', number)
|
||||
self.desc = "Pesca 3 carte dalla cima del mazzo"
|
||||
self.desc_eng = "Draw 3 cards from the deck"
|
||||
self.icon = '💸'
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
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 = ''):
|
||||
@ -32,8 +33,8 @@ class BartCassidy(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Bart Cassidy", max_lives=4)
|
||||
self.desc = "Ogni volta che viene ferito, pesca una carta"
|
||||
self.desc_eng = "Each time he is hurt, he draws a card"
|
||||
self.icon = '💔'
|
||||
#una sola carta per ogni gruppo di danni. es: dinamite -> 1 carta
|
||||
|
||||
def on_hurt(self, dmg):
|
||||
pass
|
||||
@ -42,6 +43,7 @@ class BlackJack(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Black Jack", max_lives=4)
|
||||
self.desc = "All'inizio del suo turno, quando deve pescare, mostra a tutti la seconda carta, se è Cuori o Quadri pesca una terza carta senza farla vedere"
|
||||
self.desc_eng = "At the beginning of his turn, when he has to draw, he shows everyone the second card, if it is Hearts or Diamonds he draws a third card without showing it"
|
||||
self.icon = '🎰'
|
||||
|
||||
class CalamityJanet(Character):
|
||||
@ -49,14 +51,13 @@ class CalamityJanet(Character):
|
||||
super().__init__("Calamity Janet", max_lives=4)
|
||||
self.icon = '🔀'
|
||||
self.desc = "Può usare i Mancato! come Bang! e viceversa"
|
||||
#TODO: gestire bene la scelta multipla in ogni iterazione con la carta bang e mancato
|
||||
# vale anche per le carte indiani e duello
|
||||
# se usa un mancato come bang ovviamente non ne può usare altri lo stesso turno se non ha una volcanic
|
||||
self.desc_eng = "She can use the Missed! as Bang! and the other way around"
|
||||
|
||||
class ElGringo(Character):
|
||||
def __init__(self):
|
||||
super().__init__("El Gringo", max_lives=3)
|
||||
self.desc = "Ogni volta che perde un punto vita pesca una carta dalla mano del giocatore responsabile ma solo se il giocatore in questione ha carte in mano (una carta per ogni punto vita)"
|
||||
self.desc_eng = "Each time he is hurt, he draws a card from the hand of the attacking player"
|
||||
self.icon = '🤕'
|
||||
# ovviamente la dinamite non è considerata danno inferto da un giocatore
|
||||
|
||||
@ -64,36 +65,42 @@ class JesseJones(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Jesse Jones", max_lives=4)
|
||||
self.desc = "All'inizio del suo turno, quando deve pescare, può prendere la prima carta a caso dalla mano di un giocatore e la seconda dal mazzo"
|
||||
self.desc_eng = "When he has to draw his cards, he may draw the first card from the hand of another player"
|
||||
self.icon = '😜'
|
||||
|
||||
class Jourdonnais(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Jourdonnais", max_lives=4)
|
||||
self.desc = "Gioca come se avesse un Barile sempre attivo, nel caso in cui metta in gioco un Barile 'Reale' può estrarre due volte"
|
||||
self.desc_eng = "He plays as he had a Barrel always active, if he equips another Barrel, he can flip 2 cards"
|
||||
self.icon = '🛢'
|
||||
|
||||
class KitCarlson(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Kit Carlson", max_lives=4)
|
||||
self.desc = "All'inizio del suo turno, quando deve pescare, pesca tre carte, ne sceglie due da tenere in mano e la rimanente la rimette in cima la mazzo"
|
||||
self.desc_eng = "When he has to draw, he peeks 3 cards and chooses 2, putting the other card on the top of the deck"
|
||||
self.icon = '🤔'
|
||||
|
||||
class LuckyDuke(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Lucky Duke", max_lives=4, pick_mod=1)
|
||||
self.desc = "Ogni volta che deve estrarre, prende due carte dal mazzo, sceglie una delle due carte per l'estrazione, infine le scarta entrambe"
|
||||
self.desc_eng = "Every time he has to flip a card, he can flip 2 times"
|
||||
self.icon = '🍀'
|
||||
|
||||
class PaulRegret(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Paul Regret", max_lives=3, visibility_mod=1)
|
||||
self.desc = "Gioca come se avesse una Mustang sempre attiva, nel caso in cui metta in gioco una Mustang 'Reale' l'effetto si somma tranquillamente"
|
||||
self.desc_eng = "The other players see him at distance +1"
|
||||
self.icon = '🏇'
|
||||
|
||||
class PedroRamirez(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Pedro Ramirez", max_lives=4)
|
||||
self.desc = "All'inizio del suo turno, quando deve pescare, può prendere la prima carta dalla cima degli scarti e la seconda dal mazzo"
|
||||
self.desc_eng = "When he has to draw, he may pick the first card from the discarded cards"
|
||||
self.icon = '🚮'
|
||||
|
||||
class RoseDoolan(Character):
|
||||
@ -101,17 +108,20 @@ class RoseDoolan(Character):
|
||||
super().__init__("Rose Doolan", max_lives=4, sight_mod=1)
|
||||
self.icon = '🕵️♀️'
|
||||
self.desc = "Gioca come se avesse un Mirino sempre attivo, nel caso in cui metta in gioco una Mirino 'Reale' l'effetto si somma tranquillamente"
|
||||
self.desc_eng = "She sees the other players at distance -1"
|
||||
|
||||
class SidKetchum(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Sid Ketchum", max_lives=4)
|
||||
self.desc = "Può scartare due carte per recuperare un punto vita anche più volte di seguito a patto di avere carte da scartare, può farlo anche nel turno dell'avversario se starebbe per morire"
|
||||
self.desc_eng = "He can discard 2 cards to regain 1HP"
|
||||
self.icon = '🤤'
|
||||
|
||||
class SlabTheKiller(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Slab The Killer", max_lives=4)
|
||||
self.desc = "Per evitare i suoi Bang servono due Mancato, un eventuale barile vale solo come un Mancato"
|
||||
self.desc_eng = "To dodge his Bang! cards other players need 2 Missed!"
|
||||
self.icon = '🔪'
|
||||
#vale per tutte le carte bang non solo per la carta che si chiama Bang!
|
||||
|
||||
@ -119,22 +129,26 @@ class SuzyLafayette(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Suzy Lafayette", max_lives=4)
|
||||
self.desc = "Appena rimane senza carte in mano pesca immediatamente una carta dal mazzo"
|
||||
self.desc_eng = "Whenever she has an empty hand, she draws a card"
|
||||
self.icon = '🔂'
|
||||
|
||||
class VultureSam(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Vulture Sam", max_lives=4)
|
||||
self.desc = "Quando un personaggio viene eliminato prendi tutte le carte di quel giocatore e aggiungile alla tua mano, sia le carte in mano che quelle in gioco"
|
||||
self.desc_eng = "When a player dies, he gets all the cards in the dead's hand and equipments"
|
||||
self.icon = '💰'
|
||||
|
||||
class WillyTheKid(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Willy The Kid", max_lives=4)
|
||||
self.desc = "Questo personaggio può giocare quanti bang vuole nel suo turno"
|
||||
self.desc_eng = "He doesn't have limits to the amounts of bang he can use"
|
||||
self.icon = '🎉'
|
||||
|
||||
def all_characters():
|
||||
return [
|
||||
def all_characters(expansions: List[str]):
|
||||
from bang.expansions import DodgeCity
|
||||
base_chars = [
|
||||
BartCassidy(),
|
||||
BlackJack(),
|
||||
CalamityJanet(),
|
||||
@ -152,3 +166,6 @@ def all_characters():
|
||||
VultureSam(),
|
||||
WillyTheKid(),
|
||||
]
|
||||
if 'dodge_city' in expansions:
|
||||
base_chars.extend(DodgeCity.get_characters())
|
||||
return base_chars
|
@ -10,6 +10,10 @@ class Deck:
|
||||
for c in self.cards:
|
||||
if isinstance(c, cs.Mancato) and c.name not in self.mancato_cards:
|
||||
self.mancato_cards.append(c.name)
|
||||
self.all_cards_str: List[str] = []
|
||||
for c in self.cards:
|
||||
if c.name not in self.all_cards_str:
|
||||
self.all_cards_str.append(c.name)
|
||||
self.game = game
|
||||
random.shuffle(self.cards)
|
||||
self.scrap_pile: List[cs.Card] = []
|
||||
|
@ -1,5 +1,7 @@
|
||||
|
||||
from bang.expansions.dodge_city import cards
|
||||
from bang.expansions.dodge_city import cards, characters
|
||||
class DodgeCity():
|
||||
def get_characters():
|
||||
return characters.all_characters()
|
||||
def get_cards():
|
||||
return cards.get_starting_deck()
|
@ -17,6 +17,7 @@ class Pugno(Card):
|
||||
super().__init__(suit, 'Pugno!', number, range=1)
|
||||
self.icon = '👊'
|
||||
self.desc = "Spara a un giocatore a distanza 1"
|
||||
self.desc_eng = "Shoot a player at distance 1"
|
||||
self.need_target = True
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
@ -31,7 +32,8 @@ class Schivata(Mancato):
|
||||
super().__init__(suit, number)
|
||||
self.name = 'Schivata'
|
||||
self.icon = '🙅♂️'
|
||||
self.desc = "Usa questa carta per annullare un Bang! e poi pesca una carta"
|
||||
self.desc += " e poi pesca una carta"
|
||||
self.desc_eng += " and then draw a card."
|
||||
self.alt_text = '☝️🆓'
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
@ -46,6 +48,7 @@ class RagTime(Panico):
|
||||
Card.__init__(self, suit, 'Rag Time', number)
|
||||
self.icon = '🎹'
|
||||
self.desc = "Ruba 1 carta dalla mano di un giocatore a prescindere dalla distanza"
|
||||
self.desc_eng = "Steal a card from another player at any distance"
|
||||
self.need_target = True
|
||||
self.need_with = True
|
||||
self.alt_text = '2🃏'
|
||||
@ -63,6 +66,7 @@ class Rissa(CatBalou):
|
||||
self.name = 'Rissa'
|
||||
self.icon = '🥊'
|
||||
self.desc = "Fai scartare una carta a tutti gli altri giocatori, scegli a caso dalla mano, oppure fra quelle che hanno in gioco"
|
||||
self.desc_eng = "Choose a card to discard from the hand/equipment ofc all the other players"
|
||||
self.need_with = True
|
||||
self.need_target = False
|
||||
self.alt_text = '2🃏'
|
||||
@ -75,7 +79,7 @@ class Rissa(CatBalou):
|
||||
player.game.deck.scrap(_with)
|
||||
player.event_type = 'rissa'
|
||||
super().play_card(player, against=players_with_cards[0])
|
||||
player.sio.emit('chat_message', room=player.game.name, data=f'{player.name} ha giocato {self.name}')
|
||||
player.sio.emit('chat_message', room=player.game.name, data=f'{player.name} ha giocato {self.name}.')
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -84,6 +88,7 @@ class SpringField(Card):
|
||||
super().__init__(suit, 'Springfield', number)
|
||||
self.icon = '🌵'
|
||||
self.desc = "Spara a un giocatore a prescindere dalla distanza"
|
||||
self.desc_eng = "Shoot a player at any distance"
|
||||
self.need_target = True
|
||||
self.need_with = True
|
||||
self.alt_text = '2🃏'
|
||||
@ -101,6 +106,7 @@ class Tequila(Card):
|
||||
super().__init__(suit, 'Tequila', number)
|
||||
self.icon = '🍹'
|
||||
self.desc = "Fai recuperare 1 vita a un giocatore a tua scelta, anche te stesso"
|
||||
self.desc_eng = "Heal 1 HP to a player of your choice (can be you)"
|
||||
self.need_target = True
|
||||
self.can_target_self = True
|
||||
self.need_with = True
|
||||
@ -121,6 +127,7 @@ class Whisky(Card):
|
||||
super().__init__(suit, 'Whisky', number)
|
||||
self.icon = '🥃'
|
||||
self.desc = "Gioca questa carta per recuperare fino a 2 punti vita"
|
||||
self.desc_eng = "Heal 2 HP"
|
||||
self.need_with = True
|
||||
self.alt_text = '2🃏'
|
||||
|
||||
@ -149,10 +156,6 @@ class Bibbia(Schivata):
|
||||
player.equipment.append(self)
|
||||
return True
|
||||
|
||||
def use_card(self, player):
|
||||
player.hand.append(player.game.deck.draw())
|
||||
player.notify_self()
|
||||
|
||||
class Cappello(Mancato):
|
||||
def __init__(self, suit, number):
|
||||
super().__init__(suit, number)
|
||||
@ -202,6 +205,8 @@ class Derringer(Pugnale):
|
||||
self.name = 'Derringer'
|
||||
self.icon = '🚬'
|
||||
self.alt_text += ' ☝️🆓'
|
||||
self.desc += ' e poi pesca una carta'
|
||||
self.desc_eng += ' and then draw a card.'
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
if self.can_be_used_now:
|
||||
@ -211,17 +216,25 @@ class Derringer(Pugnale):
|
||||
player.equipment.append(self)
|
||||
return True
|
||||
|
||||
class Borraccia(Birra):
|
||||
def use_card(self, player):
|
||||
player.hand.append(player.game.deck.draw())
|
||||
player.notify_self()
|
||||
|
||||
class Borraccia(Card):
|
||||
def __init__(self, suit, number):
|
||||
super().__init__(suit, number)
|
||||
self.name = 'Borraccia'
|
||||
super().__init__(suit, 'Borraccia', number)
|
||||
self.icon = '🍼'
|
||||
self.desc = 'Recupera 1 vita'
|
||||
self.desc_eng = 'Regain 1 HP'
|
||||
self.usable_next_turn = True
|
||||
self.can_be_used_now = False
|
||||
|
||||
def play_card(self, player, against, _with=None):
|
||||
if self.can_be_used_now:
|
||||
return super().play_card(player, against)
|
||||
super().play_card(player, against)
|
||||
player.lives = min(player.lives+1, player.max_lives)
|
||||
player.notify_self()
|
||||
return True
|
||||
else:
|
||||
player.equipment.append(self)
|
||||
return True
|
||||
|
84
backend/bang/expansions/dodge_city/characters.py
Normal file
@ -0,0 +1,84 @@
|
||||
from typing import List
|
||||
from bang.characters import *
|
||||
|
||||
class PixiePete(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Pixie Pete", max_lives=3)
|
||||
self.desc = "All'inizio del turno pesca 3 carte invece che 2"
|
||||
self.desc_eng = "He draws 3 cards instead of 2"
|
||||
self.icon = '☘️'
|
||||
|
||||
class TequilaJoe(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Tequila Joe", max_lives=4)
|
||||
self.desc = "Se gioca la carta Birra recupera 2 vite invece che una sola"
|
||||
self.desc_eng = "When he plays Beer, he regains 2 Health Points"
|
||||
self.icon = '🍻'
|
||||
|
||||
class GregDigger(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Greg Digger", max_lives=4)
|
||||
self.desc = "Quando un giocatore muore, recupera fino a 2 vite"
|
||||
self.desc_eng = "Whenever a player dies, he regains up to 2 lives"
|
||||
self.icon = '🦴'
|
||||
|
||||
class HerbHunter(Character):
|
||||
def __init__(self):
|
||||
super().__init__("HerbHunter", max_lives=4)
|
||||
self.desc = "Quando un giocatore muore, pesca 2 carte"
|
||||
self.desc_eng = "Whenever a player dies, he draws 2 cards"
|
||||
self.icon = '⚰️'
|
||||
|
||||
class ElenaFuente(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Elena Fuente", max_lives=3)
|
||||
self.desc = "Può usare una carta qualsiasi nella sua mano come mancato"
|
||||
self.desc_eng = "She can use any card of her hand as missed"
|
||||
self.icon = '🧘♀️'
|
||||
|
||||
class BillNoface(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Bill Noface", max_lives=4)
|
||||
self.desc = "All'inizio del turno pesca 1 carta + 1 carta per ogni ferita che ha"
|
||||
self.desc_eng = "Draw 1 card + 1 card for each wound he has"
|
||||
self.icon = '🙈'
|
||||
|
||||
class MollyStark(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Molly Stark", max_lives=4)
|
||||
self.desc = "Quando usa volontariamente una carta che ha in mano, fuori dal suo turno, ne ottiene un'altra dal mazzo"
|
||||
self.desc_eng = "When she uses a card from her hand outside her turn, he draws a card."
|
||||
self.icon = '🙅♀️'
|
||||
|
||||
class ApacheKid(Character):
|
||||
def __init__(self):
|
||||
super().__init__("Apache Kid", max_lives=3)
|
||||
self.desc = "Le carte di quadri ♦️ giocate contro di lui non hanno effetto (non vale durante i duelli)"
|
||||
self.desc_eng = "Cards of diamonds ♦️ played against him, do no have effect (doesn't work in duels)."
|
||||
self.icon = '♦️'
|
||||
|
||||
def all_characters() -> List[Character]:
|
||||
return [
|
||||
PixiePete(),
|
||||
TequilaJoe(),
|
||||
GregDigger(),
|
||||
HerbHunter(),
|
||||
ElenaFuente(),
|
||||
BillNoface(),
|
||||
MollyStark(),
|
||||
ApacheKid(),
|
||||
]
|
||||
|
||||
#Apache Kid: il suo effetto non conta nei duelli
|
||||
#belle star: vale solo per le carte blu e verdi
|
||||
#chuck wengam: può usarlo più volte in un turno, ma non può suicidarsi
|
||||
#doc holiday: il suo effetto non conta nel limite di un bang per turno,
|
||||
# se deve sparare a Apache Kid una delle due carte scartate non deve essere di quadri
|
||||
#molly stark: le carte scartate che valgono sono solo quelle scartate volontariamente,
|
||||
# carte scartate per colpa di can can, cat balou, rissa, panico non valgono,
|
||||
# invece carte scartata per indiani, birra(in caso di morte), o un mancato valgono,
|
||||
# in un duello pesca solo quando il duello è finito (una carta x ogni bang scartato)
|
||||
#pat brennan: quando pesca con il suo effetto, pesca solo la carta del giocatore non anche dal mazzo
|
||||
#vera custer: la scelta può essere fatta solo appena prima di pescare,
|
||||
# quando inizia la partita serve farle scegliere, poi può rimanere quello finchè non decide di cambiarlo
|
||||
# eventualmente fare una schermata dove vede tutti i personaggi
|
@ -6,6 +6,7 @@ import bang.players as players
|
||||
import bang.characters as characters
|
||||
from bang.deck import Deck
|
||||
import bang.roles as roles
|
||||
import eventlet
|
||||
|
||||
class Game:
|
||||
def __init__(self, name, sio:socketio):
|
||||
@ -13,6 +14,7 @@ class Game:
|
||||
self.sio = sio
|
||||
self.name = name
|
||||
self.players: List[players.Player] = []
|
||||
self.dead_players: List[players.Player] = []
|
||||
self.deck: Deck = None
|
||||
self.started = False
|
||||
self.turn = 0
|
||||
@ -62,10 +64,12 @@ class Game:
|
||||
self.notify_room()
|
||||
|
||||
def notify_character_selection(self):
|
||||
self.readyCount += 1
|
||||
self.notify_room()
|
||||
if self.readyCount == len(self.players):
|
||||
if len([p for p in self.players if p.character == None]) == 0:
|
||||
for i in range(len(self.players)):
|
||||
print(self.name)
|
||||
print(self.players[i].name)
|
||||
print(self.players[i].character)
|
||||
self.sio.emit('chat_message', room=self.name, data=f'{self.players[i].name} ha come personaggio {self.players[i].character.name}, la sua abilità speciale è: {self.players[i].character.desc}')
|
||||
self.players[i].prepare()
|
||||
for k in range(self.players[i].max_lives):
|
||||
@ -74,7 +78,7 @@ class Game:
|
||||
self.players[self.turn].play_turn()
|
||||
|
||||
def choose_characters(self):
|
||||
char_cards = random.sample(characters.all_characters(), len(self.players)*2)
|
||||
char_cards = random.sample(characters.all_characters(self.expansions), len(self.players)*2)
|
||||
for i in range(len(self.players)):
|
||||
self.players[i].set_available_character(char_cards[i * 2 : i * 2 + 2])
|
||||
|
||||
@ -137,8 +141,8 @@ class Game:
|
||||
attacker.pending_action = players.PendingAction.PLAY
|
||||
attacker.notify_self()
|
||||
|
||||
def attack(self, attacker: players.Player, target_username:str):
|
||||
if self.players[self.players_map[target_username]].get_banged(attacker=attacker, double=isinstance(attacker.character, characters.SlabTheKiller)):
|
||||
def attack(self, attacker: players.Player, target_username:str, double:bool=False):
|
||||
if self.players[self.players_map[target_username]].get_banged(attacker=attacker, double=double):
|
||||
self.readyCount = 0
|
||||
self.waiting_for = 1
|
||||
attacker.pending_action = players.PendingAction.WAIT
|
||||
@ -202,13 +206,14 @@ class Game:
|
||||
|
||||
def handle_disconnect(self, player: players.Player):
|
||||
print(f'player {player.name} left the game {self.name}')
|
||||
self.player_death(player=player)
|
||||
self.player_death(player=player, disconnected=True)
|
||||
if len(self.players) == 0:
|
||||
print(f'no players left in game {self.name}')
|
||||
return True
|
||||
else: return False
|
||||
|
||||
def player_death(self, player: players.Player):
|
||||
def player_death(self, player: players.Player, disconnected=False):
|
||||
import bang.expansions.dodge_city.characters as chd
|
||||
print(player.attacker)
|
||||
if player.attacker and isinstance(player.attacker, roles.Sheriff) and isinstance(player.role, roles.Vice):
|
||||
for i in range(len(player.attacker.hand)):
|
||||
@ -223,22 +228,15 @@ class Game:
|
||||
print(f'player {player.name} died')
|
||||
if (self.waiting_for > 0):
|
||||
self.responders_did_respond_resume_turn()
|
||||
vulture = [p for p in self.players if isinstance(p.character, characters.VultureSam)]
|
||||
if len(vulture) == 0:
|
||||
for i in range(len(player.hand)):
|
||||
self.deck.scrap(player.hand.pop())
|
||||
for i in range(len(player.equipment)):
|
||||
self.deck.scrap(player.equipment.pop())
|
||||
else:
|
||||
for i in range(len(player.hand)):
|
||||
vulture[0].hand.append(player.hand.pop())
|
||||
for i in range(len(player.equipment)):
|
||||
vulture[0].hand.append(player.equipment.pop())
|
||||
|
||||
index = self.players.index(player)
|
||||
died_in_his_turn = self.started and index == self.turn
|
||||
if self.started and index <= self.turn:
|
||||
self.turn -= 1
|
||||
self.players.pop(index)
|
||||
|
||||
corpse = self.players.pop(index)
|
||||
if not disconnected:
|
||||
self.dead_players.append()
|
||||
self.notify_room()
|
||||
self.sio.emit('chat_message', room=self.name, data=f'{player.name} è morto.')
|
||||
if self.started:
|
||||
@ -256,12 +254,47 @@ class Game:
|
||||
print('WE HAVE A WINNER')
|
||||
for p in self.players:
|
||||
p.win_status = p in winners
|
||||
self.sio.emit('chat_message', room=self.name, data=f'{p.name} ha vinto.')
|
||||
p.notify_self()
|
||||
return
|
||||
eventlet.sleep(5.0)
|
||||
return self.reset()
|
||||
|
||||
vulture = [p for p in self.players if isinstance(p.character, characters.VultureSam)]
|
||||
if len(vulture) == 0:
|
||||
for i in range(len(player.hand)):
|
||||
self.deck.scrap(player.hand.pop())
|
||||
for i in range(len(player.equipment)):
|
||||
self.deck.scrap(player.equipment.pop())
|
||||
else:
|
||||
for i in range(len(player.hand)):
|
||||
vulture[0].hand.append(player.hand.pop())
|
||||
for i in range(len(player.equipment)):
|
||||
vulture[0].hand.append(player.equipment.pop())
|
||||
vulture[0].notify_self()
|
||||
greg = [p for p in self.players if isinstance(p.character, chd.GregDigger)]
|
||||
if len(greg) > 0:
|
||||
greg[0].lives = min(greg[0].lives+2, greg[0].max_lives)
|
||||
herb = [p for p in self.players if isinstance(p.character, chd.HerbHunter)]
|
||||
if len(herb) > 0:
|
||||
herb[0].hand.append(self.deck.draw())
|
||||
herb[0].hand.append(self.deck.draw())
|
||||
|
||||
if died_in_his_turn:
|
||||
self.next_turn()
|
||||
|
||||
def reset(self):
|
||||
print('resetting lobby')
|
||||
self.players.extend(self.dead_players)
|
||||
self.dead_players = []
|
||||
print(self.players)
|
||||
self.started = False
|
||||
self.waiting_for = 0
|
||||
for p in self.players:
|
||||
p.reset()
|
||||
p.notify_self()
|
||||
eventlet.sleep(0.5)
|
||||
self.notify_room()
|
||||
|
||||
def get_visible_players(self, player: players.Player):
|
||||
i = self.players.index(player)
|
||||
sight = player.get_sight()
|
||||
|
@ -7,6 +7,7 @@ import bang.roles as r
|
||||
import bang.cards as cs
|
||||
import bang.expansions.dodge_city.cards as csd
|
||||
import bang.characters as chars
|
||||
import bang.expansions.dodge_city.characters as chd
|
||||
|
||||
class PendingAction(IntEnum):
|
||||
PICK = 0
|
||||
@ -41,10 +42,38 @@ class Player:
|
||||
self.on_failed_response_cb = None
|
||||
self.event_type: str = None
|
||||
self.expected_response = []
|
||||
self.attacker = None
|
||||
self.attacker: Player = None
|
||||
self.target_p: str = None
|
||||
self.is_drawing = False
|
||||
self.mancato_needed = 0
|
||||
self.molly_discarded_cards = 0
|
||||
|
||||
def reset(self):
|
||||
self.hand: cs.Card = []
|
||||
self.equipment: cs.Card = []
|
||||
self.role: r.Role = None
|
||||
self.character: chars.Character = None
|
||||
self.lives = 0
|
||||
self.max_lives = 0
|
||||
self.is_my_turn = False
|
||||
self.is_waiting_for_action = True
|
||||
self.has_played_bang = False
|
||||
self.pending_action: PendingAction = None
|
||||
self.available_characters = []
|
||||
self.was_shot = False
|
||||
self.on_pick_cb = None
|
||||
self.on_failed_response_cb = None
|
||||
self.event_type: str = None
|
||||
self.expected_response = []
|
||||
self.attacker: Player = None
|
||||
self.target_p: str = None
|
||||
self.is_drawing = False
|
||||
try:
|
||||
del self.win_status
|
||||
except:
|
||||
pass
|
||||
self.mancato_needed = 0
|
||||
self.molly_discarded_cards = 0
|
||||
|
||||
def join_game(self, game):
|
||||
self.game = game
|
||||
@ -164,6 +193,10 @@ class Player:
|
||||
self.sio.emit('chat_message', room=self.game.name,
|
||||
data=f'{self.name} ha pescato la prima carta dalla mano di {pile}.')
|
||||
self.hand.append(self.game.deck.draw())
|
||||
elif isinstance(self.character, chd.BillNoface):
|
||||
self.hand.append(self.game.deck.draw())
|
||||
for i in range(self.max_lives-self.lives):
|
||||
self.hand.append(self.game.deck.draw())
|
||||
else:
|
||||
for i in range(2):
|
||||
card: cs.Card = self.game.deck.draw()
|
||||
@ -174,6 +207,8 @@ class Player:
|
||||
p.notify_card(self, card)
|
||||
if card.suit == cs.Suit.HEARTS or card.suit == cs.Suit.DIAMONDS:
|
||||
self.hand.append(self.game.deck.draw())
|
||||
if isinstance(self.character, chd.PixiePete):
|
||||
self.hand.append(self.game.deck.draw())
|
||||
self.notify_self()
|
||||
|
||||
def pick(self):
|
||||
@ -192,12 +227,13 @@ class Player:
|
||||
if picked.suit == cs.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0:
|
||||
self.lives -= 3
|
||||
self.game.deck.scrap(self.equipment.pop(i))
|
||||
if isinstance(self.character, chars.BartCassidy):
|
||||
self.sio.emit('chat_message', room=self.game.name,
|
||||
data=f'{self.name} ha fatto esplodere la dinamite.')
|
||||
if isinstance(self.character, chars.BartCassidy) and self.lives > 0:
|
||||
for i in range(3):
|
||||
self.hand.append(self.game.deck.draw())
|
||||
self.sio.emit('chat_message', room=self.game.name,
|
||||
data=f'{self.name} ha ricevuto un risarcimento perchè è stato ferito.')
|
||||
self.sio.emit('chat_message', room=self.game.name,
|
||||
data=f'{self.name} ha fatto esplodere la dinamite.')
|
||||
print(f'{self.name} Boom, -3 hp')
|
||||
else:
|
||||
self.game.next_player().equipment.append(self.equipment.pop(i))
|
||||
@ -258,6 +294,8 @@ class Player:
|
||||
if _with != None:
|
||||
withCard = self.hand.pop(_with) if hand_index > _with else self.hand.pop(_with - 1)
|
||||
print(self.name, 'is playing ', card, ' against:', against, ' with:', _with)
|
||||
did_play_card = False
|
||||
if not(against != None and isinstance(self.game.get_player_named(against).character, chd.ApacheKid) and card.suit == cs.Suit.DIAMONDS):
|
||||
did_play_card = card.play_card(self, against, withCard)
|
||||
if not card.is_equipment and not card.usable_next_turn:
|
||||
if did_play_card:
|
||||
@ -327,13 +365,15 @@ class Player:
|
||||
if self.mancato_needed <= 0:
|
||||
self.game.responders_did_respond_resume_turn()
|
||||
return
|
||||
if len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang))]) == 0\
|
||||
if len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
||||
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
||||
self.take_damage_response()
|
||||
self.game.responders_did_respond_resume_turn()
|
||||
else:
|
||||
self.pending_action = PendingAction.RESPOND
|
||||
self.expected_response = self.game.deck.mancato_cards
|
||||
if isinstance(self.character, chd.ElenaFuente):
|
||||
self.expected_response = self.game.deck.all_cards_str
|
||||
self.on_failed_response_cb = self.take_damage_response
|
||||
self.notify_self()
|
||||
|
||||
@ -344,7 +384,7 @@ class Player:
|
||||
if self.equipment[i].can_be_used_now:
|
||||
print('usable', self.equipment[i])
|
||||
if len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not isinstance(self.character, chars.Jourdonnais)\
|
||||
and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang))]) == 0\
|
||||
and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
||||
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
||||
print('Cant defend')
|
||||
self.take_damage_response()
|
||||
@ -358,6 +398,8 @@ class Player:
|
||||
print('has mancato')
|
||||
self.pending_action = PendingAction.RESPOND
|
||||
self.expected_response = self.game.deck.mancato_cards
|
||||
if isinstance(self.character, chd.ElenaFuente):
|
||||
self.expected_response = self.game.deck.all_cards_str
|
||||
self.on_failed_response_cb = self.take_damage_response
|
||||
self.notify_self()
|
||||
return True
|
||||
@ -408,6 +450,8 @@ class Player:
|
||||
while self.lives <= 0 and len(self.game.players) > 2 and len([c for c in self.hand if isinstance(c, cs.Birra)]) > 0:
|
||||
for i in range(len(self.hand)):
|
||||
if isinstance(self.hand[i], cs.Birra):
|
||||
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
|
||||
self.hand.append(self.game.deck.draw())
|
||||
self.lives += 1
|
||||
self.game.deck.scrap(self.hand.pop(i))
|
||||
self.sio.emit('chat_message', room=self.game.name,
|
||||
@ -424,6 +468,8 @@ class Player:
|
||||
((hand_index < len(self.hand) and self.hand[hand_index].name in self.expected_response)) or
|
||||
self.equipment[hand_index-len(self.hand)].name in self.expected_response):
|
||||
card = self.hand.pop(hand_index) if hand_index < len(self.hand) else self.equipment.pop(hand_index-len(self.hand))
|
||||
if isinstance(self.character, chd.MollyStark) and hand_index < len(self.hand) and not self.is_my_turn and self.event_type != 'duel':
|
||||
self.hand.append(self.game.deck.draw())
|
||||
card.use_card(self)
|
||||
self.game.deck.scrap(card)
|
||||
self.notify_self()
|
||||
@ -431,6 +477,8 @@ class Player:
|
||||
if self.mancato_needed <= 0:
|
||||
if self.event_type == 'duel':
|
||||
self.game.duel(self, self.attacker.name)
|
||||
if isinstance(self.character, chd.MollyStark) and hand_index < len(self.hand) and not self.is_my_turn:
|
||||
self.molly_discarded_cards += 1
|
||||
else:
|
||||
self.game.responders_did_respond_resume_turn()
|
||||
self.event_type = ''
|
||||
@ -438,6 +486,16 @@ class Player:
|
||||
self.pending_action = PendingAction.RESPOND
|
||||
self.notify_self()
|
||||
else:
|
||||
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
|
||||
for i in range(self.molly_discarded_cards):
|
||||
self.hand.append(self.game.deck.draw())
|
||||
self.molly_discarded_cards = 0
|
||||
self.notify_self()
|
||||
elif self.attacker and isinstance(self.attacker.character, chd.MollyStark) and self.is_my_turn:
|
||||
for i in range(self.attacker.molly_discarded_cards):
|
||||
self.attacker.hand.append(self.attacker.game.deck.draw())
|
||||
self.attacker.molly_discarded_cards = 0
|
||||
self.attacker.notify_self()
|
||||
self.on_failed_response_cb()
|
||||
self.game.responders_did_respond_resume_turn()
|
||||
if self.mancato_needed <= 0:
|
||||
|
@ -14,6 +14,7 @@ class Role(ABC):
|
||||
class Sheriff(Role):
|
||||
def __init__(self):
|
||||
super().__init__("Sceriffo", "Elimina tutti i Fuorilegge e il Rinnegato!", health_mod=+1)
|
||||
self.goal_eng = "Kill the Outlaws and the Renegade!"
|
||||
self.max_players = 1
|
||||
self.icon = '⭐️'
|
||||
|
||||
@ -29,6 +30,7 @@ class Sheriff(Role):
|
||||
class Vice(Role):
|
||||
def __init__(self, alternative_goal=None):
|
||||
super().__init__("Vice", "Proteggi lo Sceriffo! Elimina tutti i Fuorilegge e il Rinnegato!")
|
||||
self.goal_eng = "Protect the Sheriff! Kill the Outlaws and the Renegade!"
|
||||
if alternative_goal:
|
||||
self.goal = alternative_goal
|
||||
self.max_players = 2
|
||||
@ -47,6 +49,7 @@ class Vice(Role):
|
||||
class Outlaw(Role):
|
||||
def __init__(self, alternative_goal=None):
|
||||
super().__init__("Fuorilegge", "Elimina lo Sceriffo!")
|
||||
self.goal_eng = "Kill the Sheriff!"
|
||||
if alternative_goal:
|
||||
self.goal = alternative_goal
|
||||
self.max_players = 3
|
||||
@ -65,6 +68,7 @@ class Outlaw(Role):
|
||||
class Renegade(Role):
|
||||
def __init__(self, alternative_goal=None):
|
||||
super().__init__("Rinnegato", "Rimani l'ultimo personaggio in gioco!")
|
||||
self.goal_eng = "Be the last man standing!"
|
||||
if alternative_goal:
|
||||
self.goal = alternative_goal
|
||||
self.max_players = 1
|
||||
|
@ -1,5 +1,5 @@
|
||||
certifi==2020.11.8
|
||||
dnspython==2.0.0
|
||||
dnspython==1.16.0
|
||||
eventlet==0.29.1
|
||||
greenlet==0.4.17
|
||||
python-engineio==3.13.2
|
||||
|
@ -10,14 +10,19 @@
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"pretty-checkbox-vue": "^1.1.9",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"socket.io-client": "^3.0.3",
|
||||
"vue": "^2.6.11",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
"vue-i18n": "^8.22.2",
|
||||
"vue-router": "^3.2.0",
|
||||
"vue-socket.io": "^3.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-pwa": "~4.5.0",
|
||||
"@vue/cli-plugin-router": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
|
BIN
frontend/public/img/icons/android-launchericon-144-144.png
Executable file
After Width: | Height: | Size: 10 KiB |
BIN
frontend/public/img/icons/android-launchericon-192-192.png
Executable file
After Width: | Height: | Size: 18 KiB |
BIN
frontend/public/img/icons/android-launchericon-48-48.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
frontend/public/img/icons/android-launchericon-512-512.png
Executable file
After Width: | Height: | Size: 105 KiB |
BIN
frontend/public/img/icons/android-launchericon-72-72.png
Executable file
After Width: | Height: | Size: 3.3 KiB |
BIN
frontend/public/img/icons/android-launchericon-96-96.png
Executable file
After Width: | Height: | Size: 5.1 KiB |
BIN
frontend/public/img/icons/chrome-extensionmanagementpage-48-48.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
frontend/public/img/icons/chrome-favicon-16-16.png
Executable file
After Width: | Height: | Size: 527 B |
BIN
frontend/public/img/icons/chrome-installprocess-128-128.png
Executable file
After Width: | Height: | Size: 8.6 KiB |
BIN
frontend/public/img/icons/firefox-general-128-128.png
Executable file
After Width: | Height: | Size: 8.6 KiB |
BIN
frontend/public/img/icons/firefox-general-16-16.png
Executable file
After Width: | Height: | Size: 527 B |
BIN
frontend/public/img/icons/firefox-general-256-256.png
Executable file
After Width: | Height: | Size: 29 KiB |
BIN
frontend/public/img/icons/firefox-general-32-32.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
frontend/public/img/icons/firefox-general-48-48.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
frontend/public/img/icons/firefox-general-64-64.png
Executable file
After Width: | Height: | Size: 3.1 KiB |
BIN
frontend/public/img/icons/firefox-general-90-90.png
Executable file
After Width: | Height: | Size: 4.7 KiB |
BIN
frontend/public/img/icons/firefox-marketplace-128-128.png
Executable file
After Width: | Height: | Size: 8.6 KiB |
BIN
frontend/public/img/icons/firefox-marketplace-512-512.png
Executable file
After Width: | Height: | Size: 105 KiB |
BIN
frontend/public/img/icons/msteams-192-192.png
Executable file
After Width: | Height: | Size: 18 KiB |
BIN
frontend/public/img/icons/msteams-silhouette-32-32.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
@ -5,7 +5,18 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<meta name="description" content="Bang multiplayer online.">
|
||||
<title>PewPew!</title>
|
||||
|
||||
<!-- Twitter Card data -->
|
||||
<meta name="twitter:card" value="Wanna play Bang with your friends but you cannot meet in person? Play Bang! multiplayer online.">
|
||||
|
||||
<!-- Open Graph data -->
|
||||
<meta property="og:title" content="PewPew!" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:url" content="https://bang.xamin.it/" />
|
||||
<!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->
|
||||
<meta property="og:description" content="Wanna play Bang with your friends but you cannot meet in person? Play Bang! multiplayer online." />
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
|
2
frontend/public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
@ -1,36 +1,7 @@
|
||||
<template>
|
||||
<div id="app" class="dark-mode">
|
||||
<div v-if="!isInLobby" id="logo" class="center-stuff" style="margin-bottom:10pt;">
|
||||
<h1 style="margin-bottom:0pt;">PewPew!</h1>
|
||||
<i style="font-size: x-small;">{{$t("trademark")}}</i>
|
||||
</div>
|
||||
<div v-if="isConnected">
|
||||
<div v-if="!didSetUsername">
|
||||
<p>{{$t("choose_username")}}</p>
|
||||
<form @submit="setUsername">
|
||||
<input v-model="username" />
|
||||
<input type="submit"/>
|
||||
</form>
|
||||
<p>{{$t("online_players")}}{{onlinePlayers}}</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!isInLobby" >
|
||||
<p>{{$t("online_players")}}{{onlinePlayers}}</p>
|
||||
<Card :card="getSelfCard" style="position:absolute; top:10pt; left: 10pt;"/>
|
||||
<h2>{{$t("available_lobbies")}}</h2>
|
||||
<div style="display: flex">
|
||||
<Card v-for="lobby in openLobbies" v-bind:key="lobby.name" :card="getLobbyCard(lobby)" @click.native="joinLobby(lobby)"/>
|
||||
<p v-if="noLobbyAvailable">{{$t("no_lobby_available")}}</p>
|
||||
</div>
|
||||
<form @submit="createLobby">
|
||||
<h2>{{$t("create_lobby")}}</h2>
|
||||
<p>{{$t("lobby_name")}}</p>
|
||||
<input v-model="lobbyName"/>
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</div>
|
||||
<Lobby v-show="isInLobby" :username="username" />
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<div v-else class="center-stuff">
|
||||
<h2>{{$t("warning")}}</h2>
|
||||
@ -48,96 +19,31 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import Card from './components/Card.vue'
|
||||
import Lobby from './components/Lobby.vue'
|
||||
// import Vue from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Card,
|
||||
Lobby,
|
||||
},
|
||||
data: () => ({
|
||||
isConnected: false,
|
||||
didSetUsername: false,
|
||||
username: '',
|
||||
openLobbies: [],
|
||||
lobbyName: '',
|
||||
isInLobby: false,
|
||||
onlinePlayers: 0,
|
||||
}),
|
||||
computed: {
|
||||
noLobbyAvailable() {
|
||||
return this.openLobbies && this.openLobbies.length == 0
|
||||
},
|
||||
getSelfCard() {
|
||||
return {
|
||||
name: this.username,
|
||||
number: this.$t('you'),
|
||||
icon: '🤠',
|
||||
is_character: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
sockets: {
|
||||
connect() {
|
||||
this.isConnected = true;
|
||||
document.title = 'PewPew!'
|
||||
if (Vue.config.devtools) {
|
||||
setTimeout(function(){
|
||||
this.username =(1+Math.random() * 100 % 100).toFixed(2).toString();
|
||||
this.setUsername();
|
||||
}.bind(this), 1000)
|
||||
}
|
||||
},
|
||||
disconnect() {
|
||||
this.isConnected = false;
|
||||
},
|
||||
lobbies(data) {
|
||||
this.openLobbies = data;
|
||||
},
|
||||
room() {
|
||||
room(data) {
|
||||
this.isInLobby = true;
|
||||
this.$router.push({path:'game', query: { code: data.name, pwd: data.password }})
|
||||
},
|
||||
players(num) {
|
||||
this.onlinePlayers = num;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setUsername(e){
|
||||
if (this.username.trim().length > 0){
|
||||
this.didSetUsername = true
|
||||
localStorage.setItem('username', this.username)
|
||||
this.$socket.emit('set_username', this.username)
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
getLobbyCard(lobby) {
|
||||
return {
|
||||
name: lobby.name,
|
||||
icon: "💥",
|
||||
number: `${lobby.players}🤠 ${lobby.locked?'🔐':''}`,
|
||||
is_equipment: true,
|
||||
}
|
||||
},
|
||||
createLobby(e) {
|
||||
if (this.lobbyName.trim().length > 0) {
|
||||
this.$socket.emit('create_room', this.lobbyName)
|
||||
}
|
||||
e.preventDefault();
|
||||
},
|
||||
joinLobby(lobby) {
|
||||
let password = lobby.locked ? prompt(this.$t("room_password_prompt"), "") : '';
|
||||
this.$socket.emit('join_room', {name:lobby.name,password:password})
|
||||
},
|
||||
init() {
|
||||
location.reload();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.getItem('username'))
|
||||
this.username = localStorage.getItem('username')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<form @submit="sendChatMessage" id="msg-form">
|
||||
<input v-model="text" style="flex-grow:2;"/>
|
||||
<input type="submit"/>
|
||||
<input type="submit" :value="$t('submit')"/>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -42,7 +42,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
showDesc(card) {
|
||||
this.desc = card.desc
|
||||
this.desc = (this.$i18n.locale=='it'?card.desc:card.desc_eng)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -64,7 +64,7 @@ export default {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.8); /* Black background with opacity */
|
||||
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;
|
||||
|
@ -11,7 +11,7 @@
|
||||
<card v-if="previousScrap" :card="previousScrap"/>
|
||||
<card v-else :card="card" class="back" style="opacity:0"/>
|
||||
<card v-if="lastScrap" :card="lastScrap" :key="lastScrap" class="last-scrap" @click.native="action('scrap')"
|
||||
@pointerenter.native="desc=lastScrap.desc" @pointerleave.native="desc=''" />
|
||||
@pointerenter.native="desc=($i18n.locale=='it'?lastScrap.desc:lastScrap.desc_eng)" @pointerleave.native="desc=''" />
|
||||
</div>
|
||||
</div>
|
||||
<transition name="list">
|
||||
@ -36,7 +36,6 @@ export default {
|
||||
name: 'PewPew!',
|
||||
icon: '💥',
|
||||
},
|
||||
endTurnCard: null,
|
||||
lastScrap: null,
|
||||
previousScrap: null,
|
||||
pending_action: false,
|
||||
@ -53,11 +52,13 @@ export default {
|
||||
this.lastScrap = card
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.endTurnCard = {
|
||||
computed: {
|
||||
endTurnCard() {
|
||||
return {
|
||||
name: this.$t('end_turn'),
|
||||
icon: '⛔️'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
action(pile) {
|
||||
|
108
frontend/src/components/FullScreenInput.vue
Normal file
@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div id="overlay" class="center-stuff">
|
||||
<h1>{{text}}</h1>
|
||||
<form @submit="submit">
|
||||
<input v-model="val" class="chooserInput"/>
|
||||
</form>
|
||||
<p v-if="hintText">{{hintText}}</p>
|
||||
<div style="margin-top:6pt;" class="button center-stuff" v-if="showCancelBtn && val" @click="cancel(val)"><span>{{realCancelText}}</span></div>
|
||||
<p v-if="desc" style="bottom:10pt;right:0;left:0;position:absolute;margin:16pt;font-size:18pt">{{desc}}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FullScreenInput',
|
||||
props: {
|
||||
cancel: Function,
|
||||
defaultValue: String,
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
text: String,
|
||||
hintText: String,
|
||||
},
|
||||
data: () => ({
|
||||
val: '',
|
||||
desc: '',
|
||||
realCancelText: ''
|
||||
}),
|
||||
computed: {
|
||||
showCancelBtn() {
|
||||
if (this.cancel)
|
||||
return true
|
||||
return false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showDesc(card) {
|
||||
this.desc = (this.$i18n.locale=='it'?card.desc:card.desc_eng)
|
||||
},
|
||||
submit(e) {
|
||||
e.preventDefault();
|
||||
this.cancel(this.val);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.realCancelText = this.cancelText
|
||||
this.val = this.defaultValue
|
||||
if (this.realCancelText == '') {
|
||||
this.realCancelText = this.$t('cancel')
|
||||
}
|
||||
},
|
||||
}
|
||||
</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;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
#overlay div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.card {
|
||||
width: 72pt;
|
||||
min-width:72pt;
|
||||
height: 120pt;
|
||||
}
|
||||
.card:hover {
|
||||
transform: translate(0, -5px) scale(1.05, 1.05);
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.chooserInput {
|
||||
background: none;
|
||||
color: white;
|
||||
font-size: 20pt;
|
||||
}
|
||||
</style>
|
@ -6,6 +6,7 @@
|
||||
<div v-if="!started">
|
||||
<PrettyCheck v-if="isRoomOwner" class="p-switch p-fill" v-model="privateRoom" style="margin-top:5px; margin-bottom:3px;">{{$t("private_room")}}</PrettyCheck>
|
||||
<label v-if="password !== ''">{{$t('password')}}<b class="selectable" style="font-size:larger;">{{ password }}</b></label>
|
||||
<input type="button" style="margin-left: 10pt;" v-clipboard:copy="inviteLink" value="Copia"/>
|
||||
</div>
|
||||
|
||||
<div class="players-table">
|
||||
@ -19,7 +20,7 @@
|
||||
<Card :card="p.card" :class="{is_my_turn:p.is_my_turn}"/>
|
||||
<Card v-if="p.character" :card="p.character" class="character tiny-character" @click.native="selectedInfo = [p.character]"/>
|
||||
<tiny-hand :ncards="p.ncards" @click.native="drawFromPlayer(p.name)"/>
|
||||
<span style="position:absolute;top:0;" class="center-stuff">{{getActionEmoji(p)}}</span>
|
||||
<span style="position:absolute;top:10pt;" class="center-stuff">{{getActionEmoji(p)}}</span>
|
||||
<div class="tiny-equipment">
|
||||
<Card v-for="card in p.equipment" v-bind:key="card.name+card.number" :card="card" @click.native="selectedInfo = p.equipment"/>
|
||||
</div>
|
||||
@ -40,6 +41,7 @@
|
||||
<Chooser v-if="selectedInfo" :text="$t('details')" :cards="selectedInfo" :cancelText="$t('ok')" :cancel="()=>{selectedInfo = null}" :select="()=>{selectedInfo = null}"/>
|
||||
<transition name="bounce">
|
||||
<Chooser v-if="hasToChoose" :text="`${$t('choose_card')}${target_p?$t('choose_card_from') + target_p:''}`" :cards="chooseCards" :select="chooseCard"/>
|
||||
<full-screen-input v-if="!started && hasToSetUsername" :defaultValue="storedUsername" :text="$t('choose_username')" :val="username" :cancel="setUsername" :cancelText="$t('ok')"/>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
@ -52,6 +54,7 @@ import Chat from './Chat.vue'
|
||||
import Player from './Player.vue'
|
||||
import Deck from './Deck.vue'
|
||||
import TinyHand from './TinyHand.vue'
|
||||
import FullScreenInput from './FullScreenInput.vue'
|
||||
|
||||
export default {
|
||||
name: 'Lobby',
|
||||
@ -63,11 +66,10 @@ export default {
|
||||
Deck,
|
||||
TinyHand,
|
||||
PrettyCheck,
|
||||
},
|
||||
props: {
|
||||
username: String
|
||||
FullScreenInput
|
||||
},
|
||||
data: () => ({
|
||||
username: '',
|
||||
lobbyName: '',
|
||||
started: false,
|
||||
players: [],
|
||||
@ -82,6 +84,7 @@ export default {
|
||||
privateRoom: false,
|
||||
password: '',
|
||||
useDodgeCity: false,
|
||||
hasToSetUsername: false,
|
||||
}),
|
||||
sockets: {
|
||||
room(data) {
|
||||
@ -104,15 +107,28 @@ export default {
|
||||
console.log(data)
|
||||
this.players = data
|
||||
},
|
||||
// self_vis(vis) {
|
||||
// console.log('received visibility update')
|
||||
// console.log(vis)
|
||||
// this.players = JSON.parse(vis)
|
||||
// },
|
||||
me(username) {
|
||||
if (username.error) {
|
||||
alert(username.error)
|
||||
this.$router.push('/')
|
||||
}
|
||||
this.username = username
|
||||
},
|
||||
change_username() {
|
||||
this.hasToSetUsername = true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
inviteLink() {
|
||||
return `${window.location.origin}/game?code=${this.lobbyName}&pwd=${this.password}`
|
||||
},
|
||||
storedUsername() {
|
||||
if (localStorage.getItem('username'))
|
||||
return localStorage.getItem('username')
|
||||
return ''
|
||||
},
|
||||
isRoomOwner() {
|
||||
return this.players[0].name == this.username
|
||||
return this.players.length > 0 && this.players[0].name == this.username
|
||||
},
|
||||
startGameCard() {
|
||||
if (!this.started && this.players.length > 2 && this.isRoomOwner) {
|
||||
@ -196,12 +212,25 @@ export default {
|
||||
console.log(name)
|
||||
this.$socket.emit('draw', name)
|
||||
},
|
||||
setUsername(name){
|
||||
if (name.trim().length > 0){
|
||||
localStorage.setItem('username', name)
|
||||
this.hasToSetUsername = false
|
||||
this.$socket.emit('set_username', name)
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
privateRoom() {
|
||||
this.$socket.emit('private')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log('mounted lobby')
|
||||
if (!this.$route.query.code)
|
||||
return this.$router.push('/')
|
||||
this.$socket.emit('get_me', {name:this.$route.query.code, password:this.$route.query.pwd})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -236,27 +265,29 @@ export default {
|
||||
right: -35pt;
|
||||
transform: scale(0.45);
|
||||
transform-origin: 50% 0%;
|
||||
top: 0;
|
||||
top: 10pt;
|
||||
}
|
||||
.tiny-health {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
top: -16pt;
|
||||
transform: scale(0.8);
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin-bottom: -4pt;
|
||||
}
|
||||
.tiny-equipment .card:nth-child(n+2) {
|
||||
margin-top: -60pt;
|
||||
}
|
||||
.tiny-equipment .card:hover {
|
||||
transform: translateY(10px) scale(1.1);
|
||||
z-index: 1;
|
||||
}
|
||||
.tiny-character {
|
||||
position: absolute;
|
||||
transform: scale(0.6) translate(-80px, -50px);
|
||||
transform: scale(0.5) translate(-80px, -40px);
|
||||
top: 0;
|
||||
}
|
||||
.players-table {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
margin-bottom: 12pt;
|
||||
}
|
||||
|
121
frontend/src/components/Menu.vue
Normal file
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div id="app" class="dark-mode">
|
||||
<div v-if="!isInLobby" id="logo" class="center-stuff" style="margin-bottom:10pt;">
|
||||
<h1 style="margin-bottom:0pt;">PewPew!</h1>
|
||||
<i style="font-size: x-small;">{{$t("trademark")}}</i>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="!didSetUsername">
|
||||
<p>{{$t("choose_username")}}</p>
|
||||
<form @submit="setUsername">
|
||||
<input v-model="username" />
|
||||
<input type="submit" :value="$t('submit')"/>
|
||||
</form>
|
||||
<p>{{$t("online_players")}}{{onlinePlayers}}</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!isInLobby" >
|
||||
<p>{{$t("online_players")}}{{onlinePlayers}}</p>
|
||||
<Card :card="getSelfCard" style="position:absolute; top:10pt; left: 10pt;"/>
|
||||
<h2>{{$t("available_lobbies")}}</h2>
|
||||
<div style="display: flex">
|
||||
<Card v-for="lobby in openLobbies" v-bind:key="lobby.name" :card="getLobbyCard(lobby)" @click.native="joinLobby(lobby)"/>
|
||||
<p v-if="noLobbyAvailable">{{$t("no_lobby_available")}}</p>
|
||||
</div>
|
||||
<form @submit="createLobby">
|
||||
<h2>{{$t("create_lobby")}}</h2>
|
||||
<p>{{$t("lobby_name")}}</p>
|
||||
<input v-model="lobbyName"/>
|
||||
<input type="submit" :value="$t('submit')"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import Vue from 'vue'
|
||||
import Card from '@/components/Card.vue'
|
||||
// import Lobby from './components/Lobby.vue'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Card,
|
||||
// Lobby,
|
||||
},
|
||||
data: () => ({
|
||||
isConnected: false,
|
||||
didSetUsername: false,
|
||||
username: '',
|
||||
openLobbies: [],
|
||||
lobbyName: '',
|
||||
isInLobby: false,
|
||||
onlinePlayers: 0,
|
||||
}),
|
||||
computed: {
|
||||
noLobbyAvailable() {
|
||||
return this.openLobbies && this.openLobbies.length == 0
|
||||
},
|
||||
getSelfCard() {
|
||||
return {
|
||||
name: this.username,
|
||||
number: this.$t('you'),
|
||||
icon: '🤠',
|
||||
is_character: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
sockets: {
|
||||
lobbies(data) {
|
||||
this.openLobbies = data;
|
||||
},
|
||||
room(data) {
|
||||
this.isInLobby = true;
|
||||
this.$router.push({path:'game', query: { code: data.name }})
|
||||
},
|
||||
players(num) {
|
||||
this.onlinePlayers = num;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setUsername(e){
|
||||
if (this.username.trim().length > 0){
|
||||
this.didSetUsername = true
|
||||
localStorage.setItem('username', this.username)
|
||||
this.$socket.emit('set_username', this.username)
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
getLobbyCard(lobby) {
|
||||
return {
|
||||
name: lobby.name,
|
||||
icon: "💥",
|
||||
number: `${lobby.players}🤠 ${lobby.locked?'🔐':''}`,
|
||||
is_equipment: true,
|
||||
}
|
||||
},
|
||||
createLobby(e) {
|
||||
if (this.lobbyName.trim().length > 0) {
|
||||
this.$socket.emit('create_room', this.lobbyName)
|
||||
}
|
||||
e.preventDefault();
|
||||
},
|
||||
joinLobby(lobby) {
|
||||
let password = lobby.locked ? prompt(this.$t("room_password_prompt"), "") : '';
|
||||
this.$socket.emit('join_room', {name:lobby.name,password:password})
|
||||
},
|
||||
init() {
|
||||
location.reload();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.getItem('username'))
|
||||
this.username = localStorage.getItem('username')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -4,16 +4,16 @@
|
||||
<!-- <button v-if="canEndTurn" @click="end_turn">Termina Turno</button> -->
|
||||
<div class="equipment-slot">
|
||||
<Card v-if="my_role" :card="my_role" class="back"
|
||||
@pointerenter.native="desc=my_role.goal" @pointerleave.native="desc=''"/>
|
||||
@pointerenter.native="desc=($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" @pointerleave.native="desc=''"/>
|
||||
<Card v-if="character" :card="character" style="margin-left: -30pt;margin-right: 0pt;"
|
||||
@pointerenter.native="desc=character.desc" @pointerleave.native="desc=''"/>
|
||||
@pointerenter.native="desc=($i18n.locale=='it'?character.desc:character.desc_eng)" @pointerleave.native="desc=''"/>
|
||||
<transition-group name="list" tag="div" style="display: flex;flex-direction:column; justify-content: space-evenly; margin-left: 12pt;margin-right:-10pt;">
|
||||
<span v-for="(n, i) in lives" v-bind:key="n" :alt="i">❤️</span>
|
||||
<span v-for="(n, i) in (max_lives-lives)" v-bind:key="n" :alt="i">💀</span>
|
||||
</transition-group>
|
||||
<transition-group v-if="lives > 0" name="list" tag="div" style="margin: 0 0 0 10pt; display:flex;">
|
||||
<Card v-for="card in equipment" v-bind:key="card.name+card.number" :card="card"
|
||||
@pointerenter.native="desc=card.desc" @pointerleave.native="desc=''"
|
||||
@pointerenter.native="desc=($i18n.locale=='it'?card.desc:card.desc_eng)" @pointerleave.native="desc=''"
|
||||
@click.native="play_card(card, true)" />
|
||||
</transition-group>
|
||||
</div>
|
||||
@ -25,18 +25,19 @@
|
||||
<transition-group name="list" tag="div" class="hand">
|
||||
<Card v-for="card in hand" v-bind:key="card.name+card.number" :card="card"
|
||||
@click.native="play_card(card, false)"
|
||||
@pointerenter.native="hint=card.desc" @pointerleave.native="hint=''"/>
|
||||
@pointerenter.native="hint=($i18n.locale=='it'?card.desc:card.desc_eng)" @pointerleave.native="hint=''"/>
|
||||
</transition-group>
|
||||
</div>
|
||||
<transition name="list">
|
||||
<p v-if="hint"><i>{{hint}}</i></p>
|
||||
</transition>
|
||||
<Chooser v-if="is_my_turn && pending_action == 4" :text="$t('wait')" :cards="[]"/>
|
||||
<Chooser v-if="card_against" :text="$t('card_against')" :cards="visiblePlayers" :select="selectAgainst" :cancel="cancelCardAgainst"/>
|
||||
<Chooser v-if="pending_action == 3" :text="respondText" :cards="respondCards" :select="respond"/>
|
||||
<Chooser v-if="shouldChooseCard" :text="$t('choose_card_to_get')" :cards="available_cards" :select="choose"/>
|
||||
<Chooser v-if="lives <= 0 && max_lives > 0" :text="$t('you_died')" :cancelText="$t('spectate')" :cancel="()=>{max_lives = 0}"/>
|
||||
<Chooser v-if="win_status !== undefined" :text="win_status?$t('you_win'):$t('you_lose')" />
|
||||
<Chooser v-if="show_role" :text="$t('you_are')" :cards="[my_role]" :hintText="my_role.goal" :select="() => {show_role=false}" :cancel="() => {show_role=false}" :cancelText="$t('ok')" />
|
||||
<Chooser v-if="show_role" :text="$t('you_are')" :cards="[my_role]" :hintText="($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" :select="() => {show_role=false}" :cancel="() => {show_role=false}" :cancelText="$t('ok')" />
|
||||
<Chooser v-if="notifycard" :key="notifycard.card" :text="`${notifycard.player} ${$t('did_pick_as')}:`" :cards="[notifycard.card]" :hintText="$t('if_card_red')" class="turn-notify-4s"/>
|
||||
<Chooser v-if="!show_role && is_my_turn && pending_action < 2" :text="$t('play_your_turn')" :key="is_my_turn" class="turn-notify" />
|
||||
<Chooser v-if="!show_role && availableCharacters.length > 0" :text="$t('choose_character')" :cards="availableCharacters" :select="setCharacter"/>
|
||||
@ -197,7 +198,7 @@ export default {
|
||||
this.hand.filter(x => x.can_be_used_now && this.expected_response.indexOf(x.name) !== -1).forEach(x=>{
|
||||
cc.push(x)
|
||||
})
|
||||
this.equipment.filter(x => x.can_be_used_now && this.expected_response.indexOf(x.name) !== -1).forEach(x=>{
|
||||
this.equipment.filter(x => x.usable_next_turn && x.can_be_used_now && this.expected_response.indexOf(x.name) !== -1).forEach(x=>{
|
||||
cc.push(x)
|
||||
})
|
||||
return cc
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div style="position:absolute;transform:scale(0.45);bottom:50pt;">
|
||||
<div style="position:absolute;transform:scale(0.4);bottom:52pt;">
|
||||
<div class="card back" v-for="(n, i) in ncards" :style="`position:absolute; transform:rotate(${(i-ncards/2)*2}deg) translate(${i*15}px,0);`" v-bind:key="n" :alt="i">
|
||||
<h4 v-if="n==ncards">PewPew!</h4>
|
||||
<div class="emoji" v-if="n==ncards">💥</div>
|
||||
|
@ -51,5 +51,6 @@
|
||||
"if_card_red":"If the card is diamonds or hearts, he picks another card.",
|
||||
"choose_scarp_card_to": "CHOOSE WHICH CARD TO DISCARD TO USE",
|
||||
"pick_a_card": "FLIP A CARD",
|
||||
"to_defend_from": "TO DEFEND YOURSELF FROM"
|
||||
"to_defend_from": "TO DEFEND YOURSELF FROM",
|
||||
"submit": "Submit"
|
||||
}
|
@ -51,5 +51,6 @@
|
||||
"if_card_red": "Se la carta è cuori o quadri ne pesca un'altra",
|
||||
"choose_scarp_card_to": "SCEGLI CHE CARTA SCARTARE PER USARE",
|
||||
"pick_a_card": "ESTRAI UNA CARTA",
|
||||
"to_defend_from": "PER DIFENDERTI DA"
|
||||
"to_defend_from": "PER DIFENDERTI DA",
|
||||
"submit": "Invia"
|
||||
}
|
@ -10,11 +10,15 @@ Vue.use(new VueSocketIO({
|
||||
|
||||
import PrettyCheckbox from 'pretty-checkbox-vue';
|
||||
Vue.use(PrettyCheckbox)
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
Vue.use(VueClipboard)
|
||||
|
||||
import VueI18n from 'vue-i18n'
|
||||
Vue.use(VueI18n)
|
||||
|
||||
import { languages, defaultLocale } from './i18n';
|
||||
import './registerServiceWorker'
|
||||
import router from './router'
|
||||
const messages = Object.assign(languages)
|
||||
|
||||
const i18n = new VueI18n({
|
||||
@ -24,5 +28,6 @@ const i18n = new VueI18n({
|
||||
|
||||
new Vue({
|
||||
i18n,
|
||||
render: h => h(App),
|
||||
router,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
|
32
frontend/src/registerServiceWorker.js
Normal file
@ -0,0 +1,32 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { register } from 'register-service-worker'
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
register(`${process.env.BASE_URL}service-worker.js`, {
|
||||
ready () {
|
||||
console.log(
|
||||
'App is being served from cache by a service worker.\n' +
|
||||
'For more details, visit https://goo.gl/AFskqB'
|
||||
)
|
||||
},
|
||||
registered () {
|
||||
console.log('Service worker has been registered.')
|
||||
},
|
||||
cached () {
|
||||
console.log('Content has been cached for offline use.')
|
||||
},
|
||||
updatefound () {
|
||||
console.log('New content is downloading.')
|
||||
},
|
||||
updated () {
|
||||
console.log('New content is available; please refresh.')
|
||||
},
|
||||
offline () {
|
||||
console.log('No internet connection found. App is running in offline mode.')
|
||||
},
|
||||
error (error) {
|
||||
console.error('Error during service worker registration:', error)
|
||||
}
|
||||
})
|
||||
}
|
25
frontend/src/router/index.js
Normal file
@ -0,0 +1,25 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/game',
|
||||
name: 'Game',
|
||||
component: () => import(/* webpackChunkName: "game" */ '../components/Lobby.vue')
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: () => import(/* webpackChunkName: "game" */ '../components/Menu.vue')
|
||||
},
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
8
frontend/vue.config.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
pwa: {
|
||||
name: 'PewPew!',
|
||||
appleMobileWebAppCache: "yes",
|
||||
manifestOptions: {
|
||||
}
|
||||
}
|
||||
};
|
@ -817,7 +817,7 @@
|
||||
"@babel/types" "^7.4.4"
|
||||
esutils "^2.0.2"
|
||||
|
||||
"@babel/runtime@^7.11.0", "@babel/runtime@^7.8.4":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.0", "@babel/runtime@^7.3.4", "@babel/runtime@^7.8.4":
|
||||
version "7.12.5"
|
||||
resolved "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.12.5.tgz?cache=0&sync_timestamp=1604441258461&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
|
||||
integrity sha1-QQ5+SHRB4bNgwpvnFdhw2bmFiC4=
|
||||
@ -872,7 +872,7 @@
|
||||
resolved "https://registry.npm.taobao.org/@hapi/hoek/download/@hapi/hoek-8.5.1.tgz?cache=0&sync_timestamp=1599009344074&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Fhoek%2Fdownload%2F%40hapi%2Fhoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06"
|
||||
integrity sha1-/elgZMpEbeyMVajC8TCVewcMbgY=
|
||||
|
||||
"@hapi/joi@^15.0.1":
|
||||
"@hapi/joi@^15.0.0", "@hapi/joi@^15.0.1":
|
||||
version "15.1.1"
|
||||
resolved "https://registry.npm.taobao.org/@hapi/joi/download/@hapi/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7"
|
||||
integrity sha1-xnW4pxKW8Cgz+NbSQ7NMV7jOGdc=
|
||||
@ -1254,7 +1254,16 @@
|
||||
webpack "^4.0.0"
|
||||
yorkie "^2.0.0"
|
||||
|
||||
"@vue/cli-plugin-router@^4.5.9":
|
||||
"@vue/cli-plugin-pwa@~4.5.0":
|
||||
version "4.5.9"
|
||||
resolved "https://registry.npm.taobao.org/@vue/cli-plugin-pwa/download/@vue/cli-plugin-pwa-4.5.9.tgz?cache=0&sync_timestamp=1605596341336&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcli-plugin-pwa%2Fdownload%2F%40vue%2Fcli-plugin-pwa-4.5.9.tgz#05c0a9797ddf2611069069f4a04e2fcc1273f838"
|
||||
integrity sha1-BcCpeX3fJhEGkGn0oE4vzBJz+Dg=
|
||||
dependencies:
|
||||
"@vue/cli-shared-utils" "^4.5.9"
|
||||
webpack "^4.0.0"
|
||||
workbox-webpack-plugin "^4.3.1"
|
||||
|
||||
"@vue/cli-plugin-router@^4.5.9", "@vue/cli-plugin-router@~4.5.0":
|
||||
version "4.5.9"
|
||||
resolved "https://registry.npm.taobao.org/@vue/cli-plugin-router/download/@vue/cli-plugin-router-4.5.9.tgz?cache=0&sync_timestamp=1605594512666&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcli-plugin-router%2Fdownload%2F%40vue%2Fcli-plugin-router-4.5.9.tgz#b3d23a8083d26a81bd09bf9c8d010a3e4e4b13d0"
|
||||
integrity sha1-s9I6gIPSaoG9Cb+cjQEKPk5LE9A=
|
||||
@ -1842,6 +1851,13 @@ babel-eslint@^10.1.0:
|
||||
eslint-visitor-keys "^1.0.0"
|
||||
resolve "^1.12.0"
|
||||
|
||||
babel-extract-comments@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npm.taobao.org/babel-extract-comments/download/babel-extract-comments-1.0.0.tgz#0a2aedf81417ed391b85e18b4614e693a0351a21"
|
||||
integrity sha1-Cirt+BQX7TkbheGLRhTmk6A1GiE=
|
||||
dependencies:
|
||||
babylon "^6.18.0"
|
||||
|
||||
babel-loader@^8.1.0:
|
||||
version "8.2.1"
|
||||
resolved "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.2.1.tgz#e53313254677e86f27536f5071d807e01d24ec00"
|
||||
@ -1860,6 +1876,32 @@ babel-plugin-dynamic-import-node@^2.3.3:
|
||||
dependencies:
|
||||
object.assign "^4.1.0"
|
||||
|
||||
babel-plugin-syntax-object-rest-spread@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.npm.taobao.org/babel-plugin-syntax-object-rest-spread/download/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
|
||||
integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
|
||||
|
||||
babel-plugin-transform-object-rest-spread@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.npm.taobao.org/babel-plugin-transform-object-rest-spread/download/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
|
||||
integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=
|
||||
dependencies:
|
||||
babel-plugin-syntax-object-rest-spread "^6.8.0"
|
||||
babel-runtime "^6.26.0"
|
||||
|
||||
babel-runtime@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
|
||||
dependencies:
|
||||
core-js "^2.4.0"
|
||||
regenerator-runtime "^0.11.0"
|
||||
|
||||
babylon@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.npm.taobao.org/babylon/download/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
|
||||
integrity sha1-ry87iPpvXB5MY00aD46sT1WzleM=
|
||||
|
||||
backo2@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
|
||||
@ -2462,6 +2504,15 @@ cli-width@^3.0.0:
|
||||
resolved "https://registry.npm.taobao.org/cli-width/download/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
|
||||
integrity sha1-ovSEN6LKqaIkNueUvwceyeYc7fY=
|
||||
|
||||
clipboard@^2.0.0:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
|
||||
integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==
|
||||
dependencies:
|
||||
good-listener "^1.2.2"
|
||||
select "^1.1.2"
|
||||
tiny-emitter "^2.0.0"
|
||||
|
||||
clipboardy@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.npm.taobao.org/clipboardy/download/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"
|
||||
@ -2578,6 +2629,11 @@ commander@~2.19.0:
|
||||
resolved "https://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz?cache=0&sync_timestamp=1603600023712&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
|
||||
integrity sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=
|
||||
|
||||
common-tags@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.npm.taobao.org/common-tags/download/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
|
||||
integrity sha1-jjFT5ULUo56bEFVENK+q+YlWqTc=
|
||||
|
||||
commondir@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
@ -2727,6 +2783,11 @@ core-js-compat@^3.6.2, core-js-compat@^3.6.5:
|
||||
browserslist "^4.14.6"
|
||||
semver "7.0.0"
|
||||
|
||||
core-js@^2.4.0:
|
||||
version "2.6.12"
|
||||
resolved "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1606326948512&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw=
|
||||
|
||||
core-js@^3.6.5:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.npm.taobao.org/core-js/download/core-js-3.7.0.tgz?cache=0&sync_timestamp=1604675608816&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f"
|
||||
@ -3140,6 +3201,11 @@ delayed-stream@~1.0.0:
|
||||
resolved "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
delegate@^3.1.2:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
|
||||
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
|
||||
|
||||
depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
@ -4054,6 +4120,15 @@ from2@^2.1.0:
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
fs-extra@^4.0.2:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npm.taobao.org/fs-extra/download/fs-extra-4.0.3.tgz?cache=0&sync_timestamp=1598867217764&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
|
||||
integrity sha1-DYUhIuW8W+tFP7Ao6cDJvzY0DJQ=
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-extra@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.1.tgz?cache=0&sync_timestamp=1598867217764&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
|
||||
@ -4127,6 +4202,11 @@ get-intrinsic@^1.0.0:
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
get-own-enumerable-property-symbols@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npm.taobao.org/get-own-enumerable-property-symbols/download/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
||||
integrity sha1-tf3nfyLL4185C04ImSLFC85u9mQ=
|
||||
|
||||
get-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
@ -4239,6 +4319,13 @@ globby@^9.2.0:
|
||||
pify "^4.0.1"
|
||||
slash "^2.0.0"
|
||||
|
||||
good-listener@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
|
||||
integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=
|
||||
dependencies:
|
||||
delegate "^3.1.2"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.2:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1598867272489&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
@ -4917,6 +5004,11 @@ is-number@^7.0.0:
|
||||
resolved "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=
|
||||
|
||||
is-obj@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
||||
|
||||
is-obj@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
|
||||
@ -4960,6 +5052,11 @@ is-regex@^1.0.4, is-regex@^1.1.1:
|
||||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-regexp@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npm.taobao.org/is-regexp/download/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
|
||||
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
|
||||
|
||||
is-resolvable@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
|
||||
@ -5121,6 +5218,13 @@ json-stable-stringify-without-jsonify@^1.0.1:
|
||||
resolved "https://registry.npm.taobao.org/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-stable-stringify-without-jsonify%2Fdownload%2Fjson-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
|
||||
|
||||
json-stable-stringify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npm.taobao.org/json-stable-stringify/download/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
|
||||
integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=
|
||||
dependencies:
|
||||
jsonify "~0.0.0"
|
||||
|
||||
json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
@ -5157,6 +5261,11 @@ jsonfile@^4.0.0:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonify@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.npm.taobao.org/jsonify/download/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
@ -5280,6 +5389,11 @@ locate-path@^5.0.0:
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash._reinterpolate@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npm.taobao.org/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
|
||||
|
||||
lodash.defaultsdeep@^4.6.1:
|
||||
version "4.6.1"
|
||||
resolved "https://registry.npm.taobao.org/lodash.defaultsdeep/download/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6"
|
||||
@ -5300,6 +5414,21 @@ lodash.memoize@^4.1.2:
|
||||
resolved "https://registry.npm.taobao.org/lodash.memoize/download/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
|
||||
|
||||
lodash.template@^4.4.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npm.taobao.org/lodash.template/download/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
|
||||
integrity sha1-+XYZXPPzR9DV9SSDVp/oAxzM6Ks=
|
||||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
lodash.templatesettings "^4.0.0"
|
||||
|
||||
lodash.templatesettings@^4.0.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npm.taobao.org/lodash.templatesettings/download/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
|
||||
integrity sha1-5IExDwSdPPbUfpEq0JMTsVTw+zM=
|
||||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash.transform@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.npm.taobao.org/lodash.transform/download/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0"
|
||||
@ -6651,6 +6780,11 @@ prettier@^1.18.2:
|
||||
resolved "https://registry.npm.taobao.org/prettier/download/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
||||
integrity sha1-99f1/4qc2HKnvkyhQglZVqYHl8s=
|
||||
|
||||
pretty-bytes@^5.1.0:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.npm.taobao.org/pretty-bytes/download/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b"
|
||||
integrity sha1-zYn3m7zvIePSHrDaaP/pP4A+iEs=
|
||||
|
||||
pretty-checkbox-vue@^1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/pretty-checkbox-vue/-/pretty-checkbox-vue-1.1.9.tgz#2d4bfc7f20c54a0e7b94b3d205641dbf8f390fb4"
|
||||
@ -6894,6 +7028,11 @@ regenerate@^1.4.0:
|
||||
resolved "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.2.tgz?cache=0&sync_timestamp=1604218535967&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerate%2Fdownload%2Fregenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
|
||||
integrity sha1-uTRtiCfo9aMve6KWN9OYtpAUhIo=
|
||||
|
||||
regenerator-runtime@^0.11.0:
|
||||
version "0.11.1"
|
||||
resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
||||
integrity sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=
|
||||
|
||||
regenerator-runtime@^0.13.4:
|
||||
version "0.13.7"
|
||||
resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
|
||||
@ -6939,6 +7078,11 @@ regexpu-core@^4.7.1:
|
||||
unicode-match-property-ecmascript "^1.0.4"
|
||||
unicode-match-property-value-ecmascript "^1.2.0"
|
||||
|
||||
register-service-worker@^1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.npm.taobao.org/register-service-worker/download/register-service-worker-1.7.1.tgz#6308347ac6c0af0f6c0b22ea5d59d25e836bc932"
|
||||
integrity sha1-Ywg0esbArw9sCyLqXVnSXoNryTI=
|
||||
|
||||
regjsgen@^0.5.1:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733"
|
||||
@ -7180,6 +7324,11 @@ select-hose@^2.0.0:
|
||||
resolved "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
|
||||
|
||||
select@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
|
||||
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
|
||||
|
||||
selfsigned@^1.10.7:
|
||||
version "1.10.8"
|
||||
resolved "https://registry.npm.taobao.org/selfsigned/download/selfsigned-1.10.8.tgz?cache=0&sync_timestamp=1600186146412&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fselfsigned%2Fdownload%2Fselfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30"
|
||||
@ -7706,6 +7855,15 @@ string_decoder@~1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
stringify-object@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.npm.taobao.org/stringify-object/download/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
|
||||
integrity sha1-cDBlrvyhkwDTzoivT1s5VtdVZik=
|
||||
dependencies:
|
||||
get-own-enumerable-property-symbols "^3.0.0"
|
||||
is-obj "^1.0.1"
|
||||
is-regexp "^1.0.0"
|
||||
|
||||
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
@ -7734,6 +7892,14 @@ strip-ansi@^6.0.0:
|
||||
dependencies:
|
||||
ansi-regex "^5.0.0"
|
||||
|
||||
strip-comments@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npm.taobao.org/strip-comments/download/strip-comments-1.0.2.tgz#82b9c45e7f05873bee53f37168af930aa368679d"
|
||||
integrity sha1-grnEXn8FhzvuU/NxaK+TCqNoZ50=
|
||||
dependencies:
|
||||
babel-extract-comments "^1.0.0"
|
||||
babel-plugin-transform-object-rest-spread "^6.26.0"
|
||||
|
||||
strip-eof@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||
@ -7925,6 +8091,11 @@ timsort@^0.3.0:
|
||||
resolved "https://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
|
||||
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
|
||||
|
||||
tiny-emitter@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
@ -8293,6 +8464,13 @@ vm-browserify@^1.0.1:
|
||||
resolved "https://registry.npm.taobao.org/vm-browserify/download/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
integrity sha1-eGQcSIuObKkadfUR56OzKobl3aA=
|
||||
|
||||
vue-clipboard2@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-clipboard2/-/vue-clipboard2-0.3.1.tgz#6e551fb7bd384889b28b0da3b12289ed6bca4894"
|
||||
integrity sha512-H5S/agEDj0kXjUb5GP2c0hCzIXWRBygaWLN3NEFsaI9I3uWin778SFEMt8QRXiPG+7anyjqWiw2lqcxWUSfkYg==
|
||||
dependencies:
|
||||
clipboard "^2.0.0"
|
||||
|
||||
vue-eslint-parser@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-7.1.1.tgz?cache=0&sync_timestamp=1602499032728&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3"
|
||||
@ -8335,6 +8513,11 @@ vue-loader@^15.9.2:
|
||||
vue-hot-reload-api "^2.3.0"
|
||||
vue-style-loader "^4.1.0"
|
||||
|
||||
vue-router@^3.2.0:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.npm.taobao.org/vue-router/download/vue-router-3.4.9.tgz?cache=0&sync_timestamp=1606723745188&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.4.9.tgz#c016f42030ae2932f14e4748b39a1d9a0e250e66"
|
||||
integrity sha1-wBb0IDCuKTLxTkdIs5odmg4lDmY=
|
||||
|
||||
vue-socket.io@^3.0.10:
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/vue-socket.io/-/vue-socket.io-3.0.10.tgz#76135bf5043baf484c648636a7a9822b4c11c084"
|
||||
@ -8574,6 +8757,141 @@ word-wrap@~1.2.3:
|
||||
resolved "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
integrity sha1-YQY29rH3A4kb00dxzLF/uTtHB5w=
|
||||
|
||||
workbox-background-sync@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-background-sync/download/workbox-background-sync-4.3.1.tgz?cache=0&sync_timestamp=1605541829415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-background-sync%2Fdownload%2Fworkbox-background-sync-4.3.1.tgz#26821b9bf16e9e37fd1d640289edddc08afd1950"
|
||||
integrity sha1-JoIbm/Funjf9HWQCie3dwIr9GVA=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-broadcast-update@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-broadcast-update/download/workbox-broadcast-update-4.3.1.tgz?cache=0&sync_timestamp=1605541831487&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-broadcast-update%2Fdownload%2Fworkbox-broadcast-update-4.3.1.tgz#e2c0280b149e3a504983b757606ad041f332c35b"
|
||||
integrity sha1-4sAoCxSeOlBJg7dXYGrQQfMyw1s=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-build@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-build/download/workbox-build-4.3.1.tgz#414f70fb4d6de47f6538608b80ec52412d233e64"
|
||||
integrity sha1-QU9w+01t5H9lOGCLgOxSQS0jPmQ=
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.4"
|
||||
"@hapi/joi" "^15.0.0"
|
||||
common-tags "^1.8.0"
|
||||
fs-extra "^4.0.2"
|
||||
glob "^7.1.3"
|
||||
lodash.template "^4.4.0"
|
||||
pretty-bytes "^5.1.0"
|
||||
stringify-object "^3.3.0"
|
||||
strip-comments "^1.0.2"
|
||||
workbox-background-sync "^4.3.1"
|
||||
workbox-broadcast-update "^4.3.1"
|
||||
workbox-cacheable-response "^4.3.1"
|
||||
workbox-core "^4.3.1"
|
||||
workbox-expiration "^4.3.1"
|
||||
workbox-google-analytics "^4.3.1"
|
||||
workbox-navigation-preload "^4.3.1"
|
||||
workbox-precaching "^4.3.1"
|
||||
workbox-range-requests "^4.3.1"
|
||||
workbox-routing "^4.3.1"
|
||||
workbox-strategies "^4.3.1"
|
||||
workbox-streams "^4.3.1"
|
||||
workbox-sw "^4.3.1"
|
||||
workbox-window "^4.3.1"
|
||||
|
||||
workbox-cacheable-response@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-cacheable-response/download/workbox-cacheable-response-4.3.1.tgz?cache=0&sync_timestamp=1605541831626&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-cacheable-response%2Fdownload%2Fworkbox-cacheable-response-4.3.1.tgz#f53e079179c095a3f19e5313b284975c91428c91"
|
||||
integrity sha1-9T4HkXnAlaPxnlMTsoSXXJFCjJE=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-core@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-core/download/workbox-core-4.3.1.tgz?cache=0&sync_timestamp=1605541831386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-core%2Fdownload%2Fworkbox-core-4.3.1.tgz#005d2c6a06a171437afd6ca2904a5727ecd73be6"
|
||||
integrity sha1-AF0sagahcUN6/WyikEpXJ+zXO+Y=
|
||||
|
||||
workbox-expiration@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-expiration/download/workbox-expiration-4.3.1.tgz#d790433562029e56837f341d7f553c4a78ebe921"
|
||||
integrity sha1-15BDNWICnlaDfzQdf1U8Snjr6SE=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-google-analytics@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-google-analytics/download/workbox-google-analytics-4.3.1.tgz#9eda0183b103890b5c256e6f4ea15a1f1548519a"
|
||||
integrity sha1-ntoBg7EDiQtcJW5vTqFaHxVIUZo=
|
||||
dependencies:
|
||||
workbox-background-sync "^4.3.1"
|
||||
workbox-core "^4.3.1"
|
||||
workbox-routing "^4.3.1"
|
||||
workbox-strategies "^4.3.1"
|
||||
|
||||
workbox-navigation-preload@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-navigation-preload/download/workbox-navigation-preload-4.3.1.tgz?cache=0&sync_timestamp=1605541832010&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-navigation-preload%2Fdownload%2Fworkbox-navigation-preload-4.3.1.tgz#29c8e4db5843803b34cd96dc155f9ebd9afa453d"
|
||||
integrity sha1-Kcjk21hDgDs0zZbcFV+evZr6RT0=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-precaching@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-precaching/download/workbox-precaching-4.3.1.tgz?cache=0&sync_timestamp=1605541830658&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-precaching%2Fdownload%2Fworkbox-precaching-4.3.1.tgz#9fc45ed122d94bbe1f0ea9584ff5940960771cba"
|
||||
integrity sha1-n8Re0SLZS74fDqlYT/WUCWB3HLo=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-range-requests@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-range-requests/download/workbox-range-requests-4.3.1.tgz?cache=0&sync_timestamp=1605541832130&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-range-requests%2Fdownload%2Fworkbox-range-requests-4.3.1.tgz#f8a470188922145cbf0c09a9a2d5e35645244e74"
|
||||
integrity sha1-+KRwGIkiFFy/DAmpotXjVkUkTnQ=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-routing@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-routing/download/workbox-routing-4.3.1.tgz?cache=0&sync_timestamp=1605541831895&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-routing%2Fdownload%2Fworkbox-routing-4.3.1.tgz#a675841af623e0bb0c67ce4ed8e724ac0bed0cda"
|
||||
integrity sha1-pnWEGvYj4LsMZ85O2OckrAvtDNo=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-strategies@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-strategies/download/workbox-strategies-4.3.1.tgz?cache=0&sync_timestamp=1605541832247&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-strategies%2Fdownload%2Fworkbox-strategies-4.3.1.tgz#d2be03c4ef214c115e1ab29c9c759c9fe3e9e646"
|
||||
integrity sha1-0r4DxO8hTBFeGrKcnHWcn+Pp5kY=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-streams@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-streams/download/workbox-streams-4.3.1.tgz?cache=0&sync_timestamp=1605541830519&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-streams%2Fdownload%2Fworkbox-streams-4.3.1.tgz#0b57da70e982572de09c8742dd0cb40a6b7c2cc3"
|
||||
integrity sha1-C1facOmCVy3gnIdC3Qy0Cmt8LMM=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
workbox-sw@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-sw/download/workbox-sw-4.3.1.tgz?cache=0&sync_timestamp=1605543695464&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-sw%2Fdownload%2Fworkbox-sw-4.3.1.tgz#df69e395c479ef4d14499372bcd84c0f5e246164"
|
||||
integrity sha1-32njlcR5700USZNyvNhMD14kYWQ=
|
||||
|
||||
workbox-webpack-plugin@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-webpack-plugin/download/workbox-webpack-plugin-4.3.1.tgz?cache=0&sync_timestamp=1605541444596&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-webpack-plugin%2Fdownload%2Fworkbox-webpack-plugin-4.3.1.tgz#47ff5ea1cc074b6c40fb5a86108863a24120d4bd"
|
||||
integrity sha1-R/9eocwHS2xA+1qGEIhjokEg1L0=
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
json-stable-stringify "^1.0.1"
|
||||
workbox-build "^4.3.1"
|
||||
|
||||
workbox-window@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npm.taobao.org/workbox-window/download/workbox-window-4.3.1.tgz?cache=0&sync_timestamp=1605541832372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-window%2Fdownload%2Fworkbox-window-4.3.1.tgz#ee6051bf10f06afa5483c9b8dfa0531994ede0f3"
|
||||
integrity sha1-7mBRvxDwavpUg8m436BTGZTt4PM=
|
||||
dependencies:
|
||||
workbox-core "^4.3.1"
|
||||
|
||||
worker-farm@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.npm.taobao.org/worker-farm/download/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
|
||||
|