Просмотр исходного кода

GeoData Refactor

Moved all geodata configs to GeoData.properties
Core-Part for L2J/L2J_GeoDriver@b9d04082e5827d123ffa299159e5daff95d00a0e
HorridoJoho 10 лет назад
Родитель
Сommit
765fbef421

+ 1 - 1
L2J_Server/.classpath

@@ -8,7 +8,7 @@
 	<classpathentry kind="lib" path="dist/libs/jython-engine-2.2.1.jar" />
 	<classpathentry kind="lib" path="dist/libs/mail-1.5.2.jar" />
 	<classpathentry kind="lib" path="dist/libs/mmocore.jar" />
-	<classpathentry kind="lib" path="dist/libs/L2J_GeoAbstraction.jar" />
 	<classpathentry kind="lib" path="dist/libs/weupnp-0.1.3.jar" />
+	<classpathentry kind="lib" path="dist/libs/L2J_GeoDriver.jar" />
 	<classpathentry kind="output" path="bin" />
 </classpath>

+ 0 - 76
L2J_Server/dist/game/config/General.properties

@@ -398,82 +398,6 @@ GridNeighborTurnOnTime = 1
 # Default: 90
 GridNeighborTurnOffTime = 90
 
-# ---------------------------------------------------------------------------
-# Geodata
-# ---------------------------------------------------------------------------
-
-# GeoData options:
-# 0 = GeoData and PathFinding OFF (default)
-# 1 = GeoData is used to check Line Of Sight (LOS) targeting and 
-#     L2Playable movement. You need to download files for data/geodata folder.
-#     Monsters can pass walls but not aggro (no line of sight) through them.
-# 2 = Full GeoData enabled. Includes PathFinding (requires also /data/pathnode 
-#     files if CellPathFinding not enabled) and all character moves go through 
-#     geodata checks (if a mob passes a wall, pathfinding didn't find a route 
-#     but we allow attack and returning home).
-#     Recommended server memory minimum 2 GB, rather 3 GB.
-# Default: 0
-GeoData = 0
-
-# GeoData driver to use
-# Default: com.l2jserver.gameserver.geoengine.NullDriver
-GeoDataDriver=com.l2jserver.gameserver.geoengine.NullDriver
-#GeoDataDriver=com.l2j.geodriver.GeoDriver
-
-# Pathnode directory
-# Default: data/pathnode
-PathnodeDirectory = data/pathnode
-
-# Cell-level pathfinding, produces more accurate routes but is (maybe 10x) heavier to calculate. Recommended for small servers at least.
-# If False, pathnode files are used. Uses a max number of nodes in calculation which can be adjusted in the algorithm if it needs to be faster.
-# Default: False
-CellPathFinding = False
-
-# Pathfinding array buffers configuration
-PathFindBuffers = 100x6;128x6;192x6;256x4;320x4;384x4;500x2
-
-# Weight for nodes without obstacles far from walls
-LowWeight = 0.5
-
-# Weight for nodes near walls
-MediumWeight = 2
-
-# Weight for nodes with obstacles
-HighWeight = 3
-
-# Angle paths will be more "smart", but in cost of higher CPU utilization
-AdvancedDiagonalStrategy = True
-
-# Weight for diagonal movement. Used only with AdvancedDiagonalStrategy = True
-# Default: LowWeight * sqrt(2) 
-DiagonalWeight = 0.707
-
-# Maximum number of LOS postfilter passes, 0 will disable postfilter.
-# Default: 3
-MaxPostfilterPasses = 3
-
-# Path debug function.
-# Nodes known to pathfinder will be displayed as adena, constructed path as antidots.
-# Number of the items show node cost * 10
-# Potions display path after first stage filter
-# Red potions - actual waypoints. Green potions - nodes removed by LOS postfilter
-# This function FOR DEBUG PURPOSES ONLY, never use it on the live server !
-DebugPath = False
-
-# True = Loads GeoData buffer's content into physical memory.
-# False = Does not necessarily imply that the GeoData buffer's content is not resident in physical memory.
-# Default: True
-ForceGeodata = True
-
-# This setting controls Client <--> Server Player coordinates synchronization:
-# -1 - Will synchronize only Z from Client --> Server. Default when no geodata.
-# 1 - Synchronization Client --> Server only. Using this option (without geodata) makes it more difficult for players to bypass obstacles.
-# 2 - Intended for geodata (at least with cell-level pathfinding, otherwise can you try -1).
-# Server sends validation packet if client goes too far from server calculated coordinates.
-# Default: -1
-CoordSynchronize = -1
-
-
 # ---------------------------------------------------------------------------
 # Falling Damage
 # ---------------------------------------------------------------------------

+ 86 - 0
L2J_Server/dist/game/config/GeoData.properties

