Package l2p.gameserver.model

Source Code of l2p.gameserver.model.AutoChatHandler

package l2p.gameserver.model;

import java.sql.ResultSet;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Logger;

import javolution.util.FastMap;
import l2p.common.ThreadPoolManager;
import l2p.database.DatabaseUtils;
import l2p.database.FiltredPreparedStatement;
import l2p.database.L2DatabaseFactory;
import l2p.database.ThreadConnection;
import l2p.gameserver.model.entity.SevenSigns;
import l2p.gameserver.model.instances.L2NpcInstance;
import l2p.gameserver.serverpackets.NpcSay;
import l2p.util.GArray;
import l2p.util.Rnd;

/**
* Auto Chat Handler
* <p/>
* Allows NPCs to automatically send messages to nearby players at a set time
* interval.
*/
public class AutoChatHandler implements SpawnListener
{
  protected static Logger _log = Logger.getLogger(AutoChatHandler.class.getName());
  private static AutoChatHandler _instance;
  private static final long DEFAULT_CHAT_DELAY = 180000; // 3 mins by default
  Map<Integer, AutoChatInstance> _registeredChats;

  protected AutoChatHandler()
  {
    _registeredChats = new FastMap<Integer, AutoChatInstance>().setShared(true);
    restoreChatData();
    L2Spawn.addSpawnListener(this);
  }

