Package l2p.gameserver.instancemanager

Source Code of l2p.gameserver.instancemanager.CursedWeaponsManager$RemoveTask

package l2p.gameserver.instancemanager;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilderFactory;

import javolution.util.FastMap;
import l2p.Config;
import l2p.common.ThreadPoolManager;
import l2p.database.DatabaseUtils;
import l2p.database.FiltredPreparedStatement;
import l2p.database.L2DatabaseFactory;
import l2p.database.ThreadConnection;
import l2p.gameserver.model.CursedWeapon;
import l2p.gameserver.model.L2ObjectsStorage;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.model.instances.L2NpcInstance;
import l2p.gameserver.model.items.L2ItemInstance;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.tables.ItemTable;
import l2p.gameserver.tables.SkillTable;
import l2p.gameserver.templates.L2Item;
import l2p.util.Location;
import l2p.util.Rnd;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

public class CursedWeaponsManager
{
  private static final Logger _log = Logger.getLogger(CursedWeaponsManager.class.getName());
  private static CursedWeaponsManager _instance;

  public static CursedWeaponsManager getInstance()
  {
    if(_instance == null)
    {
      _instance = new CursedWeaponsManager();
    }
    return _instance;
  }
  Map<Integer, CursedWeapon> _cursedWeapons;
  private ScheduledFuture<?> _removeTask;
  private static final int CURSEDWEAPONS_MAINTENANCE_INTERVAL = 5 * 60 * 1000; // 5 min in millisec