@@ -0,0 +1,86 @@
+# ---------------------------------------------------------------------------
+# GeoData
+# ---------------------------------------------------------------------------
+
+# GeoData options:
+# 0 = GeoData and PathFinding OFF (default)
+# 1 = GeoData is used to check Line Of Sight (LOS) targeting and 
+#     L2Playable movement. You need to download files for data/geodata folder.
+#     Monsters can pass walls but not aggro (no line of sight) through them.
+# 2 = Full GeoData enabled. Includes PathFinding (requires also /data/pathnode 
+#     files if CellPathFinding not enabled) and all character moves go through 
+#     geodata checks (if a mob passes a wall, pathfinding didn't find a route 
+#     but we allow attack and returning home).
+#     Recommended server memory minimum 2 GB, rather 3 GB.
+# Default: 0
+GeoData = 0
+
+# Pathnode directory
+# Default: data/pathnode
+PathnodeDirectory = data/pathnode
+
+# Cell-level pathfinding, produces more accurate routes but is (maybe 10x) heavier to calculate. Recommended for small servers at least.
+# If False, pathnode files are used. Uses a max number of nodes in calculation which can be adjusted in the algorithm if it needs to be faster.
+# Default: False
+CellPathFinding = False
+
+# Pathfinding array buffers configuration
+PathFindBuffers = 100x6;128x6;192x6;256x4;320x4;384x4;500x2
+
+# Weight for nodes without obstacles far from walls
+LowWeight = 0.5
+
+# Weight for nodes near walls
+MediumWeight = 2
+
+# Weight for nodes with obstacles
+HighWeight = 3
+
+# Angle paths will be more "smart", but in cost of higher CPU utilization
+AdvancedDiagonalStrategy = True
+
+# Weight for diagonal movement. Used only with AdvancedDiagonalStrategy = True
+# Default: LowWeight * sqrt(2) 
+DiagonalWeight = 0.707
+
+# Maximum number of LOS postfilter passes, 0 will disable postfilter.
+# Default: 3
+MaxPostfilterPasses = 3
+
+# Path debug function.
+# Nodes known to pathfinder will be displayed as adena, constructed path as antidots.
+# Number of the items show node cost * 10
+# Potions display path after first stage filter
+# Red potions - actual waypoints. Green potions - nodes removed by LOS postfilter
+# This function FOR DEBUG PURPOSES ONLY, never use it on the live server !
+DebugPath = False
+
+# True = Loads GeoData buffer's content into physical memory.
+# False = Does not necessarily imply that the GeoData buffer's content is not resident in physical memory.
+# Default: True
+ForceGeoData = True
+
+# This setting controls Client <--> Server Player coordinates synchronization:
+# -1 - Will synchronize only Z from Client --> Server. Default when no geodata.
+# 1 - Synchronization Client --> Server only. Using this option (without geodata) makes it more difficult for players to bypass obstacles.
+# 2 - Intended for geodata (at least with cell-level pathfinding, otherwise can you try -1).
+# Server sends validation packet if client goes too far from server calculated coordinates.
+# Default: -1
+CoordSynchronize = -1
+
+# Geodata files folder
+GeoDataPath = ./data/geodata
+
+# True: Try to load regions not specified below(won't disturb server startup when file does not exist)
+# False: Don't load any regions other than the ones specified with True below
+TryLoadUnspecifiedRegions = True
+
+# List of regions to be required to load
+# eg.:
+# Both regions required
+# 22_22=True
+# 19_20=true
+# Exclude region from loading
+# 25_26=false
+# True: Region is required for the server to startup
+# False: Region is not considered to be loaded

+ 0 - 16
L2J_Server/dist/game/config/GeoDriver.properties

@@ -1,16 +0,0 @@
-# Geodata files folder
-geodataPath = ./data/geodata
-
-# True: Try to load regions not specified below(won't disturb server startup when file does not exist)
-# False: Don't load any regions other than the ones specified with True below
-tryLoadUnspecifiedRegions = True
-
-# List of regions to be required to load
-# eg.:
-# Both regions required
-# 22_22=True
-# 19_20=true
-# Exclude region from loading
-# 25_26=false
-# True: Region is required for the server to startup
-# False: Region is not considered to be loaded

BIN
L2J_Server/dist/libs/L2J_GeoAbstraction.jar


BIN
L2J_Server/dist/libs/L2J_GeoDriver.jar


+ 64 - 40
L2J_Server/java/com/l2jserver/Config.java

@@ -36,6 +36,7 @@ import java.net.URL;
 import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -56,6 +57,7 @@ import org.w3c.dom.Node;
 
 import com.l2jserver.gameserver.engines.DocumentParser;
 import com.l2jserver.gameserver.enums.IllegalActionPunishmentType;
+import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 import com.l2jserver.gameserver.util.FloodProtectorConfig;
@@ -104,6 +106,7 @@ public final class Config
 	public static final String CHAT_FILTER_FILE = "./config/chatfilter.txt";
 	public static final String EMAIL_CONFIG_FILE = "./config/Email.properties";
 	public static final String CH_SIEGE_FILE = "./config/ConquerableHallSiege.properties";
+	public static final String GEODATA_FILE = "./config/GeoData.properties";
 	// --------------------------------------------------
 	// L2J Variable Definitions
 	// --------------------------------------------------
@@ -506,24 +509,10 @@ public final class Config
 	public static int MAX_NPC_ANIMATION;
 	public static int MIN_MONSTER_ANIMATION;
 	public static int MAX_MONSTER_ANIMATION;
-	public static int COORD_SYNCHRONIZE;
 	public static boolean ENABLE_FALLING_DAMAGE;
 	public static boolean GRIDS_ALWAYS_ON;
 	public static int GRID_NEIGHBOR_TURNON_TIME;
 	public static int GRID_NEIGHBOR_TURNOFF_TIME;
-	public static int GEODATA;
-	public static String GEODATA_DRIVER;
-	public static File PATHNODE_DIR;
-	public static boolean GEODATA_CELLFINDING;
-	public static String PATHFIND_BUFFERS;
-	public static float LOW_WEIGHT;
-	public static float MEDIUM_WEIGHT;
-	public static float HIGH_WEIGHT;
-	public static boolean ADVANCED_DIAGONAL_STRATEGY;
-	public static float DIAGONAL_WEIGHT;
-	public static int MAX_POSTFILTER_PASSES;
-	public static boolean DEBUG_PATH;
-	public static boolean FORCE_GEODATA;
 	public static boolean MOVE_BASED_KNOWNLIST;
 	public static long KNOWNLIST_UPDATE_INTERVAL;
 	public static int PEACE_ZONE_MODE;
@@ -1097,6 +1086,24 @@ public final class Config
 	public static int CHS_FAME_AMOUNT;
 	public static int CHS_FAME_FREQUENCY;
 	
