Package org.pokenet.server.network

Source Code of org.pokenet.server.network.TcpProtocolHandler

package org.pokenet.server.network;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.pokenet.server.GameServer;
import org.pokenet.server.backend.ItemProcessor;
import org.pokenet.server.backend.entity.PlayerChar;
import org.pokenet.server.backend.entity.PlayerChar.RequestType;
import org.pokenet.server.backend.entity.Positionable.Direction;
import org.pokenet.server.battle.BattleTurn;
import org.pokenet.server.battle.impl.PvPBattleField;
import org.pokenet.server.battle.impl.WildBattleField;
import org.pokenet.server.network.message.ItemMessage;
import org.pokenet.server.network.message.PokenetMessage;
import org.pokenet.server.network.message.RequestMessage;

/**
* Handles packets received from players over TCP
* @author shadowkanji
*
*/
public class TcpProtocolHandler extends IoHandlerAdapter {
  private static HashMap<String, PlayerChar> m_players;
  private LoginManager m_loginManager;
  private LogoutManager m_logoutManager;
  private RegistrationManager m_regManager;
 
  /**
   * Constructor
   * @param login
   * @param logout
   */
  public TcpProtocolHandler(LoginManager login, LogoutManager logout) {
    m_loginManager = login;
    m_logoutManager = logout;
    m_regManager = new RegistrationManager();
    m_regManager.start();
  }
 
  static {
    m_players = new HashMap<String, PlayerChar>();
  }
 
  @Override
  public void sessionCreated(IoSession session) {
    //Tell the client which revision the server is on
    session.write("R" + GameServer.REVISION);
  }
 
  /**
   * Handles any exceptions involving a player's session
   */
  public void exceptionCaught(IoSession session, Throwable t)
  throws Exception {
    /*
     * Attempt to disconnect and logout the player (save their data)
     */
    try {
      PlayerChar p = (PlayerChar) session.getAttribute("player");
      if(p != null) {
        if (p.isBattling())
          p.lostBattle();
        m_logoutManager.queuePlayer(p);
        GameServer.getServiceManager().getMovementService().removePlayer(p.getName());
        m_players.remove(p);
      }
      if(!(t instanceof IOException) || session.isConnected() || !session.isClosing())
        session.close(true);
    } catch (Exception e) {
      e.printStackTrace();
    }
    t.printStackTrace();
  }
 
