Class Server

  • All Implemented Interfaces:
    java.lang.Runnable, IServer

    public final class Server
    extends java.lang.Thread
    implements IServer
    Class Server lives on the server side and handles all communcation with the clients. It talks to the server classes locally, and to the Clients via the network protocol.
    Author:
    David Ripton
    • Field Detail

      • LOGGER

        private static final java.util.logging.Logger LOGGER
      • iClients

        private final java.util.List<IClient> iClients
        Recipients for everything send to "each client" - including the stub
      • realClients

        private final java.util.List<ClientHandler> realClients
        Only real ClientHandlers (excluding the stub)
      • remoteClients

        private final java.util.List<IClient> remoteClients
      • remoteLogHandlers

        private final java.util.List<RemoteLogHandler> remoteLogHandlers
      • playerToClientMap

        private final java.util.Map<Player,​IClient> playerToClientMap
        Map of players to their clients.
      • activeSocketChannelList

        private final java.util.List<java.nio.channels.SocketChannel> activeSocketChannelList
        List of SocketChannels that are currently active
      • forcedWithdraws

        private final java.util.Map<java.lang.String,​Server.WithdrawInfo> forcedWithdraws
        ClientHandlers to be withdrawn, together with some related (timing) data; selector thread will do it then when it's the right time for it
      • waitingForClients

        private int waitingForClients
        Number of player clients we're waiting for to *connect*
      • waitingForPlayersToJoin

        private int waitingForPlayersToJoin
        Number of player clients we're waiting for to *join* - when last one has joined, then kick of newGame2() or loadGame2()
      • wfptjSemaphor

        private final java.lang.Object wfptjSemaphor
        Semaphor for synchronized access to waitingForPlayersToJoin
      • sendPingRequests

        private boolean sendPingRequests
        Will be set to true after all clients are properly connected
      • spectators

        private int spectators
      • port

        private final int port
        Server socket port.
      • strikeNumber

        private int strikeNumber
      • rolls

        private java.util.List<java.lang.String> rolls
      • serverSocket

        private java.net.ServerSocket serverSocket
      • selector

        private java.nio.channels.Selector selector
      • acceptKey

        private java.nio.channels.SelectionKey acceptKey
      • stopAcceptingFlag

        private boolean stopAcceptingFlag
      • guiRequestMutex

        private final java.lang.Object guiRequestMutex
      • guiRequestSaveFlag

        private boolean guiRequestSaveFlag
      • guiRequestSaveFilename

        private java.lang.String guiRequestSaveFilename
      • inPauseState

        private boolean inPauseState
      • fileServerThread

        private static java.lang.Thread fileServerThread
      • serverRunning

        private boolean serverRunning
      • obsolete

        private boolean obsolete
      • shuttingDown

        private boolean shuttingDown
      • forceShutDown

        private boolean forceShutDown
      • initiateDisposal

        private boolean initiateDisposal
      • caughtUpAction

        private java.lang.String caughtUpAction
      • WEBGAMES_STARTUP_TIMEOUT_SECS

        private static final int WEBGAMES_STARTUP_TIMEOUT_SECS
        How long in public server games socket shall wait for Clients.
        See Also:
        Constant Field Values
      • lastPingRound

        private long lastPingRound
        How many ms ago last ping round was done.
      • startInititatedTime

        private long startInititatedTime
        When server started to listed for clients
      • gameStartupTimeoutSecs

        private int gameStartupTimeoutSecs
        Timeout how long server waits for clients before giving up; in normal/local games 0, meaning forever; in public server usage set to WEBGAMES_STARTUP_TIMEOUT_SECS
      • disposeAllClientsDoneMutex

        private final java.lang.Object disposeAllClientsDoneMutex
      • disposeAllClientsDone

        private boolean disposeAllClientsDone
      • byteBuffer

        private final java.nio.ByteBuffer byteBuffer
      • waitUntilOverMutex

        private final java.lang.Object waitUntilOverMutex
      • waitingToCatchup

        private final java.util.HashSet<IClient> waitingToCatchup
    • Method Detail

      • run

        public void run()
        Specified by:
        run in interface java.lang.Runnable
        Overrides:
        run in class java.lang.Thread
      • initFileServer

        void initFileServer()
      • startFileServerIfNotRunning

        void startFileServerIfNotRunning()
      • isKnownClient

        public boolean isKnownClient​(java.net.InetAddress requester)
      • initSocketServer

        void initSocketServer()
      • waitForClients

        boolean waitForClients()
      • createClientHandlerStub

        public void createClientHandlerStub()
      • overrideProcessingCH

        public void overrideProcessingCH​(Player player)
      • restoreProcessingCH

        public void restoreProcessingCH()
      • waitOnSelector

        public void waitOnSelector​(int timeout,
                                   boolean stillWaitingForClients)
      • handleForcedWithdraws

        private void handleForcedWithdraws()
      • handleOutsideChanges

        private void handleOutsideChanges​(boolean wasTimeout,
                                          boolean stillWaitingForClients)
      • handleSelectedKeys

        private void handleSelectedKeys()
                                 throws java.io.IOException,
                                        java.nio.channels.ClosedChannelException
        Throws:
        java.io.IOException
        java.nio.channels.ClosedChannelException
      • handleChannelChanges

        private void handleChannelChanges()
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • externShutdown

        public void externShutdown()
        Shutdown initiated by outside, i.e. NOT by the Server thread itself. Right now, this is used by StartupProgressDialog's abort button.
      • stopAccepting

        private void stopAccepting()
                            throws java.io.IOException
        Throws:
        java.io.IOException
      • closeSocketAndSelector

        private void closeSocketAndSelector()
        Close serverSocket and selector, if needed
      • handleReadFromChannel

        private int handleReadFromChannel​(java.nio.channels.SelectionKey key,
                                          java.nio.channels.SocketChannel sc)
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • processByteBuffer

        private void processByteBuffer()
      • withdrawFromGameIfRelevant

        private void withdrawFromGameIfRelevant​(java.lang.Exception gotException,
                                                boolean didDisconnect)
        Something with the connection of "processingCH" which makes perhaps Withdraw necessary. If client seems to support reconnect, mark CH to be temp. disconnected, otherwise take care of the proper withdrawal.
        Parameters:
        gotException - An exception, if calling this was caused by an (IO)Exception, otherwise null, i.e. it was triggered by EOF.
        didDisconnect - whether an explicit dicsonnect request message had been received already from that client ( = no point to wait for reconnect attempt).
      • triggerWithdrawIfDoesNotReconnect

        private void triggerWithdrawIfDoesNotReconnect​(long intervalLen,
                                                       int intervals)
      • queueClientHandlerForChannelChanges

        void queueClientHandlerForChannelChanges​(ClientHandlerStub ch)
        Put the ClientHandler into the queue to be removed from selector on next possible opportunity
      • notifyThatGameFinished

        public void notifyThatGameFinished()
      • waitUntilGameFinishes

        public void waitUntilGameFinishes()
      • stopServerRunning

        public void stopServerRunning()
      • isServerRunning

        public boolean isServerRunning()
      • stopFileServer

        public void stopFileServer()
      • disconnectChannel

        private void disconnectChannel​(java.nio.channels.SocketChannel sc,
                                       java.nio.channels.SelectionKey key)
                                throws java.io.IOException
        Close the SocketChannel, cancel the selection key and unregister the SocketChannel from list of active SocketChannels.
        Parameters:
        sc - SocketChannel of the client
        key - Key for that SocketChannel
        Throws:
        java.io.IOException
      • unregisterSocketChannel

        public void unregisterSocketChannel​(java.nio.channels.SocketChannel socketChannel)
      • setBoardVisibility

        public void setBoardVisibility​(Player player,
                                       boolean val)
      • isClientGone

        public boolean isClientGone​(Player player)
      • anyNonAiSocketsLeft

        private boolean anyNonAiSocketsLeft()
      • setObsolete

        public void setObsolete()
      • getPlayerName

        java.lang.String getPlayerName()
        Name of the player, for which data from socket is currently processed.
      • getPlayer

        private Player getPlayer()
        The player, for which data from socket is currently processed.
      • getClientHandlerByName

        public ClientHandler getClientHandlerByName​(java.lang.String name)
        Might be a player or a spectator (but not a stub)
        Parameters:
        name - Name of the player/client/spectator for which ClientHandler is needed
      • isActivePlayer

        private boolean isActivePlayer()
        returns true if the active player is the player owning the connection from which data is currently processed
      • isBattleActivePlayer

        private boolean isBattleActivePlayer()
      • addClient

        java.lang.String addClient​(ClientHandler client,
                                   java.lang.String playerName,
                                   boolean remote,
                                   int clientVersion,
                                   java.lang.String buildInfo,
                                   boolean spectator)
        Add a Client.
        Parameters:
        client -
        playerName -
        remote -
        clientVersion -
        spectator -
        Returns:
        Reason why adding Client was refused, null if all is fine.
      • startGame

        public void startGame()
        When the last player has *joined* (not just connected), he calls this here, and this will proceed with either loadGame2() or newGame2().
      • initWaitingForPlayersToJoin

        private void initWaitingForPlayersToJoin​(int count)
        Initialize the number of players we wait for to join (thread-safe)
        Parameters:
        count - the number of players that are expected to join
      • addRemoteClient

        private void addRemoteClient​(IClient client,
                                     Player player)
      • disposeAllClients

        void disposeAllClients()
      • loadFailed

        public void loadFailed()
      • cleanupStartlog

        public void cleanupStartlog()
      • doCleanup

        public void doCleanup()
      • allUpdatePlayerInfo

        void allUpdatePlayerInfo​(boolean treatDeadAsAlive,
                                 java.lang.String reason)
      • allUpdatePlayerInfo

        void allUpdatePlayerInfo​(java.lang.String reason)
      • allUpdateCreatureCount

        void allUpdateCreatureCount​(CreatureType type,
                                    int count,
                                    int deadCount)
      • allTellMovementRoll

        void allTellMovementRoll​(int roll)
      • isDoneWithStrikesOk

        private java.lang.String isDoneWithStrikesOk()
        Validates that it it OK to be "done with strikes" now for executing player
        Returns:
        reason why it's not OK; null if all is ok
      • allInitBoard

        void allInitBoard()
      • allTellReplay

        void allTellReplay​(boolean val,
                           int maxTurn)
      • allTellRedo

        void allTellRedo​(boolean val)
      • allRequestConfirmCatchup

        void allRequestConfirmCatchup​(java.lang.String action,
                                      boolean skipInTrouble)
      • allTellAllLegionLocations

        void allTellAllLegionLocations()
      • allTellLegionLocation

        void allTellLegionLocation​(Legion legion)
      • allRemoveLegion

        void allRemoveLegion​(Legion legion)
      • allTellPlayerElim

        void allTellPlayerElim​(Player eliminatedPlayer,
                               Player slayer,
                               boolean updateHistory)
      • repeatTellOneHasNetworkTrouble

        void repeatTellOneHasNetworkTrouble()
      • othersTellOneHasNetworkTrouble

        void othersTellOneHasNetworkTrouble​(ClientHandler chInTrouble)
      • othersTellOnesTroubleIsOver

        void othersTellOnesTroubleIsOver​(ClientHandler chInTrouble)
      • othersTellReconnectOngoing

        void othersTellReconnectOngoing​(ClientHandler chInTrouble)
      • othersTellRemainingTime

        void othersTellRemainingTime​(ClientHandler chInTrouble,
                                     int secondsLeft)
      • othersTellReconnectCompleted

        void othersTellReconnectCompleted​(ClientHandler chInTrouble)
      • appendToConnLogs

        void appendToConnLogs​(ClientHandler chInTrouble,
                              java.lang.String message)
      • allRequestPingIfNeeded

        void allRequestPingIfNeeded()
        IF last ping round is at least PING_REQUEST_INTERVAL_SEC seconds ago, then send a ping request to all clients (except those which are in trouble anyway).
      • allTellGameOver

        void allTellGameOver​(java.lang.String message,
                             boolean disposeFollows)
      • allSetupTurnState

        void allSetupTurnState()
        Needed if loading game outside the split phase.
      • allSetupSplit

        void allSetupSplit()
      • allSetupMove

        void allSetupMove()
      • allSetupFight

        void allSetupFight()
      • allSetupMuster

        void allSetupMuster()
      • kickPhase

        void kickPhase()
      • allSetupBattleSummon

        void allSetupBattleSummon()
      • allSetupBattleRecruit

        void allSetupBattleRecruit()
      • allSetupBattleMove

        void allSetupBattleMove()
      • allSetupBattleFight

        void allSetupBattleFight()
      • allRemoveDeadBattleChits

        void allRemoveDeadBattleChits()
      • allTellEngagementResults

        void allTellEngagementResults​(Legion winner,
                                      java.lang.String method,
                                      int points,
                                      int turns)
      • nextEngagement

        void nextEngagement()
      • askAcquireAngel

        void askAcquireAngel​(PlayerServerSide player,
                             Legion legion,
                             java.util.List<CreatureType> recruits)
        Find out if the player wants to acquire an angel or archangel.
      • createSummonAngel

        void createSummonAngel​(Legion legion)
      • reinforce

        void reinforce​(Legion legion)
      • doSummon

        public void doSummon​(Summoning event)
        Description copied from interface: IServer
        Handles a summon event
        Specified by:
        doSummon in interface IServer
        Parameters:
        event - The summon event or null if summoning is not wanted.
      • doRecruit

        public void doRecruit​(Recruitment event)
        Handle mustering for legion. if recruiting with nothing, recruiterName is a non-null String that contains "null".
        Specified by:
        doRecruit in interface IServer
      • undidRecruit

        void undidRecruit​(Legion legion,
                          CreatureType recruit,
                          boolean reinforced)
      • askConcede

        void askConcede​(Legion ally,
                        Legion enemy)
        Ask ally's player whether he wants to concede with ally.
      • askFlee

        void askFlee​(Legion ally,
                     Legion enemy)
        Ask ally's player whether he wants to flee with ally.
      • flee

        public void flee​(Legion legion)
        Specified by:
        flee in interface IServer
      • twoNegotiate

        void twoNegotiate​(Legion attacker,
                          Legion defender)
      • makeProposal

        public void makeProposal​(java.lang.String proposalString)
        playerName makes a proposal.
        Specified by:
        makeProposal in interface IServer
      • tellProposal

        void tellProposal​(Player player,
                          Proposal proposal)
        Tell playerName about proposal.
      • allTellBattleMove

        void allTellBattleMove​(int tag,
                               BattleHex startingHex,
                               BattleHex endingHex,
                               boolean undo)
      • allTellStrikeResults

        void allTellStrikeResults​(CreatureServerSide striker,
                                  CreatureServerSide target,
                                  int strikeNumber,
                                  java.util.List<java.lang.String> rolls,
                                  int damage,
                                  int carryDamageLeft,
                                  java.util.Set<java.lang.String> carryTargetDescriptions)
      • allTellCarryResults

        void allTellCarryResults​(CreatureServerSide carryTarget,
                                 int carryDamageDone,
                                 int carryDamageLeft,
                                 java.util.Set<java.lang.String> carryTargetDescriptions)
      • allTellHexSlowResults

        void allTellHexSlowResults​(CreatureServerSide target,
                                   int slowValue)
      • allTellHexDamageResults

        void allTellHexDamageResults​(CreatureServerSide target,
                                     int damage)
      • askChooseStrikePenalty

        void askChooseStrikePenalty​(java.util.SortedSet<PenaltyOption> penaltyOptions)
        Takes a Set of PenaltyOptions.
      • assignStrikePenalty

        public void assignStrikePenalty​(java.lang.String prompt)
        Specified by:
        assignStrikePenalty in interface IServer
      • allInitBattle

        void allInitBattle​(MasterHex masterHex)
      • allCleanupBattle

        void allCleanupBattle()
      • mulligan

        public void mulligan()
        Specified by:
        mulligan in interface IServer
      • undidSplit

        void undidSplit​(Legion splitoff,
                        Legion survivor,
                        boolean updateHistory,
                        int turn)
      • allTellUndidMove

        public void allTellUndidMove​(Legion legion,
                                     MasterHex formerHex,
                                     MasterHex currentHex,
                                     boolean splitLegionHasForcedMove)
      • isWithdrawalIrrelevant

        public boolean isWithdrawalIrrelevant()
      • withdrawFromGame

        public void withdrawFromGame()
        Withdraw the player for which data was currently processed on socket (if it is a real one, and withdrawal still makes sense).
        Specified by:
        withdrawFromGame in interface IServer
      • withdrawFromGame

        public void withdrawFromGame​(java.lang.String playerName)
        Withdraw a specific player of which we know only the name; e.g. when one clientHandler when trying to write to another clientHandler encountered closed socket.
        Parameters:
        playerName - Name of the player to withdraw
      • stopGame

        public void stopGame()
        Specified by:
        stopGame in interface IServer
      • triggerDispose

        void triggerDispose()
      • getPlayerInfo

        private java.util.List<java.lang.String> getPlayerInfo​(boolean treatDeadAsAlive)
      • doSplit

        public void doSplit​(Legion parent,
                            java.lang.String childId,
                            java.util.List<CreatureType> creaturesToSplit)
        Description copied from interface: IServer
        Executes a split of certain creatures from a legion.
        Specified by:
        doSplit in interface IServer
        Parameters:
        parent - The legion to split the creatures out of.
        childId - A marker for the new legion.
        creaturesToSplit - The creatures to split out.
      • allTellDidSplit

        void allTellDidSplit​(Legion parent,
                             Legion child,
                             int turn,
                             boolean history)
        Called from game after this legion was split off, or by history
      • allTellAddCreature

        void allTellAddCreature​(AddCreatureAction event,
                                boolean updateHistory,
                                java.lang.String reason)
      • allTellRemoveCreature

        void allTellRemoveCreature​(Legion legion,
                                   CreatureType creature,
                                   boolean updateHistory,
                                   java.lang.String reason)
      • allRevealLegion

        void allRevealLegion​(Legion legion,
                             java.lang.String reason)
      • allRevealEngagedLegion

        void allRevealEngagedLegion​(Legion legion,
                                    boolean isAttacker,
                                    java.lang.String reason)
        pass to all clients the 'revealEngagedCreatures' message, then fire an 'revealEvent' to the history.
        Parameters:
        legion - the legion marker to reveal which is in a battle
        isAttacker - true if the 'legion' is the atackker in the battle, false for the defender.
      • allRevealLegion

        void allRevealLegion​(Legion legion,
                             java.util.List<CreatureType> creatures,
                             java.lang.String reason)
        Call from History during load game only
      • oneRevealLegion

        void oneRevealLegion​(Legion legion,
                             Player player,
                             java.lang.String reason)
      • oneRevealLegion

        void oneRevealLegion​(Player player,
                             Legion legion,
                             java.util.List<CreatureType> creatureNames,
                             java.lang.String reason)
        Call from History during load game only
      • allFullyUpdateLegionStatus

        void allFullyUpdateLegionStatus()
      • allFullyUpdateAllLegionContents

        void allFullyUpdateAllLegionContents​(java.lang.String reason)
      • allRevealCreatures

        void allRevealCreatures​(Legion legion,
                                java.util.List<CreatureType> creatureNames,
                                java.lang.String reason)
      • newGame

        public void newGame()
        Specified by:
        newGame in interface IServer
      • loadGame

        public void loadGame​(java.lang.String filename)
        Specified by:
        loadGame in interface IServer
      • saveGame

        public void saveGame​(java.lang.String filename)
        Specified by:
        saveGame in interface IServer
      • saveGame

        public void saveGame​(java.lang.String filename,
                             boolean autoSave)
      • initiateSaveGame

        public void initiateSaveGame​(java.lang.String filename)
      • setPauseState

        public void setPauseState​(boolean newState)
      • handleGuiRequests

        public boolean handleGuiRequests()
        Handle GUI-initiated requests: Save and Pause
        Returns:
        true if it did something (saving the game)
      • clientWontConfirmCatchup

        public void clientWontConfirmCatchup​(ClientHandler ch,
                                             java.lang.String reason)
        Check whether client is currently expected to send a caught-Up confirmation. If yes: it won't happen, so act accordingly. If no : even better so, so just do nothing.
        Parameters:
        reason - Reason why client won't send the confirmation (typically disconnected or something).
      • actOnAllCaughtUp

        private void actOnAllCaughtUp()
      • setPlayerName

        void setPlayerName​(Player player,
                           java.lang.String newName)
        Used to change a player name after color is assigned.
      • askPickColor

        void askPickColor​(Player player,
                          java.util.List<PlayerColor> colorsLeft)
      • askPickFirstMarker

        void askPickFirstMarker​(Player player)
      • assignFirstMarker

        public void assignFirstMarker​(java.lang.String markerId)
        Specified by:
        assignFirstMarker in interface IServer
      • allSetColor

        void allSetColor()
        Hack to set color on load game.
      • getIntOption

        int getIntOption​(java.lang.String optname)
      • oneSetOption

        void oneSetOption​(Player player,
                          java.lang.String optname,
                          java.lang.String value)
      • oneSetOption

        void oneSetOption​(Player player,
                          java.lang.String optname,
                          boolean value)
      • allSyncOption

        void allSyncOption​(java.lang.String optname,
                           java.lang.String value)
      • allSyncOption

        void allSyncOption​(java.lang.String optname,
                           boolean value)
      • allSyncOption

        void allSyncOption​(java.lang.String optname,
                           int value)
      • allLog

        void allLog​(java.lang.String message)
        DO NOT USE: package so that it can be called from Log4J Appender.
      • logToStartLog

        void logToStartLog​(java.lang.String message)
      • disableAutoCloseStartupLog

        private void disableAutoCloseStartupLog()
      • startupProgressAbort

        public void startupProgressAbort()
      • startupProgressQuit

        public void startupProgressQuit()
      • replyToRequestGameInfo

        public void replyToRequestGameInfo()
      • requestSyncDelta

        public void requestSyncDelta​(int lastReceivedMessageNr,
                                     int syncRequestNumber)
      • joinGame

        public void joinGame​(java.lang.String playerName)
        Specified by:
        joinGame in interface IServer
      • watchGame

        public void watchGame()
        Specified by:
        watchGame in interface IServer
      • enforcedDisconnectClient

        public void enforcedDisconnectClient​(java.lang.String name)