+	// GeoData Settings
+	public static int GEODATA;
+	public static File PATHNODE_DIR;
+	public static boolean GEODATA_CELLFINDING;
+	public static String PATHFIND_BUFFERS;
+	public static float LOW_WEIGHT;
+	public static float MEDIUM_WEIGHT;
+	public static float HIGH_WEIGHT;
+	public static boolean ADVANCED_DIAGONAL_STRATEGY;
+	public static float DIAGONAL_WEIGHT;
+	public static int MAX_POSTFILTER_PASSES;
+	public static boolean DEBUG_PATH;
+	public static boolean FORCE_GEODATA;
+	public static int COORD_SYNCHRONIZE;
+	public static Path GEODATA_PATH;
+	public static boolean TRY_LOAD_UNSPECIFIED_REGIONS;
+	public static Map<String, Boolean> GEODATA_REGIONS;
+	
 	/**
 	 * This class initializes all global variables for configuration.<br>
 	 * If the key doesn't appear in properties file, a default value is set by this class. {@link #CONFIGURATION_FILE} (properties file) for configuring your server.
@@ -1809,32 +1816,6 @@ public final class Config
 			GRIDS_ALWAYS_ON = General.getBoolean("GridsAlwaysOn", false);
 			GRID_NEIGHBOR_TURNON_TIME = General.getInt("GridNeighborTurnOnTime", 1);
 			GRID_NEIGHBOR_TURNOFF_TIME = General.getInt("GridNeighborTurnOffTime", 90);
-			GEODATA = General.getInt("GeoData", 0);
-			GEODATA_DRIVER = General.getString("GeoDataDriver", "com.l2jserver.gameserver.geoengine.NullDriver");
-			try
-			{
-				PATHNODE_DIR = new File(General.getString("PathnodeDirectory", "data/pathnode").replaceAll("\\\\", "/")).getCanonicalFile();
-			}
-			catch (IOException e)
-			{
-				_log.log(Level.WARNING, "Error setting pathnode directory!", e);
-				PATHNODE_DIR = new File("data/pathnode");
-			}
-			GEODATA_CELLFINDING = General.getBoolean("CellPathFinding", false);
-			PATHFIND_BUFFERS = General.getString("PathFindBuffers", "100x6;128x6;192x6;256x4;320x4;384x4;500x2");
-			LOW_WEIGHT = General.getFloat("LowWeight", 0.5f);
-			MEDIUM_WEIGHT = General.getFloat("MediumWeight", 2);
-			HIGH_WEIGHT = General.getFloat("HighWeight", 3);
-			ADVANCED_DIAGONAL_STRATEGY = General.getBoolean("AdvancedDiagonalStrategy", true);
-			DIAGONAL_WEIGHT = General.getFloat("DiagonalWeight", 0.707f);
-			MAX_POSTFILTER_PASSES = General.getInt("MaxPostfilterPasses", 3);
-			DEBUG_PATH = General.getBoolean("DebugPath", false);
-			FORCE_GEODATA = General.getBoolean("ForceGeodata", true);
-			COORD_SYNCHRONIZE = General.getInt("CoordSynchronize", -1);
-			
-			String str = General.getString("EnableFallingDamage", "auto");
-			ENABLE_FALLING_DAMAGE = "auto".equalsIgnoreCase(str) ? GEODATA > 0 : Boolean.parseBoolean(str);
-			
 			PEACE_ZONE_MODE = General.getInt("PeaceZoneMode", 0);
 			DEFAULT_GLOBAL_CHAT = General.getString("GlobalChat", "ON");
 			DEFAULT_TRADE_CHAT = General.getString("TradeChat", "ON");
@@ -2676,6 +2657,49 @@ public final class Config
 			CHS_ENABLE_FAME = ClanHallSiege.getBoolean("EnableFame", false);
 			CHS_FAME_AMOUNT = ClanHallSiege.getInt("FameAmount", 0);
 			CHS_FAME_FREQUENCY = ClanHallSiege.getInt("FameFrequency", 0);
+			
+			final PropertiesParser geoData = new PropertiesParser(GEODATA_FILE);
+			
+			GEODATA = geoData.getInt("GeoData", 0);
+			
+			try
+			{
+				PATHNODE_DIR = new File(geoData.getString("PathnodeDirectory", "data/pathnode").replaceAll("\\\\", "/")).getCanonicalFile();
+			}
+			catch (IOException e)
+			{
+				_log.log(Level.WARNING, "Error setting pathnode directory!", e);
+				PATHNODE_DIR = new File("data/pathnode");
+			}
+			
+			GEODATA_CELLFINDING = geoData.getBoolean("CellPathFinding", false);
+			PATHFIND_BUFFERS = geoData.getString("PathFindBuffers", "100x6;128x6;192x6;256x4;320x4;384x4;500x2");
+			LOW_WEIGHT = geoData.getFloat("LowWeight", 0.5f);
+			MEDIUM_WEIGHT = geoData.getFloat("MediumWeight", 2);
+			HIGH_WEIGHT = geoData.getFloat("HighWeight", 3);
+			ADVANCED_DIAGONAL_STRATEGY = geoData.getBoolean("AdvancedDiagonalStrategy", true);
+			DIAGONAL_WEIGHT = geoData.getFloat("DiagonalWeight", 0.707f);
+			MAX_POSTFILTER_PASSES = geoData.getInt("MaxPostfilterPasses", 3);
+			DEBUG_PATH = geoData.getBoolean("DebugPath", false);
+			FORCE_GEODATA = geoData.getBoolean("ForceGeoData", true);
+			COORD_SYNCHRONIZE = geoData.getInt("CoordSynchronize", -1);
+			GEODATA_PATH = Paths.get(geoData.getString("GeoDataPath", "./data/geodata"));
+			TRY_LOAD_UNSPECIFIED_REGIONS = geoData.getBoolean("TryLoadUnspecifiedRegions", true);
+			GEODATA_REGIONS = new HashMap<>();
+			for (int regionX = L2World.TILE_X_MIN; regionX <= L2World.TILE_X_MAX; regionX++)
+			{
+				for (int regionY = L2World.TILE_Y_MIN; regionY <= L2World.TILE_Y_MAX; regionY++)
+				{
+					String key = regionX + "_" + regionY;
+					if (geoData.containskey(regionX + "_" + regionY))
+					{
+						GEODATA_REGIONS.put(key, geoData.getBoolean(key, false));
+					}
+				}
+			}
+			
+			String str = General.getString("EnableFallingDamage", "auto");
+			ENABLE_FALLING_DAMAGE = "auto".equalsIgnoreCase(str) ? GEODATA > 0 : Boolean.parseBoolean(str);
 		}
 		else if (Server.serverMode == Server.MODE_LOGINSERVER)
 		{

+ 191 - 180
L2J_Server/java/com/l2jserver/gameserver/GeoData.java

@@ -18,137 +18,218 @@
  */
 package com.l2jserver.gameserver;
 
