Explorar el Código

BETA: Separating all classes inside WalkingManager into own files.

Rumen Nikiforov hace 12 años
padre
commit
a23e8cc39a

+ 33 - 201
L2J_Server_BETA/java/com/l2jserver/gameserver/instancemanager/WalkingManager.java

@@ -22,7 +22,6 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ScheduledFuture;
 
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
@@ -30,18 +29,20 @@ import org.w3c.dom.Node;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.ai.CtrlIntention;
 import com.l2jserver.gameserver.engines.DocumentParser;
+import com.l2jserver.gameserver.model.ArrivedTask;
 import com.l2jserver.gameserver.model.L2CharPosition;
 import com.l2jserver.gameserver.model.L2NpcWalkerNode;
 import com.l2jserver.gameserver.model.L2WalkRoute;
 import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.WalkInfo;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jserver.gameserver.model.holders.NpcRoutesHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 import com.l2jserver.gameserver.util.Broadcast;
-import com.l2jserver.util.Rnd;
 
 /**
  * This class manages walking monsters.
@@ -54,170 +55,15 @@ public class WalkingManager extends DocumentParser
 	// 1 - go to first point (circle style)
 	// 2 - teleport to first point (conveyor style)
 	// 3 - random walking between points.
-	private static final byte REPEAT_GO_BACK = 0;
-	private static final byte REPEAT_GO_FIRST = 1;
-	private static final byte REPEAT_TELE_FIRST = 2;
-	private static final byte REPEAT_RANDOM = 3;
+	public static final byte REPEAT_GO_BACK = 0;
+	public static final byte REPEAT_GO_FIRST = 1;
+	public static final byte REPEAT_TELE_FIRST = 2;
+	public static final byte REPEAT_RANDOM = 3;
 	
-	protected final Map<String, L2WalkRoute> _routes = new HashMap<>(); // all available routes
+	private final Map<String, L2WalkRoute> _routes = new HashMap<>(); // all available routes
 	private final Map<Integer, WalkInfo> _activeRoutes = new HashMap<>(); // each record represents NPC, moving by predefined route from _routes, and moving progress
 	private final Map<Integer, NpcRoutesHolder> _routesToAttach = new HashMap<>(); // each record represents NPC and all available routes for it
 	
-	/**
-	 * Holds depending between NPC's spawn point and route
-	 */
-	private class NpcRoutesHolder
-	{
-		private final Map<String, String> _correspondences;
-		
-		public NpcRoutesHolder()
-		{
-			_correspondences = new HashMap<>();
-		}
-		
-		/**
-		 * Add correspondence between specific route and specific spawn point
-		 * @param routeName name of route
-		 * @param loc Location of spawn point
-		 */
-		public void addRoute(String routeName, Location loc)
-		{
-			_correspondences.put(getUniqueKey(loc), routeName);
-		}
-		
-		/**
-		 * @param npc
-		 * @return route name for given NPC.
-		 */
-		public String getRouteName(L2Npc npc)
-		{
-			if (npc.getSpawn() != null)
-			{
-				String key = getUniqueKey(npc.getSpawn().getSpawnLocation());
-				return _correspondences.containsKey(key) ? _correspondences.get(key) : "";
-			}
-			return "";
-		}
-		
-		/**
-		 * @param loc
-		 * @return unique text string for given Location.
-		 */
-		private String getUniqueKey(Location loc)
-		{
-			return (loc.getX() + "-" + loc.getY() + "-" + loc.getZ());
-		}
-	}
-	
-	/**
-	 * Holds info about current walk progress.<br>
-	 * Zoey76: TODO: Move to own file, and use getters and setters.
-	 */
-	private class WalkInfo
-	{
-		protected ScheduledFuture<?> _walkCheckTask;
-		protected boolean _blocked = false;
-		protected boolean _suspended = false;
-		protected boolean _stoppedByAttack = false;
-		protected int _currentNode = 0;
-		protected boolean _forward = true; // Determines first --> last or first <-- last direction
-		private final String _routeName;
-		protected long _lastActionTime; // Debug field
-		
-		public WalkInfo(String routeName)
-		{
-			_routeName = routeName;
-		}
-		
-		/**
-		 * @return name of route of this WalkInfo.
-		 */
-		protected L2WalkRoute getRoute()
-		{
-			return _routes.get(_routeName);
-		}
-		
-		/**
-		 * @return current node of this WalkInfo.
-		 */
-		protected L2NpcWalkerNode getCurrentNode()
-		{
-			return getRoute().getNodeList().get(_currentNode);
-		}
-		
-		/**
-		 * Calculate next node for this WalkInfo and send debug message from given npc
-		 * @param npc NPC to debug message to be sent from
-		 */
-		protected void calculateNextNode(L2Npc npc)
-		{
-			// Check this first, within the bounds of random moving, we have no conception of "first" or "last" node
-			if (getRoute().getRepeatType() == REPEAT_RANDOM)
-			{
-				int newNode = _currentNode;
-				
-				while (newNode == _currentNode)
-				{
-					newNode = Rnd.get(getRoute().getNodesCount());
-				}
-				
-				_currentNode = newNode;
-				npc.sendDebugMessage("Route: " + getRoute().getName() + ", next random node is " + _currentNode);
-			}
-			else
-			{
-				if (_forward)
-				{
-					_currentNode++;
-				}
-				else
-				{
-					_currentNode--;
-				}
-				
-				if (_currentNode == getRoute().getNodesCount()) // Last node arrived
-				{
-					// Notify quest
-					if (npc.getTemplate().getEventQuests(Quest.QuestEventType.ON_ROUTE_FINISHED) != null)
-					{
-						for (Quest quest : npc.getTemplate().getEventQuests(Quest.QuestEventType.ON_ROUTE_FINISHED))
-						{
-							quest.notifyRouteFinished(npc);
-						}
-					}
-					npc.sendDebugMessage("Route: " + getRoute().getName() + ", last node arrived");
-					
-					if (!getRoute().repeatWalk())
-					{
-						cancelMoving(npc);
-						return;
-					}
-					
-					switch (getRoute().getRepeatType())
-					{
-						case REPEAT_GO_BACK:
-							_forward = false;
-							_currentNode -= 2;
-							break;
-						case REPEAT_GO_FIRST:
-							_currentNode = 0;
-							break;
-						case REPEAT_TELE_FIRST:
-							npc.teleToLocation(npc.getSpawn().getLocx(), npc.getSpawn().getLocy(), npc.getSpawn().getLocz());
-							_currentNode = 0;
-							break;
-					}
-				}
-				
-				else if (_currentNode == -1) // First node arrived, when direction is first <-- last
-				{
-					_currentNode = 1;
-					_forward = true;
-				}
-			}
-		}
-	}
-	
 	protected WalkingManager()
 	{
 		load();
@@ -363,13 +209,18 @@ public class WalkingManager extends DocumentParser
 		}
 		
 		WalkInfo walk = monster != null ? _activeRoutes.get(monster.getObjectId()) : _activeRoutes.get(npc.getObjectId());