  /**
      * Once the server receives a packet from the client, this method is run.
      * @param IoSession session - A client session
      * @param Object msg - The packet received from the client
    */
  public void messageReceived(IoSession session, Object msg) throws Exception {
    String message = (String) msg;
    String [] details;
    if (!message.equals("L") && !message.equals("R") && !message.equals("D") && !message.equals("U")) {
      System.out.println(message);
    }
    if(session.getAttribute("player") == null) {
      /*
       * The player hasn't been logged in, only allow login and registration packets
       */
      switch(message.charAt(0)) {
      case 'l':
        //Login packet
        details = message.substring(1).split(",");
        m_loginManager.queuePlayer(session, details[0], details[1]);
        break;
      case 'r':
        //Registration packet
        m_regManager.queueRegistration(session, message.substring(1));
        break;
      case 'c':
        //Change password packet
        details = message.substring(1).split(",");
        m_loginManager.queuePasswordChange(session, details[0], details[1], details[2]);
        break;
      case 'f':
        //Force login
        details = message.substring(1).split(",");
        m_loginManager.queuePlayer(session, details[0], details[1]);
        break;
      }
    } else {
      /*
       * Player is logged in, allow interaction with their player object
       */
      PlayerChar p = (PlayerChar) session.getAttribute("player");
      p.lastPacket = System.currentTimeMillis();
      switch(message.charAt(0)) {
      case 'U':
        //Move up
        p.queueMovement(Direction.Up);
        break;
      case 'D':
        //Move down
        p.queueMovement(Direction.Down);
        break;
      case 'L':
        //Move left
        p.queueMovement(Direction.Left);
        break;
      case 'R':
        //Move right
        p.queueMovement(Direction.Right);
        break;
      case 'P':
        //Pokemon interaction
        int pokemonIndex = 0;
        String move;
        switch(message.charAt(1)) {
        case 'm':
          //Player is allowing move to be learned
          pokemonIndex = Integer.parseInt(String.valueOf(message.charAt(2)));
          int moveIndex = Integer.parseInt(String.valueOf(message.charAt(3)));
          move = message.substring(4);
          if(move != null && !move.equalsIgnoreCase("") &&
              p.getParty()[pokemonIndex] != null) {
            if(p.getParty()[pokemonIndex].getMovesLearning().contains(move)) {
              p.getParty()[pokemonIndex].learnMove(moveIndex, move);
              p.updateClientPP(pokemonIndex, moveIndex);
            }
          }
          break;
        case 'M':
          //Player is not allowing the move to be learned
          pokemonIndex = Integer.parseInt(String.valueOf(message.charAt(2)));
          move = message.substring(3);
          if(p.getParty()[pokemonIndex] != null) {
            if(p.getParty()[pokemonIndex].getMovesLearning().contains(move)) {
              p.getParty()[pokemonIndex].getMovesLearning().remove(move);
            }
          }
          break;
        case 'e':
          //Evolution response
          pokemonIndex = Integer.parseInt(String.valueOf(message.charAt(3)));
          if(p.getParty()[pokemonIndex] != null) {
            switch(message.charAt(2)) {
            case '0':
              //Cancel evolution
              p.getParty()[pokemonIndex].evolutionResponse(false, p);
              break;
            case '1':
              //Allow evolution
              p.getParty()[pokemonIndex].evolutionResponse(true, p);
              break;
            }
          }
          break;
        }
        break;
      case 's':
        //Party swapping
        p.swapPokemon(Integer.parseInt(message.substring(1, message.indexOf(','))),
            Integer.parseInt(message.substring(message.indexOf(',') + 1)));
        break;
      case 'S':
        //Shop interaction
        if(p.isShopping()) {
          int item = -1;
          switch(message.charAt(1)) {
          case 'b':
            //Buy items. Sent as SbITEMID,QUANTITY
            item = Integer.parseInt(message.substring(2, message.indexOf(',')));
            //int q = Integer.parseInt(message.substring(message.indexOf(',') + 1));
            p.buyItem(item, 1);
            break;
          case 's':
            //Sell items. Sent as SsITEMID,QUANTITY
            item = Integer.parseInt(message.substring(2, message.indexOf(',')));
            //int q = Integer.parseInt(message.substring(message.indexOf(',') + 1));
            p.sellItem(item, 1);
            break;
          case 'f':
            //Finished shopping
            p.setShopping(false);
            break;
          }
        } else if(p.isSpriting()) {
          //Sprite changing
          int sprite = Integer.parseInt(message.substring(1));
          /* Ensure the user buys a visible sprite */
          if(sprite > 0 && !GameServer.getServiceManager().
              getSpriteList().getUnbuyableSprites().contains(sprite)) {
            if(p.getMoney() >= 500) {
              p.setMoney(p.getMoney() - 500);
              p.updateClientMoney();
              p.setSprite(sprite);
              p.setSpriting(false);
            }
          }
        }
        break;
      case 'r':
        String player = message.substring(2);
        //A request was sent
        switch(message.charAt(1)) {
        case 'b':
          //Battle Request rbUSERNAME
          if(m_players.containsKey(player)) {
            TcpProtocolHandler.writeMessage(m_players.get(player).getTcpSession(),
                new RequestMessage(RequestType.BATTLE, p.getName()));
            p.addRequest(player, RequestType.BATTLE);
          }
          break;
        case 't':
          //Trade Request rtUSERNAME
          if(m_players.containsKey(player)) {
            TcpProtocolHandler.writeMessage(m_players.get(player).getTcpSession(),
                new RequestMessage(RequestType.TRADE, p.getName()));
            p.addRequest(player, RequestType.TRADE);
          }
          break;
        case 'a':
          //Request accepted raUSERNAME
          if(m_players.containsKey(player)) {
            m_players.get(player).requestAccepted(p.getName());
          }
          break;
        case 'c':
          //Request declined rcUSERNAME
          if(m_players.containsKey(player)) {
            m_players.get(player).removeRequest(p.getName());
          }
          break;
        }
        break;
      case 'B':
        //Box interaction
        if(p.isBoxing()) {
          switch(message.charAt(1)) {
          case 'r':
            //Requesting info for box number - e.g. Br0
            int boxNum = Integer.parseInt(String.valueOf(message.charAt(2)));
            if(boxNum >= 0 && boxNum < 9)
              p.sendBoxInfo(boxNum);
            break;
          case 'R':
            //Releasing a pokemon from storage - sent as BRBOXNUM,BOXSLOT
            details = message.substring(2).split(",");
            p.releasePokemon(Integer.parseInt(details[0]), Integer.parseInt(details[1]));
            break;
          case 's':
            //Swap pokemon between box and party - sent as BsBOXNUM,BOXSLOT,PARTYSLOT, e.g.Bs0,1,0
            details = message.substring(2).split(",");
            p.swapFromBox(Integer.parseInt(details[0]),
                Integer.parseInt(details[1]), Integer.parseInt(details[2]));
            break;
          case 'f':
            //Finished with box interfaction
            p.setBoxing(false);
            break;
          }
        }
        break;
      case 'M':
        //Moderation
        if(message.charAt(1) == 'c') {
          p.getTcpSession().write("Cl" + m_players.size() + " players online");
        } else if(p.getAdminLevel() > 0) {
          try {
            switch(message.charAt(1)) {
            case 'a':
              //Server announcement
              for (String s : m_players.keySet()){
                m_players.get(s).getTcpSession().write("q" + message.substring(2));
              }
              break;           
            case 'l':
              //Send an alert
              if(p.getAdminLevel()>1)
                for (String s : m_players.keySet()){
                  m_players.get(s).getTcpSession().write("!" + message.substring(2));
                }
              break;
            case 'b':
              //Ban player
              if(m_players.containsKey(message.substring(2))) {
                PlayerChar o = m_players.get(message.substring(2));
                MySqlManager m = new MySqlManager();
                if(m.connect(GameServer.getDatabaseHost(),
                    GameServer.getDatabaseUsername(),
                    GameServer.getDatabasePassword())) {
                  m.selectDatabase(GameServer.getDatabaseName());
                  m.query("INSERT INTO pn_bans (ip) VALUE ('" +
                      o.getIpAddress()
                      + "')");
                  m.close();
                }
              }
              break;
            case 'B':
              //Unban ip
              MySqlManager m = new MySqlManager();
              if(m.connect(GameServer.getDatabaseHost(),
                  GameServer.getDatabaseUsername(),
                  GameServer.getDatabasePassword())) {
                m.selectDatabase(GameServer.getDatabaseName());
                m.query("DELETE FROM pn_bans WHERE ip='" +
                    message.substring(2)
                    + "'");
                m.close();
              }
              break;
            case 'W':
              //Warp to player
              if(m_players.containsKey(message.substring(2))) {
                PlayerChar o = m_players.get(message.substring(2));
                p.setX(o.getX());
                p.setY(o.getY());
                p.setMap(o.getMap(), null);
              }
              break;
            case 'm':
              //Mute player
              if(m_players.containsKey(message.substring(2))) {
                PlayerChar o = m_players.get(message.substring(2));
                o.setMuted(true);
                o.getTcpSession().write("!You have been muted.");
              }
              break;
            case 'u':
              //Unmute player
              if(m_players.containsKey(message.substring(2))) {
                PlayerChar o = m_players.get(message.substring(2));
                o.setMuted(false);
                o.getTcpSession().write("!You have been unmuted.");
              }
              break;
            case 'k':
              if(m_players.containsKey(message.substring(2))) {
                PlayerChar o = m_players.get(message.substring(2));
                o.getTcpSession().write("!You have been kicked from the server.");
                o.getTcpSession().close(true);
              }
              break;
            case 'w':
              //Change weather on current map
              switch(message.charAt(2)) {
              case 'n':
                //Normal
                GameServer.getServiceManager().getTimeService().setForcedWeather(0);
                break;
              case 'r':
                //Rain
                GameServer.getServiceManager().getTimeService().setForcedWeather(1);
                break;
              case 's':
                //Snow/Hail
                GameServer.getServiceManager().getTimeService().setForcedWeather(2);
                break;   
              case 'f':
                //Fog
                GameServer.getServiceManager().getTimeService().setForcedWeather(3);
                break;
              case 'S':
                //Sandstorm
                GameServer.getServiceManager().getTimeService().setForcedWeather(4);
                break;
              case 'R':
                //Random
                GameServer.getServiceManager().getTimeService().setForcedWeather(9);
                break;
              }
            case 's':
              if(p.getAdminLevel() == 2) {
                GameServer.getServiceManager().stop();
                return;
              }
              break;
            case 'n':
              //Announce message to server
              if(p.getAdminLevel() == 2) {
                //TODO: add code?
                  String mes = message.substring(3);
                                  GameServer.getServiceManager().getNetworkService().getChatManager().
                                  queueLocalChatMessage("<SERVER> " + mes, p.getMapX(), p.getMapY(), p.getLanguage());
              }
              break;
            }
          } catch (Exception e) {}
        }
        break;
      case 'b':
        //Battle information
        if(p.isBattling()) {
          BattleTurn turn;
          switch(message.charAt(1)) {
          case 'm':
            //Move selected (bmINDEXOFMOVE)
            turn = BattleTurn.getMoveTurn(Integer.parseInt(message.substring(2)));
            p.getBattleField().queueMove(p.getBattleId(), turn);
            break;
          case 's':
            //Pokemon switch (bsPARTYINDEX)
            int pIndex = Integer.parseInt(message.substring(2));
            if(p.getParty()[pIndex] != null) {
              if(!p.getParty()[pIndex].isFainted()) {
                turn = BattleTurn.getSwitchTurn(pIndex);
                p.getBattleField().queueMove(p.getBattleId(), turn);
              }
            }
            break;
          case 'r':
            //Run
            if(p.getBattleField() instanceof WildBattleField) {
              ((WildBattleField) p.getBattleField()).run();
            }
            break;
          }
        }
        break;
      case 'F':
        //Friend list
        String friend = message.substring(2);
        switch(message.charAt(1)) {
        case 'a':
          //Add a friend
          if(m_players.containsKey(friend));
            p.addFriend(message.substring(2));
          break;
        case 'r':
          //Remove a friend
          p.removeFriend(message.substring(2));
          break;
        }
        break;
      case 'I':
        //Use an item, applies inside and outside of battle
        details = message.substring(1).split(",");
        System.out.println("Item used. "+message);
        new Thread(new ItemProcessor(p, details)).start();
        break;
      case 'i':
        //Drop item
        if(p.getBag().removeItem(Integer.parseInt(message.substring(1)), 1)) {
          TcpProtocolHandler.writeMessage(p.getTcpSession(), new ItemMessage(false,
              Integer.parseInt(message.substring(1)), 1));
        }
        break;
      case 'T':
        //Trade packets
        if(p.isTrading()) {
          switch (message.charAt(1)){
          case 'o':
            //Make an offer ToPOKENUM,MONEYAMOUNT
            details = message.substring(2).split(",");
            p.getTrade().setOffer(p, Integer.parseInt(String.valueOf(details[0])) ,
                Integer.parseInt(String.valueOf(details[1])));
            break;
          case 't':
            //Ready to perform the trade
            p.setTradeAccepted(true);
            break;
          case 'c':
            //Cancel the offer
            p.cancelTradeOffer();
            break;
          case 'C':
            //Cancel the trade
            p.getTrade().endTrade();
            break;
          }
        }
        break;
      case 'C':
        //Chat/Interact
                switch(message.charAt(1)) {
                case 'l':
                        //Local chat
                        String mes = message.substring(2);
                        if(!p.isMuted())
                                GameServer.getServiceManager().getNetworkService().getChatManager().
                                queueLocalChatMessage("<" + p.getName() + "> " + mes, p.getMapX(), p.getMapY(), p.getLanguage());
                        break;
                case 'p':
                        //Private chat
                        details = message.substring(2).split(",");
                        if(m_players.containsKey(details[0])) {
                                GameServer.getServiceManager().getNetworkService().getChatManager().
                                queuePrivateMessage(details[1], m_players.get(details[0]).getTcpSession(), p.getName());
                        }
                        break;
        case 't':
          //Start talking
          if(!p.isTalking() && !p.isBattling())
            p.talkToNpc();
          break;
        case 'f':
          //Finish talking
          if(p.isTalking())
            p.setTalking(false);
          break;
        }
        break;
      }
    }
  }
 