-import java.io.FileInputStream;
-import java.lang.reflect.Constructor;
-import java.nio.file.Paths;
-import java.util.Properties;
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.datatables.DoorTable;
-import com.l2jserver.gameserver.geoengine.Direction;
-import com.l2jserver.gameserver.geoengine.NullDriver;
-import com.l2jserver.gameserver.geoengine.abstraction.IGeoDriver;
 import com.l2jserver.gameserver.model.L2Object;
+import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.interfaces.ILocational;
 import com.l2jserver.gameserver.util.GeoUtils;
 import com.l2jserver.gameserver.util.LinePointIterator;
 import com.l2jserver.gameserver.util.LinePointIterator3D;
+import com.l2jserver.geodriver.Cell;
+import com.l2jserver.geodriver.GeoDriver;
 
 /**
  * @author -Nemesiss-, HorridoJoho
  */
-public class GeoData implements IGeoDriver
+public class GeoData
 {
 	private static final Logger LOGGER = Logger.getLogger(GeoData.class.getName());
+	private static final String FILE_NAME_FORMAT = "%d_%d.l2j";
 	private static final int ELEVATED_SEE_OVER_DISTANCE = 2;
 	private static final int MAX_SEE_OVER_HEIGHT = 48;
+	private static final int Z_DELTA_LIMIT = 100;
 	
-	private final IGeoDriver _driver;
+	private final GeoDriver _driver = new GeoDriver();
 	
 	protected GeoData()
 	{
-		if (Config.GEODATA > 0)
+		if (Config.GEODATA == 0)
 		{
-			IGeoDriver driver = null;
-			try
+			LOGGER.info(getClass().getSimpleName() + ": Disabled.");
+			return;
+		}
+		
+		int loadedRegions = 0;
+		try
+		{
+			for (int regionX = L2World.TILE_X_MIN; regionX <= L2World.TILE_X_MAX; regionX++)
 			{
-				Class<?> cls = Class.forName(Config.GEODATA_DRIVER);
-				if (!IGeoDriver.class.isAssignableFrom(cls))
-				{
-					throw new ClassCastException("Geodata driver class needs to implement IGeoDriver!");
-				}
-				Constructor<?> ctor = cls.getConstructor(Properties.class);
-				Properties props = new Properties();
-				try (FileInputStream fis = new FileInputStream(Paths.get("config", "GeoDriver.properties").toString()))
+				for (int regionY = L2World.TILE_Y_MIN; regionY <= L2World.TILE_Y_MAX; regionY++)
 				{
-					props.load(fis);
+					final Path geoFilePath = Config.GEODATA_PATH.resolve(String.format(FILE_NAME_FORMAT, regionX, regionY));
+					final Boolean loadFile = Config.GEODATA_REGIONS.get(regionX + "_" + regionY);
+					if (loadFile != null)
+					{
+						if (loadFile)
+						{
+							LOGGER.info(getClass().getSimpleName() + ": Loading " + geoFilePath.getFileName() + "...");
+							_driver.loadRegion(geoFilePath, regionX, regionY);
+							loadedRegions++;
+						}
+					}
+					else if (Config.TRY_LOAD_UNSPECIFIED_REGIONS)
+					{
+						try
+						{
+							LOGGER.info(getClass().getSimpleName() + ": Loading " + geoFilePath.getFileName() + "...");
+							_driver.loadRegion(geoFilePath, regionX, regionY);
+							loadedRegions++;
+						}
+						catch (Exception e)
+						{
+							// ignore file not found errors
+							if (!(e instanceof FileNotFoundException))
+							{
+								LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed to load " + geoFilePath.getFileName() + "!", e);
+							}
+						}
+					}
 				}
-				driver = (IGeoDriver) ctor.newInstance(props);
 			}
-			catch (Exception ex)
-			{
-				LOGGER.log(Level.SEVERE, "Failed to load geodata driver!", ex);
-				System.exit(1);
-			}
-			// we do it this way so it's predictable for the compiler
-			_driver = driver;
 		}
-		else
+		catch (Exception e)
 		{
-			_driver = new NullDriver(null);
+			LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Failed to load geodata!", e);
+			System.exit(1);
 		}
+		
+		LOGGER.info(getClass().getSimpleName() + ": Loaded " + loadedRegions + " regions.");
 	}
 	
-	@Override
-	public int getGeoX(int worldX)
+	public boolean hasGeoPos(int geoX, int geoY)
 	{
-		return _driver.getGeoX(worldX);
+		return _driver.hasGeoPos(geoX, geoY);
 	}
 	
-	@Override
-	public int getGeoY(int worldY)
+	public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
 	{
-		return _driver.getGeoY(worldY);
+		return _driver.checkNearestNswe(geoX, geoY, worldZ, nswe);
 	}
 	
-	@Override
-	public int getWorldX(int geoX)
+	public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe, int zDeltaLimit)
 	{
-		return _driver.getWorldX(geoX);
+		return _driver.checkNearestNswe(geoX, geoY, worldZ, nswe, zDeltaLimit);
 	}
 	
-	@Override
-	public int getWorldY(int geoY)
+	public boolean checkNearestNsweAntiCornerCut(int geoX, int geoY, int worldZ, int nswe)
 	{
-		return _driver.getWorldY(geoY);
+		boolean can = true;
+		if ((nswe & Cell.NSWE_NORTH_EAST) != 0)
+		{
+			// can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.NORTH);
+			can = checkNearestNswe(geoX, geoY - 1, worldZ, Cell.NSWE_EAST) && checkNearestNswe(geoX + 1, geoY, worldZ, Cell.NSWE_NORTH);
+		}
+		
+		if (can && ((nswe & Cell.NSWE_NORTH_WEST) != 0))
+		{
+			// can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.NORTH);
+			can = checkNearestNswe(geoX, geoY - 1, worldZ, Cell.NSWE_WEST) && checkNearestNswe(geoX, geoY - 1, worldZ, Cell.NSWE_NORTH);
+		}
+		
+		if (can && ((nswe & Cell.NSWE_SOUTH_EAST) != 0))
+		{
+			// can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.SOUTH);
+			can = checkNearestNswe(geoX, geoY + 1, worldZ, Cell.NSWE_EAST) && checkNearestNswe(geoX + 1, geoY, worldZ, Cell.NSWE_SOUTH);
+		}
+		
+		if (can && ((nswe & Cell.NSWE_SOUTH_WEST) != 0))
+		{
+			// can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.SOUTH);
+			can = checkNearestNswe(geoX, geoY + 1, worldZ, Cell.NSWE_WEST) && checkNearestNswe(geoX - 1, geoY, worldZ, Cell.NSWE_SOUTH);
+		}
+		
+		return can && checkNearestNswe(geoX, geoY, worldZ, nswe);
 	}
 	