-		if (walk._stoppedByAttack || walk._suspended)
+		if (walk.isStoppedByAttack() || walk.isSuspended())
 		{
 			return false;
 		}
 		return true;
 	}
 	
+	public L2WalkRoute getRoute(String route)
+	{
+		return _routes.get(route);
+	}
+	
 	/**
 	 * @param npc NPC to check
 	 * @return {@code true} if given NPC controlled by Walking Manager.
@@ -406,7 +257,7 @@ public class WalkingManager extends DocumentParser
 					
 					if (npc.isDebug())
 					{
-						walk._lastActionTime = System.currentTimeMillis();
+						walk.setLastAction(System.currentTimeMillis());
 					}
 					
 					L2NpcWalkerNode node = walk.getCurrentNode();
@@ -428,14 +279,14 @@ public class WalkingManager extends DocumentParser
 					npc.sendDebugMessage("Starting to move at route " + routeName);
 					npc.setIsRunning(node.getRunning());
 					npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(node.getMoveX(), node.getMoveY(), node.getMoveZ(), 0));
-					walk._walkCheckTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new Runnable()
+					walk.setWalkCheckTask(ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new Runnable()
 					{
 						@Override
 						public void run()
 						{
 							startMoving(npc, routeName);
 						}
-					}, 60000, 60000); // start walk check task, for resuming walk after fight
+					}, 60000, 60000)); // start walk check task, for resuming walk after fight
 					
 					npc.getKnownList().startTrackingTask();
 					
@@ -462,19 +313,19 @@ public class WalkingManager extends DocumentParser
 					WalkInfo walk = _activeRoutes.get(npc.getObjectId());
 					
 					// Prevent call simultaneously from scheduled task and onArrived() or temporarily stop walking for resuming in future
-					if (walk._blocked || walk._suspended)
+					if (walk.isBlocked() || walk.isSuspended())
 					{
 						npc.sendDebugMessage("Trying continue to move at route " + routeName + ", but cannot now (operation is blocked)");
 						return;
 					}
 					
-					walk._blocked = true;
+					walk.setBlocked(true);
 					L2NpcWalkerNode node = walk.getCurrentNode();
-					npc.sendDebugMessage("Route id: " + routeName + ", continue to node " + walk._currentNode);
+					npc.sendDebugMessage("Route id: " + routeName + ", continue to node " + walk.getCurrentNodeId());
 					npc.setIsRunning(node.getRunning());
 					npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(node.getMoveX(), node.getMoveY(), node.getMoveZ(), 0));
-					walk._blocked = false;
-					walk._stoppedByAttack = false;
+					walk.setBlocked(false);
+					walk.setStoppedByAttack(false);
 				}
 				else
 				{
@@ -493,7 +344,7 @@ public class WalkingManager extends DocumentParser
 		if (_activeRoutes.containsKey(npc.getObjectId()))
 		{
 			final WalkInfo walk = _activeRoutes.remove(npc.getObjectId());
-			walk._walkCheckTask.cancel(true);
+			walk.getWalkCheckTask().cancel(true);
 			npc.getKnownList().stopTrackingTask();
 		}
 	}
@@ -510,8 +361,8 @@ public class WalkingManager extends DocumentParser
 		}
 		
 		WalkInfo walk = _activeRoutes.get(npc.getObjectId());
-		walk._suspended = false;
-		walk._stoppedByAttack = false;
+		walk.setSuspended(false);
+		walk.setStoppedByAttack(false);
 		startMoving(npc, walk.getRoute().getName());
 	}
 	
@@ -544,8 +395,8 @@ public class WalkingManager extends DocumentParser
 		
 		WalkInfo walk = monster != null ? _activeRoutes.get(monster.getObjectId()) : _activeRoutes.get(npc.getObjectId());
 		
-		walk._suspended = suspend;
-		walk._stoppedByAttack = stoppedByAttack;
+		walk.setSuspended(suspend);
+		walk.setStoppedByAttack(stoppedByAttack);
 		
 		if (monster != null)
 		{
@@ -579,16 +430,16 @@ public class WalkingManager extends DocumentParser
 			WalkInfo walk = _activeRoutes.get(npc.getObjectId());
 			
 			// Opposite should not happen... but happens sometime
-			if ((walk._currentNode >= 0) && (walk._currentNode < walk.getRoute().getNodesCount()))
+			if ((walk.getCurrentNodeId() >= 0) && (walk.getCurrentNodeId() < walk.getRoute().getNodesCount()))
 			{
-				L2NpcWalkerNode node = walk.getRoute().getNodeList().get(walk._currentNode);
+				L2NpcWalkerNode node = walk.getRoute().getNodeList().get(walk.getCurrentNodeId());
 				if (npc.isInsideRadius(node.getMoveX(), node.getMoveY(), node.getMoveZ(), 10, false, false))
 				{
-					npc.sendDebugMessage("Route: " + walk.getRoute().getName() + ", arrived to node " + walk._currentNode);
-					npc.sendDebugMessage("Done in " + ((System.currentTimeMillis() - walk._lastActionTime) / 1000) + " s.");
+					npc.sendDebugMessage("Route: " + walk.getRoute().getName() + ", arrived to node " + walk.getCurrentNodeId());
+					npc.sendDebugMessage("Done in " + ((System.currentTimeMillis() - walk.getLastAction()) / 1000) + " s.");
 					walk.calculateNextNode(npc);
 					int delay = node.getDelay();
-					walk._blocked = true; // prevents to be ran from walk check task, if there is delay in this node.
+					walk.setBlocked(true); // prevents to be ran from walk check task, if there is delay in this node.
 					
 					if (node.getNpcString() != null)
 					{
@@ -605,7 +456,7 @@ public class WalkingManager extends DocumentParser
 					
 					if (npc.isDebug())
 					{
-						walk._lastActionTime = System.currentTimeMillis();
+						walk.setLastAction(System.currentTimeMillis());
 					}
 					ThreadPoolManager.getInstance().scheduleGeneral(new ArrivedTask(npc, walk), 100 + (delay * 1000L));
 				}
@@ -638,25 +489,6 @@ public class WalkingManager extends DocumentParser
 		}
 	}
 	
-	private class ArrivedTask implements Runnable
-	{
-		WalkInfo _walk;
-		L2Npc _npc;
-		
-		public ArrivedTask(L2Npc npc, WalkInfo walk)
-		{
-			_npc = npc;
-			_walk = walk;
-		}
-		
-		@Override
-		public void run()
-		{
-			_walk._blocked = false;
-			startMoving(_npc, _walk.getRoute().getName());
-		}
-	}
-	
 	public static final WalkingManager getInstance()
 	{
 		return SingletonHolder._instance;

+ 44 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/ArrivedTask.java

@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004-2013 L2J Server
+ * 
+ * This file is part of L2J Server.
+ * 
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.model;
+
+import com.l2jserver.gameserver.instancemanager.WalkingManager;
+import com.l2jserver.gameserver.model.actor.L2Npc;
+
+/**
+ * @author GKR
+ */
+public class ArrivedTask implements Runnable
+{
+	private final WalkInfo _walk;
+	private final L2Npc _npc;
+	
+	public ArrivedTask(L2Npc npc, WalkInfo walk)
+	{
+		_npc = npc;
+		_walk = walk;
+	}
+	
+	@Override
+	public void run()
+	{
+		_walk.setBlocked(false);
+		WalkingManager.getInstance().startMoving(_npc, _walk.getRoute().getName());
+	}
+}