  public CursedWeaponsManager()
  {
    _cursedWeapons = new FastMap<Integer, CursedWeapon>().setShared(true);
    if(!Config.ALLOW_CURSED_WEAPONS)
    {
      return;
    }
    _log.info("CursedWeaponsManager: Initializing");
    load();
    restore();
    checkConditions();
    cancelTask();
    _removeTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new RemoveTask(), CURSEDWEAPONS_MAINTENANCE_INTERVAL, CURSEDWEAPONS_MAINTENANCE_INTERVAL);
    _log.info("CursedWeaponsManager: Loaded " + _cursedWeapons.size() + " cursed weapon(s).");
  }

  public final void reload()
  {
    _instance = new CursedWeaponsManager();
  }

  private void load()
  {
    try
    {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      factory.setValidating(false);
      factory.setIgnoringComments(true);
      File file = new File(Config.DATAPACK_ROOT + "/data/cursed_weapons.xml");
      if(!file.exists())
      {
        return;
      }
      Document doc = factory.newDocumentBuilder().parse(file);
      for(Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
      {
        if("list".equalsIgnoreCase(n.getNodeName()))
        {
          for(Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
          {
            if("item".equalsIgnoreCase(d.getNodeName()))
            {
              NamedNodeMap attrs = d.getAttributes();
              int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
              Integer skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
              String name = "Unknown cursed weapon";
              if(attrs.getNamedItem("name") != null)
              {
                name = attrs.getNamedItem("name").getNodeValue();
              }
              else if(ItemTable.getInstance().getTemplate(id) != null)
              {
                name = ItemTable.getInstance().getTemplate(id).getName();
              }
              if(id == 0)
              {
                continue;
              }
              CursedWeapon cw = new CursedWeapon(id, skillId, name);
              for(Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
              {
                if("dropRate".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setDropRate(Integer.parseInt(cd.getAttributes().getNamedItem("val").getNodeValue()));
                }
                else if("duration".equalsIgnoreCase(cd.getNodeName()))
                {
                  attrs = cd.getAttributes();
                  cw.setDurationMin(Integer.parseInt(attrs.getNamedItem("min").getNodeValue()));
                  cw.setDurationMax(Integer.parseInt(attrs.getNamedItem("max").getNodeValue()));
                }
                else if("durationLost".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setDurationLost(Integer.parseInt(cd.getAttributes().getNamedItem("val").getNodeValue()));
                }
                else if("disapearChance".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setDisapearChance(Integer.parseInt(cd.getAttributes().getNamedItem("val").getNodeValue()));
                }
                else if("stageKills".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setStageKills(Integer.parseInt(cd.getAttributes().getNamedItem("val").getNodeValue()));
                }
                else if("transformationId".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setTransformationId(Integer.parseInt(cd.getAttributes().getNamedItem("val").getNodeValue()));
                }
                else if("transformationTemplateId".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setTransformationTemplateId(Integer.parseInt(cd.getAttributes().getNamedItem("val").getNodeValue()));
                }
                else if("transformationName".equalsIgnoreCase(cd.getNodeName()))
                {
                  cw.setTransformationName(cd.getAttributes().getNamedItem("val").getNodeValue());
                }
              }
              // Store cursed weapon
              _cursedWeapons.put(id, cw);
            }
          }
        }
      }
    }
    catch(Exception e)
    {
      _log.severe("CursedWeaponsManager: Error parsing cursed_weapons file. " + e);
    }
  }

  private void restore()
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement = null;
    ResultSet rset = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      statement = con.prepareStatement("SELECT * FROM cursed_weapons");
      rset = statement.executeQuery();
      while(rset.next())
      {
        int itemId = rset.getInt("item_id");
        CursedWeapon cw = _cursedWeapons.get(itemId);
        if(cw != null)
        {
          cw.setPlayerId(rset.getInt("player_id"));
          cw.setPlayerKarma(rset.getInt("player_karma"));
          cw.setPlayerPkKills(rset.getInt("player_pkkills"));
          cw.setNbKills(rset.getInt("nb_kills"));
          cw.setLoc(new Location(rset.getInt("x"), rset.getInt("y"), rset.getInt("z")));
          cw.setEndTime(rset.getLong("end_time") * 1000L);
          if(!cw.reActivate())
          {
            endOfLife(cw);
          }
        }
        else
        {
          removeFromDb(itemId);
          _log.warning("CursedWeaponsManager: Unknown cursed weapon " + itemId + ", deleted");
        }
      }
    }
    catch(Exception e)
    {
      _log.warning("CursedWeaponsManager: Could not restore cursed_weapons data: " + e);
      e.printStackTrace();
    }
    finally
    {
      DatabaseUtils.closeDatabaseCSR(con, statement, rset);
    }
  }

  private void checkConditions()
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement1 = null, statement2 = null;
    ResultSet rset = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      statement1 = con.prepareStatement("DELETE FROM character_skills WHERE skill_id=?");
      statement2 = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?");
      for(CursedWeapon cw : _cursedWeapons.values())
      {
        // Do an item check to be sure that the cursed weapon and/or skill isn't hold by someone
        int itemId = cw.getItemId();
        int skillId = cw.getSkillId();
        boolean foundedInItems = false;
        // Delete all cursed weapons skills (we don`t care about same skill on multiply weapons, when player back, skill will appears again)
        statement1.setInt(1, skillId);
        statement1.executeUpdate();
        statement2.setInt(1, itemId);
        rset = statement2.executeQuery();
        while(rset.next())
        {
          // A player has the cursed weapon in his inventory ...
          int playerId = rset.getInt("owner_id");
          if(!foundedInItems)
          {
            if(playerId != cw.getPlayerId() || cw.getPlayerId() == 0)
            {
              emptyPlayerCursedWeapon(playerId, itemId, cw);
              _log.info("CursedWeaponsManager[254]: Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
            }
            else
            {
              foundedInItems = true;
            }
          }
          else
          {
            emptyPlayerCursedWeapon(playerId, itemId, cw);
            _log.info("CursedWeaponsManager[262]: Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
          }
        }
        if(!foundedInItems && cw.getPlayerId() != 0)
        {
          removeFromDb(cw.getItemId());
          _log.info("CursedWeaponsManager: Unownered weapon, removing from table...");
        }
      }
    }
    catch(Exception e)
    {
      _log.warning("CursedWeaponsManager: Could not check cursed_weapons data: " + e);
      return;
    }
    finally
    {
      DatabaseUtils.closeStatement(statement1);
      DatabaseUtils.closeDatabaseCSR(con, statement2, rset);
    }
  }

  private void emptyPlayerCursedWeapon(int playerId, int itemId, CursedWeapon cw)
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      // Delete the item
      statement = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?");
      statement.setInt(1, playerId);
      statement.setInt(2, itemId);
      statement.executeUpdate();
      DatabaseUtils.closeStatement(statement);
      statement = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE obj_id=?");
      statement.setInt(1, cw.getPlayerKarma());
      statement.setInt(2, cw.getPlayerPkKills());
      statement.setInt(3, playerId);
      if(statement.executeUpdate() != 1)
      {
        _log.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
      }
      // clean up the cursedweapons table.
      removeFromDb(itemId);
    }
    catch(SQLException e)
    {
    }
    finally
    {
      DatabaseUtils.closeDatabaseCS(con, statement);
    }
  }

  public void removeFromDb(int itemId)
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      statement = con.prepareStatement("DELETE FROM cursed_weapons WHERE item_id = ?");
      statement.setInt(1, itemId);
      statement.executeUpdate();
      if(getCursedWeapon(itemId) != null)
      {
        getCursedWeapon(itemId).initWeapon();
      }
    }
    catch(SQLException e)
    {
      _log.severe("CursedWeaponsManager: Failed to remove data: " + e);
    }
    finally
    {
      DatabaseUtils.closeDatabaseCS(con, statement);
    }
  }

  private void cancelTask()
  {
    if(_removeTask != null)
    {
      _removeTask.cancel(true);
      _removeTask = null;
    }
  }

  private class RemoveTask implements Runnable
  {
    @Override
    public void run()
    {
      for(CursedWeapon cw : _cursedWeapons.values())
      {
        if(cw.isActive() && cw.getTimeLeft() <= 0)
        {
          endOfLife(cw);
        }
      }
    }
  }

  public void endOfLife(CursedWeapon cw)
  {
    if(cw.isActivated())
    {
      L2Player player = cw.getOnlineOwner();
      if(player != null)
      {
        // Remove from player
        _log.info("CursedWeaponsManager: " + cw.getName() + " being removed online from " + player + ".");
        player.abortAttack(true, true);
        player.setKarma(cw.getPlayerKarma());
        player.setPkKills(cw.getPlayerPkKills());
        player.setCursedWeaponEquippedId(0);
        player.setTransformation(0);
        player.setTransformationName(null);
        player.removeSkill(SkillTable.getInstance().getInfo(cw.getSkillId(), player.getSkillLevel(cw.getSkillId())), false);
        // Remove
        player.getInventory().unEquipItemInBodySlot(L2Item.SLOT_LR_HAND, null);
        player.store(false);
        // Destroy
        if(player.getInventory().destroyItemByItemId(cw.getItemId(), 1, false) == null)
        {
          _log.info("CursedWeaponsManager[395]: Error! Cursed weapon not found!!!");
        }
        player.broadcastUserInfo(true);
      }
      else
      {
        // Remove from Db
        _log.info("CursedWeaponsManager: " + cw.getName() + " being removed offline.");
        ThreadConnection con = null;
        FiltredPreparedStatement statement = null;
        try
        {
          con = L2DatabaseFactory.getInstance().getConnection();
          // Delete the item
          statement = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?");
          statement.setInt(1, cw.getPlayerId());
          statement.setInt(2, cw.getItemId());
          statement.executeUpdate();
          DatabaseUtils.closeStatement(statement);
          // Delete the skill
          statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND skill_id=?");
          statement.setInt(1, cw.getPlayerId());
          statement.setInt(2, cw.getSkillId());
          statement.executeUpdate();
          DatabaseUtils.closeStatement(statement);
          // Restore the karma
          statement = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE obj_Id=?");
          statement.setInt(1, cw.getPlayerKarma());
          statement.setInt(2, cw.getPlayerPkKills());
          statement.setInt(3, cw.getPlayerId());
          statement.executeUpdate();
        }
        catch(SQLException e)
        {
          _log.warning("CursedWeaponsManager: Could not delete : " + e);
        }
        finally
        {
          DatabaseUtils.closeDatabaseCS(con, statement);
        }
      }
    }
    else // either this cursed weapon is in the inventory of someone who has another cursed weapon equipped,
    // OR this cursed weapon is on the ground.
    if(cw.getPlayer() != null && cw.getPlayer().getInventory().getItemByItemId(cw.getItemId()) != null)
    {
      L2Player player = cw.getPlayer();
      if(cw.getPlayer().getInventory().destroyItemByItemId(cw.getItemId(), 1, false) == null)
      {
        _log.info("CursedWeaponsManager[453]: Error! Cursed weapon not found!!!");
      }
      player.sendChanges();
      player.broadcastUserInfo(true);
    }
    // is dropped on the ground
    else if(cw.getItem() != null)
    {
      cw.getItem().removeFromDb(true);
      cw.getItem().deleteMe();
      _log.info("CursedWeaponsManager: " + cw.getName() + " item has been removed from World.");
    }
    cw.initWeapon();
    removeFromDb(cw.getItemId());
    announce(new SystemMessage(SystemMessage.S1_HAS_DISAPPEARED_CW).addString(cw.getName()));
  }

  public void saveData(CursedWeapon cw)
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement = null;
    synchronized(cw)
    {
      try
      {
        con = L2DatabaseFactory.getInstance().getConnection();
        // Delete previous datas
        statement = con.prepareStatement("DELETE FROM cursed_weapons WHERE item_id = ?");
        statement.setInt(1, cw.getItemId());
        statement.executeUpdate();
        DatabaseUtils.closeStatement(statement);
        statement = null;
        if(cw.isActive())
        {
          statement = con.prepareStatement("REPLACE INTO cursed_weapons (item_id, player_id, player_karma, player_pkkills, nb_kills, x, y, z, end_time) VALUES (?,?,?,?,?,?,?,?,?)");
          statement.setInt(1, cw.getItemId());
          statement.setInt(2, cw.getPlayerId());
          statement.setInt(3, cw.getPlayerKarma());
          statement.setInt(4, cw.getPlayerPkKills());
          statement.setInt(5, cw.getNbKills());
          statement.setInt(6, cw.getLoc().x);
          statement.setInt(7, cw.getLoc().y);
          statement.setInt(8, cw.getLoc().z);
          statement.setLong(9, cw.getEndTime() / 1000);
          statement.executeUpdate();
        }
      }
      catch(SQLException e)
      {
        _log.severe("CursedWeapon: Failed to save data: " + e);
      }
      finally
      {
        DatabaseUtils.closeDatabaseCS(con, statement);
      }
    }
  }

  public void saveData()
  {
    for(CursedWeapon cw : _cursedWeapons.values())
    {
      saveData(cw);
    }
  }

  /**
   * вызывается, когда проклятое оружие оказывается в инвентаре игрока
   */
  public void checkPlayer(L2Player player, L2ItemInstance item)
  {
    if(player == null || item == null || player.isInOlympiadMode())
    {
      return;
    }
    CursedWeapon cw = _cursedWeapons.get(item.getItemId());
    if(cw == null)
    {
      return;
    }
    if(player.getObjectId() == cw.getPlayerId() || cw.getPlayerId() == 0 || cw.isDropped())
    {
      activate(player, item);
      showUsageTime(player, cw);
    }
    else
    {
      // wtf? how you get it?
      _log.warning("CursedWeaponsManager: " + player + " tried to obtain " + item + " in wrong way");
      player.getInventory().destroyItem(item, item.getCount(), true);
    }
  }

  public void activate(L2Player player, L2ItemInstance item)
  {
    if(player == null || player.isInOlympiadMode())
    {
      return;
    }
    CursedWeapon cw = _cursedWeapons.get(item.getItemId());
    if(cw == null)
    {
      return;
    }
    if(player.isCursedWeaponEquipped()) // cannot own 2 cursed swords
    {
      if(player.getCursedWeaponEquippedId() != item.getItemId())
      {
        CursedWeapon cw2 = _cursedWeapons.get(player.getCursedWeaponEquippedId());
        cw2.setNbKills(cw2.getStageKills() - 1);
        cw2.increaseKills();
      }
      // erase the newly obtained cursed weapon
      endOfLife(cw);
      player.getInventory().destroyItem(item, 1, true);
    }
    else if(cw.getTimeLeft() > 0)
    {
      cw.activate(player, item);
      saveData(cw);
      announce(new SystemMessage(SystemMessage.THE_OWNER_OF_S2_HAS_APPEARED_IN_THE_S1_REGION).addZoneName(player.getLoc()).addString(cw.getName()));
    }
    else
    {
      endOfLife(cw);
      player.getInventory().destroyItem(item, 1, true);
    }
  }

  public void doLogout(L2Player player)
  {
    for(CursedWeapon cw : _cursedWeapons.values())
    {
      if(player.getInventory().getItemByItemId(cw.getItemId()) != null)
      {
        cw.setPlayer(null);
        cw.setItem(null);
      }
    }
  }

  /**
   * drop from L2NpcInstance killed by L2Player
   */
  public void dropAttackable(L2NpcInstance attackable, L2Player killer)
  {
    if(killer.isInOlympiadMode() || killer.isCursedWeaponEquipped() || _cursedWeapons.isEmpty())
    {
      return;
    }
    synchronized(_cursedWeapons)
    {
      int num = 0;
      short count = 0;
      byte breakFlag = 0;
      while(breakFlag == 0)
      {
        num = _cursedWeapons.keySet().toArray(new Integer[_cursedWeapons.size()])[Rnd.get(_cursedWeapons.size())];
        count++;
        if(_cursedWeapons.get(num) != null && !_cursedWeapons.get(num).isActive())
        {
          breakFlag = 1;
        }
        else if(count >= getCursedWeapons().size())
        {
          breakFlag = 2;
        }
      }
      if(breakFlag == 1)
      {
        _cursedWeapons.get(num).create(attackable, killer, false);
      }
    }
  }

  /**
   * Выпадение оружия из владельца, или исчезновение с определенной вероятностью.
   * Вызывается при смерти игрока.
   */
  public void dropPlayer(L2Player player)
  {
    CursedWeapon cw = _cursedWeapons.get(player.getCursedWeaponEquippedId());
    if(cw == null)
    {
      return;
    }
    if(cw.dropIt(null, null, player))
    {
      saveData(cw);
      announce(new SystemMessage(SystemMessage.S2_WAS_DROPPED_IN_THE_S1_REGION).addZoneName(player.getLoc()).addString(cw.getName()));
    }
    else
    {
      endOfLife(cw);
    }
  }

  public void increaseKills(int itemId)
  {
    CursedWeapon cw = _cursedWeapons.get(itemId);
    if(cw != null)
    {
      cw.increaseKills();
      saveData(cw);
    }
  }

  public int getLevel(int itemId)
  {
    CursedWeapon cw = _cursedWeapons.get(itemId);
    return cw != null ? cw.getLevel() : 0;
  }

  public void announce(SystemMessage sm)
  {
    for(L2Player player : L2ObjectsStorage.getAllPlayersForIterate())
    {
      player.sendPacket(sm);
    }
  }

  public void showUsageTime(L2Player player, short itemId)
  {
    CursedWeapon cw = _cursedWeapons.get(itemId);
    if(cw != null)
    {
      showUsageTime(player, cw);
    }
  }

  public void showUsageTime(L2Player player, CursedWeapon cw)
  {
    SystemMessage sm = new SystemMessage(SystemMessage.S2_MINUTE_OF_USAGE_TIME_ARE_LEFT_FOR_S1);
    sm.addString(cw.getName());
    sm.addNumber(new Long(cw.getTimeLeft() / 60000).intValue());
    player.sendPacket(sm);
  }

  public boolean isCursed(int itemId)
  {
    return _cursedWeapons.containsKey(itemId);
  }

  public Collection<CursedWeapon> getCursedWeapons()
  {
    return _cursedWeapons.values();
  }

  public Set<Integer> getCursedWeaponsIds()
  {
    return _cursedWeapons.keySet();
  }

  public CursedWeapon getCursedWeapon(int itemId)
  {
    return _cursedWeapons.get(itemId);
  }
}
TOP

Related Classes of l2p.gameserver.instancemanager.CursedWeaponsManager$RemoveTask

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.