-	@Override
-	public boolean hasGeoPos(int geoX, int geoY)
+	public boolean checkNearestNsweAntiCornerCut(int geoX, int geoY, int worldZ, int nswe, int zDeltaLimit)
 	{
-		return _driver.hasGeoPos(geoX, geoY);
+		boolean can = true;
+		if ((nswe & Cell.NSWE_NORTH_EAST) != 0)
+		{
+			// can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.NORTH);
+			can = checkNearestNswe(geoX, geoY - 1, worldZ, Cell.NSWE_EAST, zDeltaLimit) && checkNearestNswe(geoX + 1, geoY, worldZ, Cell.NSWE_NORTH, zDeltaLimit);
+		}
+		
+		if (can && ((nswe & Cell.NSWE_NORTH_WEST) != 0))
+		{
+			// can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.NORTH);
+			can = checkNearestNswe(geoX, geoY - 1, worldZ, Cell.NSWE_WEST, zDeltaLimit) && checkNearestNswe(geoX, geoY - 1, worldZ, Cell.NSWE_NORTH, zDeltaLimit);
+		}
+		
+		if (can && ((nswe & Cell.NSWE_SOUTH_EAST) != 0))
+		{
+			// can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.SOUTH);
+			can = checkNearestNswe(geoX, geoY + 1, worldZ, Cell.NSWE_EAST, zDeltaLimit) && checkNearestNswe(geoX + 1, geoY, worldZ, Cell.NSWE_SOUTH, zDeltaLimit);
+		}
+		
+		if (can && ((nswe & Cell.NSWE_SOUTH_WEST) != 0))
+		{
+			// can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.SOUTH);
+			can = checkNearestNswe(geoX, geoY + 1, worldZ, Cell.NSWE_WEST, zDeltaLimit) && checkNearestNswe(geoX - 1, geoY, worldZ, Cell.NSWE_SOUTH, zDeltaLimit);
+		}
+		
+		return can && checkNearestNswe(geoX, geoY, worldZ, nswe, zDeltaLimit);
 	}
 	
-	@Override
 	public int getNearestZ(int geoX, int geoY, int worldZ)
 	{
 		return _driver.getNearestZ(geoX, geoY, worldZ);
 	}
 	
-	@Override
+	public int getNearestZ(int geoX, int geoY, int worldZ, int zDeltaLimit)
+	{
+		return _driver.getNearestZ(geoX, geoY, worldZ, zDeltaLimit);
+	}
+	
 	public int getNextLowerZ(int geoX, int geoY, int worldZ)
 	{
 		return _driver.getNextLowerZ(geoX, geoY, worldZ);
 	}
 	
-	@Override
+	public int getNextLowerZ(int geoX, int geoY, int worldZ, int zDeltaLimit)
+	{
+		return _driver.getNextLowerZ(geoX, geoY, worldZ, zDeltaLimit);
+	}
+	
 	public int getNextHigherZ(int geoX, int geoY, int worldZ)
 	{
 		return _driver.getNextHigherZ(geoX, geoY, worldZ);
 	}
 	
-	@Override
-	public boolean canEnterNeighbors(int geoX, int geoY, int worldZ, Direction first, Direction... more)
+	public int getNextHigherZ(int geoX, int geoY, int worldZ, int zDeltaLimit)
+	{
+		return _driver.getNextHigherZ(geoX, geoY, worldZ, zDeltaLimit);
+	}
+	
+	public int getGeoX(int worldX)
 	{
-		return _driver.canEnterNeighbors(geoX, geoY, worldZ, first, more);
+		return _driver.getGeoX(worldX);
 	}
 	
-	@Override
-	public boolean canEnterAllNeighbors(int geoX, int geoY, int worldZ)
+	public int getGeoY(int worldY)
 	{
-		return _driver.canEnterAllNeighbors(geoX, geoY, worldZ);
+		return _driver.getGeoY(worldY);
 	}
 	
-	// ///////////////////
-	// L2J METHODS
-	public boolean isNullDriver()
+	public int getWorldX(int geoX)
 	{
-		return _driver instanceof NullDriver;
+		return _driver.getWorldX(geoX);
+	}
+	
+	public int getWorldY(int geoY)
+	{
+		return _driver.getWorldY(geoY);
 	}
 	