+ 230 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/WalkInfo.java

@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2004-2013 L2J Server
+ * 
+ * This file is part of L2J Server.
+ * 
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.model;
+
+import java.util.concurrent.ScheduledFuture;
+
+import com.l2jserver.gameserver.instancemanager.WalkingManager;
+import com.l2jserver.gameserver.model.actor.L2Npc;
+import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.util.Rnd;
+
+/**
+ * Holds info about current walk progress
+ * @author GKR, UnAfraid
+ */
+public class WalkInfo
+{
+	private final String _routeName;
+	
+	private ScheduledFuture<?> _walkCheckTask;
+	private boolean _blocked = false;
+	private boolean _suspended = false;
+	private boolean _stoppedByAttack = false;
+	private int _currentNode = 0;
+	private boolean _forward = true; // Determines first --> last or first <-- last direction
+	private long _lastActionTime; // Debug field
+	
+	public WalkInfo(String routeName)
+	{
+		_routeName = routeName;
+	}
+	
+	/**
+	 * @return name of route of this WalkInfo.
+	 */
+	public L2WalkRoute getRoute()
+	{
+		return WalkingManager.getInstance().getRoute(_routeName);
+	}
+	
+	/**
+	 * @return current node of this WalkInfo.
+	 */
+	public L2NpcWalkerNode getCurrentNode()
+	{
+		return getRoute().getNodeList().get(_currentNode);
+	}
+	
+	/**
+	 * Calculate next node for this WalkInfo and send debug message from given npc
+	 * @param npc NPC to debug message to be sent from
+	 */
+	public void calculateNextNode(L2Npc npc)
+	{
+		// Check this first, within the bounds of random moving, we have no conception of "first" or "last" node
+		if (getRoute().getRepeatType() == WalkingManager.REPEAT_RANDOM)
+		{
+			int newNode = _currentNode;
+			
+			while (newNode == _currentNode)
+			{
+				newNode = Rnd.get(getRoute().getNodesCount());
+			}
+			
+			_currentNode = newNode;
+			npc.sendDebugMessage("Route: " + getRoute().getName() + ", next random node is " + _currentNode);
+		}
+		else
+		{
+			if (_forward)
+			{
+				_currentNode++;
+			}
+			else
+			{
+				_currentNode--;
+			}
+			
+			if (_currentNode == getRoute().getNodesCount()) // Last node arrived
+			{
+				// Notify quest
+				if (npc.getTemplate().getEventQuests(Quest.QuestEventType.ON_ROUTE_FINISHED) != null)
+				{
+					for (Quest quest : npc.getTemplate().getEventQuests(Quest.QuestEventType.ON_ROUTE_FINISHED))
+					{
+						quest.notifyRouteFinished(npc);
+					}
+				}
+				npc.sendDebugMessage("Route: " + getRoute().getName() + ", last node arrived");
+				
+				if (!getRoute().repeatWalk())
+				{
+					WalkingManager.getInstance().cancelMoving(npc);
+					return;
+				}
+				
+				switch (getRoute().getRepeatType())
+				{
+					case WalkingManager.REPEAT_GO_BACK:
+					{
+						_forward = false;
+						_currentNode -= 2;
+						break;
+					}
+					case WalkingManager.REPEAT_GO_FIRST:
+					{
+						_currentNode = 0;
+						break;
+					}
+					case WalkingManager.REPEAT_TELE_FIRST:
+					{
+						npc.teleToLocation(npc.getSpawn().getLocx(), npc.getSpawn().getLocy(), npc.getSpawn().getLocz());
+						_currentNode = 0;
+						break;
+					}
+				}
+			}
+			
+			else if (_currentNode == -1) // First node arrived, when direction is first <-- last
+			{
+				_currentNode = 1;
+				_forward = true;
+			}
+		}
+	}
+	
+	/**
+	 * @return {@code true} if walking task is blocked, {@code false} otherwise,
+	 */
+	public boolean isBlocked()
+	{
+		return _blocked;
+	}
+	
+	/**
+	 * @param val
+	 */
+	public void setBlocked(boolean val)
+	{
+		_blocked = val;
+	}
+	
+	/**
+	 * @return {@code true} if walking task is suspended, {@code false} otherwise,
+	 */
+	public boolean isSuspended()
+	{
+		return _suspended;
+	}
+	
+	/**
+	 * @param val
+	 */
+	public void setSuspended(boolean val)
+	{
+		_suspended = val;
+	}
+	
+	/**
+	 * @return {@code true} if walking task shall be stopped by attack, {@code false} otherwise,
+	 */
+	public boolean isStoppedByAttack()
+	{
+		return _stoppedByAttack;
+	}
+	
+	/**
+	 * @param val
+	 */
+	public void setStoppedByAttack(boolean val)
+	{
+		_stoppedByAttack = val;
+	}
+	
+	/**
+	 * @return the id of the current node in this walking task.
+	 */
+	public int getCurrentNodeId()
+	{
+		return _currentNode;
+	}
+	
+	/**
+	 * @return {@code long} last action time used only for debugging.
+	 */
+	public long getLastAction()
+	{
+		return _lastActionTime;
+	}
+	
+	/**
+	 * @param val
+	 */
+	public void setLastAction(long val)
+	{
+		_lastActionTime = val;
+	}
+	
+	/**
+	 * @return walking check task.
+	 */
+	public ScheduledFuture<?> getWalkCheckTask()
+	{
+		return _walkCheckTask;
+	}
+	
+	/**
+	 * @param val walking check task.
+	 */
+	public void setWalkCheckTask(ScheduledFuture<?> val)
+	{
+		_walkCheckTask = val;
+	}
+}

