Package de.creepsmash.server.game

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

/**
   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.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import org.apache.log4j.Logger;

import de.creepsmash.common.IConstants;
import de.creepsmash.common.messages.client.GameMessage;
import de.creepsmash.common.messages.server.PlayerJoinedMessage;
import de.creepsmash.common.messages.server.ServerMessage;
import de.creepsmash.server.AuthenticationService;
import de.creepsmash.server.Client;
import de.creepsmash.server.PersistenceManager;
import de.creepsmash.server.QueueConsumerThread;
import de.creepsmash.server.QueueMessage;
import de.creepsmash.server.model.GameJournal;
import de.creepsmash.server.model.Player;
/**
* Coordinates a game of Tower Defence. This class's job is mainly coordinating
* the various queues and threads, handling message and other events is
* delegated to instances of {@link GameState GameState}.
*/
public class Game
  implements QueueConsumerThread.Consumer<GameMessage>,
             TickThread.TickReceiver {

  private int gameId;
  private String gameName;
  private int mapId;
  private int maxPlayers;
  private int PlayersScore;
 
  private String Passwort;
  private Integer MaxEloPoints;
  private Integer MinEloPoints;

  private GameState gameState;
  private PlayerList clients;
  private List<String>  PlayerNames = new ArrayList<String>();
  private BlockingQueue<QueueMessage<GameMessage>> queue;
  private TickThread tickThread;

  private List<GameObserver> observers;

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


  /**
   * An object that observes a Game.
   */
  public interface GameObserver {
    /**
     * Notify the observer of a change in the game's state.
     * @param game the game that changed.
     */
    void gameStateChanged(Game game);

    /**
     * Notify the observer of a change in the game's players.
     * @param game the game that changed.
     */
    void gamePlayersChanged(Game game);

    /**
     * Notify the observer of the game's end.
     * @param game the game that changed.
     */
    void gameEnded(Game game);

    /**
     * Notify the observer of the game's termination.
     * @param game the game that changed.
     */
    void gameTerminated(Game game);
  }


  /**
   * No-arg constructor for subclasses.
   * @param gameId the game's id.
   * @param gameName a name for the game.
   * @param mapId the id of the map.
   * @param maxPlayers the max number of players in this game.
   */
  protected Game(int gameId, String gameName, int mapId, int maxPlayers,String Passwort,int MaxEloPoints,int MinEloPoints) {
    this.gameId = gameId;
    this.gameName = gameName;
    this.mapId = mapId;
    this.PlayersScore = 0;
    this.maxPlayers = maxPlayers;
    this.Passwort = Passwort;
    this.MaxEloPoints = MaxEloPoints;
    this.MinEloPoints = MinEloPoints;

    this.observers = new LinkedList<GameObserver>();
    this.clients = new PlayerList();
  }

  /**
   * Create a new game with the given gameId. This sets up the queue and the
   * thread that takes messages from the queue.
   * @param gameId the game's id.
   * @param gameName a name for the game.
   * @param mapId the id of the map.
   * @param maxPlayers the max number of players in this game.
   * @param creator the client who created the game.
   */
  public Game(int gameId, String gameName, int mapId, int maxPlayers,
      Client creator,String Passwort,int MaxEloPoints,int MinEloPoints) {
    this.gameId = gameId;
    this.gameName = gameName;
    this.mapId = mapId;
    this.maxPlayers = maxPlayers;
   
    this.Passwort = Passwort;
    this.MaxEloPoints = MaxEloPoints;
    this.MinEloPoints = MinEloPoints;
   
    this.gameState = new WaitingGameState(this, creator);
    this.clients = new PlayerList();
    this.queue = new LinkedBlockingQueue<QueueMessage<GameMessage>>();

    (new QueueConsumerThread<GameMessage>(this, this.queue)).start();

    this.observers = new LinkedList<GameObserver>();
  }

  /**
   * Returns the current list of players.
   * @return the current list of players.
   */
  public synchronized PlayerList getClients() {
         
      return this.clients ; 
  }

  /**
   * Sets the current list of players.
   * @param clients the new list of players. Must not be null.
   */
  public synchronized void setClients(PlayerList clients) {
    if (clients == null) {
     
      //logger.info("score Playersender: " + String.valueOf(clients));
      throw new IllegalArgumentException("'clients' was null");
     
    }
    this.clients = clients;
  }
  /**
   * Set the game's mapId.
   * @return the game's mapId.
   */
  public synchronized void setMapId(int mapId) {
    this.mapId = mapId;
  }
  /**
   * Send a message to all players.
   * @param message the message to be sent
   */
  public void sendAll(ServerMessage message) {
    for (PlayerInGame p : this.clients) {
      p.getClient().send(message);
    }
  }

  /**
   * Returns the current number of players.
   * @return the current number of players.
   */
  public int getCurrentPlayers() {
    return this.clients.size();
  }

  /**
   * Return the game's gameId.
   * @return the game's gameId.
   */
  public int getGameId() {
    return this.gameId;
  }
  public int getPlayerScore() {
    return this.PlayersScore;
  }
  /**
   * Return the game's gameName.
   * @return the game's gameName.
   */
  public String getGameName() {
    return this.gameName;
  }

  /**
   * Return the game's mapId.
   * @return the game's mapId.
   */
  public int getMapId() {
    return this.mapId;
  }

  /**
   * Return the maximum number of players for this game.
   * @return the maximum number of players for this game.
   */
  public int getMaxPlayers() {
    return this.maxPlayers;
  }
 
  /**
   * Return the Game Passwort
   * @return Passwort.
   */
  public String getPasswort() {
    return this.Passwort;
  }
 
  /**
   * Return the Game Passwort
   * @return Passwort.
   */
  public int getMaxEloPoints() {
    return this.MaxEloPoints;
  }
 
  /**
   * Return the Game Passwort
   * @return Passwort.
   */
  public int getMinEloPoints() {
    return this.MinEloPoints;
  }
  public List<String> getPlayerNames(){
    return this.PlayerNames;
  }
  /**
   * Returns the queue that can be used to send messages to this game.
   * @return the game's queue
   */
  public BlockingQueue<QueueMessage<GameMessage>> getQueue() {
    return this.queue;
  }

  /**
   * Returns the current state.
   * @return "waiting", "running", "ended" or "terminated".
   */
  public String getState() {
    return this.gameState.toString();
  }

  /**
   * Handle a message (from a client, presumably).
   * @param message the message
   */
  public synchronized void consume(GameMessage message) {
    try {
      PlayerInGame sender = this.clients.get(message.getClientId());
      if (sender == null) {
        logger.error("got message from client " + message.getClientId()
            + ", but that client is not in the game.");
      }
      changeState(this.gameState.consume(message, sender));
    } catch (Exception e) {
      logger.error(
          "Caught Exception while handling message '" + message + "'", e);
    }
  }

  /**
   * Change the game's GameState.
   * @param newState the new state.
   */
  private void changeState(GameState newState) {
    if (this.gameState.getClass() != newState.getClass()) {
      logger.info("game '" + this + "' enters state " + newState);
    }
    if (this.gameState instanceof WaitingGameState
        && newState instanceof RunningGameState) {
      this.tickThread = new TickThread(this, IConstants.TICK_MS);
      this.tickThread.start();
    }
    if (newState instanceof EndedGameState) {
      if (this.tickThread != null) {
        this.tickThread.terminate();
      }
      gameEnded();
    }
    if (newState instanceof TerminatedGameState) {
      shutdown();
      gameTerminated();
    }

    GameState oldState = this.gameState;
    this.gameState = newState;

    if (oldState.getClass() != newState.getClass()) {
      gameStateChanged();
    }
  }

  /**
   * Called periodically by TickThread when the game is running.
   */
  public synchronized void tick() {
    this.gameState.tick();
  }

  /**
   * Returns true if another player can join this game.
   * @return true if another player can join this game.
   */
  public synchronized boolean canClientJoin() {
    return
      this.gameState instanceof WaitingGameState
      && this.clients.size() < this.maxPlayers;
  }

  /**
   * Register a new client with the game.
   * @param newClient the new client. Must not be null.
   */
  public synchronized void newClient(Client newClient) {
    if (newClient == null) {
      throw new IllegalArgumentException("'newClient' was null!");
    }
   
    this.PlayersScore +=  AuthenticationService.getPlayer(
        newClient.getUserName()).getElopoints() - 500;
   
    this.PlayerNames.add(newClient.getUserName());
   
    if (!(this.gameState instanceof WaitingGameState)) {
      throw new RuntimeException("game has started--no more players can join");
    }
    if (this.clients.size() >= this.maxPlayers) {
      throw new RuntimeException(
          "max # of players reached--no more players can join");
    }
    newClient.send(
        new PlayerJoinedMessage(
          newClient.getUserName(), newClient.getClientID(), AuthenticationService.getPlayer(
              newClient.getUserName()).getElopoints() - 500));
    sendAll(
        new PlayerJoinedMessage(
          newClient.getUserName(), newClient.getClientID(), AuthenticationService.getPlayer(
              newClient.getUserName()).getElopoints() - 500));
    for (PlayerInGame p : this.clients) {
      Client c = p.getClient();
      newClient.send(
          new PlayerJoinedMessage(c.getUserName(), c.getClientID(), AuthenticationService.getPlayer(
              c.getUserName()).getElopoints() - 500));
    }
     
    this.clients.add(newClient);
    gamePlayersChanged();
  }
  public synchronized void removeClient(Client removeClient) {
   
   
    this.PlayersScore -=  AuthenticationService.getPlayer(
                  removeClient.getUserName()).getElopoints() - 500;
   
    this.clients.remove(removeClient.getClientID());
    this.PlayerNames.remove(removeClient.getUserName());
   
  }

  /**
   * Shutdown the game, including all threads it might have spawned.
   */
  public synchronized void shutdown() {
    if (this.tickThread != null) {
      this.tickThread.terminate();
    }
    try {
      this.queue.put(QueueMessage.<GameMessage>sentinel());
    } catch (InterruptedException e) {
      logger.warn("caught InterruptedException", e);
    }
  }

  /**
   * Adds an observer. It will be notified of any change in the game's state or
   * list of players.
   * @param observer the observer. Must not be null.
   */
  public void addObserver(GameObserver observer) {
    if (observer == null) {
      throw new IllegalArgumentException("'observer' was null");
    }
    this.observers.add(observer);
  }

  /**
   * Notifies all observers.
   */
  public void gameStateChanged() {
    for (GameObserver observer : this.observers) {
      observer.gameStateChanged(this);
    }
  }

  /**
   * Notifies all observers.
   */
  public void gamePlayersChanged() {
    for (GameObserver observer : this.observers) {
      observer.gamePlayersChanged(this);
    }
  }

  /**
   * Notifies all observers.
   */
  public void gameEnded() {
    for (GameObserver observer : this.observers) {
      observer.gameEnded(this);
    }
  }

  /**
   * Notifies all observers.
   */
  public void gameTerminated() {
    for (GameObserver observer : this.observers) {
      observer.gameTerminated(this);
    }
  }

  /**
   * Returns the gameName.
   * @return the gameName.
   */
  public String toString() {
    return this.gameName;
  }

  /**
   * Set the GameState.
   * @param gameState the new GameState.
   */
  protected void setGameState(GameState gameState) {
    this.gameState = gameState;
  }
  /**
   * Return the current GameState.
   * @return the current GameState.
   */
  protected GameState getGameState() {
    return this.gameState;
  }
 
  /**
   * The Function saves actual ended game into DB
   *
   * @param playerNamePositionMap Players with position
   * @param startDate Start date of game
   */
  public void SaveToJournal(Map<String, Integer> playerNamePositionMap, long startDate) {
    try {     
      EntityManager entityManager = PersistenceManager.getInstance().getEntityManager();
      EntityTransaction entityTransaction = entityManager.getTransaction();
      entityTransaction.begin();
 
      GameJournal gameJournalEntry = new GameJournal();
      String mapname = IConstants.Map.getMapById(mapId).getFilename();
      mapname = mapname.replaceAll("de/creepsmash/client/resources/maps/map_", "");
      gameJournalEntry.setMap(mapname.replaceAll(".map", ""));
      gameJournalEntry.setName(gameName);
      gameJournalEntry.setNumPlayers(playerNamePositionMap.size());
      gameJournalEntry.setStart_date(startDate);
      gameJournalEntry.setEnd_date(System.currentTimeMillis() / 1000);
      int i = 0;
      for (String playerName : playerNamePositionMap.keySet()) {
        i++;
        Player player = AuthenticationService.getPlayer(playerName);
        if (player != null) {
          int num = playerNamePositionMap.get(playerName);
          // Ich habe keine idee wie man da ohne switch macht^^
          switch(i) {
            case 1:
              gameJournalEntry.setPlayer1(player.getName());
              gameJournalEntry.setPlayer1_score(player.getOldElopoints());
              gameJournalEntry.setScore1(player.getElopoints());
              gameJournalEntry.setPlayer1_position(num);
              gameJournalEntry.setIp1(player.getIp());
              gameJournalEntry.setMac1(player.getMac());
              break;
            case 2:
              gameJournalEntry.setPlayer2(player.getName());
              gameJournalEntry.setPlayer2_score(player.getOldElopoints());
              gameJournalEntry.setScore2(player.getElopoints());
              gameJournalEntry.setPlayer2_position(num);
              gameJournalEntry.setIp2(player.getIp());
              gameJournalEntry.setMac2(player.getMac());
              break;
            case 3:
              gameJournalEntry.setPlayer3(player.getName());
              gameJournalEntry.setPlayer3_score(player.getOldElopoints());
              gameJournalEntry.setScore3(player.getElopoints());
              gameJournalEntry.setPlayer3_position(num);
              gameJournalEntry.setIp3(player.getIp());
              gameJournalEntry.setMac3(player.getMac());
              break;
            case 4:
              gameJournalEntry.setPlayer4(player.getName());
              gameJournalEntry.setPlayer4_score(player.getOldElopoints());
              gameJournalEntry.setScore4(player.getElopoints());
              gameJournalEntry.setPlayer4_position(num);
              gameJournalEntry.setIp4(player.getIp());
              gameJournalEntry.setMac4(player.getMac());
              break;
            default:
              logger.error("False number of players: " + i);
              break;
          }
        }
      }
     
      entityManager.persist(gameJournalEntry);
      entityManager.flush();
      entityTransaction.commit();
      logger.debug("GameJournal saved.");
    } catch (Throwable t) {
      logger.error("error while saving GameJournal", t);
    }
  }

  /**
   * The function check for multiaccounting.
   *
   * @param ip IP Address of Client
   */
  public boolean check4Multi(String ip, String mac) {
    if (IConstants.MUTIACCOUNT_IP_CHECK || IConstants.MUTIACCOUNT_MAC_CHECK) {
      boolean a = false;
      for (PlayerInGame p : this.clients) {
        Client c = p.getClient();
        // If the client from same Computer
        if (mac.equalsIgnoreCase(c.getMACAddress())
            && IConstants.MUTIACCOUNT_MAC_CHECK) {
          logger.warn("Multiaccounting detected. MAC: " + mac);
          return false;
        }
        // If the client from same IP
        if (ip.equalsIgnoreCase(c.getIPAddress())
            && IConstants.MUTIACCOUNT_IP_CHECK) {
          if (a) {
            logger.warn("Multiaccounting detected. IP: " + ip);
            return false;
          }
          a = true;
        }
      }
    }
    return true;
  }
}
TOP

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

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.