+	// ///////////////////
+	// L2J METHODS
 	/**
 	 * Gets the height.
 	 * @param x the x coordinate
@@ -170,8 +251,7 @@ public class GeoData implements IGeoDriver
 	 */
 	public int getSpawnHeight(int x, int y, int z)
 	{
-		// + 30, defend against defective geodata and invalid spawn z :(
-		return getNextLowerZ(getGeoX(x), getGeoY(y), z + 30);
+		return getNearestZ(getGeoX(x), getGeoY(y), z, Z_DELTA_LIMIT);
 	}
 	
 	/**
@@ -253,31 +333,17 @@ public class GeoData implements IGeoDriver
 		return canSeeTarget(x, y, z, tx, ty, tz);
 	}
 	
-	private int getLosGeoZ(int prevX, int prevY, int prevGeoZ, int curX, int curY, Direction dir)
+	private int getLosGeoZ(int prevX, int prevY, int prevGeoZ, int curX, int curY, int nswe)
 	{
-		boolean can = true;
-		
-		switch (dir)
+		if ((((nswe & Cell.NSWE_NORTH) != 0) && ((nswe & Cell.NSWE_SOUTH) != 0)) || (((nswe & Cell.NSWE_WEST) != 0) && ((nswe & Cell.NSWE_EAST) != 0)))
 		{
-			case NORTH_EAST:
-				can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.NORTH);
-				break;
-			case NORTH_WEST:
-				can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.NORTH);
-				break;
-			case SOUTH_EAST:
-				can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.SOUTH);
-				break;
-			case SOUTH_WEST:
-				can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.SOUTH);
-				break;
-		
+			throw new RuntimeException("Multiple directions!");
 		}
-		if (can && canEnterNeighbors(prevX, prevY, prevGeoZ, dir))
+		
+		if (checkNearestNsweAntiCornerCut(prevX, prevY, prevGeoZ, nswe, Z_DELTA_LIMIT))
 		{
-			return getNearestZ(curX, curY, prevGeoZ);
+			return getNearestZ(curX, curY, prevGeoZ, Z_DELTA_LIMIT);
 		}
-		
 		return getNextHigherZ(curX, curY, prevGeoZ);
 	}
 	
@@ -298,9 +364,10 @@ public class GeoData implements IGeoDriver
 		int tGeoX = getGeoX(tx);
 		int tGeoY = getGeoY(ty);
 		
-		z = getNearestZ(geoX, geoY, z);
-		tz = getNearestZ(tGeoX, tGeoY, tz);
+		z = getNearestZ(geoX, geoY, z, Z_DELTA_LIMIT);
+		tz = getNearestZ(tGeoX, tGeoY, tz, Z_DELTA_LIMIT);
 		
+		// fastpath
 		if ((geoX == tGeoX) && (geoY == tGeoY))
 		{
 			if (hasGeoPos(tGeoX, tGeoY))
@@ -356,12 +423,12 @@ public class GeoData implements IGeoDriver
 			int beeCurZ = pointIter.z();
 			int curGeoZ = prevGeoZ;
 			
-			// the current position has geodata
+			// check if the position has geodata
 			if (hasGeoPos(curX, curY))
 			{
 				int beeCurGeoZ = getNearestZ(curX, curY, beeCurZ);
-				Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
-				curGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, curX, curY, dir);
+				int nswe = GeoUtils.computeNswe(prevX, prevY, curX, curY);// .computeDirection(prevX, prevY, curX, curY);
+				curGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, curX, curY, nswe);
 				int maxHeight;
 				if (ptIndex < ELEVATED_SEE_OVER_DISTANCE)
 				{
@@ -375,41 +442,33 @@ public class GeoData implements IGeoDriver
 				boolean canSeeThrough = false;
 				if ((curGeoZ <= maxHeight) && (curGeoZ <= beeCurGeoZ))
 				{
-					switch (dir)
+					if ((nswe & Cell.NSWE_NORTH_EAST) != 0)
 					{
-						case NORTH_EAST:
-						{
-							int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Direction.EAST);
-							int eastGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX + 1, prevY, Direction.NORTH);
-							canSeeThrough = (northGeoZ <= maxHeight) && (eastGeoZ <= maxHeight) && (northGeoZ <= getNearestZ(prevX, prevY - 1, beeCurZ)) && (eastGeoZ <= getNearestZ(prevX + 1, prevY, beeCurZ));
-							break;
-						}
-						case NORTH_WEST:
-						{
-							int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Direction.WEST);
-							int westGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX - 1, prevY, Direction.NORTH);
-							canSeeThrough = (northGeoZ <= maxHeight) && (westGeoZ <= maxHeight) && (northGeoZ <= getNearestZ(prevX, prevY - 1, beeCurZ)) && (westGeoZ <= getNearestZ(prevX - 1, prevY, beeCurZ));
-							break;
-						}
-						case SOUTH_EAST:
-						{
-							int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Direction.EAST);
-							int eastGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX + 1, prevY, Direction.SOUTH);
-							canSeeThrough = (southGeoZ <= maxHeight) && (eastGeoZ <= maxHeight) && (southGeoZ <= getNearestZ(prevX, prevY + 1, beeCurZ)) && (eastGeoZ <= getNearestZ(prevX + 1, prevY, beeCurZ));
-							break;
-						}
-						case SOUTH_WEST:
-						{
-							int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Direction.WEST);
-							int westGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX - 1, prevY, Direction.SOUTH);
-							canSeeThrough = (southGeoZ <= maxHeight) && (westGeoZ <= maxHeight) && (southGeoZ <= getNearestZ(prevX, prevY + 1, beeCurZ)) && (westGeoZ <= getNearestZ(prevX - 1, prevY, beeCurZ));
-							break;
-						}
-						default:
-						{
-							canSeeThrough = true;
-							break;
-						}
+						int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Cell.NSWE_EAST);
+						int eastGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX + 1, prevY, Cell.NSWE_NORTH);
+						canSeeThrough = (northGeoZ <= maxHeight) && (eastGeoZ <= maxHeight) && (northGeoZ <= getNearestZ(prevX, prevY - 1, beeCurZ)) && (eastGeoZ <= getNearestZ(prevX + 1, prevY, beeCurZ));
+					}
+					else if ((nswe & Cell.NSWE_NORTH_WEST) != 0)
+					{
+						int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Cell.NSWE_WEST);
+						int westGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX - 1, prevY, Cell.NSWE_NORTH);
+						canSeeThrough = (northGeoZ <= maxHeight) && (westGeoZ <= maxHeight) && (northGeoZ <= getNearestZ(prevX, prevY - 1, beeCurZ)) && (westGeoZ <= getNearestZ(prevX - 1, prevY, beeCurZ));
+					}
+					else if ((nswe & Cell.NSWE_SOUTH_EAST) != 0)
+					{
+						int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Cell.NSWE_EAST);
+						int eastGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX + 1, prevY, Cell.NSWE_SOUTH);
+						canSeeThrough = (southGeoZ <= maxHeight) && (eastGeoZ <= maxHeight) && (southGeoZ <= getNearestZ(prevX, prevY + 1, beeCurZ)) && (eastGeoZ <= getNearestZ(prevX + 1, prevY, beeCurZ));
+					}
+					else if ((nswe & Cell.NSWE_SOUTH_WEST) != 0)
+					{
+						int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Cell.NSWE_WEST);
+						int westGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX - 1, prevY, Cell.NSWE_SOUTH);
+						canSeeThrough = (southGeoZ <= maxHeight) && (westGeoZ <= maxHeight) && (southGeoZ <= getNearestZ(prevX, prevY + 1, beeCurZ)) && (westGeoZ <= getNearestZ(prevX - 1, prevY, beeCurZ));
+					}
+					else
+					{
+						canSeeThrough = true;
 					}
 				}
 				
@@ -443,10 +502,10 @@ public class GeoData implements IGeoDriver
 	{
 		int geoX = getGeoX(x);
 		int geoY = getGeoY(y);
-		z = getNearestZ(geoX, geoY, z);
+		z = getNearestZ(geoX, geoY, z, Z_DELTA_LIMIT);
 		int tGeoX = getGeoX(tx);
 		int tGeoY = getGeoY(ty);
-		tz = getNearestZ(tGeoX, tGeoY, tz);
+		tz = getNearestZ(tGeoX, tGeoY, tz, Z_DELTA_LIMIT);
 		
 		if (DoorTable.getInstance().checkIfDoorsBetween(x, y, z, tx, ty, tz, instanceId, false))
 		{
@@ -464,36 +523,12 @@ public class GeoData implements IGeoDriver
 		{
 			int curX = pointIter.x();
 			int curY = pointIter.y();
-			int curZ = getNearestZ(curX, curY, prevZ);
+			int curZ = getNearestZ(curX, curY, prevZ, Z_DELTA_LIMIT);
 			
 			if (hasGeoPos(prevX, prevY))
 			{
-				Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
-				boolean canEnter = false;
-				if (canEnterNeighbors(prevX, prevY, prevZ, dir))
-				{
-					// check diagonal movement
-					switch (dir)
-					{
-						case NORTH_EAST:
-							canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.NORTH);
-							break;
-						case NORTH_WEST:
-							canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.NORTH);
-							break;
-						case SOUTH_EAST:
-							canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.SOUTH);
-							break;
-						case SOUTH_WEST:
-							canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.SOUTH);
-							break;
-						default:
-							canEnter = true;
-							break;
-					}
-				}
-				
-				if (!canEnter)
+				int nswe = GeoUtils.computeNswe(prevX, prevY, curX, curY);
+				if (!checkNearestNsweAntiCornerCut(prevX, prevY, prevZ, nswe, Z_DELTA_LIMIT))
 				{
 					// can't move, return previous location
 					return new Location(getWorldX(prevX), getWorldY(prevY), prevZ);
@@ -529,10 +564,10 @@ public class GeoData implements IGeoDriver
 	{
 		int geoX = getGeoX(fromX);
 		int geoY = getGeoY(fromY);
-		fromZ = getNearestZ(geoX, geoY, fromZ);
+		fromZ = getNearestZ(geoX, geoY, fromZ, Z_DELTA_LIMIT);
 		int tGeoX = getGeoX(toX);
 		int tGeoY = getGeoY(toY);
-		toZ = getNearestZ(tGeoX, tGeoY, toZ);
+		toZ = getNearestZ(tGeoX, tGeoY, toZ, Z_DELTA_LIMIT);
 		
 		if (DoorTable.getInstance().checkIfDoorsBetween(fromX, fromY, fromZ, toX, toY, toZ, instanceId, false))
 		{
@@ -550,36 +585,12 @@ public class GeoData implements IGeoDriver
 		{
 			int curX = pointIter.x();
 			int curY = pointIter.y();
-			int curZ = getNearestZ(curX, curY, prevZ);
+			int curZ = getNearestZ(curX, curY, prevZ, Z_DELTA_LIMIT);
 			
 			if (hasGeoPos(prevX, prevY))
 			{
-				Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
-				boolean canEnter = false;
-				if (canEnterNeighbors(prevX, prevY, prevZ, dir))
-				{
-					// check diagonal movement
-					switch (dir)
-					{
-						case NORTH_EAST:
-							canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.NORTH);
-							break;
-						case NORTH_WEST:
-							canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.NORTH);
-							break;
-						case SOUTH_EAST:
-							canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.SOUTH);
-							break;
-						case SOUTH_WEST:
-							canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.SOUTH);
-							break;
-						default:
-							canEnter = true;
-							break;
-					}
-				}
-				
-				if (!canEnter)
+				int nswe = GeoUtils.computeNswe(prevX, prevY, curX, curY);
+				if (!checkNearestNsweAntiCornerCut(prevX, prevY, prevZ, nswe, Z_DELTA_LIMIT))
 				{
 					return false;
 				}
@@ -603,7 +614,7 @@ public class GeoData implements IGeoDriver
 	{
 		int geoX = getGeoX(x);
 		int geoY = getGeoY(y);
-		z = getNearestZ(geoX, geoY, z);
+		z = getNearestZ(geoX, geoY, z, Z_DELTA_LIMIT);
 		int tGeoX = getGeoX(tx);
 		int tGeoY = getGeoY(ty);
 		
@@ -616,7 +627,7 @@ public class GeoData implements IGeoDriver
 		{
 			int curX = pointIter.x();
 			int curY = pointIter.y();
-			int curZ = getNearestZ(curX, curY, prevZ);
+			int curZ = getNearestZ(curX, curY, prevZ, Z_DELTA_LIMIT);
 			
 			prevZ = curZ;
 		}

+ 10 - 11
L2J_Server/java/com/l2jserver/gameserver/pathfinding/cellnodes/NodeLoc.java

@@ -19,8 +19,8 @@
 package com.l2jserver.gameserver.pathfinding.cellnodes;
 
 import com.l2jserver.gameserver.GeoData;
-import com.l2jserver.gameserver.geoengine.Direction;
 import com.l2jserver.gameserver.pathfinding.AbstractNodeLoc;
+import com.l2jserver.geodriver.Cell;
 
 /**
  * @author -Nemesiss-, HorridoJoho
@@ -44,10 +44,10 @@ public class NodeLoc extends AbstractNodeLoc
 	{
 		_x = x;
 		_y = y;
-		_goNorth = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.NORTH);
-		_goEast = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.EAST);
-		_goSouth = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.SOUTH);
-		_goWest = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.WEST);
+		_goNorth = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_NORTH);
+		_goEast = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_EAST);
+		_goSouth = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_SOUTH);
+		_goWest = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_WEST);
 		_geoHeight = GeoData.getInstance().getNearestZ(x, y, z);
 	}
 	
@@ -120,28 +120,27 @@ public class NodeLoc extends AbstractNodeLoc
 	@Override
 	public int hashCode()
 	{
-		
 		final int prime = 31;
 		int result = 1;
 		result = (prime * result) + _x;
 		result = (prime * result) + _y;
 		
-		byte nswe = 0;
+		int nswe = 0;
 		if (canGoNorth())
 		{
-			nswe |= 1;
+			nswe |= Cell.NSWE_NORTH;
 		}
 		if (canGoEast())
 		{
-			nswe |= 1 << 1;
+			nswe |= Cell.NSWE_EAST;
 		}
 		if (canGoSouth())
 		{
-			nswe |= 1 << 2;
+			nswe |= Cell.NSWE_SOUTH;
 		}
 		if (canGoEast())
 		{
-			nswe |= 1 << 3;
+			nswe |= Cell.NSWE_EAST;
 		}
 		
 		result = (prime * result) + (((_geoHeight & 0xFFFF) << 1) | nswe);

+ 18 - 18
L2J_Server/java/com/l2jserver/gameserver/util/GeoUtils.java

@@ -21,9 +21,9 @@ package com.l2jserver.gameserver.util;
 import java.awt.Color;
 
 import com.l2jserver.gameserver.GeoData;
-import com.l2jserver.gameserver.geoengine.Direction;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.serverpackets.ExServerPrimitive;
+import com.l2jserver.geodriver.Cell;
 
 /**
  * @author HorridoJoho
@@ -93,9 +93,9 @@ public final class GeoUtils
 		player.sendPacket(prim);
 	}
 	
-	private static Color getDirectionColor(int x, int y, int z, Direction dir)
+	private static Color getDirectionColor(int x, int y, int z, int nswe)
 	{
-		if (GeoData.getInstance().canEnterNeighbors(x, y, z, dir))
+		if (GeoData.getInstance().checkNearestNswe(x, y, z, nswe, 100))
 		{
 			return Color.GREEN;
 		}
@@ -146,27 +146,27 @@ public final class GeoUtils
 				int z = gd.getNearestZ(gx, gy, player.getZ());
 				
 				// north arrow
-				Color col = getDirectionColor(gx, gy, z, Direction.NORTH);
+				Color col = getDirectionColor(gx, gy, z, Cell.NSWE_NORTH);
 				exsp.addLine(col, x - 1, y - 7, z, x + 1, y - 7, z);
 				exsp.addLine(col, x - 2, y - 6, z, x + 2, y - 6, z);
 				exsp.addLine(col, x - 3, y - 5, z, x + 3, y - 5, z);
 				exsp.addLine(col, x - 4, y - 4, z, x + 4, y - 4, z);
 				
 				// east arrow
-				col = getDirectionColor(gx, gy, z, Direction.EAST);
+				col = getDirectionColor(gx, gy, z, Cell.NSWE_EAST);
 				exsp.addLine(col, x + 7, y - 1, z, x + 7, y + 1, z);
 				exsp.addLine(col, x + 6, y - 2, z, x + 6, y + 2, z);
 				exsp.addLine(col, x + 5, y - 3, z, x + 5, y + 3, z);
 				exsp.addLine(col, x + 4, y - 4, z, x + 4, y + 4, z);
 				
 				// south arrow
-				col = getDirectionColor(gx, gy, z, Direction.SOUTH);
+				col = getDirectionColor(gx, gy, z, Cell.NSWE_SOUTH);
 				exsp.addLine(col, x - 1, y + 7, z, x + 1, y + 7, z);
 				exsp.addLine(col, x - 2, y + 6, z, x + 2, y + 6, z);
 				exsp.addLine(col, x - 3, y + 5, z, x + 3, y + 5, z);
 				exsp.addLine(col, x - 4, y + 4, z, x + 4, y + 4, z);
 				
-				col = getDirectionColor(gx, gy, z, Direction.WEST);
+				col = getDirectionColor(gx, gy, z, Cell.NSWE_WEST);
 				exsp.addLine(col, x - 7, y - 1, z, x - 7, y + 1, z);
 				exsp.addLine(col, x - 6, y - 2, z, x - 6, y + 2, z);
 				exsp.addLine(col, x - 5, y - 3, z, x - 5, y + 3, z);
@@ -180,7 +180,7 @@ public final class GeoUtils
 	}
 	
 	/**
-	 * difference between x values: never abover 1<br>
+	 * difference between x values: never above 1<br>
 	 * difference between y values: never above 1
 	 * @param lastX
 	 * @param lastY
@@ -188,36 +188,36 @@ public final class GeoUtils
 	 * @param y
 	 * @return
 	 */
