Package de.creepsmash.server.game

Source Code of de.creepsmash.server.game.RunningGameState

/**
   Creep Smash, a multiplayer towerdefence game
   created as a project at the Hochschule fuer
   Technik Stuttgart (University of Applied Science)
   http://www.hft-stuttgart.de
  
   Copyright (C) 2008 by     
    * Andreas Wittig
    * Bernd Hietler
    * Christoph Fritz
    * Fabian Kessel
    * Levin Fritz
    * Nikolaj Langner
    * Philipp Schulte-Hubbert
    * Robert Rapczynski
    * Ron Trautsch
    * Sven Supper
    http://creepsmash.sf.net/

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/


package de.creepsmash.server.game;

import java.awt.Point;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import de.creepsmash.common.IConstants;
import de.creepsmash.common.IConstants.ErrorType;
import de.creepsmash.common.messages.client.BuildCreepMessage;
import de.creepsmash.common.messages.client.BuildTowerMessage;
import de.creepsmash.common.messages.client.ChangeStrategyMessage;
import de.creepsmash.common.messages.client.ExitGameMessage;
import de.creepsmash.common.messages.client.GameMessage;
import de.creepsmash.common.messages.client.GameOverMessage;
import de.creepsmash.common.messages.client.KickPlayerRequestMessage;
import de.creepsmash.common.messages.client.LogoutMessage;
import de.creepsmash.common.messages.client.SellTowerMessage;
import de.creepsmash.common.messages.client.SendMessageMessage;
import de.creepsmash.common.messages.client.StartGameRequestMessage;
import de.creepsmash.common.messages.client.UpgradeTowerMessage;
import de.creepsmash.common.messages.server.BuildCreepRoundMessage;
import de.creepsmash.common.messages.server.BuildTowerRoundMessage;
import de.creepsmash.common.messages.server.ChangeStrategyRoundMessage;
import de.creepsmash.common.messages.server.RoundMessage;
import de.creepsmash.common.messages.server.SellTowerRoundMessage;
import de.creepsmash.common.messages.server.UpgradeTowerRoundMessage;
import de.creepsmash.server.Client;
import de.creepsmash.server.HighscoreService;

/**
* GameState for a game that's running (has started).
*/
public class RunningGameState extends GameState {

  private int nextTowerId;
  private long maxTick;
  private Map<String, Integer> playerNamePositionMap;
  private long startDate;

  private static Logger logger = Logger.getLogger(RunningGameState.class);

  /**
   * Constructor.
   * @param game the game. Must not be null.
   * Must not be null or empty.
   */
  public RunningGameState(Game game) {
    super(game);
    this.nextTowerId = 1;
    this.maxTick = 0;
    this.playerNamePositionMap = new HashMap<String, Integer>();
    this.startDate = System.currentTimeMillis() / 1000;
   
  }

  /**
   * Advance the maxTick counter and send a "ROUND n OK" message to all
   * players.
   */
  public void tick() {
    if (this.maxTick % IConstants.USER_ACTION_DELAY == 0) {
      RoundMessage message = new RoundMessage();
      message.setRoundId(this.maxTick + IConstants.USER_ACTION_DELAY);
      this.getGame().sendAll(message);
    }
    this.maxTick += 1;
  }

  /**
   * Handle a message (from a client, presumably).
   * @param message the message. Must not be null.
   * @param sender the player who sent the message. Must not be null.
   * @return the new state
   */
  public GameState consume(GameMessage message, PlayerInGame sender) {
    if (message == null) {
      throw new IllegalArgumentException("'message' was null");
    }
    if (sender == null) {
      throw new IllegalArgumentException("'sender' was null");
    }

    if (message instanceof StartGameRequestMessage
        || message instanceof KickPlayerRequestMessage) {
      this.wrongStateForMessage(message, sender);
    } else if (message instanceof BuildTowerMessage) {
      this.handle((BuildTowerMessage) message);
    } else if (message instanceof UpgradeTowerMessage) {
      this.handle((UpgradeTowerMessage) message, sender);
    } else if (message instanceof ChangeStrategyMessage) {
      this.handle((ChangeStrategyMessage) message, sender);
    } else if (message instanceof SellTowerMessage) {
      this.handle((SellTowerMessage) message, sender);
    } else if (message instanceof BuildCreepMessage) {
      this.handle((BuildCreepMessage) message);
    } else if (message instanceof GameOverMessage) {
      return this.handle((GameOverMessage) message, sender);
    } else if (message instanceof ExitGameMessage) {
      return this.handle((ExitGameMessage) message);
    } else if (message instanceof SendMessageMessage) {
      this.handle((SendMessageMessage) message);
    } else if (message instanceof LogoutMessage) {
      return this.handle((LogoutMessage) message);
    } else {
      logger.error("cannot handle message: " + message);
    }

    return this;
  }
 
  private void handle(ChangeStrategyMessage message, PlayerInGame sender) {
    int towerId = message.getTowerId();

    // sanity checks on the id
    Client client = sender.getClient();
    if (towerId <= 0) {
      client.handleError(ErrorType.Error,
          "Invalid tower id (tried to change strategy " + towerId + ")");
      return;
    } else if (towerId >= this.nextTowerId) {
      client.handleError(ErrorType.Error,
          "No such tower (tried to change strategy " + towerId + ")");
      return;
    }

    ChangeStrategyRoundMessage csm = new ChangeStrategyRoundMessage();
    csm.setRoundId(this.maxTick + IConstants.USER_ACTION_DELAY);
    csm.setPlayerId(message.getClientId());
    csm.setTowerId(towerId);
    csm.setStrategyType(message.getStrategyType());
    csm.setLocked(message.isLocked());
    this.getGame().sendAll(csm);
   
  }