+ 9 - 16
L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionPlayerCanEscape.java

@@ -40,44 +40,37 @@ public class ConditionPlayerCanEscape extends Condition
 	@Override
 	public boolean testImpl(Env env)
 	{
+		boolean canTeleport = true;
 		final L2PcInstance player = env.getPlayer();
 		if (player == null)
 		{
-			return !_val;
+			canTeleport = false;
 		}
-		
-		boolean canTeleport = true;
-		if (!TvTEvent.onEscapeUse(player.getObjectId()))
+		else if (!TvTEvent.onEscapeUse(player.getObjectId()))
 		{
 			canTeleport = false;
 		}
-		
-		if (player.isInDuel())
+		else if (player.isInDuel())
 		{
 			canTeleport = false;
 		}
-		
-		if (player.isAfraid())
+		else if (player.isAfraid())
 		{
 			canTeleport = false;
 		}
-		
-		if (player.isCombatFlagEquipped())
+		else if (player.isCombatFlagEquipped())
 		{
 			canTeleport = false;
 		}
-		
-		if (player.isFlying() || player.isFlyingMounted())
+		else if (player.isFlying() || player.isFlyingMounted())
 		{
 			canTeleport = false;
 		}
-		
-		if (player.isInOlympiadMode())
+		else if (player.isInOlympiadMode())
 		{
 			canTeleport = false;
 		}
-		
-		if ((GrandBossManager.getInstance().getZone(player) != null) && !player.canOverrideCond(PcCondOverride.SKILL_CONDITIONS))
+		else if ((GrandBossManager.getInstance().getZone(player) != null) && !player.canOverrideCond(PcCondOverride.SKILL_CONDITIONS))
 		{
 			canTeleport = false;
 		}

+ 72 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/holders/NpcRoutesHolder.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004-2013 L2J Server
+ * 
+ * This file is part of L2J Server.
+ * 
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.model.holders;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.actor.L2Npc;
+
+/**
+ * Holds depending between NPC's spawn point and route
+ * @author GKR
+ */
+public class NpcRoutesHolder
+{
+	private final Map<String, String> _correspondences;
+	
+	public NpcRoutesHolder()
+	{
+		_correspondences = new HashMap<>();
+	}
+	
+	/**
+	 * Add correspondence between specific route and specific spawn point
+	 * @param routeName name of route
+	 * @param loc Location of spawn point
+	 */
+	public void addRoute(String routeName, Location loc)
+	{
+		_correspondences.put(getUniqueKey(loc), routeName);
+	}
+	
+	/**
+	 * @param npc
+	 * @return route name for given NPC.
+	 */
+	public String getRouteName(L2Npc npc)
+	{
+		if (npc.getSpawn() != null)
+		{
+			String key = getUniqueKey(npc.getSpawn().getSpawnLocation());
+			return _correspondences.containsKey(key) ? _correspondences.get(key) : "";
+		}
+		return "";
+	}
+	
+	/**
+	 * @param loc
+	 * @return unique text string for given Location.
+	 */
+	private String getUniqueKey(Location loc)
+	{
+		return (loc.getX() + "-" + loc.getY() + "-" + loc.getZ());
+	}
+}