Package com.barrybecker4.game.common.online.server

Source Code of com.barrybecker4.game.common.online.server.ServerCommandProcessor

/** Copyright by Barry G. Becker, 2000-2011. Licensed under MIT License: http://www.opensource.org/licenses/MIT  */
package com.barrybecker4.game.common.online.server;

import com.barrybecker4.game.common.GameContext;
import com.barrybecker4.game.common.GameController;
import com.barrybecker4.game.common.online.GameCommand;
import com.barrybecker4.game.common.online.OnlineGameTable;
import com.barrybecker4.game.common.online.OnlineGameTableList;
import com.barrybecker4.game.common.player.Player;
import com.barrybecker4.game.common.player.PlayerAction;
import com.barrybecker4.game.common.player.PlayerList;
import com.barrybecker4.game.common.plugin.GamePlugin;
import com.barrybecker4.game.common.plugin.PluginManager;
import com.barrybecker4.game.common.ui.panel.GamePanel;
import com.barrybecker4.game.common.ui.viewer.GameBoardViewer;
import com.barrybecker4.game.multiplayer.common.MultiGameController;

import java.util.LinkedList;
import java.util.List;

/**
* Handles the processing of all commands send to the online game server from human players.
* All the human players will be surrogates but the robots are here and the server needs to
* issue their actions to their corresponding surrogates on the clients.
*
* @author Barry Becker
*/
class ServerCommandProcessor {

    /** Maintains the active list of game tables. */
    private GameTableManager tableManager;

    /** Maintain the master game state on the server. */
    private GameController controller_;

    /**
     * Create the online game server to serve all online clients.
     */
    public ServerCommandProcessor(String gameName) {

        createController(gameName);
        tableManager = new GameTableManager();
    }

    public OnlineGameTableList getTables() {
        return tableManager.getTables();
    }

    /**
     * Factory method to create the game controller via reflection.
     * The server should not have a ui component.
     */
    private void createController(String gameName) {

        GamePlugin plugin = PluginManager.getInstance().getPlugin(gameName);
        GameContext.loadResources(gameName);

        // for now, also create a corresponding viewer. The server should really not have knowledge of a UI component.
        // fix this by doing plugin.getModelInstance, then getting the controller from that.
        GamePanel panel  = plugin.getPanelInstance();
        panel.init(null);
        GameBoardViewer viewer = panel.getViewer();

        controller_ = viewer.getController();
    }

    public int getPort() {
        return controller_.getServerPort();
    }

    /**
     * Update our internal game table list, or server controller given the cmd from the client.
     * @param cmd to process. The command that the player has issued.
     * @return the response command(s) to send to all the clients.
     */
    public List<GameCommand> processCommand(GameCommand cmd) {

        List<GameCommand> responses = new LinkedList<GameCommand>();
        boolean useUpdateTable = true;

        switch (cmd.getName()) {
            case ENTER_ROOM :
                GameContext.log(2, "Entering room.");
                break;
            case LEAVE_ROOM :
                GameContext.log(0, "Player "+cmd.getArgument()+" is now leaving the room.");
                tableManager.removePlayer((String) cmd.getArgument());
                break;
            case ADD_TABLE :
                tableManager.addTable((OnlineGameTable) cmd.getArgument());
                break;
            case JOIN_TABLE :
                tableManager.joinTable((OnlineGameTable) cmd.getArgument());
                break;
            case CHANGE_NAME :
                String[] names = ((String)cmd.getArgument()).split(GameCommand.CHANGE_TO);
                if (names.length > 1) {
                    tableManager.changeName(names[0], names[1]);
                }
                break;
            case UPDATE_TABLES :
                break;
            case CHAT_MESSAGE :
                GameContext.log(2, "chat message=" + cmd.getArgument());
                useUpdateTable = false;
                responses.add(cmd);
                break;
            case START_GAME:
                OnlineGameTable tableToStart = (OnlineGameTable) cmd.getArgument();
                startGame(tableToStart);
                useUpdateTable = false;
                tableManager.removeTable(tableToStart);
                break;
            case DO_ACTION :
                doPlayerAction(cmd, responses);
                useUpdateTable = false;
                break;
            default:
                assert false : "Unhandled command: "+ cmd;
        }

        if (useUpdateTable) {
            GameCommand response = new GameCommand(GameCommand.Name.UPDATE_TABLES, getTables());
            responses.add(0, response)// add as first command in response.
        }

        return responses;
    }

    /**
     * One of the client players has acted. We need to apply this to the server controller
     * and then broadcast out the same command so the surrogate(s) on the client can be updated.
     * When a robot (on the server) moves, then that action is broadcast to the clients so
     * the surrogates on the clients can be updated.
     * @param cmd the client players command/action
     * @param responses at the least this will be the players action that we received, but it may contain robot
     *       actions for the robots on the server that play immediately after the player.
     */
    private void doPlayerAction(GameCommand cmd, List<GameCommand> responses) {

        PlayerAction action = (PlayerAction) cmd.getArgument();
        GameContext.log(0, "ServerCmdProc: doPlayerAction (" + action + "). Surrogates to handle");
        controller_.handlePlayerAction(action);

        responses.add(cmd);

        // get all robot player actions until the next human player
        List<PlayerAction> robotActions = ((MultiGameController)controller_).getRecentRobotActions();

        for (PlayerAction act : robotActions) {
            GameCommand robotCmd = new GameCommand(GameCommand.Name.DO_ACTION, act);
            GameContext.log(0, "adding response command for robot action on server :" + robotCmd);
            responses.add(robotCmd);
        }
    }

    /**
     * When all the conditions are met for starting a new game, we create a new game controller of the
     * appropriate type and start the game here on the server.
     * All human players will be surrogates and robots will be themselves.
     * @param table the table to start a game for
     */
    private void startGame(OnlineGameTable table) {

        GameContext.log(0, "Now starting game on Server! "+ table);

        // Create players from the table and start.
        PlayerList players = table.getPlayers();
        assert (players.size() == table.getNumPlayersNeeded());
        PlayerList newPlayers = new PlayerList();
        for (Player player : players) {
            if (player.isHuman()) {
                newPlayers.add(player.createSurrogate(controller_.getServerConnection()));
            } else {
                newPlayers.add(player);
            }
        }
        controller_.reset();
        controller_.setPlayers(newPlayers);

        // if getFirstPlayer returns null, then it is not a turn based game
        Player firstPlayer = controller_.getPlayers().getFirstPlayer();
        if (firstPlayer != null && !firstPlayer.isHuman()) {
            controller_.computerMovesFirst();
        }
    }
}
TOP

Related Classes of com.barrybecker4.game.common.online.server.ServerCommandProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.