-	public static Direction computeDirection(int lastX, int lastY, int x, int y)
+	public static int computeNswe(int lastX, int lastY, int x, int y)
 	{
 		if (x > lastX) // east
 		{
 			if (y > lastY)
 			{
-				return Direction.SOUTH_EAST;
+				return Cell.NSWE_SOUTH_EAST;// Direction.SOUTH_EAST;
 			}
 			else if (y < lastY)
 			{
-				return Direction.NORTH_EAST;
+				return Cell.NSWE_NORTH_EAST;// Direction.NORTH_EAST;
 			}
 			else
 			{
-				return Direction.EAST;
+				return Cell.NSWE_EAST;// Direction.EAST;
 			}
 		}
 		else if (x < lastX) // west
 		{
 			if (y > lastY)
 			{
-				return Direction.SOUTH_WEST;
+				return Cell.NSWE_SOUTH_WEST;// Direction.SOUTH_WEST;
 			}
 			else if (y < lastY)
 			{
-				return Direction.NORTH_WEST;
+				return Cell.NSWE_NORTH_WEST;// Direction.NORTH_WEST;
 			}
 			else
 			{
-				return Direction.WEST;
+				return Cell.NSWE_WEST;// Direction.WEST;
 			}
 		}
 		else
@@ -225,15 +225,15 @@ public final class GeoUtils
 		{
 			if (y > lastY)
 			{
-				return Direction.SOUTH;
+				return Cell.NSWE_SOUTH;// Direction.SOUTH;
 			}
 			else if (y < lastY)
 			{
-				return Direction.NORTH;
+				return Cell.NSWE_NORTH;// Direction.NORTH;
 			}
 			else
 			{
-				return null;// error, should never happen, TODO: Logging
+				throw new RuntimeException();
 			}
 		}
 	}