  private void restoreChatData()
  {
    int numLoaded = 0;
    ThreadConnection con = null;
    FiltredPreparedStatement statement = null;
    FiltredPreparedStatement statement2 = null;
    ResultSet rset = null, rset2 = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      statement = con.prepareStatement("SELECT * FROM auto_chat ORDER BY groupId ASC");
      statement2 = con.prepareStatement("SELECT * FROM auto_chat_text WHERE groupId=?");
      rset = statement.executeQuery();
      while(rset.next())
      {
        numLoaded++;
        statement2.setInt(1, rset.getInt("groupId"));
        rset2 = statement2.executeQuery();
        GArray<String> list = new GArray<String>();
        while(rset2.next())
        {
          list.add(rset2.getString("chatText"));
        }
        registerGlobalChat(rset.getInt("npcId"), list.toArray(new String[] {}), rset.getLong("chatDelay") * 1000L);
        DatabaseUtils.closeResultSet(rset2);
      }
    }
    catch(Exception e)
    {
      _log.warning("AutoSpawnHandler: Could not restore chat data: " + e);
    }
    finally
    {
      DatabaseUtils.closeDatabaseSR(statement2, rset2);
      DatabaseUtils.closeDatabaseCSR(con, statement, rset);
    }
  }

  public static AutoChatHandler getInstance()
  {
    if(_instance == null)
    {
      _instance = new AutoChatHandler();
    }
    return _instance;
  }

  public int size()
  {
    return _registeredChats.size();
  }

  /**
   * Registers a globally active auto chat for ALL instances of the given NPC
   * ID. <BR>
   * Returns the associated auto chat instance.
   *
   * @param int      npcId
   * @param String[] chatTexts
   * @param int      chatDelay (-1 = default delay)
   * @return AutoChatInstance chatInst
   */
  public AutoChatInstance registerGlobalChat(int npcId, String[] chatTexts, long chatDelay)
  {
    return registerChat(npcId, null, chatTexts, chatDelay);
  }

  /**
   * Registers a NON globally-active auto chat for the given NPC instance, and
   * adds to the currently assigned chat instance for this NPC ID, otherwise
   * creates a new instance if a previous one is not found. <BR>
   * Returns the associated auto chat instance.
   *
   * @param L2NpcInstance npcInst
   * @param String[]      chatTexts
   * @param int           chatDelay (-1 = default delay)
   * @return AutoChatInstance chatInst
   */
  public AutoChatInstance registerChat(L2NpcInstance npcInst, String[] chatTexts, long chatDelay)
  {
    return registerChat(npcInst.getNpcId(), npcInst, chatTexts, chatDelay);
  }

  private AutoChatInstance registerChat(int npcId, L2NpcInstance npcInst, String[] chatTexts, long chatDelay)
  {
    AutoChatInstance chatInst;
    if(chatDelay < 0)
    {
      chatDelay = DEFAULT_CHAT_DELAY;
    }
    if(_registeredChats.containsKey(npcId))
    {
      chatInst = _registeredChats.get(npcId);
    }
    else
    {
      chatInst = new AutoChatInstance(npcId, chatTexts, chatDelay, (npcInst == null));
    }
    if(npcInst != null)
    {
      chatInst.addChatDefinition(npcInst);
    }
    _registeredChats.put(npcId, chatInst);
    return chatInst;
  }

  /**
   * Removes and cancels ALL auto chat definition for the given NPC ID, and
   * removes its chat instance if it exists.
   *
   * @param int npcId
   * @return boolean removedSuccessfully
   */
  public boolean removeChat(int npcId)
  {
    AutoChatInstance chatInst = _registeredChats.get(npcId);
    return removeChat(chatInst);
  }

  /**
   * Removes and cancels ALL auto chats for the given chat instance.
   *
   * @param AutoChatInstance chatInst
   * @return boolean removedSuccessfully
   */
  public boolean removeChat(AutoChatInstance chatInst)
  {
    if(chatInst == null)
    {
      return false;
    }
    _registeredChats.remove(chatInst.getNPCId());
    chatInst.setActive(false);
    return true;
  }

  /**
   * Returns the associated auto chat instance either by the given NPC ID or
   * object ID.
   *
   * @param int     id
   * @param boolean byObjectId
   * @return AutoChatInstance chatInst
   */
  public AutoChatInstance getAutoChatInstance(int id, boolean byObjectId)
  {
    if(!byObjectId)
    {
      return _registeredChats.get(id);
    }
    for(AutoChatInstance chatInst : _registeredChats.values())
    {
      if(chatInst.getChatDefinition(id) != null)
      {
        return chatInst;
      }
    }
    return null;
  }

  /**
   * Sets the active state of all auto chat instances to that specified, and
   * cancels the scheduled chat task if necessary.
   *
   * @param boolean isActive
   */
  public void setAutoChatActive(boolean isActive)
  {
    for(AutoChatInstance chatInst : _registeredChats.values())
    {
      chatInst.setActive(isActive);
    }
  }

  /**
   * Used in conjunction with a SpawnListener, this method is called every
   * time an NPC is spawned in the world. <BR>
   * <BR>
   * If an auto chat instance is set to be "global", all instances matching
   * the registered NPC ID will be added to that chat instance.
   */
  @Override
  public void npcSpawned(L2NpcInstance npc)
  {
    synchronized(_registeredChats)
    {
      if(npc == null)
      {
        return;
      }
      int npcId = npc.getNpcId();
      if(_registeredChats.containsKey(npcId))
      {
        AutoChatInstance chatInst = _registeredChats.get(npcId);
        if(chatInst != null && chatInst.isGlobal())
        {
          chatInst.addChatDefinition(npc);
        }
      }
    }
  }

  @Override
  public void npcDeSpawned(L2NpcInstance npc)
  {
  }

  /**
   * Auto Chat Instance <BR>
   * <BR>
   * Manages the auto chat instances for a specific registered NPC ID.
   *
   * @author Tempy
   */
  public class AutoChatInstance
  {
    int _npcId;
    private long _defaultDelay = DEFAULT_CHAT_DELAY;
    private String[] _defaultTexts;
    private boolean _defaultRandom = false;
    private boolean _globalChat = false;
    private boolean _isActive;
    private Map<Integer, AutoChatDefinition> _chatDefinitions = new FastMap<Integer, AutoChatDefinition>().setShared(true);
    private ScheduledFuture<?> _chatTask;

    AutoChatInstance(int npcId, String[] chatTexts, long chatDelay, boolean isGlobal)
    {
      _defaultTexts = chatTexts;
      _npcId = npcId;
      _defaultDelay = chatDelay;
      _globalChat = isGlobal;
      setActive(true);
    }

    AutoChatDefinition getChatDefinition(int objectId)
    {
      return _chatDefinitions.get(objectId);
    }

    AutoChatDefinition[] getChatDefinitions()
    {
      return _chatDefinitions.values().toArray(new AutoChatDefinition[_chatDefinitions.values().size()]);
    }

    /**
     * Defines an auto chat for an instance matching this auto chat
     * instance's registered NPC ID, and launches the scheduled chat task.
     * <BR>
     * Returns the object ID for the NPC instance, with which to refer to
     * the created chat definition. <BR>
     * <B>Note</B>: Uses pre-defined default values for texts and chat
     * delays from the chat instance.
     *
     * @param L2NpcInstance npcInst
     * @return int objectId
     */
    public int addChatDefinition(L2NpcInstance npcInst)
    {
      return addChatDefinition(npcInst, null, 0);
    }

    /**
     * Defines an auto chat for an instance matching this auto chat
     * instance's registered NPC ID, and launches the scheduled chat task.
     * <BR>
     * Returns the object ID for the NPC instance, with which to refer to
     * the created chat definition.
     *
     * @param L2NpcInstance npcInst
     * @param String[]      chatTexts
     * @param int           chatDelay
     * @return int objectId
     */
    public int addChatDefinition(L2NpcInstance npcInst, String[] chatTexts, long chatDelay)
    {
      int objectId = npcInst.getObjectId();
      AutoChatDefinition chatDef = new AutoChatDefinition(this, npcInst, chatTexts, chatDelay);
      _chatDefinitions.put(objectId, chatDef);
      return objectId;
    }

    /**
     * Removes a chat definition specified by the given object ID.
     *
     * @param int objectId
     * @return boolean removedSuccessfully
     */
    public boolean removeChatDefinition(int objectId)
    {
      if(!_chatDefinitions.containsKey(objectId))
      {
        return false;
      }
      AutoChatDefinition chatDefinition = _chatDefinitions.get(objectId);
      chatDefinition.setActive(false);
      _chatDefinitions.remove(objectId);
      return true;
    }

    /**
     * Tests if this auto chat instance is active.
     *
     * @return boolean isActive
     */
    public boolean isActive()
    {
      return _isActive;
    }

    /**
     * Tests if this auto chat instance applies to ALL currently spawned
     * instances of the registered NPC ID.
     *
     * @return boolean isGlobal
     */
    public boolean isGlobal()
    {
      return _globalChat;
    }

    /**
     * Tests if random order is the DEFAULT for new chat definitions.
     *
     * @return boolean isRandom
     */
    public boolean isDefaultRandom()
    {
      return _defaultRandom;
    }

    /**
     * Tests if the auto chat definition given by its object ID is set to be
     * random.
     *
     * @return boolean isRandom
     */
    public boolean isRandomChat(int objectId)
    {
      if(!_chatDefinitions.containsKey(objectId))
      {
        return false;
      }
      return _chatDefinitions.get(objectId).isRandomChat();
    }

    /**
     * Returns the ID of the NPC type managed by this auto chat instance.
     *
     * @return int npcId
     */
    public int getNPCId()
    {
      return _npcId;
    }

    /**
     * Returns the number of auto chat definitions stored for this instance.
     *
     * @return int definitionCount
     */
    public int getDefinitionCount()
    {
      return _chatDefinitions.size();
    }

    /**
     * Returns a list of all NPC instances handled by this auto chat
     * instance.
     *
     * @return L2NpcInstance[] npcInsts
     */
    public L2NpcInstance[] getNPCInstanceList()
    {
      GArray<L2NpcInstance> npcInsts = new GArray<L2NpcInstance>();
      for(AutoChatDefinition chatDefinition : _chatDefinitions.values())
      {
        npcInsts.add(chatDefinition._npcInstance);
      }
      return npcInsts.toArray(new L2NpcInstance[npcInsts.size()]);
    }

    /**
     * A series of methods used to get and set default values for new chat
     * definitions.
     */
    public long getDefaultDelay()
    {
      return _defaultDelay;
    }

    public String[] getDefaultTexts()
    {
      return _defaultTexts;
    }

    public void setDefaultChatDelay(long delayValue)
    {
      _defaultDelay = delayValue;
    }

    public void setDefaultChatTexts(String[] textsValue)
    {
      _defaultTexts = textsValue;
    }

    public void setDefaultRandom(boolean randValue)
    {
      _defaultRandom = randValue;
    }

    /**
     * Sets a specific chat delay for the specified auto chat definition
     * given by its object ID.
     *
     * @param int  objectId
     * @param long delayValue
     */
    public void setChatDelay(int objectId, long delayValue)
    {
      AutoChatDefinition chatDef = getChatDefinition(objectId);
      if(chatDef != null)
      {
        chatDef.setChatDelay(delayValue);
      }
    }

    /**
     * Sets a specific set of chat texts for the specified auto chat
     * definition given by its object ID.
     *
     * @param int      objectId
     * @param String[] textsValue
     */
    public void setChatTexts(int objectId, String[] textsValue)
    {
      AutoChatDefinition chatDef = getChatDefinition(objectId);
      if(chatDef != null)
      {
        chatDef.setChatTexts(textsValue);
      }
    }

    /**
     * Sets specifically to use random chat order for the auto chat
     * definition given by its object ID.
     *
     * @param int     objectId
     * @param boolean randValue
     */
    public void setRandomChat(int objectId, boolean randValue)
    {
      AutoChatDefinition chatDef = getChatDefinition(objectId);
      if(chatDef != null)
      {
        chatDef.setRandomChat(randValue);
      }
    }

    /**
     * Sets the activity of ALL auto chat definitions handled by this chat
     * instance.
     *
     * @param boolean isActive
     */
    public void setActive(boolean activeValue)
    {
      if(_isActive == activeValue)
      {
        return;
      }
      _isActive = activeValue;
      if(!isGlobal())
      {
        for(AutoChatDefinition chatDefinition : _chatDefinitions.values())
        {
          chatDefinition.setActive(activeValue);
        }
        return;
      }
      if(isActive())
      {
        AutoChatRunner acr = new AutoChatRunner(_npcId, -1);
        _chatTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(acr, _defaultDelay, _defaultDelay);
      }
      else
      {
        _chatTask.cancel(false);
      }
    }

    /**
     * Auto Chat Definition <BR>
     * <BR>
     * Stores information about specific chat data for an instance of the
     * NPC ID specified by the containing auto chat instance. <BR>
     * Each NPC instance of this type should be stored in a subsequent
     * AutoChatDefinition class.
     *
     * @author Tempy
     */
    private class AutoChatDefinition
    {
      protected int _chatIndex = 0;
      protected L2NpcInstance _npcInstance;
      protected AutoChatInstance _chatInstance;
      protected ScheduledFuture<?> _chatTask;
      private long _chatDelay = 0;
      private String[] _chatTexts = null;
      private boolean _isActive;
      private boolean _randomChat;

      protected AutoChatDefinition(AutoChatInstance chatInst, L2NpcInstance npcInst, String[] chatTexts, long chatDelay)
      {
        _npcInstance = npcInst;
        _chatInstance = chatInst;
        _randomChat = chatInst.isDefaultRandom();
        _chatDelay = chatDelay;
        _chatTexts = chatTexts;
        // If global chat isn't enabled for the parent instance,
        // then handle the chat task locally.
        if(!chatInst.isGlobal())
        {
          setActive(true);
        }
      }

      String[] getChatTexts()
      {
        if(_chatTexts != null)
        {
          return _chatTexts;
        }
        return _chatInstance.getDefaultTexts();
      }

      private long getChatDelay()
      {
        if(_chatDelay > 0)
        {
          return _chatDelay;
        }
        return _chatInstance.getDefaultDelay();
      }

      private boolean isActive()
      {
        return _isActive;
      }

      boolean isRandomChat()
      {
        return _randomChat;
      }

      void setRandomChat(boolean randValue)
      {
        _randomChat = randValue;
      }

      void setChatDelay(long delayValue)
      {
        _chatDelay = delayValue;
      }

      void setChatTexts(String[] textsValue)
      {
        _chatTexts = textsValue;
      }

      void setActive(boolean activeValue)
      {
        if(isActive() == activeValue)
        {
          return;
        }
        if(activeValue)
        {
          AutoChatRunner acr = new AutoChatRunner(_npcId, _npcInstance.getObjectId());
          _chatTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(acr, getChatDelay(), getChatDelay());
        }
        else
        {
          _chatTask.cancel(false);
        }
        _isActive = activeValue;
      }
    }

    /**
     * Auto Chat Runner <BR>
     * <BR>
     * Represents the auto chat scheduled task for each chat instance.
     */
    private class AutoChatRunner implements Runnable
    {
      private int _npcId;
      private int _objectId;

      protected AutoChatRunner(int npcId, int objectId)
      {
        _npcId = npcId;
        _objectId = objectId;
      }

      public synchronized void run()
      {
        AutoChatInstance chatInst = _registeredChats.get(_npcId);
        AutoChatDefinition[] chatDefinitions;
        if(chatInst.isGlobal())
        {
          chatDefinitions = chatInst.getChatDefinitions();
        }
        else
        {
          AutoChatDefinition chatDef = chatInst.getChatDefinition(_objectId);
          if(chatDef == null)
          {
            _log.warning("AutoChatHandler: Auto chat definition is NULL for NPC ID " + _npcId + ".");
            return;
          }
          chatDefinitions = new AutoChatDefinition[] {chatDef};
        }
        for(AutoChatDefinition chatDef : chatDefinitions)
        {
          try
          {
            if(chatDef == null)
            {
              continue;
            }
            int maxIndex = chatDef.getChatTexts().length;
            int lastIndex = Rnd.get(maxIndex);
            String text;
            if(!chatDef.isRandomChat())
            {
              lastIndex = chatDef._chatIndex;
              lastIndex++;
              if(lastIndex == maxIndex)
              {
                lastIndex = 0;
              }
              chatDef._chatIndex = lastIndex;
            }
            text = chatDef.getChatTexts()[lastIndex];
            if(text == null || text.equals(""))
            {
              return;
            }
            L2NpcInstance chatNpc = chatDef._npcInstance;
            if(!chatNpc.isVisible())
            {
              return;
            }
            GArray<L2Player> nearbyPlayers = text.startsWith("!") ? L2World.getAroundPlayers(chatNpc) : L2World.getAroundPlayers(chatNpc, 1500, 200);
            if(nearbyPlayers == null || nearbyPlayers.isEmpty())
            {
              return;
            }
            L2Player randomPlayer = nearbyPlayers.get(Rnd.get(nearbyPlayers.size()));
            final int winningCabal = SevenSigns.getInstance().getCabalHighestScore();
            int losingCabal = SevenSigns.CABAL_NULL;
            if(winningCabal == SevenSigns.CABAL_DAWN)
            {
              losingCabal = SevenSigns.CABAL_DUSK;
            }
            else if(winningCabal == SevenSigns.CABAL_DUSK)
            {
              losingCabal = SevenSigns.CABAL_DAWN;
            }
            if(text.indexOf("%player_random%") > -1)
            {
              text = text.replaceAll("%player_random%", randomPlayer.getName());
            }
            if(text.indexOf("%player_cabal_winner%") > -1)
            {
              boolean playerFound = false;
              for(L2Player nearbyPlayer : nearbyPlayers)
              {
                if(nearbyPlayer == null)
                {
                  continue;
                }
                if(SevenSigns.getInstance().getPlayerCabal(nearbyPlayer) == winningCabal)
                {
                  text = text.replaceAll("%player_cabal_winner%", nearbyPlayer.getName());
                  playerFound = true;
                  break;
                }
              }
              // If a player on the winning side isn't nearby,
              // just use the randomly selected player.
              if(!playerFound)
              {
                text = "";
              }// text =
              // text.replaceAll("%player_cabal_winner%",
              // randomPlayer.getName());
            }
            if(text.indexOf("%player_cabal_loser%") > -1)
            {
              boolean playerFound = false;
              for(L2Player nearbyPlayer : nearbyPlayers)
              {
                if(nearbyPlayer == null)
                {
                  continue;
                }
                if(SevenSigns.getInstance().getPlayerCabal(nearbyPlayer) == losingCabal)
                {
                  text = text.replaceAll("%player_cabal_loser%", nearbyPlayer.getName());
                  playerFound = true;
                  break;
                }
              }
              // If a player on the winning side isn't nearby,
              // just use the randomly selected player.
              if(!playerFound)
              {
                text = "";
              }// text =
              // text.replaceAll("%player_cabal_loser%",
              // randomPlayer.getName());
            }
            if(text.equals(""))
            {
              return;
            }
            NpcSay cs = new NpcSay(chatNpc, text.startsWith("!") ? 1 : 0, text.startsWith("!") ? text.substring(1, text.length() - 1) : text);
            for(L2Player nearbyPlayer : nearbyPlayers)
            {
              if(nearbyPlayer == null)
              {
                continue;
              }
              nearbyPlayer.sendPacket(cs);
            }
          }
          catch(Exception e)
          {
            e.printStackTrace();
            return;
          }
        }
      }
    }
  }
}
TOP

Related Classes of l2p.gameserver.model.AutoChatHandler

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.