/** * */ package net.sf.l2j.gameserver.experimental; import javolution.util.FastCollection; import javolution.util.FastCollection.Record; import javolution.util.FastList; import javolution.util.FastSet; import net.sf.l2j.Config; import net.sf.l2j.gameserver.model.L2Character; import net.sf.l2j.gameserver.model.L2Object; import net.sf.l2j.gameserver.model.L2PcInstance; import net.sf.l2j.gameserver.model.L2Summon; import net.sf.l2j.gameserver.model.L2World; import net.sf.l2j.util.Point3D; /** * @author Layane * */ public class NpcKnownList { public static final long MINIMUM_UPDATE_DISTANCE_SQUARED = Config.MINIMUM_UPDATE_DISTANCE * Config.MINIMUM_UPDATE_DISTANCE; protected final FastSet _knownPlayers = new FastSet(); protected final FastSet _knownSummons = new FastSet(); protected final L2Character _owner; protected Point3D lastPosition; public NpcKnownList(L2Character owner) { _owner = owner; } protected static void checkKnownList(FastList out, FastCollection in) { for(Record r = in.head(),end = in.tail(); (r = r.getNext()) != end;) { L2Object object = (L2Object)in.valueOf(r); if (object != null) out.add(object); else in.delete(r); } } protected synchronized static void checkKnownList(FastCollection in) { for(Record r = in.head(),end = in.tail(); (r = r.getNext()) != end;) { L2Object object = (L2Object)in.valueOf(r); if (object == null) in.delete(r); } } public synchronized void addObject(L2Object object) { if (object == null || !_owner.isVisible()) return; if (knowsObject(object)) { if (!object.isVisible()) _owner.removeKnownObject(object); return; } if (_owner.getDistance(object.getX(), object.getY()) > _owner.getDistanceToWatchObject(object)) return; if (object instanceof L2PcInstance) { _knownPlayers.add((L2PcInstance)object); } else if (object instanceof L2Summon) { _knownSummons.add((L2Summon)object); } } public synchronized void addPlayer(L2PcInstance player) { if (player == null || !_owner.isVisible()) return; if (knowsPlayer(player)) { if (!player.isVisible()) _owner.removeKnownPlayer(player); return; } if (_owner.getDistance(player.getX(), player.getY()) > _owner.getDistanceToWatchObject(player)) return; _knownPlayers.add(player); } public synchronized void addSummon(L2Summon summon) { if (summon == null || !_owner.isVisible()) return; if (knowsSummon(summon)) { if (!summon.isVisible()) _owner.removeKnownSummon(summon); return; } if (_owner.getDistance(summon.getX(), summon.getY()) > _owner.getDistanceToWatchObject(summon)) return; _knownSummons.add(summon); } public boolean knowsObject(L2Object object) { if (object == null) { //Do nothing } else if (object instanceof L2PcInstance) { _knownPlayers.contains((L2PcInstance)object); } else if (object instanceof L2Summon) { _knownSummons.contains((L2Summon)object); } return false; } public boolean knowsPlayer(L2PcInstance player) { if (player != null) return _knownPlayers.contains(player); return false; } public boolean knowsSummon(L2Summon summon) { if (summon != null) return _knownSummons.contains(summon); return false; } public final FastCollection getAllKnownPlayers() { checkKnownList(_knownPlayers); return _knownPlayers.unmodifiable(); } public final FastCollection getAllKnownSummons() { checkKnownList(_knownSummons); return _knownSummons.unmodifiable(); } public final FastCollection getAllKnownObjects() { FastList result = new FastList(); synchronized(this) { checkKnownList(result, _knownPlayers); checkKnownList(result, _knownSummons); } return result.unmodifiable(); } public synchronized void removeKnownObject(L2Object object) { if (object == null) { //Do nothing } else if (object instanceof L2PcInstance) { _knownPlayers.remove((L2PcInstance)object); } else if (object instanceof L2Summon) { _knownSummons.remove((L2Summon)object); } } public synchronized void removePlayer(L2PcInstance player) { if (player != null) _knownPlayers.remove(player); } public synchronized void removeSummon(L2Summon summon) { if (summon != null) _knownSummons.remove(summon); } public void clear() { _knownPlayers.clear(); _knownSummons.clear(); } public void updateKnownObjects() { synchronized (this) { Point3D worldPosition = _owner.getWorldPosition(); if (worldPosition.distanceSquaredTo(lastPosition) <= MINIMUM_UPDATE_DISTANCE_SQUARED) return; lastPosition.setTo(worldPosition); } forgetDistantObjects(); findCloseObjects(); } private void forgetDistantObjects() { for (L2Object object : getAllKnownObjects()) { if (!object.isVisible()) { _owner.removeKnownObject(object); } else if (_owner.getDistance(object.getX(),object.getY()) > _owner.getDistanceToForgetObject(object)) { _owner.removeKnownObject(object); object.removeKnownObject(_owner); } } } private void findCloseObjects() { if (_owner.isDead() || !_owner.isVisible()) return; for (L2Object object : L2World.getInstance().getVisibleObjects(_owner)) { if (object != null) { _owner.addKnownObject(object, null); object.addKnownObject(_owner, null); } } } }