Package l2p.gameserver.instancemanager

Source Code of l2p.gameserver.instancemanager.ZoneManager$UnSpawnTask

package l2p.gameserver.instancemanager;

import java.io.File;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilderFactory;

import javolution.util.FastMap;
import l2p.Config;
import l2p.common.ThreadPoolManager;
import l2p.extensions.listeners.L2ZoneEnterLeaveListener;
import l2p.extensions.listeners.PropertyCollection;
import l2p.gameserver.ai.CtrlEvent;
import l2p.gameserver.cache.Msg;
import l2p.gameserver.idfactory.IdFactory;
import l2p.gameserver.model.L2Object;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.model.L2RoundTerritory;
import l2p.gameserver.model.L2Spawn;
import l2p.gameserver.model.L2Territory;
import l2p.gameserver.model.L2Zone;
import l2p.gameserver.model.L2Zone.ZoneType;
import l2p.gameserver.model.Reflection;
import l2p.gameserver.model.entity.residence.Residence;
import l2p.gameserver.model.entity.siege.Siege;
import l2p.gameserver.model.instances.L2NpcInstance;
import l2p.gameserver.tables.NpcTable;
import l2p.gameserver.tables.PetDataTable;
import l2p.gameserver.tables.TerritoryTable;
import l2p.gameserver.templates.L2NpcTemplate;
import l2p.util.GArray;
import l2p.util.Location;
import l2p.util.Rnd;
import l2p.util.XMLUtil;

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

public class ZoneManager
{
  protected static Logger _log = Logger.getLogger(ZoneManager.class.getName());
  private static ZoneManager _instance;
  private static FastMap<ZoneType, GArray<L2Zone>> _zonesByType;
  private final NoLandingZoneListener _noLandingZoneListener = new NoLandingZoneListener();
  private final MonsterTrapZoneListener _monsterTrapZoneListener = new MonsterTrapZoneListener();
  // zoneId, reflectionObjectId, reuseTime
  // FIXME Тут будет утечка памяти
  private FastMap<Integer, FastMap<Long, Long>> _reuseMonsterTrapZones = null;
  private static final long MONSTER_TRAP_DESPAWN_TIME = 5 * 60 * 1000L; // 5 min

  private ZoneManager()
  {
    parse();
  }

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

  public boolean checkIfInZone(ZoneType zoneType, L2Object object)
  {
    return checkIfInZone(zoneType, object.getX(), object.getY(), object.getZ());
  }

