/** * */ package net.sf.l2j.gameserver.util; import java.util.Collection; import java.util.Iterator; import javolution.util.FastMap; import javolution.util.FastSet; import net.sf.l2j.gameserver.model.L2PcInstance; import net.sf.l2j.gameserver.model.L2Character; import net.sf.l2j.gameserver.model.L2Object; import net.sf.l2j.gameserver.model.L2World; import net.sf.l2j.gameserver.model.L2WorldRegion; import net.sf.l2j.util.Point3D; import net.sf.l2j.Config; /** * @author Layane * @version: $ * * MRU Alg,Zone check,Distance check */ public class NpcKnownList { private static final int MINIMUM_UPDATE_DISTANCE_SQUARED = Config.MINIMUM_UPDATE_DISTANCE * Config.MINIMUM_UPDATE_DISTANCE; protected FastMap _knownPlayers; protected Point3D _lastUpdatePosition; protected L2Character _owner; public NpcKnownList(L2Character owner) { _lastUpdatePosition = new Point3D(owner.getWorldPosition()); _owner = owner; } public void add(L2Object object) { if (object instanceof L2PcInstance) { addPlayer((L2PcInstance)object); } } public synchronized final void addPlayer(L2PcInstance player) { if (player == null) return; if (_knownPlayers == null) _knownPlayers = new FastMap().setShared(true); _knownPlayers.put(player,player); } public void remove(L2Object object) { if (object instanceof L2PcInstance) { removePlayer((L2PcInstance)object); } } public final void removePlayer(L2PcInstance player) { if (player == null || _knownPlayers == null) return; _knownPlayers.remove(player); } public final boolean knowsPlayer(L2PcInstance player) { if (player == null || _knownPlayers == null) return false; return _knownPlayers.containsKey(player); } public final Collection getKnownPlayers() { if (_knownPlayers == null) return null; return _knownPlayers.values(); } public Collection getKnownObjects() { if (_knownPlayers == null) return null; return _knownPlayers.values(); } public void clear() { if (_knownPlayers != null) _knownPlayers.clear(); } public void update() { Point3D myPosition; synchronized (this) { myPosition = _owner.getWorldPosition(); if (myPosition.distanceSquaredTo(_lastUpdatePosition) <= MINIMUM_UPDATE_DISTANCE_SQUARED) return; _lastUpdatePosition.setTo(myPosition); } //Forget distant objects for (L2PcInstance player : _knownPlayers.values()) { if (_owner.getDistanceToForgetObject(player) > MINIMUM_UPDATE_DISTANCE_SQUARED) { player.removeKnownObject(_owner); _owner.removeKnownObject(player); } } //Find close objects L2World world = L2World.getInstance(); int vision = _owner.getDistanceToWatchObject(null); int x = myPosition.getX(); int y = myPosition.getY(); FastSet adjZones = new FastSet(); adjZones.add(_owner.getCurrentWorldRegion()); adjZones.add(world.getRegion(x - vision, y + vision)); adjZones.add(world.getRegion(x - vision, y - vision)); adjZones.add(world.getRegion(x + vision, y + vision)); adjZones.add(world.getRegion(x + vision, y - vision)); adjZones.add(world.getRegion(x, y - vision)); adjZones.add(world.getRegion(x, y + vision)); adjZones.add(world.getRegion(x - vision, y)); adjZones.add(world.getRegion(x + vision, y)); Iterator it; L2PcInstance player; for (L2WorldRegion region : adjZones) { it = region.iterateAllPlayers(); while(it.hasNext()) { player = it.next(); if (myPosition.distanceSquaredTo(player.getWorldPosition()) <= vision) { player.addKnownObject(_owner, null); _owner.addKnownObject(player, null); } } } } }