  /**
   * Handles the BuildTowerMessage.
   * @param m the message
   */
  private void handle(BuildTowerMessage m) {
    String type = m.getTowerType();
    Point position = m.getPosition();
    BuildTowerRoundMessage n = new BuildTowerRoundMessage();
    n.setRoundId(this.maxTick + IConstants.USER_ACTION_DELAY);
    n.setPlayerId(m.getClientId());
    n.setTowerType(type);
    n.setTowerPosition(position);
    n.setTowerId(this.nextTowerId++);
    this.getGame().sendAll(n);
  }
 
  /**
   * Handles the UpgradeTowerMessage.
   * @param m the message.
   * @param sender the player who sent the message.
   */
  private void handle(UpgradeTowerMessage m, PlayerInGame sender) {
    int towerId = m.getTowerId();

    // sanity checks on the id
    Client client = sender.getClient();
    if (towerId <= 0) {
      client.handleError(ErrorType.Error,
          "Invalid tower id (tried to upgrade tower " + towerId + ")");
      return;
    } else if (towerId >= this.nextTowerId) {
      client.handleError(ErrorType.Error,
          "No such tower (tried to upgrade tower " + towerId + ")");
      return;
    }

    UpgradeTowerRoundMessage n = new UpgradeTowerRoundMessage();
    n.setRoundId(this.maxTick + IConstants.USER_ACTION_DELAY);
    n.setPlayerId(m.getClientId());
    n.setTowerId(towerId);
    this.getGame().sendAll(n);
  }

  /**
   * Handles the SellTowerMessage.
   * @param m the message.
   * @param sender the player who sent the message.
   */
  private void handle(SellTowerMessage m, PlayerInGame sender) {
    int towerId = m.getTowerId();

    // sanity checks on the id
    Client client = sender.getClient();
    if (towerId <= 0) {
      client.handleError(ErrorType.Error,
          "Invalid tower id (tried to sell tower " + towerId + ")");
      return;
    } else if (towerId >= this.nextTowerId) {
      client.handleError(ErrorType.Error,
          "No such tower (tried to sell tower " + towerId + ")");
      return;
    }

    SellTowerRoundMessage n = new SellTowerRoundMessage();
    n.setRoundId(this.maxTick + IConstants.USER_ACTION_DELAY);
    n.setPlayerId(m.getClientId());
    n.setTowerId(towerId);
    this.getGame().sendAll(n);
  }
 
  /**
   * Handles the BuildCreepMessage.
   * @param m the message
   */
  private void handle(BuildCreepMessage m) {
    String type = m.getCreepType();
    int senderId = m.getClientId();
    int recipientId =
      this.getGame().getClients().succ(senderId).getClient().getClientID();
    BuildCreepRoundMessage n = new BuildCreepRoundMessage();
    n.setRoundId(this.maxTick + IConstants.USER_ACTION_DELAY);
    n.setPlayerId(recipientId);
    n.setCreepType(type);
    n.setSenderId(senderId);
    this.getGame().sendAll(n);
  }

  /**
   * Handles the GameOverMessage.
   * @param m the message
   * @param sender the player who sent the message.
   * @return the new state.
   */
  private GameState handle(GameOverMessage m, PlayerInGame sender) {
    int position = m.getPosition();
    Client client = sender.getClient();

    if (position < 1) {
      client.handleError(ErrorType.Error, "position in GAME_OVER must be > 0");   
      return this;
    }

    this.playerNamePositionMap.put(client.getUserName(), position);

    logger.info("game over for " + client + " (position: " + position + ")");
    sender.gameOver();
    if (gameOverForAll()) {
      logger.info("saving scores: " + this.playerNamePositionMap);
      (new HighscoreService()).createHighscoreEntry(this.playerNamePositionMap);
     
      //save Game in DB
      this.getGame().SaveToJournal(this.playerNamePositionMap, startDate);
      return new EndedGameState(this.getGame());
    } else {
      return this;
    }
  }

  /**
   * Checks if all clients have sent GAME_OVER.
   * @return true if all clients have sent a GAME_OVER message, false otherwise.
   */
  private boolean gameOverForAll() {
    for (PlayerInGame p : this.getGame().getClients()) {
      if (!p.getGameOver()) {
        return false;
      }
    }
    return true;
  }

  /**
   * Remove client from the game.
   * @param client the client. Must not be null.
   * @param reason a short string to be used in PLAYER_QUIT messages. Must not
   * be null.
   * @return the new state.
   */
  protected GameState removeClient(Client client, String reason) {
    // save score, if necessary
    if (!this.playerNamePositionMap.containsKey(client.getUserName())) {
      int position = getGame().getCurrentPlayers();
      for (int p : this.playerNamePositionMap.values()) {
        if (p >= position) {
          position = p - 1;
        }
      }
      this.playerNamePositionMap.put(client.getUserName(), position);
    }

    // let GameState.removeClient(..) do the rest of the work
    return super.removeClient(client, reason);
  }

  /**
   * Returns a string identifying this state.
   * @return "running"
   */
  @Override
  public String toString() {
    return "running";
  }

}
TOP

Related Classes of de.creepsmash.server.game.RunningGameState

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.