  /**
   * When a user disconnects voluntarily, this method is called
   */
  @Override
  public void sessionClosed(IoSession session) throws Exception {
    /*
     * Attempt to save the player's data
     */
    try {
      PlayerChar p = (PlayerChar) session.getAttribute("player");
      if(p != null) {
        if(p.isBattling()) {
          /* If in PvP battle, the player loses */
          if(p.getBattleField() instanceof PvPBattleField) {
            ((PvPBattleField) p.getBattleField()).disconnect(p.getBattleId());
          }
          p.setBattleField(null);
          p.setBattling(false);
          p.lostBattle();
        }
        /* If trading, end the trade */
        if(p.isTrading()) {
          p.getTrade().endTrade();
        }
        m_logoutManager.queuePlayer(p);
        GameServer.getServiceManager().getMovementService().removePlayer(p.getName());
        m_players.remove(p);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
 
  /**
   * Logs out all players and stops login/logout/registration managers
   */
  public void logoutAll() {
    m_regManager.stop();
    m_loginManager.stop();
    /*
     * Queue all players to be saved
     */
    Iterator<PlayerChar> it = m_players.values().iterator();
    PlayerChar p;
    while(it.hasNext()) {
      p = it.next();
      m_logoutManager.queuePlayer(p);
    }
    /*
     * Since the method is called during a server shutdown, wait for all players to be logged out
     */
    while(m_logoutManager.getPlayerAmount() > 0);
    m_logoutManager.stop();
  }
 
  /**
   * Adds a player to the player list
   * @param p
   */
  public static void addPlayer(PlayerChar p) {
    synchronized(m_players) {
      m_players.put(p.getName(), p);
    }
  }
 
  /**
   * Removes a player from the player list
   * @param p
   */
  public static void removePlayer(PlayerChar p) {
    synchronized(m_players) {
      m_players.remove(p.getName());
    }
  }
 
  /**
   * Returns a player
   * @param username
   * @return
   */
  public static PlayerChar getPlayer(String username) {
    synchronized(m_players) {
      return m_players.get(username);
    }
  }
 
  /**
   * Returns true if the player list contains a player
   * @param username
   * @return
   */
  public static boolean containsPlayer(String username) {
    synchronized(m_players) {
      return m_players.containsKey(username);
    }
  }
 
  /**
   * Kicks idle players
   */
  public static void kickIdlePlayers() {
    synchronized(m_players) {
      for(PlayerChar p : m_players.values()) {
        if(System.currentTimeMillis() - p.lastPacket >= 900000)
          p.forceLogout();
      }
    }
  }
 
  /**
   * Returns how many players are logged in
   * @return
   */
  public static int getPlayerCount() {
    synchronized(m_players) {
      return m_players.keySet().size();
    }
  }
 
  /**
   * Writes the message to the session
   * @param session
   * @param m
   */
  public static void writeMessage(IoSession session, PokenetMessage m) {
    if(session.isConnected())
      session.write(m.getMessage());
  }
}
TOP

Related Classes of org.pokenet.server.network.TcpProtocolHandler

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.