  public boolean checkIfInZone(ZoneType zoneType, int x, int y)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return false;
    }
    for(L2Zone zone : list)
    {
      if(zone.isActive() && zone.getLoc() != null && zone.getLoc().isInside(x, y))
      {
        return true;
      }
    }
    return false;
  }

  public boolean checkIfInZone(ZoneType zoneType, int x, int y, int z)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return false;
    }
    for(L2Zone zone : list)
    {
      if(zone.isActive() && zone.getLoc() != null && zone.getLoc().isInside(x, y) && z >= zone.getLoc().getZmin() && z <= zone.getLoc().getZmax())
      {
        return true;
      }
    }
    return false;
  }

  public boolean checkIfInZoneAndIndex(ZoneType zoneType, int index, L2Object object)
  {
    return checkIfInZoneAndIndex(zoneType, index, object.getX(), object.getY(), object.getZ());
  }

  public boolean checkIfInZoneAndIndex(ZoneType zoneType, int index, int x, int y, int z)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return false;
    }
    for(L2Zone zone : list)
    {
      if(zone.isActive() && zone.getIndex() == index && zone.getLoc() != null && zone.getLoc().isInside(x, y) && z >= zone.getLoc().getZmin() && z <= zone.getLoc().getZmax())
      {
        return true;
      }
    }
    return false;
  }

  /*
   * Возвращает первую попавшуюся, соответствующую условиям зону.
   * Полезно, если нужна именно зона, а не факт нахождения в ней
   */
  public L2Zone getZoneByType(ZoneType zoneType, int x, int y, boolean onlyActive)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return null;
    }
    for(L2Zone zone : list)
    {
      if((!onlyActive || zone.isActive()) && zone.getLoc() != null && zone.getLoc().isInside(x, y))
      {
        return zone;
      }
    }
    return null;
  }

  public GArray<L2Zone> getZoneByType(ZoneType zoneType)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    GArray<L2Zone> result = new GArray<L2Zone>();
    if(list == null)
    {
      return result;
    }
    for(L2Zone zone : list)
    {
      if(zone.isActive())
      {
        result.add(zone);
      }
    }
    return result;
  }

  public L2Zone getZoneByIndex(ZoneType zoneType, int index, boolean onlyActive)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return null;
    }
    for(L2Zone zone : list)
    {
      if((!onlyActive || zone.isActive()) && zone.getIndex() == index)
      {
        return zone;
      }
    }
    return null;
  }

  public L2Zone getZoneById(ZoneType zoneType, int id, boolean onlyActive)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return null;
    }
    for(L2Zone zone : list)
    {
      if((!onlyActive || zone.isActive()) && zone.getId() == id)
      {
        return zone;
      }
    }
    return null;
  }

  public L2Zone getZoneByTypeAndObject(ZoneType zoneType, L2Object object)
  {
    return getZoneByTypeAndCoords(zoneType, object.getX(), object.getY(), object.getZ());
  }

  public L2Zone getZoneByTypeAndCoords(ZoneType zoneType, int x, int y, int z)
  {
    GArray<L2Zone> list = _zonesByType.get(zoneType);
    if(list == null)
    {
      return null;
    }
    for(L2Zone zone : list)
    {
      if(zone.isActive() && zone.getLoc() != null && zone.getLoc().isInside(x, y, z))
      {
        return zone;
      }
    }
    return null;
  }

  private void parse()
  {
    _zonesByType = new FastMap<ZoneType, GArray<L2Zone>>().setShared(true);
    GArray<File> files = new GArray<File>();
    hashFiles("zone", files);
    int count = 0;
    for(File f : files)
    {
      count += parseFile(f);
    }
    _log.info("ZoneManager: Loaded " + count + " zones");
    TerritoryTable.getInstance().registerZones();
  }

  private void hashFiles(String dirname, GArray<File> hash)
  {
    File dir = new File(Config.DATAPACK_ROOT, "data/" + dirname);
    if(!dir.exists())
    {
      _log.warning("Dir " + dir.getAbsolutePath() + " not exists");
      return;
    }
    File[] files = dir.listFiles();
    for(File f : files)
    {
      if(f.getName().endsWith(".xml"))
      {
        hash.add(f);
      }
      else if(f.isDirectory() && !f.getName().equals(".svn"))
      {
        hashFiles(dirname + "/" + f.getName(), hash);
      }
    }
  }

  public int parseFile(File f)
  {
    Document doc;
    try
    {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      factory.setValidating(false);
      factory.setIgnoringComments(true);
      doc = factory.newDocumentBuilder().parse(f);
    }
    catch(Exception e)
    {
      _log.log(Level.WARNING, "zones file couldnt be initialized: " + f, e);
      return 0;
    }
    try
    {
      return parseDocument(doc);
    }
    catch(Exception e)
    {
      _log.log(Level.WARNING, "zones file couldnt be initialized: " + f, e);
    }
    return 0;
  }

  protected int parseDocument(Document doc)
  {
    int count = 0;
    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("zone".equalsIgnoreCase(d.getNodeName()))
          {
            L2Zone z = new L2Zone(XMLUtil.getAttributeIntValue(d, "id", 0));
            z.setType(ZoneType.valueOf(XMLUtil.getAttributeValue(d, "type")));
            z.setName(XMLUtil.getAttributeValue(d, "name"));
            boolean enabled = true;
            for(Node e = d.getFirstChild(); e != null; e = e.getNextSibling())
            {
              if("set".equalsIgnoreCase(e.getNodeName()))
              {
                String name = XMLUtil.getAttributeValue(e, "name");
                if("index".equalsIgnoreCase(name))
                {
                  z.setIndex(XMLUtil.getAttributeIntValue(e, "val", 0));
                }
                else if("taxById".equalsIgnoreCase(name))
                {
                  z.setTaxById(XMLUtil.getAttributeIntValue(e, "val", 0));
                }
                else if("entering_message_no".equalsIgnoreCase(name))
                {
                  z.setEnteringMessageId(XMLUtil.getAttributeIntValue(e, "val", 0));
                }
                else if("leaving_message_no".equalsIgnoreCase(name))
                {
                  z.setLeavingMessageId(XMLUtil.getAttributeIntValue(e, "val", 0));
                }
                else if("target".equalsIgnoreCase(name))
                {
                  z.setTarget(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("skill_name".equalsIgnoreCase(name))
                {
                  z.setSkill(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("skill_prob".equalsIgnoreCase(name))
                {
                  z.setSkillProb(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("unit_tick".equalsIgnoreCase(name))
                {
                  z.setUnitTick(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("initial_delay".equalsIgnoreCase(name))
                {
                  z.setInitialDelay(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("restart_time".equalsIgnoreCase(name))
                {
                  z.setRestartTime(XMLUtil.getAttributeLongValue(e, "val", 0));
                }
                else if("blocked_actions".equalsIgnoreCase(name))
                {
                  z.setBlockedActions(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("damage_on_hp".equalsIgnoreCase(name))
                {
                  z.setDamageOnHP(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("damage_on_mp".equalsIgnoreCase(name))
                {
                  z.setDamageOnМP(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("message_no".equalsIgnoreCase(name))
                {
                  z.setMessageNumber(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("move_bonus".equalsIgnoreCase(name))
                {
                  z.setMoveBonus(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("hp_regen_bonus".equalsIgnoreCase(name))
                {
                  z.setRegenBonusHP(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("mp_regen_bonus".equalsIgnoreCase(name))
                {
                  z.setRegenBonusMP(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("affect_race".equalsIgnoreCase(name))
                {
                  z.setAffectRace(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("event".equalsIgnoreCase(name))
                {
                  z.setEvent(XMLUtil.getAttributeValue(e, "val"));
                }
                else if("reflectionId".equalsIgnoreCase(name))
                {
                  z.setReflectionId(XMLUtil.getAttributeIntValue(e, "val", 0));
                }
                else if("enabled".equalsIgnoreCase(name))
                {
                  enabled = XMLUtil.getAttributeBooleanValue(e, "val", true) || z.getType() == ZoneType.water;
                }
                else
                {
                  z.setParam(name, XMLUtil.getAttributeValue(e, "val"));
                }
              }
              else if("shape".equalsIgnoreCase(e.getNodeName()) || "restart_point".equalsIgnoreCase(e.getNodeName()) || "PKrestart_point".equalsIgnoreCase(e.getNodeName()))
              {
                int locId = IdFactory.getInstance().getNextId();
                boolean isRound = !XMLUtil.getAttributeValue(e, "loc").isEmpty();
                L2Territory territory;
                if(isRound)
                {
                  String[] coord = XMLUtil.getAttributeValue(e, "loc").replaceAll(",", " ").replaceAll(";", " ").replaceAll("  ", " ").trim().split(" ");
                  if(coord.length < 5) // Не указаны minZ и maxZ, берем граничные значения
                  {
                    territory = new L2RoundTerritory(locId, Integer.parseInt(coord[0]), Integer.parseInt(coord[1]), Integer.parseInt(coord[2]), Integer.MIN_VALUE, Integer.MAX_VALUE);
                  }
                  else
                  {
                    territory = new L2RoundTerritory(locId, Integer.parseInt(coord[0]), Integer.parseInt(coord[1]), Integer.parseInt(coord[2]), Integer.parseInt(coord[3]), Integer.parseInt(coord[4]));
                  }
                }
                else
                {
                  territory = new L2Territory(locId);
                  for(Node location = e.getFirstChild(); location != null; location = location.getNextSibling())
                  {
                    if("coords".equalsIgnoreCase(location.getNodeName()))
                    {
                      String[] coord = XMLUtil.getAttributeValue(location, "loc").replaceAll(",", " ").replaceAll(";", " ").replaceAll("  ", " ").trim().split(" ");
                      if(coord.length < 4) // Не указаны minZ и maxZ, берем граничные значения
                      {
                        territory.add(Integer.parseInt(coord[0]), Integer.parseInt(coord[1]), Integer.MIN_VALUE, Integer.MAX_VALUE);
                      }
                      else
                      {
                        territory.add(Integer.parseInt(coord[0]), Integer.parseInt(coord[1]), Integer.parseInt(coord[2]), Integer.parseInt(coord[3]));
                      }
                    }
                  }
                }
                if("shape".equalsIgnoreCase(e.getNodeName()))
                {
                  z.setLoc(territory);
                  territory.setZone(z);
                  territory.validate();
                }
                else if("restart_point".equalsIgnoreCase(e.getNodeName()))
                {
                  z.setRestartPoints(territory);
                }
                else if("PKrestart_point".equalsIgnoreCase(e.getNodeName()))
                {
                  z.setPKRestartPoints(territory);
                }
                z.setActive(enabled);
                TerritoryTable.getInstance().getLocations().put(locId, territory);
              }
            }
            if(z.getType() == ZoneType.no_landing || z.getType() == ZoneType.Siege || z.getType() == ZoneType.Castle || z.getType() == ZoneType.Fortress || z.getType() == ZoneType.OlympiadStadia)
            {
              z.getListenerEngine().addMethodInvokedListener(_noLandingZoneListener);
            }
            if(z.getType() == ZoneType.monster_trap)
            {
              z.getListenerEngine().addMethodInvokedListener(_monsterTrapZoneListener);
            }
            if(_zonesByType.get(z.getType()) == null)
            {
              _zonesByType.put(z.getType(), new GArray<L2Zone>());
            }
            _zonesByType.get(z.getType()).add(z);
            count++;
          }
        }
      }
    }
    return count;
  }

  public void reload()
  {
    parse();
  }

  public boolean checkIfInZoneFishing(int x, int y, int z)
  {
    return !Config.ENABLE_FISHING_CHECK_WATER || checkIfInZone(ZoneType.water, x, y, z);
  }

  private class NoLandingZoneListener extends L2ZoneEnterLeaveListener
  {
    @Override
    public void objectEntered(L2Zone zone, L2Object object)
    {
      L2Player player = object.getPlayer();
      if(player != null)
      {
        if(player.isFlying() && !player.isBlocked() && player.getMountNpcId() == PetDataTable.WYVERN_ID)
        {
          Siege siege = SiegeManager.getSiege(player, false);
          if(siege != null)
          {
            Residence unit = siege.getSiegeUnit();
            if(unit != null && player.getClan() != null && player.isClanLeader() && (player.getClan().getHasCastle() == unit.getId() || player.getClan().getHasFortress() == unit.getId()))
            {
              return;
            }
          }
          player.stopMove();
          player.sendPacket(Msg.THIS_AREA_CANNOT_BE_ENTERED_WHILE_MOUNTED_ATOP_OF_A_WYVERN_YOU_WILL_BE_DISMOUNTED_FROM_YOUR_WYVERN_IF_YOU_DO_NOT_LEAVE);
          Integer enterCount = (Integer) player.getProperty(PropertyCollection.ZoneEnteredNoLandingFlying);
          if(enterCount == null)
          {
            enterCount = 0;
          }
          Location loc = player.getLastServerPosition();
          if(loc == null || enterCount >= 5)
          {
            player.setMount(0, 0, 0);
            player.addProperty(PropertyCollection.ZoneEnteredNoLandingFlying, 0);
            return;
          }
          player.teleToLocation(loc);
          player.addProperty(PropertyCollection.ZoneEnteredNoLandingFlying, enterCount + 1);
        }
        else if(Config.ALT_DONT_ALLOW_PETS_ON_SIEGE && player.getPet() != null)
        {
          int id = player.getPet().getNpcId();
          if((PetDataTable.isBabyPet(id) || PetDataTable.isImprovedBabyPet(id)) && SiegeManager.getSiege(player, true) != null)
          {
            player.getPet().unSummon();
            player.sendMessage("Этих питомцев запрещено использовать в зонах осад.");
          }
        }
      }
    }

    @Override
    public void objectLeaved(L2Zone zone, L2Object object)
    {
    }
  }

  private class MonsterTrapZoneListener extends L2ZoneEnterLeaveListener
  {
    @Override
    public void objectEntered(L2Zone zone, L2Object object)
    {
      L2Player player = object.getPlayer();
      if(player == null || zone.getEvent() == null)
      {
        return;
      }
      Reflection r = player.getReflection();
      if(r.getInstancedZoneId() == zone.getReflectionId())
      {
        // Структура: reuse;chance1,id11,id12,id1N;chance2,id221,id22,id2N;chanceM,idM1,idM2,idMN; .....
        String[] params = zone.getEvent().split(";");
        int reuse = Integer.parseInt(params[0]); // В секундах
        long zoneReuse = getReuseMonsterTrapZone(zone.getId(), r.getId());
        if(zoneReuse != 0 && zoneReuse + reuse * 1000L > System.currentTimeMillis())
        {
          return;
        }
        setReuseMonsterTrapZone(zone.getId(), r.getId(), System.currentTimeMillis());
        int[] chances = new int[params.length - 1];
        int[][] groups = new int[params.length - 1][];
        for(int i = 1; i < params.length; i++)
        {
          // Структура: chance,id1,id2,idN
          String[] group = params[i].split(",");
          chances[i - 1] = Integer.parseInt(group[0]);
          int[] mobs = new int[group.length - 1];
          for(int j = 1; j < group.length; j++)
          {
            mobs[j - 1] = Integer.parseInt(group[j]);
          }
          groups[i - 1] = mobs;
        }
        int[] monsters = groups[choose_group(chances)];
        for(int monster : monsters)
        {
          try
          {
            L2NpcTemplate template = NpcTable.getTemplate(monster);
            if(template == null)
            {
              continue;
            }
            L2Spawn spawn = new L2Spawn(template);
            spawn.setLocation(zone.getLoc().getId());
            spawn.setHeading(-1);
            spawn.setAmount(1);
            spawn.setReflection(r.getId());
            spawn.stopRespawn();
            L2NpcInstance mob = spawn.doSpawn(true);
            if(mob != null)
            {
              ThreadPoolManager.getInstance().scheduleAi(new UnSpawnTask(mob), MONSTER_TRAP_DESPAWN_TIME, false);
              if(mob.isAggressive() && mob.getAI().canSeeInSilentMove(player))
              {
                mob.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, player, 1);
              }
            }
          }
          catch(Exception e)
          {
            e.printStackTrace();
          }
        }
      }
    }

    @Override
    public void objectLeaved(L2Zone zone, L2Object object)
    {
    }
  }

  private int choose_group(int[] chances)
  {
    int sum = 0;
    for(int i = 0; i < chances.length; i++)
    {
      sum += chances[i];
    }
    int[] table = new int[sum];
    int k = 0;
    for(int i = 0; i < chances.length; i++)
    {
      for(int j = 0; j < chances[i]; j++)
      {
        table[k] = i;
        k++;
      }
    }
    return table[Rnd.get(table.length)];
  }

  private void setReuseMonsterTrapZone(Integer zoneId, Long refId, Long reuseTime)
  {
    if(_reuseMonsterTrapZones == null)
    {
      _reuseMonsterTrapZones = new FastMap<Integer, FastMap<Long, Long>>();
    }
    FastMap<Long, Long> zoneReuse = new FastMap<Long, Long>();
    zoneReuse.put(refId, reuseTime);
    _reuseMonsterTrapZones.put(zoneId, zoneReuse);
  }

  private long getReuseMonsterTrapZone(Integer zoneId, Long refId)
  {
    if(_reuseMonsterTrapZones == null)
    {
      return 0;
    }
    FastMap<Long, Long> reuses = _reuseMonsterTrapZones.get(zoneId);
    if(reuses == null || reuses.isEmpty())
    {
      return 0;
    }
    for(Entry<Long, Long> zoneReuse : reuses.entrySet())
    {
      if(refId.longValue() == zoneReuse.getKey().longValue())
      {
        return zoneReuse.getValue();
      }
    }
    return 0;
  }

  public class UnSpawnTask implements Runnable
  {
    L2NpcInstance _monster;

    public UnSpawnTask(L2NpcInstance monster)
    {
      _monster = monster;
    }

    public void run()
    {
      if(_monster != null)
      {
        _monster.deleteMe();
      }
      _monster = null;
    }
  }
}
TOP

Related Classes of l2p.gameserver.instancemanager.ZoneManager$UnSpawnTask

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.