def __init__(self, ip, port, verbose=False, lagSimulation=0): super().__init__() # Set up mouse input base.cTrav = CollisionTraverser() self.handler = CollisionHandlerQueue() self.mouseHandler = MouseHandler() self.taskMgr.add(self.inputTask, "InputTask") # Set up the UI self.fonts = hud.Fonts() # View the cards at an angle self.camera.setPosHpr(4, -15, -15, 0, 45, 0) # Set up the NetworkManager instr = client.networkInstructions.NetworkInstructions() self.networkManager = ClientNetworkManager(instr, ip, port) self.networkManager.verbose = verbose # Connect to the server self.connectionManager = ConnectionManager((ip, port), self) self.connectionManager.tryConnect() self.taskMgr.add(self.networkUpdateTask, "NetworkUpdateTask") # Set up lag simulation self.lagTimer = self.lagSimulation = lagSimulation self.availableFactions = [ templars.Templar, mariners.Mariner, thieves.Thief, fae.Faerie ] self.hasMulliganed = False self.ready = False
class App(ShowBase): def __init__(self, ip, port, verbose=False, lagSimulation=0): super().__init__() # Set up mouse input base.cTrav = CollisionTraverser() self.handler = CollisionHandlerQueue() self.mouseHandler = MouseHandler() self.taskMgr.add(self.inputTask, "InputTask") # Set up the UI self.fonts = hud.Fonts() # View the cards at an angle self.camera.setPosHpr(4, -15, -15, 0, 45, 0) # Set up the NetworkManager instr = client.networkInstructions.NetworkInstructions() self.networkManager = ClientNetworkManager(instr, ip, port) self.networkManager.verbose = verbose # Connect to the server self.connectionManager = ConnectionManager((ip, port), self) self.connectionManager.tryConnect() self.taskMgr.add(self.networkUpdateTask, "NetworkUpdateTask") # Set up lag simulation self.lagTimer = self.lagSimulation = lagSimulation self.availableFactions = [ templars.Templar, mariners.Mariner, thieves.Thief, fae.Faerie ] self.hasMulliganed = False self.ready = False def onConnectedToServer(self): self.guiScene = hud.MainMenu() @property def active(self): return self.player.active if hasattr(self, 'player') else False @active.setter def active(self, value): """ Update whose turn it is. """ # Ignore setting active before mulligans # b/c the opcode is False instead of None # TODO: change this if self.hasMulliganed: # (not value) gives us 0 for player 1 and 1 for player 2 self.game.turn = not value if (self.player == self.game.players[0]) else value @property def guiScene(self): return self._guiScene @guiScene.setter def guiScene(self, value): """ Used to control which menu is being shown """ if hasattr(self, '_guiScene') and self._guiScene: # TODO: kludge self._guiScene.unmake() self._guiScene = value def readyUp(self): """ We are ready to play a game. """ if not self.ready: self.networkManager.addPlayer() self.guiScene.showWaitMessage() self.ready = True def onEnteredGame(self): self.guiScene = hud.FactionSelect() def pickFaction(self, index): """ Tell the server we've picked a faction and are ready to start the game. """ self.networkManager.selectFaction(index) self.faction = self.availableFactions[index] self._active = False self._started = False # Don't show game yet; it hasn't started # Tell the user we're waiting for opponent self.guiScene.showWaitMessage() def goFirst(self): base.networkManager.decideWhetherToGoFirst(1) self.onGameStarted(goingFirst=True) def goSecond(self): base.networkManager.decideWhetherToGoFirst(0) self.onGameStarted(goingFirst=False) def onGameStarted(self, goingFirst=True): self.isFirstPlayer = goingFirst # Set up game state information if goingFirst: self.game = Game(self.faction, self.enemyFaction) self.player, self.enemy = self.game.players else: self.game = Game(self.enemyFaction, self.faction) self.enemy, self.player = self.game.players self.hasMulliganed = False self.bothPlayersMulliganed = False self.toMulligan = [] # Set up the game UI if isinstance(self.player, templars.Templar): self.guiScene = templarHud.TemplarHud() elif isinstance(self.player, mariners.Mariner): self.guiScene = marinerHud.MarinerHud() elif isinstance(self.player, thieves.Thief): self.guiScene = thiefHud.ThiefHud() elif isinstance(self.player, fae.Faerie): self.guiScene = faerieHud.FaerieHud() else: self.guiScene = hud.GameHud() self.zoneMaker = ZoneMaker() self.hasFirstPlayerPenalty = goingFirst def decideWhetherToGoFirst(self): self.guiScene = hud.GoingFirstDecision() @property def phase(self): return self.game.phase @phase.setter def phase(self, value): self.game.phase = value def mulligan(self): if not self.hasMulliganed: indices = [self.player.hand.index(c) for c in self.toMulligan] self.networkManager.mulligan(*indices) self.hasMulliganed = True self.toMulligan = [] # These get GC'd else: print("Already mulliganed.") def findCard(self, card): """ Given a card node, get its zone, index in that zone, and whether we control it """ if card is None: return (-1, -1, 0) enemy = True index = -1 zone = -1 if card.getPythonTag('zone') is self.player.facedowns: zone = Zone.facedown enemy = False elif card.getPythonTag('zone') is self.enemy.facedowns: zone = Zone.facedown elif card.getPythonTag('zone') is self.player.faceups: zone = Zone.faceup enemy = False elif card.getPythonTag('zone') is self.enemy.faceups: zone = Zone.faceup elif card.getPythonTag('zone') is self.player.hand: zone = Zone.hand enemy = False elif card.getPythonTag('zone') is self.enemy.hand: zone = Zone.hand elif card.getPythonTag('zone') is self.player.face: zone = Zone.face enemy = False elif card.getPythonTag('zone') is self.enemy.face: zone = Zone.face try: c = card.getPythonTag('card') index = card.getPythonTag('zone').index(c) except ValueError: pass return (zone, index, int(enemy)) def finishTargeting(self): self.targetCallback = None self.activeDecision = None self.mouseHandler.targeting = False self.guiScene.hideTargeting() def playCard(self, card, target=None): """ If it's our reveal phase and the card is fast, play it face-up, otherwise play it face-down. """ c = card.getPythonTag('card') idx = c.zone.index(c) if self.phase == Phase.reveal: if c.requiresTarget: self.networkManager.playFaceup(idx, *self.findCard(target)) else: self.networkManager.playFaceup(idx) else: self.networkManager.play(idx) def revealFacedown(self, card, target=None): card = card.getPythonTag('card') index = card.zone.index(card) self.networkManager.revealFacedown(index, *self.findCard(target)) def attack(self, card, target): try: zone, index, enemy = self.findCard(card) targetZone, targetIndex, targetsEnemy = self.findCard(target) except ValueError as e: print("Card not found: " + e) return self.networkManager.attack(index, targetIndex, targetZone) def endPhase(self, *args, **kwargs): # For each value in args, append the indices for that value # For each value in kwargs, append it if it's a bool, otherwise # assume it's a card and append the indices for it args = [i for arg in args for i in self.findCard(arg)] +\ [i for arg in kwargs.values() for i in ([arg] if isinstance(arg, bool) else self.findCard(arg))] self.networkManager.endPhase(*args) self.hasFirstPlayerPenalty = False def endPhaseWithCard(self, card): """ Hack to pass a card rather than card node to endPhase """ self.networkManager.endPhase(card.owner.zones.index(card.zone), card.zone.index(card), card.controller is self.enemy) self.hasFirstPlayerPenalty = False def replace(self, cards): args = [i for card in cards for i in self.findCard(card)] self.networkManager.replace(*args) for card in cards: # Do getParent.getParent because of pivots # TODO: make this cleaner # NEVER COMPARE NODE PATHS w/ is. It seems to always return False if (card is not None and card.getParent().getParent() == self.zoneMaker.playerHand): card.removeNode() def redraw(self): self.player.fishing = False self.zoneMaker.redrawAll() if self.mouseHandler.targeting: self.mouseHandler.targeting = False self.guiScene.redraw() def quitToMainMenu(self): self.taskMgr.doMethodLater(1, self._quitToMainMenuTask, "QuitToMainMenu") def _quitToMainMenuTask(self, task): if hasattr(self, 'zoneMaker'): # TODO: kludge self.zoneMaker.unmake() self.guiScene = hud.MainMenu() self.networkManager.requestNumPlayers() self.ready = False return Task.done def inputTask(self, task): try: self.mouseHandler.mouseOverTask() except IllegalMoveError as e: print(e) return Task.cont def networkUpdateTask(self, task): if self.lagTimer > 0: self.lagTimer -= globalClock.getDt() else: try: self.networkManager.recv() self.lagTimer = self.lagSimulation except ConnectionClosed: return Task.done return Task.cont