diff --git a/L2J_Mobius_C4/.classpath b/L2J_Mobius_C4/.classpath
index cc58ca923e..4ba780a682 100644
--- a/L2J_Mobius_C4/.classpath
+++ b/L2J_Mobius_C4/.classpath
@@ -9,8 +9,6 @@
-
-
diff --git a/L2J_Mobius_C4/dist/game/config/GeoData.ini b/L2J_Mobius_C4/dist/game/config/GeoData.ini
new file mode 100644
index 0000000000..52ef701461
--- /dev/null
+++ b/L2J_Mobius_C4/dist/game/config/GeoData.ini
@@ -0,0 +1,75 @@
+# ---------------------------------------------------------------------------
+# GeoData
+# ---------------------------------------------------------------------------
+
+# Pathfinding options:
+# 0 = Disabled
+# 1 = Enabled using path node files
+# 2 = Enabled using geodata cells at runtime
+# Default: 0
+PathFinding = 0
+
+# Pathnode directory
+# Default: data/pathnode
+PathnodeDirectory = data/pathnode
+
+# 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
diff --git a/L2J_Mobius_C4/dist/game/config/GeoDriver.ini b/L2J_Mobius_C4/dist/game/config/GeoDriver.ini
deleted file mode 100644
index 007a38481d..0000000000
--- a/L2J_Mobius_C4/dist/game/config/GeoDriver.ini
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/L2J_Mobius_C4/dist/game/config/command-privileges.ini b/L2J_Mobius_C4/dist/game/config/command-privileges.ini
index 54b937bfc9..a22e46bb19 100644
--- a/L2J_Mobius_C4/dist/game/config/command-privileges.ini
+++ b/L2J_Mobius_C4/dist/game/config/command-privileges.ini
@@ -376,9 +376,8 @@ admin_geo_pos = 100
admin_geo_spawn_pos = 100
admin_geo_can_see = 100
admin_geo_can_move = 100
-admin_geoeditor_connect = 100
-admin_geoeditor_join = 100
-admin_geoeditor_leave = 100
+admin_geogrid = 100
+admin_geomap =100
###############
### MANOR ###
diff --git a/L2J_Mobius_C4/dist/game/config/options.ini b/L2J_Mobius_C4/dist/game/config/options.ini
index 126d9a728a..23d865b2b3 100644
--- a/L2J_Mobius_C4/dist/game/config/options.ini
+++ b/L2J_Mobius_C4/dist/game/config/options.ini
@@ -5,7 +5,6 @@
Debug = False
Assert = False
Developer = False
-AcceptGeoeditorConn = False
# if true the server will be a test server (listed by clients setted up to list testserver)
TestServer = False
@@ -253,77 +252,6 @@ GridsAlwaysOn = False
GridNeighborTurnOnTime = 1
GridNeighborTurnOffTime = 90
-# =================================================================
-# GeoData & PathNode
-# =================================================================
-
-# GeoData options:
-# 0 = GeoData and PathFinding OFF (default)
-# 1 = GeoData used to check Line Of Sight (LOS) targetting and
-# L2Playable movement. You need to download files for data/geodata folder.
-# Monsters can pass walls but not aggro 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.
-GeoData = 0
-
-# GeoData driver to use
-# Default: com.l2j.geodriver.GeoDriver
-GeoDataDriver = com.l2j.geodriver.GeoDriver
-
-# 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 nr of nodes in calculation which can
-# be adjusted in the algorithm if it needs to be faster.
-CellPathFinding = False
-
-# Pathnode directory folder
-PathnodeDirectory = ./data/pathnode
-
-# 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.
-ForceGeodata = True
-
-# This is setting of 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) it is more difficult for players to bypass obstacles
-# 2 - Intended for geodata (at least when cell-level pathfinding, otherwise can try -1 also)!
-# Server sends validation packet if client goes too far from server calculated coordinates.
-CoordSynchronize = -1
-
# Falling Damage
# ---------------------------------------------------------------------------
# Allow characters to receive damage from falling.
diff --git a/L2J_Mobius_C4/dist/game/data/scripts/ai/bosses/Baium.java b/L2J_Mobius_C4/dist/game/data/scripts/ai/bosses/Baium.java
index 90d7c1ee28..f95f7a304f 100644
--- a/L2J_Mobius_C4/dist/game/data/scripts/ai/bosses/Baium.java
+++ b/L2J_Mobius_C4/dist/game/data/scripts/ai/bosses/Baium.java
@@ -23,9 +23,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.datatables.SkillTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Effect;
@@ -165,24 +165,20 @@ public class Baium extends Quest
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, loc_x, loc_y, loc_z, heading, false, 0);
GrandBossManager.getInstance().addBoss(baium);
final L2NpcInstance _baium = baium;
- ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
+ ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
- @Override
- public void run()
+ try
{
- try
- {
- _baium.setCurrentHpMp(hp, mp);
- _baium.setIsInvul(true);
- _baium.setIsImmobilized(true);
- _baium.setRunning();
- _baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
- startQuestTimer("baium_wakeup", 15000, _baium, null);
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- }
+ _baium.setCurrentHpMp(hp, mp);
+ _baium.setIsInvul(true);
+ _baium.setIsImmobilized(true);
+ _baium.setRunning();
+ _baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
+ startQuestTimer("baium_wakeup", 15000, _baium, null);
+ }
+ catch (final Exception e)
+ {
+ e.printStackTrace();
}
}, 100L);
}
@@ -219,20 +215,16 @@ public class Baium extends Quest
startQuestTimer("baium_despawn", 60000, npc, null, true);
startQuestTimer("skill_range", 500, npc, null, true);
final L2NpcInstance baium = npc;
- ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
+ ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
- @Override
- public void run()
+ try
{
- try
- {
- baium.setIsInvul(false);
- baium.setIsImmobilized(false);
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- }
+ baium.setIsInvul(false);
+ baium.setIsImmobilized(false);
+ }
+ catch (final Exception e)
+ {
+ e.printStackTrace();
}
}, 11100L);
@@ -313,23 +305,19 @@ public class Baium extends Quest
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, npc);
GrandBossManager.getInstance().addBoss(baium);
final L2NpcInstance _baium = baium;
- ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
+ ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
- @Override
- public void run()
+ try
{
- try
- {
- _baium.setIsInvul(true);
- _baium.setIsImmobilized(true);
- _baium.setRunning();
- _baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
- startQuestTimer("baium_wakeup", 15000, _baium, null);
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- }
+ _baium.setIsInvul(true);
+ _baium.setIsImmobilized(true);
+ _baium.setRunning();
+ _baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
+ startQuestTimer("baium_wakeup", 15000, _baium, null);
+ }
+ catch (final Exception e)
+ {
+ e.printStackTrace();
}
}, 100L);
}
diff --git a/L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Elpy.java b/L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Elpy.java
index 3c93b6afdd..5ac0da9627 100644
--- a/L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Elpy.java
+++ b/L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Elpy.java
@@ -16,8 +16,8 @@
*/
package ai.individual;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ai.CtrlIntention;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Summon;
diff --git a/L2J_Mobius_C4/dist/libs/L2J_GeoAbstraction.jar b/L2J_Mobius_C4/dist/libs/L2J_GeoAbstraction.jar
deleted file mode 100644
index af841f999e..0000000000
Binary files a/L2J_Mobius_C4/dist/libs/L2J_GeoAbstraction.jar and /dev/null differ
diff --git a/L2J_Mobius_C4/dist/libs/L2J_GeoDriver.jar b/L2J_Mobius_C4/dist/libs/L2J_GeoDriver.jar
deleted file mode 100644
index 2abd4fc5f6..0000000000
Binary files a/L2J_Mobius_C4/dist/libs/L2J_GeoDriver.jar and /dev/null differ
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/Config.java b/L2J_Mobius_C4/java/com/l2jmobius/Config.java
index 314b55dc2d..57dc06bc98 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/Config.java
@@ -22,12 +22,16 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;
+import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.base.Experience;
import com.l2jmobius.gameserver.util.FloodProtectorConfig;
import com.l2jmobius.util.StringUtil;
@@ -46,6 +50,9 @@ import javolution.util.FastMap;
public final class Config
{
protected static Logger _log = Logger.getLogger(Config.class.getName());
+
+ public static final String EOL = System.lineSeparator();
+
/** Debug/release mode */
public static boolean DEBUG;
/** Enable/disable assertions */
@@ -578,8 +585,6 @@ public final class Config
/** Accept multi-items drop ? */
public static boolean MULTIPLE_ITEM_DROP;
- /** Coord Synchronization */
- public static int COORD_SYNCHRONIZE;
/** Falling Damage */
public static boolean ENABLE_FALLING_DAMAGE;
@@ -730,6 +735,8 @@ public final class Config
public static final String OLYMPIAD_CONFIGURATION_FILE = "config/olympiad.ini";
/** Properties file for extensions configurations */
public static final String EXTENSIONS_CONFIGURATION_FILE = "config/extensions.ini";
+ /** Properties file for GeoData configurations */
+ public static final String GEODATA_CONFIGURATION_FILE = "config/GeoData.ini";
/** Text file containing hexadecimal value of server ID */
public static final String HEXID_FILE = "./config/hexid.txt";
/**
@@ -1269,12 +1276,8 @@ public final class Config
public static int CS_SUPPORT3_FEE;
public static int CS_SUPPORT4_FEE;
- /** GeoData 0/1/2 */
- public static int GEODATA;
- public static String GEODATA_DRIVER;
-
- /** Cell PathFinding */
- public static boolean GEODATA_CELLFINDING;
+ /** GeoData Settings */
+ public static int PATHFINDING;
public static File PATHNODE_DIR;
public static String PATHFIND_BUFFERS;
public static float LOW_WEIGHT;
@@ -1284,10 +1287,11 @@ public final class Config
public static float DIAGONAL_WEIGHT;
public static int MAX_POSTFILTER_PASSES;
public static boolean DEBUG_PATH;
-
- /** Force loading GeoData to physical memory */
public static boolean FORCE_GEODATA;
- public static boolean ACCEPT_GEOEDITOR_CONN;
+ public static int COORD_SYNCHRONIZE;
+ public static Path GEODATA_PATH;
+ public static boolean TRY_LOAD_UNSPECIFIED_REGIONS;
+ public static Map GEODATA_REGIONS;
/** Max number of buffs */
public static byte BUFFS_MAX_AMOUNT;
@@ -1376,6 +1380,45 @@ public final class Config
throw new Error("MinProtocolRevision is bigger than MaxProtocolRevision in server configuration file.");
}
+ _log.info("Loading GeoData Configuration Files.");
+
+ final Properties geoData = new Properties();
+ try (InputStream is = new FileInputStream(new File(GEODATA_CONFIGURATION_FILE)))
+ {
+ geoData.load(is);
+ }
+ catch (final Exception e)
+ {
+ e.printStackTrace();
+ throw new Error("Failed to Load " + GEODATA_CONFIGURATION_FILE + " File.");
+ }
+
+ PATHFINDING = Integer.parseInt(geoData.getProperty("PathFinding", "0"));
+ PATHFIND_BUFFERS = geoData.getProperty("PathFindBuffers", "100x6;128x6;192x6;256x4;320x4;384x4;500x2");
+ LOW_WEIGHT = Float.parseFloat(geoData.getProperty("LowWeight", "0.5f"));
+ MEDIUM_WEIGHT = Float.parseFloat(geoData.getProperty("MediumWeight", "2"));
+ HIGH_WEIGHT = Float.parseFloat(geoData.getProperty("HighWeight", "3"));
+ ADVANCED_DIAGONAL_STRATEGY = Boolean.parseBoolean(geoData.getProperty("AdvancedDiagonalStrategy", "true"));
+ DIAGONAL_WEIGHT = Float.parseFloat(geoData.getProperty("DiagonalWeight", "0.707f"));
+ MAX_POSTFILTER_PASSES = Integer.parseInt(geoData.getProperty("MaxPostfilterPasses", "3"));
+ DEBUG_PATH = Boolean.parseBoolean(geoData.getProperty("DebugPath", "false"));
+ FORCE_GEODATA = Boolean.parseBoolean(geoData.getProperty("ForceGeoData", "true"));
+ COORD_SYNCHRONIZE = Integer.parseInt(geoData.getProperty("CoordSynchronize", "-1"));
+ GEODATA_PATH = Paths.get(geoData.getProperty("GeoDataPath", "./data/geodata"));
+ TRY_LOAD_UNSPECIFIED_REGIONS = Boolean.parseBoolean(geoData.getProperty("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++)
+ {
+ final String key = regionX + "_" + regionY;
+ if (geoData.containsKey(regionX + "_" + regionY))
+ {
+ GEODATA_REGIONS.put(key, Boolean.parseBoolean(geoData.getProperty(key, "false")));
+ }
+ }
+ }
+
final Properties optionsSettings = new Properties();
try (InputStream is = new FileInputStream(new File(OPTIONS_FILE)))
{
@@ -1392,7 +1435,6 @@ public final class Config
DEBUG = Boolean.parseBoolean(optionsSettings.getProperty("Debug", "false"));
ASSERT = Boolean.parseBoolean(optionsSettings.getProperty("Assert", "false"));
DEVELOPER = Boolean.parseBoolean(optionsSettings.getProperty("Developer", "false"));
- ACCEPT_GEOEDITOR_CONN = Boolean.parseBoolean(optionsSettings.getProperty("AcceptGeoeditorConn", "False"));
TEST_SERVER = Boolean.parseBoolean(optionsSettings.getProperty("TestServer", "false"));
SERVER_LIST_TESTSERVER = Boolean.parseBoolean(optionsSettings.getProperty("TestServer", "false"));
@@ -1422,7 +1464,7 @@ public final class Config
MULTIPLE_ITEM_DROP = Boolean.valueOf(optionsSettings.getProperty("MultipleItemDrop", "True"));
final String str = optionsSettings.getProperty("EnableFallingDamage", "auto");
- ENABLE_FALLING_DAMAGE = "auto".equalsIgnoreCase(str) ? GEODATA > 0 : Boolean.parseBoolean(str);
+ ENABLE_FALLING_DAMAGE = "auto".equalsIgnoreCase(str) ? PATHFINDING > 0 : Boolean.parseBoolean(str);
ALLOW_WAREHOUSE = Boolean.valueOf(optionsSettings.getProperty("AllowWarehouse", "True"));
WAREHOUSE_CACHE = Boolean.valueOf(optionsSettings.getProperty("WarehouseCache", "False"));
@@ -1511,31 +1553,6 @@ public final class Config
GRID_NEIGHBOR_TURNON_TIME = Integer.parseInt(optionsSettings.getProperty("GridNeighborTurnOnTime", "1"));
GRID_NEIGHBOR_TURNOFF_TIME = Integer.parseInt(optionsSettings.getProperty("GridNeighborTurnOffTime", "90"));
- GEODATA = Integer.parseInt(optionsSettings.getProperty("GeoData", "0"));
- GEODATA_DRIVER = optionsSettings.getProperty("GeoDataDriver", "com.l2j.geodriver.GeoDriver");
- GEODATA_CELLFINDING = Boolean.parseBoolean(optionsSettings.getProperty("CellPathFinding", "False"));
-
- try
- {
- PATHNODE_DIR = new File(optionsSettings.getProperty("PathnodeDirectory", "./data/pathnode").replaceAll("\\\\", "/")).getCanonicalFile();
- }
- catch (final Exception e)
- {
- _log.warning("Error setting pathnode directory!");
- PATHNODE_DIR = new File("./data/pathnode");
- }
-
- PATHFIND_BUFFERS = optionsSettings.getProperty("PathFindBuffers", "100x6;128x6;192x6;256x4;320x4;384x4;500x2");
- LOW_WEIGHT = Float.parseFloat(optionsSettings.getProperty("LowWeight", "0.5"));
- MEDIUM_WEIGHT = Float.parseFloat(optionsSettings.getProperty("MediumWeight", "2"));
- HIGH_WEIGHT = Float.parseFloat(optionsSettings.getProperty("HighWeight", "3"));
- ADVANCED_DIAGONAL_STRATEGY = Boolean.parseBoolean(optionsSettings.getProperty("AdvancedDiagonalStrategy", "True"));
- DIAGONAL_WEIGHT = Float.parseFloat(optionsSettings.getProperty("DiagonalWeight", "0.707"));
- MAX_POSTFILTER_PASSES = Integer.parseInt(optionsSettings.getProperty("MaxPostfilterPasses", "3"));
- DEBUG_PATH = Boolean.parseBoolean(optionsSettings.getProperty("DebugPath", "False"));
- FORCE_GEODATA = Boolean.parseBoolean(optionsSettings.getProperty("ForceGeoData", "True"));
- COORD_SYNCHRONIZE = Integer.parseInt(optionsSettings.getProperty("CoordSynchronize", "-1"));
-
// ---------------------------------------------------
// Configuration values not found in config files
// ---------------------------------------------------
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GameServer.java
index b4864940e0..e391a84724 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GameServer.java
@@ -63,7 +63,8 @@ import com.l2jmobius.gameserver.datatables.StaticObjects;
import com.l2jmobius.gameserver.datatables.SummonItemsData;
import com.l2jmobius.gameserver.datatables.TeleportLocationTable;
import com.l2jmobius.gameserver.datatables.ZoneTable;
-import com.l2jmobius.gameserver.geoeditorcon.GeoEditorListener;
+import com.l2jmobius.gameserver.geodata.GeoData;
+import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
import com.l2jmobius.gameserver.handler.AdminCommandHandler;
import com.l2jmobius.gameserver.handler.ItemHandler;
import com.l2jmobius.gameserver.handler.SkillHandler;
@@ -87,7 +88,6 @@ import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEnchant;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEventEngine;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminExpSp;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminFightCalculator;
-import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGeoEditor;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGeodata;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGm;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGmChat;
@@ -223,7 +223,6 @@ import com.l2jmobius.gameserver.model.entity.AutoRewarder;
import com.l2jmobius.gameserver.model.entity.Hero;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.L2GamePacketHandler;
-import com.l2jmobius.gameserver.pathfinding.PathFinding;
import com.l2jmobius.gameserver.script.faenor.FaenorScriptEngine;
import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager;
import com.l2jmobius.gameserver.taskmanager.AutoAnnounceTaskManager;
@@ -359,7 +358,7 @@ public class GameServer
ClanTable.getInstance();
GeoData.getInstance();
- if (Config.GEODATA == 2)
+ if (Config.PATHFINDING > 0)
{
PathFinding.getInstance();
}
@@ -588,7 +587,6 @@ public class GameServer
_adminCommandHandler.registerAdminCommandHandler(new AdminQuest());
_adminCommandHandler.registerAdminCommandHandler(new AdminZone());
_adminCommandHandler.registerAdminCommandHandler(new AdminGeodata());
- _adminCommandHandler.registerAdminCommandHandler(new AdminGeoEditor());
_adminCommandHandler.registerAdminCommandHandler(new AdminManor());
// _adminCommandHandler.registerAdminCommandHandler(new AdminRadar());
@@ -630,11 +628,6 @@ public class GameServer
// read pet stats from db
L2PetDataTable.getInstance().loadPetsData();
- if (Config.ACCEPT_GEOEDITOR_CONN)
- {
- GeoEditorListener.getInstance();
- }
-
_shutdownHandler = Shutdown.getInstance();
Runtime.getRuntime().addShutdownHook(_shutdownHandler);
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GeoData.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GeoData.java
deleted file mode 100644
index cccc913157..0000000000
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/GeoData.java
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver;
-
-import java.io.FileInputStream;
-import java.lang.reflect.Constructor;
-import java.nio.file.Paths;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.datatables.DoorTable;
-import com.l2jmobius.gameserver.model.L2Object;
-import com.l2jmobius.gameserver.model.Location;
-import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
-import com.l2jmobius.gameserver.util.GeoUtils;
-import com.l2jmobius.gameserver.util.LinePointIterator;
-import com.l2jmobius.gameserver.util.LinePointIterator3D;
-import com.l2jserver.gameserver.geoengine.Direction;
-import com.l2jserver.gameserver.geoengine.NullDriver;
-import com.l2jserver.gameserver.geoengine.abstraction.IGeoDriver;
-
-/**
- * @author -Nemesiss-, FBIagent
- */
-public class GeoData implements IGeoDriver
-{
- private static Logger LOGGER = Logger.getLogger(GeoData.class.getName());
- private static final int ELEVATED_SEE_OVER_DISTANCE = 2;
- private static final int MAX_SEE_OVER_HEIGHT = 48;
-
- private final IGeoDriver _driver;
- private static GeoData _instance;
-
- public static GeoData getInstance()
- {
- if (_instance == null)
- {
- _instance = new GeoData();
- }
- return _instance;
- }
-
- protected GeoData()
- {
- if (Config.GEODATA > 0)
- {
- IGeoDriver driver = null;
- try
- {
- final Class> cls = Class.forName(Config.GEODATA_DRIVER);
- if (!IGeoDriver.class.isAssignableFrom(cls))
- {
- throw new ClassCastException("Geodata driver class needs to implement IGeoDriver!");
- }
-
- final Constructor> ctor = cls.getConstructor(Properties.class);
- final Properties props = new Properties();
- try (FileInputStream fis = new FileInputStream(Paths.get("config", "GeoDriver.ini").toString()))
- {
- props.load(fis);
- }
- driver = (IGeoDriver) ctor.newInstance(props);
- }
- catch (final 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
- {
- _driver = new NullDriver(null);
- }
- }
-
- public boolean isNullDriver()
- {
- return _driver instanceof NullDriver;
- }
-
- @Override
- public int getGeoX(int worldX)
- {
- return _driver.getGeoX(worldX);
- }
-
- @Override
- public int getGeoY(int worldY)
- {
- return _driver.getGeoY(worldY);
- }
-
- @Override
- public int getWorldX(int geoX)
- {
- return _driver.getWorldX(geoX);
- }
-
- @Override
- public int getWorldY(int geoY)
- {
- return _driver.getWorldY(geoY);
- }
-
- @Override
- public boolean hasGeoPos(int geoX, int geoY)
- {
- return _driver.hasGeoPos(geoX, geoY);
- }
-
- @Override
- public int getNearestZ(int geoX, int geoY, int worldZ)
- {
- return _driver.getNearestZ(geoX, geoY, worldZ);
- }
-
- @Override
- public int getNextLowerZ(int geoX, int geoY, int worldZ)
- {
- return _driver.getNextLowerZ(geoX, geoY, worldZ);
- }
-
- @Override
- 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)
- {
- return _driver.canEnterNeighbors(geoX, geoY, worldZ, first, more);
- }
-
- @Override
- public boolean canEnterAllNeighbors(int geoX, int geoY, int worldZ)
- {
- return _driver.canEnterAllNeighbors(geoX, geoY, worldZ);
- }
-
- /**
- * @param x
- * @param y
- * @param z
- * @return Nearles Z
- */
- public int getHeight(int x, int y, int z)
- {
- return getNearestZ(getGeoX(x), getGeoY(y), z);
- }
-
- /**
- * @param x
- * @param y
- * @param zmin
- * @param zmax
- * @return
- */
- public int getSpawnHeight(int x, int y, int zmin, int zmax)
- {
- // + 30, defend against defective geodata and invalid spawn z :(
- return getNextLowerZ(getGeoX(x), getGeoY(y), zmax + 30);
- }
-
- private int getLosGeoZ(int prevX, int prevY, int prevGeoZ, int curX, int curY, Direction dir)
- {
- boolean can = true;
-
- switch (dir)
- {
- 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;
- }
-
- if (can && canEnterNeighbors(prevX, prevY, prevGeoZ, dir))
- {
- return getNearestZ(curX, curY, prevGeoZ);
- }
-
- return getNextHigherZ(curX, curY, prevGeoZ);
- }
-
- /**
- * Can see target. Doors as target always return true. Checks doors between.
- * @param cha
- * @param target
- * @return True if cha can see target (LOS)
- */
- public boolean canSeeTarget(L2Object cha, L2Object target)
- {
- if (target instanceof L2DoorInstance)
- {
- // can always see doors :o
- return true;
- }
-
- if (DoorTable.getInstance().checkIfDoorsBetween(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ()))
- {
- return false;
- }
-
- return canSeeTarget(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ());
- }
-
- /**
- * Can see target. Does not check doors between.
- * @param x the x coordinate
- * @param y the y coordinate
- * @param z the z coordinate
- * @param tx the target's x coordinate
- * @param ty the target's y coordinate
- * @param tz the target's z coordinate
- * @return {@code true} if there is line of sight between the given coordinate sets, {@code false} otherwise
- */
- public boolean canSeeTarget(int x, int y, int z, int tx, int ty, int tz)
- {
- int geoX = getGeoX(x);
- int geoY = getGeoY(y);
- int tGeoX = getGeoX(tx);
- int tGeoY = getGeoY(ty);
-
- z = getNearestZ(geoX, geoY, z);
- tz = getNearestZ(tGeoX, tGeoY, tz);
-
- if ((geoX == tGeoX) && (geoY == tGeoY))
- {
- if (hasGeoPos(tGeoX, tGeoY))
- {
- return z == tz;
- }
- return true;
- }
-
- if (tz > z)
- {
- int tmp = tx;
- tx = x;
- x = tmp;
-
- tmp = ty;
- ty = y;
- y = tmp;
-
- tmp = tz;
- tz = z;
- z = tmp;
-
- tmp = tGeoX;
- tGeoX = geoX;
- geoX = tmp;
-
- tmp = tGeoY;
- tGeoY = geoY;
- geoY = tmp;
- }
-
- final LinePointIterator3D pointIter = new LinePointIterator3D(geoX, geoY, z, tGeoX, tGeoY, tz);
- // first point is guaranteed to be available, skip it, we can always see our own position
- pointIter.next();
- int prevX = pointIter.x();
- int prevY = pointIter.y();
- final int prevZ = pointIter.z();
- int prevGeoZ = prevZ;
- int ptIndex = 0;
-
- while (pointIter.next())
- {
- final int curX = pointIter.x();
- final int curY = pointIter.y();
-
- if ((curX == prevX) && (curY == prevY))
- {
- continue;
- }
-
- final int beeCurZ = pointIter.z();
- int curGeoZ = prevGeoZ;
-
- // the current position has geodata
- if (hasGeoPos(curX, curY))
- {
- final int beeCurGeoZ = getNearestZ(curX, curY, beeCurZ);
- final Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
- curGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, curX, curY, dir);
-
- int maxHeight;
- if (ptIndex < ELEVATED_SEE_OVER_DISTANCE)
- {
- maxHeight = z + MAX_SEE_OVER_HEIGHT;
- }
- else
- {
- maxHeight = beeCurZ + MAX_SEE_OVER_HEIGHT;
- }
-
- boolean canSeeThrough = false;
- if ((curGeoZ <= maxHeight) && (curGeoZ <= beeCurGeoZ))
- {
- switch (dir)
- {
- case NORTH_EAST:
- {
- final int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Direction.EAST);
- final 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:
- {
- final int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Direction.WEST);
- final 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:
- {
- final int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Direction.EAST);
- final 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:
- {
- final int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Direction.WEST);
- final 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;
- }
- }
- }
-
- if (!canSeeThrough)
- {
- return false;
- }
- }
-
- prevX = curX;
- prevY = curY;
- prevGeoZ = curGeoZ;
- ++ptIndex;
- }
- return true;
- }
-
- /**
- * @param x
- * @param y
- * @param z
- * @param tx
- * @param ty
- * @param tz
- * @return Last Location (x,y,z) where player can walk - just before wall
- */
- public Location moveCheck(int x, int y, int z, int tx, int ty, int tz)
- {
- final int geoX = getGeoX(x);
- final int geoY = getGeoY(y);
- z = getNearestZ(geoX, geoY, z);
- final int tGeoX = getGeoX(tx);
- final int tGeoY = getGeoY(ty);
- tz = getNearestZ(tGeoX, tGeoY, tz);
-
- if (DoorTable.getInstance().checkIfDoorsBetween(x, y, z, tx, ty, tz))
- {
- return new Location(x, y, getHeight(x, y, z));
- }
-
- final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
- // first point is guaranteed to be available
- pointIter.next();
-
- int prevX = pointIter.x();
- int prevY = pointIter.y();
- int prevZ = z;
-
- while (pointIter.next())
- {
- final int curX = pointIter.x();
- final int curY = pointIter.y();
- final int curZ = getNearestZ(curX, curY, prevZ);
-
- if (hasGeoPos(prevX, prevY))
- {
- final 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)
- {
- // can't move, return previous location
- return new Location(getWorldX(prevX), getWorldY(prevY), prevZ);
- }
- }
-
- prevX = curX;
- prevY = curY;
- prevZ = curZ;
- }
-
- if (hasGeoPos(prevX, prevY) && (prevZ != tz))
- {
- // different floors, return start location
- return new Location(x, y, z);
- }
- return new Location(tx, ty, tz);
- }
-
- public int traceTerrainZ(int x, int y, int z, int tx, int ty)
- {
- final int geoX = getGeoX(x);
- final int geoY = getGeoY(y);
- z = getNearestZ(geoX, geoY, z);
- final int tGeoX = getGeoX(tx);
- final int tGeoY = getGeoY(ty);
-
- final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
- // first point is guaranteed to be available
- pointIter.next();
- int prevZ = z;
-
- while (pointIter.next())
- {
- final int curX = pointIter.x();
- final int curY = pointIter.y();
- final int curZ = getNearestZ(curX, curY, prevZ);
-
- prevZ = curZ;
- }
-
- return prevZ;
- }
-
- /**
- * Checks if its possible to move from one location to another.
- * @param fromX the X coordinate to start checking from
- * @param fromY the Y coordinate to start checking from
- * @param fromZ the Z coordinate to start checking from
- * @param toX the X coordinate to end checking at
- * @param toY the Y coordinate to end checking at
- * @param toZ the Z coordinate to end checking at
- * @return {@code true} if the character at start coordinates can move to end coordinates, {@code false} otherwise
- */
- public boolean canMove(int fromX, int fromY, int fromZ, int toX, int toY, int toZ)
- {
- final int geoX = getGeoX(fromX);
- final int geoY = getGeoY(fromY);
- fromZ = getNearestZ(geoX, geoY, fromZ);
- final int tGeoX = getGeoX(toX);
- final int tGeoY = getGeoY(toY);
- toZ = getNearestZ(tGeoX, tGeoY, toZ);
-
- if (DoorTable.getInstance().checkIfDoorsBetween(fromX, fromY, fromZ, toX, toY, toZ))
- {
- return false;
- }
-
- final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
-
- // first point is guaranteed to be available
- pointIter.next();
-
- int prevX = pointIter.x();
- int prevY = pointIter.y();
- int prevZ = fromZ;
-
- while (pointIter.next())
- {
- final int curX = pointIter.x();
- final int curY = pointIter.y();
- final int curZ = getNearestZ(curX, curY, prevZ);
-
- if (hasGeoPos(prevX, prevY))
- {
- final 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)
- {
- return false;
- }
- }
-
- prevX = curX;
- prevY = curY;
- prevZ = curZ;
- }
-
- if (hasGeoPos(prevX, prevY) && (prevZ != toZ))
- {
- // different floors
- return false;
- }
- return true;
- }
-
- public boolean hasGeo(int x, int y)
- {
- return hasGeoPos(getGeoX(x), getGeoY(y));
- }
-}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2AttackableAI.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2AttackableAI.java
index d448e1e5a6..36f88667b0 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2AttackableAI.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2AttackableAI.java
@@ -25,9 +25,9 @@ import java.util.concurrent.Future;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.GameTimeController;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.Territory;
import com.l2jmobius.gameserver.ThreadPoolManager;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.instancemanager.DimensionalRiftManager;
import com.l2jmobius.gameserver.model.L2Attackable;
import com.l2jmobius.gameserver.model.L2CharPosition;
@@ -976,7 +976,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
}
// Considering, if bigger range will be attempted
- if ((dist2 < (10000 + (combinedCollision * combinedCollision))) && !_selfAnalysis.isFighter && !_selfAnalysis.isBalanced && (_selfAnalysis.hasLongRangeSkills || _selfAnalysis.isArcher) && (_mostHatedAnalysis.isBalanced || _mostHatedAnalysis.isFighter) && (_mostHatedAnalysis.character.isRooted() || _mostHatedAnalysis.isSlower) && ((Config.GEODATA == 2 ? 20 : 12) >= Rnd.get(100))) // chance
+ if ((dist2 < (10000 + (combinedCollision * combinedCollision))) && !_selfAnalysis.isFighter && !_selfAnalysis.isBalanced && (_selfAnalysis.hasLongRangeSkills || _selfAnalysis.isArcher) && (_mostHatedAnalysis.isBalanced || _mostHatedAnalysis.isFighter) && (_mostHatedAnalysis.character.isRooted() || _mostHatedAnalysis.isSlower) && ((Config.PATHFINDING == 2 ? 20 : 12) >= Rnd.get(100))) // chance
{
int posX = _actor.getX();
int posY = _actor.getY();
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2SiegeGuardAI.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2SiegeGuardAI.java
index 682acdea08..a3a490db5d 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2SiegeGuardAI.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/ai/L2SiegeGuardAI.java
@@ -24,8 +24,8 @@ import java.util.concurrent.Future;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.GameTimeController;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ThreadPoolManager;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.L2Attackable;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Effect;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/datatables/DoorTable.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/datatables/DoorTable.java
index 1b5ad2d3b5..1054c5418c 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/datatables/DoorTable.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/datatables/DoorTable.java
@@ -27,11 +27,11 @@ import java.util.StringTokenizer;
import java.util.logging.Logger;
import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.entity.ClanHall;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
import com.l2jmobius.gameserver.templates.L2CharTemplate;
import com.l2jmobius.gameserver.templates.StatsSet;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/GeoData.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/GeoData.java
new file mode 100644
index 0000000000..46872a5597
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/GeoData.java
@@ -0,0 +1,559 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.datatables.DoorTable;
+import com.l2jmobius.gameserver.geodata.geodriver.Cell;
+import com.l2jmobius.gameserver.geodata.geodriver.GeoDriver;
+import com.l2jmobius.gameserver.model.L2Object;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
+import com.l2jmobius.gameserver.util.GeoUtils;
+import com.l2jmobius.gameserver.util.LinePointIterator;
+import com.l2jmobius.gameserver.util.LinePointIterator3D;
+
+/**
+ * @author -Nemesiss-, HorridoJoho
+ */
+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 SPAWN_Z_DELTA_LIMIT = 100;
+
+ private final GeoDriver _driver = new GeoDriver();
+
+ protected GeoData()
+ {
+ int loadedRegions = 0;
+ try
+ {
+ 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++)
+ {
+ 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 && Files.exists(geoFilePath))
+ {
+ try
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Loading " + geoFilePath.getFileName() + "...");
+ _driver.loadRegion(geoFilePath, regionX, regionY);
+ loadedRegions++;
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed to load " + geoFilePath.getFileName() + "!", e);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Failed to load geodata!", e);
+ System.exit(1);
+ }
+
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + loadedRegions + " regions.");
+ }
+
+ public boolean hasGeoPos(int geoX, int geoY)
+ {
+ return _driver.hasGeoPos(geoX, geoY);
+ }
+
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
+ {
+ return _driver.checkNearestNswe(geoX, geoY, worldZ, nswe);
+ }
+
+ public boolean checkNearestNsweAntiCornerCut(int geoX, int geoY, int worldZ, int nswe)
+ {
+ boolean can = true;
+ if ((nswe & Cell.NSWE_NORTH_EAST) == Cell.NSWE_NORTH_EAST)
+ {
+ // 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) == Cell.NSWE_NORTH_WEST))
+ {
+ // 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) == Cell.NSWE_SOUTH_EAST))
+ {
+ // 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) == Cell.NSWE_SOUTH_WEST))
+ {
+ // 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);
+ }
+
+ public int getNearestZ(int geoX, int geoY, int worldZ)
+ {
+ return _driver.getNearestZ(geoX, geoY, worldZ);
+ }
+
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
+ {
+ return _driver.getNextLowerZ(geoX, geoY, worldZ);
+ }
+
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ return _driver.getNextHigherZ(geoX, geoY, worldZ);
+ }
+
+ public int getGeoX(int worldX)
+ {
+ return _driver.getGeoX(worldX);
+ }
+
+ public int getGeoY(int worldY)
+ {
+ return _driver.getGeoY(worldY);
+ }
+
+ public int getGeoZ(int worldZ)
+ {
+ return _driver.getGeoZ(worldZ);
+ }
+
+ public int getWorldX(int geoX)
+ {
+ return _driver.getWorldX(geoX);
+ }
+
+ public int getWorldY(int geoY)
+ {
+ return _driver.getWorldY(geoY);
+ }
+
+ public int getWorldZ(int geoZ)
+ {
+ return _driver.getWorldZ(geoZ);
+ }
+
+ // ///////////////////
+ // L2J METHODS
+ /**
+ * Gets the height.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the height
+ */
+ public int getHeight(int x, int y, int z)
+ {
+ return getNearestZ(getGeoX(x), getGeoY(y), z);
+ }
+
+ /**
+ * Gets the spawn height.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the the z coordinate
+ * @return the spawn height
+ */
+ public int getSpawnHeight(int x, int y, int z)
+ {
+ final int geoX = getGeoX(x);
+ final int geoY = getGeoY(y);
+
+ if (!hasGeoPos(geoX, geoY))
+ {
+ return z;
+ }
+
+ final int nextLowerZ = getNextLowerZ(geoX, geoY, z + 100);
+ return Math.abs(nextLowerZ - z) <= SPAWN_Z_DELTA_LIMIT ? nextLowerZ : z;
+ }
+
+ /**
+ * Gets the spawn height.
+ * @param location the location
+ * @return the spawn height
+ */
+ public int getSpawnHeight(Location location)
+ {
+ return getSpawnHeight(location.getX(), location.getY(), location.getZ());
+ }
+
+ /**
+ * Can see target. Doors as target always return true. Checks doors between.
+ * @param cha the character
+ * @param target the target
+ * @return {@code true} if the character can see the target (LOS), {@code false} otherwise
+ */
+ public boolean canSeeTarget(L2Object cha, L2Object target)
+ {
+ if (target instanceof L2DoorInstance)
+ {
+ // can always see doors :o
+ return true;
+ }
+
+ return canSeeTarget(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ());
+ }
+
+ private int getLosGeoZ(int prevX, int prevY, int prevGeoZ, int curX, int curY, int nswe)
+ {
+ if ((((nswe & Cell.NSWE_NORTH) != 0) && ((nswe & Cell.NSWE_SOUTH) != 0)) || (((nswe & Cell.NSWE_WEST) != 0) && ((nswe & Cell.NSWE_EAST) != 0)))
+ {
+ throw new RuntimeException("Multiple directions!");
+ }
+
+ if (checkNearestNsweAntiCornerCut(prevX, prevY, prevGeoZ, nswe))
+ {
+ return getNearestZ(curX, curY, prevGeoZ);
+ }
+ return getNextHigherZ(curX, curY, prevGeoZ);
+ }
+
+ /**
+ * Can see target. Does not check doors between.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @param tx the target's x coordinate
+ * @param ty the target's y coordinate
+ * @param tz the target's z coordinate
+ * @return {@code true} if there is line of sight between the given coordinate sets, {@code false} otherwise
+ */
+ public boolean canSeeTarget(int x, int y, int z, int tx, int ty, int tz)
+ {
+ int geoX = getGeoX(x);
+ int geoY = getGeoY(y);
+ int tGeoX = getGeoX(tx);
+ int tGeoY = getGeoY(ty);
+
+ z = getNearestZ(geoX, geoY, z);
+ tz = getNearestZ(tGeoX, tGeoY, tz);
+
+ // fastpath
+ if ((geoX == tGeoX) && (geoY == tGeoY))
+ {
+ if (hasGeoPos(tGeoX, tGeoY))
+ {
+ return z == tz;
+ }
+
+ return true;
+ }
+
+ if (tz > z)
+ {
+ int tmp = tx;
+ tx = x;
+ x = tmp;
+
+ tmp = ty;
+ ty = y;
+ y = tmp;
+
+ tmp = tz;
+ tz = z;
+ z = tmp;
+
+ tmp = tGeoX;
+ tGeoX = geoX;
+ geoX = tmp;
+
+ tmp = tGeoY;
+ tGeoY = geoY;
+ geoY = tmp;
+ }
+
+ final LinePointIterator3D pointIter = new LinePointIterator3D(geoX, geoY, z, tGeoX, tGeoY, tz);
+ // first point is guaranteed to be available, skip it, we can always see our own position
+ pointIter.next();
+ int prevX = pointIter.x();
+ int prevY = pointIter.y();
+ final int prevZ = pointIter.z();
+ int prevGeoZ = prevZ;
+ int ptIndex = 0;
+ while (pointIter.next())
+ {
+ final int curX = pointIter.x();
+ final int curY = pointIter.y();
+
+ if ((curX == prevX) && (curY == prevY))
+ {
+ continue;
+ }
+
+ final int beeCurZ = pointIter.z();
+ int curGeoZ = prevGeoZ;
+
+ // check if the position has geodata
+ if (hasGeoPos(curX, curY))
+ {
+ final int beeCurGeoZ = getNearestZ(curX, curY, beeCurZ);
+ final 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)
+ {
+ maxHeight = z + MAX_SEE_OVER_HEIGHT;
+ }
+ else
+ {
+ maxHeight = beeCurZ + MAX_SEE_OVER_HEIGHT;
+ }
+
+ boolean canSeeThrough = false;
+ if ((curGeoZ <= maxHeight) && (curGeoZ <= beeCurGeoZ))
+ {
+ if ((nswe & Cell.NSWE_NORTH_EAST) == Cell.NSWE_NORTH_EAST)
+ {
+ final int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Cell.NSWE_EAST);
+ final 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) == Cell.NSWE_NORTH_WEST)
+ {
+ final int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Cell.NSWE_WEST);
+ final 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) == Cell.NSWE_SOUTH_EAST)
+ {
+ final int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Cell.NSWE_EAST);
+ final 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) == Cell.NSWE_SOUTH_WEST)
+ {
+ final int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Cell.NSWE_WEST);
+ final 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;
+ }
+ }
+
+ if (!canSeeThrough)
+ {
+ return false;
+ }
+ }
+
+ prevX = curX;
+ prevY = curY;
+ prevGeoZ = curGeoZ;
+ ++ptIndex;
+ }
+
+ return true;
+ }
+
+ /**
+ * Move check.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @param tx the target's x coordinate
+ * @param ty the target's y coordinate
+ * @param tz the target's z coordinate
+ * @return the last Location (x,y,z) where player can walk - just before wall
+ */
+ public Location moveCheck(int x, int y, int z, int tx, int ty, int tz)
+ {
+ final int geoX = getGeoX(x);
+ final int geoY = getGeoY(y);
+ z = getNearestZ(geoX, geoY, z);
+ final int tGeoX = getGeoX(tx);
+ final int tGeoY = getGeoY(ty);
+ tz = getNearestZ(tGeoX, tGeoY, tz);
+
+ if (DoorTable.getInstance().checkIfDoorsBetween(x, y, z, tx, ty, tz))
+ {
+ return new Location(x, y, getHeight(x, y, z));
+ }
+
+ final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
+ // first point is guaranteed to be available
+ pointIter.next();
+ int prevX = pointIter.x();
+ int prevY = pointIter.y();
+ int prevZ = z;
+
+ while (pointIter.next())
+ {
+ final int curX = pointIter.x();
+ final int curY = pointIter.y();
+ final int curZ = getNearestZ(curX, curY, prevZ);
+
+ if (hasGeoPos(prevX, prevY))
+ {
+ final int nswe = GeoUtils.computeNswe(prevX, prevY, curX, curY);
+ if (!checkNearestNsweAntiCornerCut(prevX, prevY, prevZ, nswe))
+ {
+ // can't move, return previous location
+ return new Location(getWorldX(prevX), getWorldY(prevY), prevZ);
+ }
+ }
+
+ prevX = curX;
+ prevY = curY;
+ prevZ = curZ;
+ }
+
+ if (hasGeoPos(prevX, prevY) && (prevZ != tz))
+ {
+ // different floors, return start location
+ return new Location(x, y, z);
+ }
+
+ return new Location(tx, ty, tz);
+ }
+
+ /**
+ * Checks if its possible to move from one location to another.
+ * @param fromX the X coordinate to start checking from
+ * @param fromY the Y coordinate to start checking from
+ * @param fromZ the Z coordinate to start checking from
+ * @param toX the X coordinate to end checking at
+ * @param toY the Y coordinate to end checking at
+ * @param toZ the Z coordinate to end checking at
+ * @return {@code true} if the character at start coordinates can move to end coordinates, {@code false} otherwise
+ */
+ public boolean canMove(int fromX, int fromY, int fromZ, int toX, int toY, int toZ)
+ {
+ final int geoX = getGeoX(fromX);
+ final int geoY = getGeoY(fromY);
+ fromZ = getNearestZ(geoX, geoY, fromZ);
+ final int tGeoX = getGeoX(toX);
+ final int tGeoY = getGeoY(toY);
+ toZ = getNearestZ(tGeoX, tGeoY, toZ);
+
+ if (DoorTable.getInstance().checkIfDoorsBetween(fromX, fromY, fromZ, toX, toY, toZ))
+ {
+ return false;
+ }
+
+ final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
+ // first point is guaranteed to be available
+ pointIter.next();
+ int prevX = pointIter.x();
+ int prevY = pointIter.y();
+ int prevZ = fromZ;
+
+ while (pointIter.next())
+ {
+ final int curX = pointIter.x();
+ final int curY = pointIter.y();
+ final int curZ = getNearestZ(curX, curY, prevZ);
+
+ if (hasGeoPos(prevX, prevY))
+ {
+ final int nswe = GeoUtils.computeNswe(prevX, prevY, curX, curY);
+ if (!checkNearestNsweAntiCornerCut(prevX, prevY, prevZ, nswe))
+ {
+ return false;
+ }
+ }
+
+ prevX = curX;
+ prevY = curY;
+ prevZ = curZ;
+ }
+
+ if (hasGeoPos(prevX, prevY) && (prevZ != toZ))
+ {
+ // different floors
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks if its possible to move from one location to another.
+ * @param from the {@code WorldObject} to start checking from
+ * @param toX the X coordinate to end checking at
+ * @param toY the Y coordinate to end checking at
+ * @param toZ the Z coordinate to end checking at
+ * @return {@code true} if the character at start coordinates can move to end coordinates, {@code false} otherwise
+ */
+ public boolean canMove(L2Object from, int toX, int toY, int toZ)
+ {
+ return canMove(from.getX(), from.getY(), from.getZ(), toX, toY, toZ);
+ }
+
+ /**
+ * Checks if its possible to move from one location to another.
+ * @param from the {@code WorldObject} to start checking from
+ * @param to the {@code WorldObject} to end checking at
+ * @return {@code true} if the character at start coordinates can move to end coordinates, {@code false} otherwise
+ */
+ public boolean canMove(L2Object from, L2Object to)
+ {
+ return canMove(from, to.getX(), to.getY(), to.getZ());
+ }
+
+ /**
+ * Checks the specified position for available geodata.
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ * @return {@code true} if there is geodata for the given coordinates, {@code false} otherwise
+ */
+ public boolean hasGeo(int x, int y)
+ {
+ return hasGeoPos(getGeoX(x), getGeoY(y));
+ }
+
+ public static GeoData getInstance()
+ {
+ return SingletonHolder._instance;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final GeoData _instance = new GeoData();
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/Cell.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/Cell.java
new file mode 100644
index 0000000000..4914b1d72e
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/Cell.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver;
+
+/**
+ * @author HorridoJoho
+ */
+public final class Cell
+{
+ /** East NSWE flag */
+ public static final byte NSWE_EAST = 1 << 0;
+ /** West NSWE flag */
+ public static final byte NSWE_WEST = 1 << 1;
+ /** South NSWE flag */
+ public static final byte NSWE_SOUTH = 1 << 2;
+ /** North NSWE flag */
+ public static final byte NSWE_NORTH = 1 << 3;
+
+ /** North-East NSWE flags */
+ public static final byte NSWE_NORTH_EAST = NSWE_NORTH | NSWE_EAST;
+ /** North-West NSWE flags */
+ public static final byte NSWE_NORTH_WEST = NSWE_NORTH | NSWE_WEST;
+ /** South-East NSWE flags */
+ public static final byte NSWE_SOUTH_EAST = NSWE_SOUTH | NSWE_EAST;
+ /** South-West NSWE flags */
+ public static final byte NSWE_SOUTH_WEST = NSWE_SOUTH | NSWE_WEST;
+
+ /** All directions NSWE flags */
+ public static final byte NSWE_ALL = NSWE_EAST | NSWE_WEST | NSWE_SOUTH | NSWE_NORTH;
+
+ private Cell()
+ {
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/GeoDriver.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/GeoDriver.java
new file mode 100644
index 0000000000..ffef644f31
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/GeoDriver.java
@@ -0,0 +1,189 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.Path;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+import com.l2jmobius.gameserver.geodata.geodriver.regions.NullRegion;
+import com.l2jmobius.gameserver.geodata.geodriver.regions.Region;
+
+/**
+ * @author HorridoJoho
+ */
+public final class GeoDriver
+{
+ // world dimensions: 1048576 * 1048576 = 1099511627776
+ private static final int WORLD_MIN_X = -655360;
+ private static final int WORLD_MAX_X = 393215;
+ private static final int WORLD_MIN_Y = -589824;
+ private static final int WORLD_MAX_Y = 458751;
+ private static final int WORLD_MIN_Z = -16384;
+ private static final int WORLD_MAX_Z = 16384;
+
+ /** Regions in the world on the x axis */
+ public static final int GEO_REGIONS_X = 32;
+ /** Regions in the world on the y axis */
+ public static final int GEO_REGIONS_Y = 32;
+ /** Region in the world */
+ public static final int GEO_REGIONS = GEO_REGIONS_X * GEO_REGIONS_Y;
+
+ /** Blocks in the world on the x axis */
+ public static final int GEO_BLOCKS_X = GEO_REGIONS_X * IRegion.REGION_BLOCKS_X;
+ /** Blocks in the world on the y axis */
+ public static final int GEO_BLOCKS_Y = GEO_REGIONS_Y * IRegion.REGION_BLOCKS_Y;
+ /** Blocks in the world */
+ public static final int GEO_BLOCKS = GEO_REGIONS * IRegion.REGION_BLOCKS;
+
+ /** Cells in the world on the x axis */
+ public static final int GEO_CELLS_X = GEO_BLOCKS_X * IBlock.BLOCK_CELLS_X;
+ /** Cells in the world in the y axis */
+ public static final int GEO_CELLS_Y = GEO_BLOCKS_Y * IBlock.BLOCK_CELLS_Y;
+ /** Cells in the world in the z axis */
+ public static final int GEO_CELLS_Z = (Math.abs(WORLD_MIN_Z) + Math.abs(WORLD_MAX_Z)) / 16;
+
+ /** The regions array */
+ private final AtomicReferenceArray _regions = new AtomicReferenceArray<>(GEO_REGIONS);
+
+ public GeoDriver()
+ {
+ for (int i = 0; i < _regions.length(); i++)
+ {
+ _regions.set(i, NullRegion.INSTANCE);
+ }
+ }
+
+ private void checkGeoX(int geoX)
+ {
+ if ((geoX < 0) || (geoX >= GEO_CELLS_X))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void checkGeoY(int geoY)
+ {
+ if ((geoY < 0) || (geoY >= GEO_CELLS_Y))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void checkGeoZ(int geoZ)
+ {
+ if ((geoZ < 0) || (geoZ >= GEO_CELLS_Z))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private IRegion getRegion(int geoX, int geoY)
+ {
+ checkGeoX(geoX);
+ checkGeoY(geoY);
+ return _regions.get(((geoX / IRegion.REGION_CELLS_X) * GEO_REGIONS_Y) + (geoY / IRegion.REGION_CELLS_Y));
+ }
+
+ public void loadRegion(Path filePath, int regionX, int regionY) throws IOException
+ {
+ final int regionOffset = (regionX * GEO_REGIONS_Y) + regionY;
+
+ try (RandomAccessFile raf = new RandomAccessFile(filePath.toFile(), "r"))
+ {
+ _regions.set(regionOffset, new Region(raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length()).load().order(ByteOrder.LITTLE_ENDIAN)));
+ }
+ }
+
+ public void unloadRegion(int regionX, int regionY)
+ {
+ _regions.set((regionX * GEO_REGIONS_Y) + regionY, NullRegion.INSTANCE);
+ }
+
+ public boolean hasGeoPos(int geoX, int geoY)
+ {
+ return getRegion(geoX, geoY).hasGeo();
+ }
+
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
+ {
+ return getRegion(geoX, geoY).checkNearestNswe(geoX, geoY, worldZ, nswe);
+ }
+
+ public int getNearestZ(int geoX, int geoY, int worldZ)
+ {
+ return getRegion(geoX, geoY).getNearestZ(geoX, geoY, worldZ);
+ }
+
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
+ {
+ return getRegion(geoX, geoY).getNextLowerZ(geoX, geoY, worldZ);
+ }
+
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ return getRegion(geoX, geoY).getNextHigherZ(geoX, geoY, worldZ);
+ }
+
+ public int getGeoX(int worldX)
+ {
+ if ((worldX < WORLD_MIN_X) || (worldX > WORLD_MAX_X))
+ {
+ throw new IllegalArgumentException();
+ }
+ return (worldX - WORLD_MIN_X) / 16;
+ }
+
+ public int getGeoY(int worldY)
+ {
+ if ((worldY < WORLD_MIN_Y) || (worldY > WORLD_MAX_Y))
+ {
+ throw new IllegalArgumentException();
+ }
+ return (worldY - WORLD_MIN_Y) / 16;
+ }
+
+ public int getGeoZ(int worldZ)
+ {
+ if ((worldZ < WORLD_MIN_Z) || (worldZ > WORLD_MAX_Z))
+ {
+ throw new IllegalArgumentException();
+ }
+ return (worldZ - WORLD_MIN_Z) / 16;
+ }
+
+ public int getWorldX(int geoX)
+ {
+ checkGeoX(geoX);
+ return (geoX * 16) + WORLD_MIN_X + 8;
+ }
+
+ public int getWorldY(int geoY)
+ {
+ checkGeoY(geoY);
+ return (geoY * 16) + WORLD_MIN_Y + 8;
+ }
+
+ public int getWorldZ(int geoZ)
+ {
+ checkGeoZ(geoZ);
+ return (geoZ * 16) + WORLD_MIN_Z + 8;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/IBlock.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/IBlock.java
new file mode 100644
index 0000000000..21df97c40d
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/IBlock.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver;
+
+/**
+ * @author HorridoJoho
+ */
+public interface IBlock
+{
+ int TYPE_FLAT = 0;
+ int TYPE_COMPLEX = 1;
+ int TYPE_MULTILAYER = 2;
+
+ /** Cells in a block on the x axis */
+ int BLOCK_CELLS_X = 8;
+ /** Cells in a block on the y axis */
+ int BLOCK_CELLS_Y = 8;
+ /** Cells in a block */
+ int BLOCK_CELLS = BLOCK_CELLS_X * BLOCK_CELLS_Y;
+
+ boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe);
+
+ int getNearestZ(int geoX, int geoY, int worldZ);
+
+ int getNextLowerZ(int geoX, int geoY, int worldZ);
+
+ int getNextHigherZ(int geoX, int geoY, int worldZ);
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/IRegion.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/IRegion.java
new file mode 100644
index 0000000000..3eb23da03e
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/IRegion.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver;
+
+/**
+ * @author HorridoJoho
+ */
+public interface IRegion
+{
+ /** Blocks in a region on the x axis. */
+ int REGION_BLOCKS_X = 256;
+ /** Blocks in a region on the y axis. */
+ int REGION_BLOCKS_Y = 256;
+ /** Blocks in a region. */
+ int REGION_BLOCKS = REGION_BLOCKS_X * REGION_BLOCKS_Y;
+
+ /** Cells in a region on the x axis. */
+ int REGION_CELLS_X = REGION_BLOCKS_X * IBlock.BLOCK_CELLS_X;
+ /** Cells in a regioin on the y axis. */
+ int REGION_CELLS_Y = REGION_BLOCKS_Y * IBlock.BLOCK_CELLS_Y;
+ /** Cells in a region. */
+ int REGION_CELLS = REGION_CELLS_X * REGION_CELLS_Y;
+
+ boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe);
+
+ int getNearestZ(int geoX, int geoY, int worldZ);
+
+ int getNextLowerZ(int geoX, int geoY, int worldZ);
+
+ int getNextHigherZ(int geoX, int geoY, int worldZ);
+
+ boolean hasGeo();
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/ComplexBlock.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/ComplexBlock.java
new file mode 100644
index 0000000000..4d6410672e
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/ComplexBlock.java
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver.blocks;
+
+import java.nio.ByteBuffer;
+
+import com.l2jmobius.gameserver.geodata.geodriver.IBlock;
+
+/**
+ * @author HorridoJoho
+ */
+public final class ComplexBlock implements IBlock
+{
+ private final short[] _data;
+
+ public ComplexBlock(ByteBuffer bb)
+ {
+ _data = new short[IBlock.BLOCK_CELLS];
+ for (int cellOffset = 0; cellOffset < IBlock.BLOCK_CELLS; cellOffset++)
+ {
+ _data[cellOffset] = bb.getShort();
+ }
+ }
+
+ private short _getCellData(int geoX, int geoY)
+ {
+ return _data[((geoX % IBlock.BLOCK_CELLS_X) * IBlock.BLOCK_CELLS_Y) + (geoY % IBlock.BLOCK_CELLS_Y)];
+ }
+
+ private byte _getCellNSWE(int geoX, int geoY)
+ {
+ return (byte) (_getCellData(geoX, geoY) & 0x000F);
+ }
+
+ private int _getCellHeight(int geoX, int geoY)
+ {
+ return (short) (_getCellData(geoX, geoY) & 0x0FFF0) >> 1;
+ }
+
+ @Override
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
+ {
+ return (_getCellNSWE(geoX, geoY) & nswe) == nswe;
+ }
+
+ @Override
+ public int getNearestZ(int geoX, int geoY, int worldZ)
+ {
+ return _getCellHeight(geoX, geoY);
+ }
+
+ @Override
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
+ {
+ final int cellHeight = _getCellHeight(geoX, geoY);
+ return cellHeight <= worldZ ? cellHeight : worldZ;
+ }
+
+ @Override
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ final int cellHeight = _getCellHeight(geoX, geoY);
+ return cellHeight >= worldZ ? cellHeight : worldZ;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/FlatBlock.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/FlatBlock.java
new file mode 100644
index 0000000000..d5bcff094b
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/FlatBlock.java
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver.blocks;
+
+import java.nio.ByteBuffer;
+
+import com.l2jmobius.gameserver.geodata.geodriver.IBlock;
+
+/**
+ * @author HorridoJoho
+ */
+public class FlatBlock implements IBlock
+{
+ private final short _height;
+
+ public FlatBlock(ByteBuffer bb)
+ {
+ _height = bb.getShort();
+ }
+
+ @Override
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
+ {
+ return true;
+ }
+
+ @Override
+ public int getNearestZ(int geoX, int geoY, int worldZ)
+ {
+ return _height;
+ }
+
+ @Override
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
+ {
+ return _height <= worldZ ? _height : worldZ;
+ }
+
+ @Override
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ return _height >= worldZ ? _height : worldZ;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/MultilayerBlock.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/MultilayerBlock.java
new file mode 100644
index 0000000000..313131bd5a
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/blocks/MultilayerBlock.java
@@ -0,0 +1,186 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver.blocks;
+
+import java.nio.ByteBuffer;
+
+import com.l2jmobius.gameserver.geodata.geodriver.IBlock;
+
+/**
+ * @author HorridoJoho
+ */
+public class MultilayerBlock implements IBlock
+{
+ private final byte[] _data;
+
+ /**
+ * Initializes a new instance of this block reading the specified buffer.
+ * @param bb the buffer
+ */
+ public MultilayerBlock(ByteBuffer bb)
+ {
+ final int start = bb.position();
+
+ for (int blockCellOffset = 0; blockCellOffset < IBlock.BLOCK_CELLS; blockCellOffset++)
+ {
+ final byte nLayers = bb.get();
+ if ((nLayers <= 0) || (nLayers > 125))
+ {
+ throw new RuntimeException("L2JGeoDriver: Geo file corrupted! Invalid layers count!");
+ }
+
+ bb.position(bb.position() + (nLayers * 2));
+ }
+
+ _data = new byte[bb.position() - start];
+ bb.position(start);
+ bb.get(_data);
+ }
+
+ private short _getNearestLayer(int geoX, int geoY, int worldZ)
+ {
+ final int startOffset = _getCellDataOffset(geoX, geoY);
+ final byte nLayers = _data[startOffset];
+ final int endOffset = startOffset + 1 + (nLayers * 2);
+
+ // 1 layer at least was required on loading so this is set at least once on the loop below
+ int nearestDZ = 0;
+ short nearestData = 0;
+ for (int offset = startOffset + 1; offset < endOffset; offset += 2)
+ {
+ final short layerData = _extractLayerData(offset);
+ final int layerZ = _extractLayerHeight(layerData);
+ if (layerZ == worldZ)
+ {
+ // exact z
+ return layerData;
+ }
+
+ final int layerDZ = Math.abs(layerZ - worldZ);
+ if ((offset == (startOffset + 1)) || (layerDZ < nearestDZ))
+ {
+ nearestDZ = layerDZ;
+ nearestData = layerData;
+ }
+ }
+
+ return nearestData;
+ }
+
+ private int _getCellDataOffset(int geoX, int geoY)
+ {
+ final int cellLocalOffset = ((geoX % IBlock.BLOCK_CELLS_X) * IBlock.BLOCK_CELLS_Y) + (geoY % IBlock.BLOCK_CELLS_Y);
+ int cellDataOffset = 0;
+ // move index to cell, we need to parse on each request, OR we parse on creation and save indexes
+ for (int i = 0; i < cellLocalOffset; i++)
+ {
+ cellDataOffset += 1 + (_data[cellDataOffset] * 2);
+ }
+ // now the index points to the cell we need
+
+ return cellDataOffset;
+ }
+
+ private short _extractLayerData(int dataOffset)
+ {
+ return (short) ((_data[dataOffset] & 0xFF) | (_data[dataOffset + 1] << 8));
+ }
+
+ private int _getNearestNSWE(int geoX, int geoY, int worldZ)
+ {
+ return _extractLayerNswe(_getNearestLayer(geoX, geoY, worldZ));
+ }
+
+ private int _extractLayerNswe(short layer)
+ {
+ return (byte) (layer & 0x000F);
+ }
+
+ private int _extractLayerHeight(short layer)
+ {
+ layer = (short) (layer & 0x0fff0);
+ return layer >> 1;
+ }
+
+ @Override
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
+ {
+ return (_getNearestNSWE(geoX, geoY, worldZ) & nswe) == nswe;
+ }
+
+ @Override
+ public int getNearestZ(int geoX, int geoY, int worldZ)
+ {
+ return _extractLayerHeight(_getNearestLayer(geoX, geoY, worldZ));
+ }
+
+ @Override
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
+ {
+ final int startOffset = _getCellDataOffset(geoX, geoY);
+ final byte nLayers = _data[startOffset];
+ final int endOffset = startOffset + 1 + (nLayers * 2);
+
+ int lowerZ = Integer.MIN_VALUE;
+ for (int offset = startOffset + 1; offset < endOffset; offset += 2)
+ {
+ final short layerData = _extractLayerData(offset);
+
+ final int layerZ = _extractLayerHeight(layerData);
+ if (layerZ == worldZ)
+ {
+ // exact z
+ return layerZ;
+ }
+
+ if ((layerZ < worldZ) && (layerZ > lowerZ))
+ {
+ lowerZ = layerZ;
+ }
+ }
+
+ return lowerZ == Integer.MIN_VALUE ? worldZ : lowerZ;
+ }
+
+ @Override
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ final int startOffset = _getCellDataOffset(geoX, geoY);
+ final byte nLayers = _data[startOffset];
+ final int endOffset = startOffset + 1 + (nLayers * 2);
+
+ int higherZ = Integer.MAX_VALUE;
+ for (int offset = startOffset + 1; offset < endOffset; offset += 2)
+ {
+ final short layerData = _extractLayerData(offset);
+
+ final int layerZ = _extractLayerHeight(layerData);
+ if (layerZ == worldZ)
+ {
+ // exact z
+ return layerZ;
+ }
+
+ if ((layerZ > worldZ) && (layerZ < higherZ))
+ {
+ higherZ = layerZ;
+ }
+ }
+
+ return higherZ == Integer.MAX_VALUE ? worldZ : higherZ;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/utils/FastNodeList.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/regions/NullRegion.java
similarity index 51%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/utils/FastNodeList.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/regions/NullRegion.java
index 83a7f7d9e4..60ecac873a 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/utils/FastNodeList.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/regions/NullRegion.java
@@ -14,50 +14,44 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package com.l2jmobius.gameserver.pathfinding.utils;
+package com.l2jmobius.gameserver.geodata.geodriver.regions;
-import com.l2jmobius.gameserver.pathfinding.AbstractNode;
+import com.l2jmobius.gameserver.geodata.geodriver.IRegion;
/**
- * @author -Nemesiss-
+ * @author HorridoJoho
*/
-public class FastNodeList
+public final class NullRegion implements IRegion
{
- private final AbstractNode[] _list;
- private int _size;
+ public static final NullRegion INSTANCE = new NullRegion();
- public FastNodeList(int size)
+ @Override
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
{
- _list = new AbstractNode[size];
+ return true;
}
- public void add(AbstractNode n)
+ @Override
+ public int getNearestZ(int geoX, int geoY, int worldZ)
{
- _list[_size] = n;
- _size++;
+ return worldZ;
}
- public boolean contains(AbstractNode n)
+ @Override
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
{
- for (int i = 0; i < _size; i++)
- {
- if (_list[i].equals(n))
- {
- return true;
- }
- }
- return false;
+ return worldZ;
}
- public boolean containsRev(AbstractNode n)
+ @Override
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ return worldZ;
+ }
+
+ @Override
+ public boolean hasGeo()
{
- for (int i = _size - 1; i >= 0; i--)
- {
- if (_list[i].equals(n))
- {
- return true;
- }
- }
return false;
}
}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/regions/Region.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/regions/Region.java
new file mode 100644
index 0000000000..d2d02481ed
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/geodriver/regions/Region.java
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.geodriver.regions;
+
+import java.nio.ByteBuffer;
+
+import com.l2jmobius.gameserver.geodata.geodriver.IBlock;
+import com.l2jmobius.gameserver.geodata.geodriver.IRegion;
+import com.l2jmobius.gameserver.geodata.geodriver.blocks.ComplexBlock;
+import com.l2jmobius.gameserver.geodata.geodriver.blocks.FlatBlock;
+import com.l2jmobius.gameserver.geodata.geodriver.blocks.MultilayerBlock;
+
+/**
+ * @author HorridoJoho
+ */
+public final class Region implements IRegion
+{
+ private final IBlock[] _blocks = new IBlock[IRegion.REGION_BLOCKS];
+
+ public Region(ByteBuffer bb)
+ {
+ for (int blockOffset = 0; blockOffset < IRegion.REGION_BLOCKS; blockOffset++)
+ {
+ final int blockType = bb.get();
+ switch (blockType)
+ {
+ case IBlock.TYPE_FLAT:
+ {
+ _blocks[blockOffset] = new FlatBlock(bb);
+ break;
+ }
+ case IBlock.TYPE_COMPLEX:
+ {
+ _blocks[blockOffset] = new ComplexBlock(bb);
+ break;
+ }
+ case IBlock.TYPE_MULTILAYER:
+ {
+ _blocks[blockOffset] = new MultilayerBlock(bb);
+ break;
+ }
+ default:
+ {
+ throw new RuntimeException("Invalid block type " + blockType + "!");
+ }
+ }
+ }
+ }
+
+ private IBlock getBlock(int geoX, int geoY)
+ {
+ return _blocks[(((geoX / IBlock.BLOCK_CELLS_X) % IRegion.REGION_BLOCKS_X) * IRegion.REGION_BLOCKS_Y) + ((geoY / IBlock.BLOCK_CELLS_Y) % IRegion.REGION_BLOCKS_Y)];
+ }
+
+ @Override
+ public boolean checkNearestNswe(int geoX, int geoY, int worldZ, int nswe)
+ {
+ return getBlock(geoX, geoY).checkNearestNswe(geoX, geoY, worldZ, nswe);
+ }
+
+ @Override
+ public int getNearestZ(int geoX, int geoY, int worldZ)
+ {
+ return getBlock(geoX, geoY).getNearestZ(geoX, geoY, worldZ);
+ }
+
+ @Override
+ public int getNextLowerZ(int geoX, int geoY, int worldZ)
+ {
+ return getBlock(geoX, geoY).getNextLowerZ(geoX, geoY, worldZ);
+ }
+
+ @Override
+ public int getNextHigherZ(int geoX, int geoY, int worldZ)
+ {
+ return getBlock(geoX, geoY).getNextHigherZ(geoX, geoY, worldZ);
+ }
+
+ @Override
+ public boolean hasGeo()
+ {
+ return true;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/AbstractNode.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/AbstractNode.java
similarity index 70%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/AbstractNode.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/AbstractNode.java
index 8cfe369e34..e3476f28c2 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/AbstractNode.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/AbstractNode.java
@@ -1,93 +1,87 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding;
-
-public abstract class AbstractNode
-{
- private AbstractNodeLoc _loc;
- private AbstractNode _parent;
-
- public AbstractNode(AbstractNodeLoc loc)
- {
- _loc = loc;
- }
-
- public void setParent(AbstractNode p)
- {
- _parent = p;
- }
-
- public AbstractNode getParent()
- {
- return _parent;
- }
-
- public AbstractNodeLoc getLoc()
- {
- return _loc;
- }
-
- public void setLoc(AbstractNodeLoc l)
- {
- _loc = l;
- }
-
- /**
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + ((_loc == null) ? 0 : _loc.hashCode());
- return result;
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof AbstractNode))
- {
- return false;
- }
- final AbstractNode other = (AbstractNode) obj;
- if (_loc == null)
- {
- if (other._loc != null)
- {
- return false;
- }
- }
- else if (!_loc.equals(other._loc))
- {
- return false;
- }
- return true;
- }
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding;
+
+public abstract class AbstractNode
+{
+ private T _loc;
+ private AbstractNode _parent;
+
+ public AbstractNode(T loc)
+ {
+ _loc = loc;
+ }
+
+ public void setParent(AbstractNode p)
+ {
+ _parent = p;
+ }
+
+ public AbstractNode getParent()
+ {
+ return _parent;
+ }
+
+ public T getLoc()
+ {
+ return _loc;
+ }
+
+ public void setLoc(T l)
+ {
+ _loc = l;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + ((_loc == null) ? 0 : _loc.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof AbstractNode))
+ {
+ return false;
+ }
+ final AbstractNode> other = (AbstractNode>) obj;
+ if (_loc == null)
+ {
+ if (other._loc != null)
+ {
+ return false;
+ }
+ }
+ else if (!_loc.equals(other._loc))
+ {
+ return false;
+ }
+ return true;
+ }
}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/AbstractNodeLoc.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/AbstractNodeLoc.java
similarity index 88%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/AbstractNodeLoc.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/AbstractNodeLoc.java
index b398fe2e5e..ec3bd23d44 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/AbstractNodeLoc.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/AbstractNodeLoc.java
@@ -1,35 +1,33 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding;
-
-/**
- * @author -Nemesiss-
- */
-public abstract class AbstractNodeLoc
-{
- public abstract int getX();
-
- public abstract int getY();
-
- public abstract int getZ();
-
- public abstract void setZ(short z);
-
- public abstract int getNodeX();
-
- public abstract int getNodeY();
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding;
+
+/**
+ * @author -Nemesiss-
+ */
+public abstract class AbstractNodeLoc
+{
+ public abstract int getX();
+
+ public abstract int getY();
+
+ public abstract int getZ();
+
+ public abstract int getNodeX();
+
+ public abstract int getNodeY();
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/PathFinding.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/PathFinding.java
new file mode 100644
index 0000000000..37b74dc4a2
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/PathFinding.java
@@ -0,0 +1,210 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding;
+
+import java.util.List;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.geodata.pathfinding.cellnodes.CellPathFinding;
+import com.l2jmobius.gameserver.geodata.pathfinding.geonodes.GeoPathFinding;
+import com.l2jmobius.gameserver.model.L2World;
+
+/**
+ * @author -Nemesiss-
+ */
+public abstract class PathFinding
+{
+ public static PathFinding getInstance()
+ {
+ if (Config.PATHFINDING == 1)
+ {
+ // Higher Memory Usage, Smaller Cpu Usage
+ return GeoPathFinding.getInstance();
+ }
+ // Cell pathfinding, calculated directly from geodata files
+ return CellPathFinding.getInstance();
+ }
+
+ public abstract boolean pathNodesExist(short regionoffset);
+
+ public abstract List findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable);
+
+ // @formatter:off
+ /*
+ public List search(AbstractNode start, AbstractNode end, int instanceId)
+ {
+ // The simplest grid-based pathfinding.
+ // Drawback is not having higher cost for diagonal movement (means funny routes)
+ // Could be optimized e.g. not to calculate backwards as far as forwards.
+
+ // List of Visited Nodes
+ LinkedList visited = new LinkedList();
+
+ // List of Nodes to Visit
+ LinkedList to_visit = new LinkedList();
+ to_visit.add(start);
+
+ int i = 0;
+ while (i < 800)
+ {
+ AbstractNode node;
+ try
+ {
+ node = to_visit.removeFirst();
+ }
+ catch (Exception e)
+ {
+ // No Path found
+ return null;
+ }
+ if (node.equals(end)) //path found!
+ return constructPath(node, instanceId);
+ else
+ {
+ i++;
+ visited.add(node);
+ node.attachNeighbors();
+ Node[] neighbors = node.getNeighbors();
+ if (neighbors == null)
+ continue;
+ for (Node n : neighbors)
+ {
+ if (!visited.contains(n) && !to_visit.contains(n))
+ {
+ n.setParent(node);
+ to_visit.add(n);
+ }
+ }
+ }
+ }
+ //No Path found
+ return null;
+ }
+ */
+ /*
+ public List searchAStar(Node start, Node end, int instanceId)
+ {
+ // Not operational yet?
+ int start_x = start.getLoc().getX();
+ int start_y = start.getLoc().getY();
+ int end_x = end.getLoc().getX();
+ int end_y = end.getLoc().getY();
+ //List of Visited Nodes
+ FastNodeList visited = new FastNodeList(800);//TODO! Add limit to cfg
+
+ // List of Nodes to Visit
+ BinaryNodeHeap to_visit = new BinaryNodeHeap(800);
+ to_visit.add(start);
+
+ int i = 0;
+ while (i < 800)//TODO! Add limit to cfg
+ {
+ AbstractNode node;
+ try
+ {
+ node = to_visit.removeFirst();
+ }
+ catch (Exception e)
+ {
+ // No Path found
+ return null;
+ }
+ if (node.equals(end)) //path found!
+ return constructPath(node, instanceId);
+ else
+ {
+ visited.add(node);
+ node.attachNeighbors();
+ for (Node n : node.getNeighbors())
+ {
+ if (!visited.contains(n) && !to_visit.contains(n))
+ {
+ i++;
+ n.setParent(node);
+ n.setCost(Math.abs(start_x - n.getLoc().getNodeX()) + Math.abs(start_y - n.getLoc().getNodeY())
+ + Math.abs(end_x - n.getLoc().getNodeX()) + Math.abs(end_y - n.getLoc().getNodeY()));
+ to_visit.add(n);
+ }
+ }
+ }
+ }
+ //No Path found
+ return null;
+ }
+ */
+ // @formatter:on
+
+ /**
+ * Convert geodata position to pathnode position
+ * @param geo_pos
+ * @return pathnode position
+ */
+ public short getNodePos(int geo_pos)
+ {
+ return (short) (geo_pos >> 3); // OK?
+ }
+
+ /**
+ * Convert node position to pathnode block position
+ * @param node_pos
+ * @return pathnode block position (0...255)
+ */
+ public short getNodeBlock(int node_pos)
+ {
+ return (short) (node_pos % 256);
+ }
+
+ public byte getRegionX(int node_pos)
+ {
+ return (byte) ((node_pos >> 8) + L2World.TILE_X_MIN);
+ }
+
+ public byte getRegionY(int node_pos)
+ {
+ return (byte) ((node_pos >> 8) + L2World.TILE_Y_MIN);
+ }
+
+ public short getRegionOffset(byte rx, byte ry)
+ {
+ return (short) ((rx << 5) + ry);
+ }
+
+ /**
+ * Convert pathnode x to World x position
+ * @param node_x rx
+ * @return
+ */
+ public int calculateWorldX(short node_x)
+ {
+ return L2World.MAP_MIN_X + (node_x * 128) + 48;
+ }
+
+ /**
+ * Convert pathnode y to World y position
+ * @param node_y
+ * @return
+ */
+ public int calculateWorldY(short node_y)
+ {
+ return L2World.MAP_MIN_Y + (node_y * 128) + 48;
+ }
+
+ public String[] getStat()
+ {
+ return null;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellNode.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellNode.java
similarity index 79%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellNode.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellNode.java
index 1c56cb9773..dd2c0f2d8e 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellNode.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellNode.java
@@ -1,70 +1,69 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.cellnodes;
-
-import com.l2jmobius.gameserver.pathfinding.AbstractNode;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-
-public class CellNode extends AbstractNode
-{
- private CellNode _next = null;
- private boolean _isInUse = true;
- private float _cost = -1000;
-
- public CellNode(AbstractNodeLoc loc)
- {
- super(loc);
- }
-
- public boolean isInUse()
- {
- return _isInUse;
- }
-
- public void setInUse()
- {
- _isInUse = true;
- }
-
- public CellNode getNext()
- {
- return _next;
- }
-
- public void setNext(CellNode next)
- {
- _next = next;
- }
-
- public float getCost()
- {
- return _cost;
- }
-
- public void setCost(double cost)
- {
- _cost = (float) cost;
- }
-
- public void free()
- {
- setParent(null);
- _cost = -1000;
- _isInUse = false;
- _next = null;
- }
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
+
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
+
+public class CellNode extends AbstractNode
+{
+ private CellNode _next = null;
+ private boolean _isInUse = true;
+ private float _cost = -1000;
+
+ public CellNode(NodeLoc loc)
+ {
+ super(loc);
+ }
+
+ public boolean isInUse()
+ {
+ return _isInUse;
+ }
+
+ public void setInUse()
+ {
+ _isInUse = true;
+ }
+
+ public CellNode getNext()
+ {
+ return _next;
+ }
+
+ public void setNext(CellNode next)
+ {
+ _next = next;
+ }
+
+ public float getCost()
+ {
+ return _cost;
+ }
+
+ public void setCost(double cost)
+ {
+ _cost = (float) cost;
+ }
+
+ public void free()
+ {
+ setParent(null);
+ _cost = -1000;
+ _isInUse = false;
+ _next = null;
+ }
}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellNodeBuffer.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellNodeBuffer.java
similarity index 76%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellNodeBuffer.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellNodeBuffer.java
index 08aa8ca1d1..5747e430ea 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellNodeBuffer.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellNodeBuffer.java
@@ -1,364 +1,361 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.cellnodes;
-
-import java.util.concurrent.locks.ReentrantLock;
-
-import com.l2jmobius.Config;
-
-import javolution.util.FastList;
-
-/**
- * @author DS Credits to Diamond
- */
-public class CellNodeBuffer
-{
- private static final int MAX_ITERATIONS = 3500;
-
- private final ReentrantLock _lock = new ReentrantLock();
- private final int _mapSize;
- private final CellNode[][] _buffer;
-
- private int _baseX = 0;
- private int _baseY = 0;
-
- private int _targetX = 0;
- private int _targetY = 0;
- private int _targetZ = 0;
-
- private long _timeStamp = 0;
- private long _lastElapsedTime = 0;
-
- private CellNode _current = null;
-
- public CellNodeBuffer(int size)
- {
- _mapSize = size;
- _buffer = new CellNode[_mapSize][_mapSize];
- }
-
- public final boolean lock()
- {
- return _lock.tryLock();
- }
-
- public final CellNode findPath(int x, int y, int z, int tx, int ty, int tz)
- {
- _timeStamp = System.currentTimeMillis();
- _baseX = x + ((tx - x - _mapSize) / 2); // middle of the line (x,y) - (tx,ty)
- _baseY = y + ((ty - y - _mapSize) / 2); // will be in the center of the buffer
- _targetX = tx;
- _targetY = ty;
- _targetZ = tz;
- _current = getNode(x, y, z);
- _current.setCost(getCost(x, y, z, Config.HIGH_WEIGHT));
-
- for (int count = 0; count < MAX_ITERATIONS; count++)
- {
- if ((_current.getLoc().getNodeX() == _targetX) && (_current.getLoc().getNodeY() == _targetY) && (Math.abs(_current.getLoc().getZ() - _targetZ) < 64))
- {
- return _current; // found
- }
-
- getNeighbors();
- if (_current.getNext() == null)
- {
- return null; // no more ways
- }
-
- _current = _current.getNext();
- }
- return null;
- }
-
- public final void free()
- {
- _current = null;
-
- CellNode node;
- for (int i = 0; i < _mapSize; i++)
- {
- for (int j = 0; j < _mapSize; j++)
- {
- node = _buffer[i][j];
- if (node != null)
- {
- node.free();
- }
- }
- }
-
- _lock.unlock();
- _lastElapsedTime = System.currentTimeMillis() - _timeStamp;
- }
-
- public final long getElapsedTime()
- {
- return _lastElapsedTime;
- }
-
- public final FastList debugPath()
- {
- final FastList result = new FastList<>();
-
- for (CellNode n = _current; n.getParent() != null; n = (CellNode) n.getParent())
- {
- result.add(n);
- n.setCost(-n.getCost());
- }
-
- for (int i = 0; i < _mapSize; i++)
- {
- for (int j = 0; j < _mapSize; j++)
- {
- final CellNode n = _buffer[i][j];
- if ((n == null) || !n.isInUse() || (n.getCost() <= 0))
- {
- continue;
- }
-
- result.add(n);
- }
- }
-
- return result;
- }
-
- private final void getNeighbors()
- {
- if (((NodeLoc) _current.getLoc()).canGoNone())
- {
- return;
- }
-
- final int x = _current.getLoc().getNodeX();
- final int y = _current.getLoc().getNodeY();
- final int z = _current.getLoc().getZ();
-
- CellNode nodeE = null;
- CellNode nodeS = null;
- CellNode nodeW = null;
- CellNode nodeN = null;
-
- // East
- if (((NodeLoc) _current.getLoc()).canGoEast())
- {
- nodeE = addNode(x + 1, y, z, false);
- }
-
- // South
- if (((NodeLoc) _current.getLoc()).canGoSouth())
- {
- nodeS = addNode(x, y + 1, z, false);
- }
-
- // West
- if (((NodeLoc) _current.getLoc()).canGoWest())
- {
- nodeW = addNode(x - 1, y, z, false);
- }
-
- // North
- if (((NodeLoc) _current.getLoc()).canGoNorth())
- {
- nodeN = addNode(x, y - 1, z, false);
- }
-
- if (Config.ADVANCED_DIAGONAL_STRATEGY)
- {
- // SouthEast
- if ((nodeE != null) && (nodeS != null))
- {
- if (((NodeLoc) nodeE.getLoc()).canGoSouth() && ((NodeLoc) nodeS.getLoc()).canGoEast())
- {
- addNode(x + 1, y + 1, z, true);
- }
- }
-
- // SouthWest
- if ((nodeS != null) && (nodeW != null))
- {
- if (((NodeLoc) nodeW.getLoc()).canGoSouth() && ((NodeLoc) nodeS.getLoc()).canGoWest())
- {
- addNode(x - 1, y + 1, z, true);
- }
- }
-
- // NorthEast
- if ((nodeN != null) && (nodeE != null))
- {
- if (((NodeLoc) nodeE.getLoc()).canGoNorth() && ((NodeLoc) nodeN.getLoc()).canGoEast())
- {
- addNode(x + 1, y - 1, z, true);
- }
- }
-
- // NorthWest
- if ((nodeN != null) && (nodeW != null))
- {
- if (((NodeLoc) nodeW.getLoc()).canGoNorth() && ((NodeLoc) nodeN.getLoc()).canGoWest())
- {
- addNode(x - 1, y - 1, z, true);
- }
- }
- }
- }
-
- private final CellNode getNode(int x, int y, int z)
- {
- final int aX = x - _baseX;
- if ((aX < 0) || (aX >= _mapSize))
- {
- return null;
- }
-
- final int aY = y - _baseY;
- if ((aY < 0) || (aY >= _mapSize))
- {
- return null;
- }
-
- CellNode result = _buffer[aX][aY];
- if (result == null)
- {
- result = new CellNode(new NodeLoc(x, y, z));
- _buffer[aX][aY] = result;
- }
- else if (!result.isInUse())
- {
- result.setInUse();
- // reinit node if needed
- if (result.getLoc() != null)
- {
- ((NodeLoc) result.getLoc()).set(x, y, z);
- }
- else
- {
- result.setLoc(new NodeLoc(x, y, z));
- }
- }
-
- return result;
- }
-
- private final CellNode addNode(int x, int y, int z, boolean diagonal)
- {
- final CellNode newNode = getNode(x, y, z);
- if (newNode == null)
- {
- return null;
- }
- if (newNode.getCost() >= 0)
- {
- return newNode;
- }
-
- final int geoZ = newNode.getLoc().getZ();
-
- final int stepZ = Math.abs(geoZ - _current.getLoc().getZ());
- float weight = diagonal ? Config.DIAGONAL_WEIGHT : Config.LOW_WEIGHT;
-
- if (!((NodeLoc) newNode.getLoc()).canGoAll() || (stepZ > 16))
- {
- weight = Config.HIGH_WEIGHT;
- }
- else
- {
- if (isHighWeight(x + 1, y, geoZ))
- {
- weight = Config.MEDIUM_WEIGHT;
- }
- else if (isHighWeight(x - 1, y, geoZ))
- {
- weight = Config.MEDIUM_WEIGHT;
- }
- else if (isHighWeight(x, y + 1, geoZ))
- {
- weight = Config.MEDIUM_WEIGHT;
- }
- else if (isHighWeight(x, y - 1, geoZ))
- {
- weight = Config.MEDIUM_WEIGHT;
- }
- }
-
- newNode.setParent(_current);
- newNode.setCost(getCost(x, y, geoZ, weight));
-
- CellNode node = _current;
- int count = 0;
- while ((node.getNext() != null) && (count < (MAX_ITERATIONS * 4)))
- {
- count++;
- if (node.getNext().getCost() > newNode.getCost())
- {
- // insert node into a chain
- newNode.setNext(node.getNext());
- break;
- }
- node = node.getNext();
- }
- if (count == (MAX_ITERATIONS * 4))
- {
- System.err.println("Pathfinding: too long loop detected, cost:" + newNode.getCost());
- }
-
- node.setNext(newNode); // add last
-
- return newNode;
- }
-
- private final boolean isHighWeight(int x, int y, int z)
- {
- final CellNode result = getNode(x, y, z);
- if (result == null)
- {
- return true;
- }
-
- if (!((NodeLoc) result.getLoc()).canGoAll())
- {
- return true;
- }
- if (Math.abs(result.getLoc().getZ() - z) > 16)
- {
- return true;
- }
-
- return false;
- }
-
- private final double getCost(int x, int y, int z, float weight)
- {
- final int dX = x - _targetX;
- final int dY = y - _targetY;
- final int dZ = z - _targetZ;
- // Math.abs(dx) + Math.abs(dy) + Math.abs(dz) / 16
- double result = Math.sqrt((dX * dX) + (dY * dY) + ((dZ * dZ) / 256));
- if (result > weight)
- {
- result += weight;
- }
-
- if (result > Float.MAX_VALUE)
- {
- result = Float.MAX_VALUE;
- }
-
- return result;
- }
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.l2jmobius.Config;
+
+/**
+ * @author DS Credits to Diamond
+ */
+public class CellNodeBuffer
+{
+ private static final int MAX_ITERATIONS = 3500;
+
+ private final ReentrantLock _lock = new ReentrantLock();
+ private final int _mapSize;
+ private final CellNode[][] _buffer;
+
+ private int _baseX = 0;
+ private int _baseY = 0;
+
+ private int _targetX = 0;
+ private int _targetY = 0;
+ private int _targetZ = 0;
+
+ private long _timeStamp = 0;
+ private long _lastElapsedTime = 0;
+
+ private CellNode _current = null;
+
+ public CellNodeBuffer(int size)
+ {
+ _mapSize = size;
+ _buffer = new CellNode[_mapSize][_mapSize];
+ }
+
+ public final boolean lock()
+ {
+ return _lock.tryLock();
+ }
+
+ public final CellNode findPath(int x, int y, int z, int tx, int ty, int tz)
+ {
+ _timeStamp = System.currentTimeMillis();
+ _baseX = x + ((tx - x - _mapSize) / 2); // middle of the line (x,y) - (tx,ty)
+ _baseY = y + ((ty - y - _mapSize) / 2); // will be in the center of the buffer
+ _targetX = tx;
+ _targetY = ty;
+ _targetZ = tz;
+ _current = getNode(x, y, z);
+ _current.setCost(getCost(x, y, z, Config.HIGH_WEIGHT));
+
+ for (int count = 0; count < MAX_ITERATIONS; count++)
+ {
+ if ((_current.getLoc().getNodeX() == _targetX) && (_current.getLoc().getNodeY() == _targetY) && (Math.abs(_current.getLoc().getZ() - _targetZ) < 64))
+ {
+ return _current; // found
+ }
+
+ getNeighbors();
+ if (_current.getNext() == null)
+ {
+ return null; // no more ways
+ }
+
+ _current = _current.getNext();
+ }
+ return null;
+ }
+
+ public final void free()
+ {
+ _current = null;
+
+ CellNode node;
+ for (int i = 0; i < _mapSize; i++)
+ {
+ for (int j = 0; j < _mapSize; j++)
+ {
+ node = _buffer[i][j];
+ if (node != null)
+ {
+ node.free();
+ }
+ }
+ }
+
+ _lock.unlock();
+ _lastElapsedTime = System.currentTimeMillis() - _timeStamp;
+ }
+
+ public final long getElapsedTime()
+ {
+ return _lastElapsedTime;
+ }
+
+ public final List debugPath()
+ {
+ final List result = new LinkedList<>();
+
+ for (CellNode n = _current; n.getParent() != null; n = (CellNode) n.getParent())
+ {
+ result.add(n);
+ n.setCost(-n.getCost());
+ }
+
+ for (int i = 0; i < _mapSize; i++)
+ {
+ for (int j = 0; j < _mapSize; j++)
+ {
+ final CellNode n = _buffer[i][j];
+ if ((n == null) || !n.isInUse() || (n.getCost() <= 0))
+ {
+ continue;
+ }
+
+ result.add(n);
+ }
+ }
+
+ return result;
+ }
+
+ private void getNeighbors()
+ {
+ if (!_current.getLoc().canGoAll())
+ {
+ return;
+ }
+
+ final int x = _current.getLoc().getNodeX();
+ final int y = _current.getLoc().getNodeY();
+ final int z = _current.getLoc().getZ();
+
+ CellNode nodeE = null;
+ CellNode nodeS = null;
+ CellNode nodeW = null;
+ CellNode nodeN = null;
+
+ // East
+ if (_current.getLoc().canGoEast())
+ {
+ nodeE = addNode(x + 1, y, z, false);
+ }
+
+ // South
+ if (_current.getLoc().canGoSouth())
+ {
+ nodeS = addNode(x, y + 1, z, false);
+ }
+
+ // West
+ if (_current.getLoc().canGoWest())
+ {
+ nodeW = addNode(x - 1, y, z, false);
+ }
+
+ // North
+ if (_current.getLoc().canGoNorth())
+ {
+ nodeN = addNode(x, y - 1, z, false);
+ }
+
+ if (Config.ADVANCED_DIAGONAL_STRATEGY)
+ {
+ // SouthEast
+ if ((nodeE != null) && (nodeS != null))
+ {
+ if (nodeE.getLoc().canGoSouth() && nodeS.getLoc().canGoEast())
+ {
+ addNode(x + 1, y + 1, z, true);
+ }
+ }
+
+ // SouthWest
+ if ((nodeS != null) && (nodeW != null))
+ {
+ if (nodeW.getLoc().canGoSouth() && nodeS.getLoc().canGoWest())
+ {
+ addNode(x - 1, y + 1, z, true);
+ }
+ }
+
+ // NorthEast
+ if ((nodeN != null) && (nodeE != null))
+ {
+ if (nodeE.getLoc().canGoNorth() && nodeN.getLoc().canGoEast())
+ {
+ addNode(x + 1, y - 1, z, true);
+ }
+ }
+
+ // NorthWest
+ if ((nodeN != null) && (nodeW != null))
+ {
+ if (nodeW.getLoc().canGoNorth() && nodeN.getLoc().canGoWest())
+ {
+ addNode(x - 1, y - 1, z, true);
+ }
+ }
+ }
+ }
+
+ private CellNode getNode(int x, int y, int z)
+ {
+ final int aX = x - _baseX;
+ if ((aX < 0) || (aX >= _mapSize))
+ {
+ return null;
+ }
+
+ final int aY = y - _baseY;
+ if ((aY < 0) || (aY >= _mapSize))
+ {
+ return null;
+ }
+
+ CellNode result = _buffer[aX][aY];
+ if (result == null)
+ {
+ result = new CellNode(new NodeLoc(x, y, z));
+ _buffer[aX][aY] = result;
+ }
+ else if (!result.isInUse())
+ {
+ result.setInUse();
+ // reinit node if needed
+ if (result.getLoc() != null)
+ {
+ result.getLoc().set(x, y, z);
+ }
+ else
+ {
+ result.setLoc(new NodeLoc(x, y, z));
+ }
+ }
+
+ return result;
+ }
+
+ private CellNode addNode(int x, int y, int z, boolean diagonal)
+ {
+ final CellNode newNode = getNode(x, y, z);
+ if (newNode == null)
+ {
+ return null;
+ }
+ if (newNode.getCost() >= 0)
+ {
+ return newNode;
+ }
+
+ final int geoZ = newNode.getLoc().getZ();
+
+ final int stepZ = Math.abs(geoZ - _current.getLoc().getZ());
+ float weight = diagonal ? Config.DIAGONAL_WEIGHT : Config.LOW_WEIGHT;
+
+ if (!newNode.getLoc().canGoAll() || (stepZ > 16))
+ {
+ weight = Config.HIGH_WEIGHT;
+ }
+ else if (isHighWeight(x + 1, y, geoZ))
+ {
+ weight = Config.MEDIUM_WEIGHT;
+ }
+ else if (isHighWeight(x - 1, y, geoZ))
+ {
+ weight = Config.MEDIUM_WEIGHT;
+ }
+ else if (isHighWeight(x, y + 1, geoZ))
+ {
+ weight = Config.MEDIUM_WEIGHT;
+ }
+ else if (isHighWeight(x, y - 1, geoZ))
+ {
+ weight = Config.MEDIUM_WEIGHT;
+ }
+
+ newNode.setParent(_current);
+ newNode.setCost(getCost(x, y, geoZ, weight));
+
+ CellNode node = _current;
+ int count = 0;
+ while ((node.getNext() != null) && (count < (MAX_ITERATIONS * 4)))
+ {
+ count++;
+ if (node.getNext().getCost() > newNode.getCost())
+ {
+ // insert node into a chain
+ newNode.setNext(node.getNext());
+ break;
+ }
+ node = node.getNext();
+ }
+ if (count == (MAX_ITERATIONS * 4))
+ {
+ System.err.println("Pathfinding: too long loop detected, cost:" + newNode.getCost());
+ }
+
+ node.setNext(newNode); // add last
+
+ return newNode;
+ }
+
+ private boolean isHighWeight(int x, int y, int z)
+ {
+ final CellNode result = getNode(x, y, z);
+ if (result == null)
+ {
+ return true;
+ }
+
+ if (!result.getLoc().canGoAll())
+ {
+ return true;
+ }
+ if (Math.abs(result.getLoc().getZ() - z) > 16)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private double getCost(int x, int y, int z, float weight)
+ {
+ final int dX = x - _targetX;
+ final int dY = y - _targetY;
+ final int dZ = z - _targetZ;
+ // Math.abs(dx) + Math.abs(dy) + Math.abs(dz) / 16
+ double result = Math.sqrt((dX * dX) + (dY * dY) + ((dZ * dZ) / 256.0));
+ if (result > weight)
+ {
+ result += weight;
+ }
+
+ if (result > Float.MAX_VALUE)
+ {
+ result = Float.MAX_VALUE;
+ }
+
+ return result;
+ }
}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellPathFinding.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellPathFinding.java
similarity index 69%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellPathFinding.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellPathFinding.java
index df28c26345..aacee44b2d 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/CellPathFinding.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/CellPathFinding.java
@@ -1,413 +1,439 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.cellnodes;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
-import com.l2jmobius.gameserver.idfactory.IdFactory;
-import com.l2jmobius.gameserver.model.L2ItemInstance;
-import com.l2jmobius.gameserver.pathfinding.AbstractNode;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-import com.l2jmobius.gameserver.pathfinding.PathFinding;
-import com.l2jmobius.util.StringUtil;
-
-import javolution.util.FastList;
-
-/**
- * @author Sami, DS Credits to Diamond
- */
-public class CellPathFinding extends PathFinding
-{
- private static final Logger _log = Logger.getLogger(CellPathFinding.class.getName());
- private BufferInfo[] _allBuffers;
- private int _findSuccess = 0;
- private int _findFails = 0;
- private int _postFilterUses = 0;
- private int _postFilterPlayableUses = 0;
- private int _postFilterPasses = 0;
- private long _postFilterElapsed = 0;
-
- private FastList _debugItems = null;
-
- private static CellPathFinding _instance;
-
- public static CellPathFinding getInstance()
- {
- if (_instance == null)
- {
- _instance = new CellPathFinding();
- }
- return _instance;
- }
-
- private CellPathFinding()
- {
- try
- {
- final String[] array = Config.PATHFIND_BUFFERS.split(";");
-
- _allBuffers = new BufferInfo[array.length];
-
- String buf;
- String[] args;
- for (int i = 0; i < array.length; i++)
- {
- buf = array[i];
- args = buf.split("x");
- if (args.length != 2)
- {
- throw new Exception("Invalid buffer definition: " + buf);
- }
-
- _allBuffers[i] = new BufferInfo(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
- }
- }
- catch (final Exception e)
- {
- _log.warning("CellPathFinding: Problem during buffer init: " + e.getMessage());
- throw new Error("CellPathFinding: load aborted");
- }
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.PathFinding#pathNodesExist(short)
- */
- @Override
- public boolean pathNodesExist(short regionoffset)
- {
- return false;
- }
-
- @Override
- public List findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
- {
- final int gx = GeoData.getInstance().getGeoX(x);
- final int gy = GeoData.getInstance().getGeoY(y);
- if (!GeoData.getInstance().hasGeo(x, y))
- {
- return null;
- }
- final int gz = GeoData.getInstance().getHeight(x, y, z);
- final int gtx = GeoData.getInstance().getGeoX(tx);
- final int gty = GeoData.getInstance().getGeoY(ty);
- if (!GeoData.getInstance().hasGeo(tx, ty))
- {
- return null;
- }
- final int gtz = GeoData.getInstance().getHeight(tx, ty, tz);
- final CellNodeBuffer buffer = alloc(64 + (2 * Math.max(Math.abs(gx - gtx), Math.abs(gy - gty))), playable);
- if (buffer == null)
- {
- return null;
- }
-
- final boolean debug = playable && Config.DEBUG_PATH;
-
- if (debug)
- {
- if (_debugItems == null)
- {
- _debugItems = new FastList<>();
- }
- else
- {
- for (final L2ItemInstance item : _debugItems)
- {
- if (item == null)
- {
- continue;
- }
- item.decayMe();
- }
-
- _debugItems.clear();
- }
- }
-
- FastList path = null;
- try
- {
- final CellNode result = buffer.findPath(gx, gy, gz, gtx, gty, gtz);
-
- if (debug)
- {
- for (final CellNode n : buffer.debugPath())
- {
- if (n.getCost() < 0)
- {
- dropDebugItem(1831, (int) (-n.getCost() * 10), n.getLoc());
- }
- else
- {
- dropDebugItem(57, (int) (n.getCost() * 10), n.getLoc());
- }
- }
- }
-
- if (result == null)
- {
- _findFails++;
- return null;
- }
-
- path = constructPath(result);
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- return null;
- }
- finally
- {
- buffer.free();
- }
-
- if ((path.size() < 3) || (Config.MAX_POSTFILTER_PASSES <= 0))
- {
- _findSuccess++;
- return path;
- }
-
- final long timeStamp = System.currentTimeMillis();
- _postFilterUses++;
- if (playable)
- {
- _postFilterPlayableUses++;
- }
-
- int currentX, currentY, currentZ;
- ListIterator middlePoint, endPoint;
- AbstractNodeLoc locMiddle, locEnd;
- boolean remove;
- int pass = 0;
- do
- {
- pass++;
- _postFilterPasses++;
-
- remove = false;
- middlePoint = path.listIterator();
- endPoint = path.listIterator(1);
- locEnd = null;
- currentX = x;
- currentY = y;
- currentZ = z;
-
- while (endPoint.hasNext())
- {
- locEnd = endPoint.next();
- locMiddle = middlePoint.next();
- if (GeoData.getInstance().canMove(currentX, currentY, currentZ, locEnd.getX(), locEnd.getY(), locEnd.getZ()))
- {
- middlePoint.remove();
- remove = true;
- if (debug)
- {
- dropDebugItem(735, 1, locMiddle);
- }
- }
- else
- {
- currentX = locMiddle.getX();
- currentY = locMiddle.getY();
- currentZ = locMiddle.getZ();
- }
- }
- }
- // only one postfilter pass for AI
- while (playable && remove && (path.size() > 2) && (pass < Config.MAX_POSTFILTER_PASSES));
-
- if (debug)
- {
- middlePoint = path.listIterator();
- while (middlePoint.hasNext())
- {
- locMiddle = middlePoint.next();
- dropDebugItem(65, 1, locMiddle);
- }
- }
-
- _findSuccess++;
- _postFilterElapsed += System.currentTimeMillis() - timeStamp;
- return path;
- }
-
- private FastList constructPath(AbstractNode node)
- {
- final FastList path = new FastList<>();
- int previousDirectionX = Integer.MIN_VALUE;
- int previousDirectionY = Integer.MIN_VALUE;
- int directionX, directionY;
-
- while (node.getParent() != null)
- {
- if (!Config.ADVANCED_DIAGONAL_STRATEGY && (node.getParent().getParent() != null))
- {
- final int tmpX = node.getLoc().getNodeX() - node.getParent().getParent().getLoc().getNodeX();
- final int tmpY = node.getLoc().getNodeY() - node.getParent().getParent().getLoc().getNodeY();
- if (Math.abs(tmpX) == Math.abs(tmpY))
- {
- directionX = tmpX;
- directionY = tmpY;
- }
- else
- {
- directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
- directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
- }
- }
- else
- {
- directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
- directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
- }
-
- // only add a new route point if moving direction changes
- if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
- {
- previousDirectionX = directionX;
- previousDirectionY = directionY;
-
- path.addFirst(node.getLoc());
- node.setLoc(null);
- }
-
- node = node.getParent();
- }
-
- return path;
- }
-
- private final CellNodeBuffer alloc(int size, boolean playable)
- {
- CellNodeBuffer current = null;
- for (final BufferInfo i : _allBuffers)
- {
- if (i.mapSize >= size)
- {
- for (final CellNodeBuffer buf : i.bufs)
- {
- if (buf.lock())
- {
- i.uses++;
- if (playable)
- {
- i.playableUses++;
- }
- i.elapsed += buf.getElapsedTime();
- current = buf;
- break;
- }
- }
- if (current != null)
- {
- break;
- }
-
- // not found, allocate temporary buffer
- current = new CellNodeBuffer(i.mapSize);
- current.lock();
- if (i.bufs.size() < i.count)
- {
- i.bufs.add(current);
- i.uses++;
- if (playable)
- {
- i.playableUses++;
- }
- break;
- }
-
- i.overflows++;
- if (playable)
- {
- i.playableOverflows++;
- }
- }
- }
-
- return current;
- }
-
- private final void dropDebugItem(int itemId, int num, AbstractNodeLoc loc)
- {
- final L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
- item.setCount(num);
- item.spawnMe(loc.getX(), loc.getY(), loc.getZ());
- _debugItems.add(item);
- }
-
- private static final class BufferInfo
- {
- final int mapSize;
- final int count;
- ArrayList bufs;
- int uses = 0;
- int playableUses = 0;
- int overflows = 0;
- int playableOverflows = 0;
- long elapsed = 0;
-
- public BufferInfo(int size, int cnt)
- {
- mapSize = size;
- count = cnt;
- bufs = new ArrayList<>(count);
- }
-
- @Override
- public String toString()
- {
- final StringBuilder stat = new StringBuilder(100);
- StringUtil.append(stat, String.valueOf(mapSize), "x", String.valueOf(mapSize), " num:", String.valueOf(bufs.size()), "/", String.valueOf(count), " uses:", String.valueOf(uses), "/", String.valueOf(playableUses));
- if (uses > 0)
- {
- StringUtil.append(stat, " total/avg(ms):", String.valueOf(elapsed), "/", String.format("%1.2f", (double) elapsed / uses));
- }
-
- StringUtil.append(stat, " ovf:", String.valueOf(overflows), "/", String.valueOf(playableOverflows));
-
- return stat.toString();
- }
- }
-
- @Override
- public String[] getStat()
- {
- final String[] result = new String[_allBuffers.length + 1];
- for (int i = 0; i < _allBuffers.length; i++)
- {
- result[i] = _allBuffers[i].toString();
- }
-
- final StringBuilder stat = new StringBuilder(100);
- StringUtil.append(stat, "LOS postfilter uses:", String.valueOf(_postFilterUses), "/", String.valueOf(_postFilterPlayableUses));
- if (_postFilterUses > 0)
- {
- StringUtil.append(stat, " total/avg(ms):", String.valueOf(_postFilterElapsed), "/", String.format("%1.2f", (double) _postFilterElapsed / _postFilterUses), " passes total/avg:", String.valueOf(_postFilterPasses), "/", String.format("%1.1f", (double) _postFilterPasses / _postFilterUses), "\r\n");
- }
- StringUtil.append(stat, "Pathfind success/fail:", String.valueOf(_findSuccess), "/", String.valueOf(_findFails));
- result[result.length - 1] = stat.toString();
-
- return result;
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.geodata.GeoData;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
+import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
+import com.l2jmobius.gameserver.idfactory.IdFactory;
+import com.l2jmobius.gameserver.model.Inventory;
+import com.l2jmobius.gameserver.model.L2ItemInstance;
+
+/**
+ * @author Sami, DS Credits to Diamond
+ */
+public class CellPathFinding extends PathFinding
+{
+ private static final Logger _log = Logger.getLogger(CellPathFinding.class.getName());
+ private BufferInfo[] _allBuffers;
+ private int _findSuccess = 0;
+ private int _findFails = 0;
+ private int _postFilterUses = 0;
+ private int _postFilterPlayableUses = 0;
+ private int _postFilterPasses = 0;
+ private long _postFilterElapsed = 0;
+
+ private List _debugItems = null;
+
+ public static CellPathFinding getInstance()
+ {
+ return SingletonHolder._instance;
+ }
+
+ protected CellPathFinding()
+ {
+ try
+ {
+ final String[] array = Config.PATHFIND_BUFFERS.split(";");
+
+ _allBuffers = new BufferInfo[array.length];
+
+ String buf;
+ String[] args;
+ for (int i = 0; i < array.length; i++)
+ {
+ buf = array[i];
+ args = buf.split("x");
+ if (args.length != 2)
+ {
+ throw new Exception("Invalid buffer definition: " + buf);
+ }
+
+ _allBuffers[i] = new BufferInfo(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
+ }
+ }
+ catch (Exception e)
+ {
+ _log.log(Level.WARNING, "CellPathFinding: Problem during buffer init: " + e.getMessage(), e);
+ throw new Error("CellPathFinding: load aborted");
+ }
+ }
+
+ @Override
+ public boolean pathNodesExist(short regionoffset)
+ {
+ return false;
+ }
+
+ @Override
+ public List findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
+ {
+ final int gx = GeoData.getInstance().getGeoX(x);
+ final int gy = GeoData.getInstance().getGeoY(y);
+ if (!GeoData.getInstance().hasGeo(x, y))
+ {
+ return null;
+ }
+ final int gz = GeoData.getInstance().getHeight(x, y, z);
+ final int gtx = GeoData.getInstance().getGeoX(tx);
+ final int gty = GeoData.getInstance().getGeoY(ty);
+ if (!GeoData.getInstance().hasGeo(tx, ty))
+ {
+ return null;
+ }
+ final int gtz = GeoData.getInstance().getHeight(tx, ty, tz);
+ final CellNodeBuffer buffer = alloc(64 + (2 * Math.max(Math.abs(gx - gtx), Math.abs(gy - gty))), playable);
+ if (buffer == null)
+ {
+ return null;
+ }
+
+ final boolean debug = playable && Config.DEBUG_PATH;
+
+ if (debug)
+ {
+ if (_debugItems == null)
+ {
+ _debugItems = new CopyOnWriteArrayList<>();
+ }
+ else
+ {
+ for (L2ItemInstance item : _debugItems)
+ {
+ if (item == null)
+ {
+ continue;
+ }
+ item.decayMe();
+ }
+
+ _debugItems.clear();
+ }
+ }
+
+ List path = null;
+ try
+ {
+ final CellNode result = buffer.findPath(gx, gy, gz, gtx, gty, gtz);
+
+ if (debug)
+ {
+ for (CellNode n : buffer.debugPath())
+ {
+ if (n.getCost() < 0)
+ {
+ dropDebugItem(1831, (int) (-n.getCost() * 10), n.getLoc());
+ }
+ else
+ {
+ // known nodes
+ dropDebugItem(Inventory.ADENA_ID, (int) (n.getCost() * 10), n.getLoc());
+ }
+ }
+ }
+
+ if (result == null)
+ {
+ _findFails++;
+ return null;
+ }
+
+ path = constructPath(result);
+ }
+ catch (Exception e)
+ {
+ _log.log(Level.WARNING, "", e);
+ return null;
+ }
+ finally
+ {
+ buffer.free();
+ }
+
+ if ((path.size() < 3) || (Config.MAX_POSTFILTER_PASSES <= 0))
+ {
+ _findSuccess++;
+ return path;
+ }
+
+ final long timeStamp = System.currentTimeMillis();
+ _postFilterUses++;
+ if (playable)
+ {
+ _postFilterPlayableUses++;
+ }
+
+ int currentX, currentY, currentZ;
+ ListIterator middlePoint;
+ boolean remove;
+ int pass = 0;
+ do
+ {
+ pass++;
+ _postFilterPasses++;
+
+ remove = false;
+ middlePoint = path.listIterator();
+ currentX = x;
+ currentY = y;
+ currentZ = z;
+
+ while (middlePoint.hasNext())
+ {
+ final AbstractNodeLoc locMiddle = middlePoint.next();
+ if (!middlePoint.hasNext())
+ {
+ break;
+ }
+
+ final AbstractNodeLoc locEnd = path.get(middlePoint.nextIndex());
+ if (GeoData.getInstance().canMove(currentX, currentY, currentZ, locEnd.getX(), locEnd.getY(), locEnd.getZ()))
+ {
+ middlePoint.remove();
+ remove = true;
+ if (debug)
+ {
+ dropDebugItem(735, 1, locMiddle);
+ }
+ }
+ else
+ {
+ currentX = locMiddle.getX();
+ currentY = locMiddle.getY();
+ currentZ = locMiddle.getZ();
+ }
+ }
+ }
+ // only one postfilter pass for AI
+ while (playable && remove && (path.size() > 2) && (pass < Config.MAX_POSTFILTER_PASSES));
+
+ if (debug)
+ {
+ path.forEach(n -> dropDebugItem(65, 1, n));
+ }
+
+ _findSuccess++;
+ _postFilterElapsed += System.currentTimeMillis() - timeStamp;
+ return path;
+ }
+
+ private List constructPath(AbstractNode node)
+ {
+ final LinkedList path = new LinkedList<>();
+ int previousDirectionX = Integer.MIN_VALUE;
+ int previousDirectionY = Integer.MIN_VALUE;
+ int directionX, directionY;
+
+ while (node.getParent() != null)
+ {
+ if (!Config.ADVANCED_DIAGONAL_STRATEGY && (node.getParent().getParent() != null))
+ {
+ final int tmpX = node.getLoc().getNodeX() - node.getParent().getParent().getLoc().getNodeX();
+ final int tmpY = node.getLoc().getNodeY() - node.getParent().getParent().getLoc().getNodeY();
+ if (Math.abs(tmpX) == Math.abs(tmpY))
+ {
+ directionX = tmpX;
+ directionY = tmpY;
+ }
+ else
+ {
+ directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
+ directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
+ }
+ }
+ else
+ {
+ directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
+ directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
+ }
+
+ // only add a new route point if moving direction changes
+ if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
+ {
+ previousDirectionX = directionX;
+ previousDirectionY = directionY;
+
+ path.addFirst(node.getLoc());
+ node.setLoc(null);
+ }
+
+ node = node.getParent();
+ }
+
+ return path;
+ }
+
+ private CellNodeBuffer alloc(int size, boolean playable)
+ {
+ CellNodeBuffer current = null;
+ for (BufferInfo i : _allBuffers)
+ {
+ if (i.mapSize >= size)
+ {
+ for (CellNodeBuffer buf : i.bufs)
+ {
+ if (buf.lock())
+ {
+ i.uses++;
+ if (playable)
+ {
+ i.playableUses++;
+ }
+ i.elapsed += buf.getElapsedTime();
+ current = buf;
+ break;
+ }
+ }
+ if (current != null)
+ {
+ break;
+ }
+
+ // not found, allocate temporary buffer
+ current = new CellNodeBuffer(i.mapSize);
+ current.lock();
+ if (i.bufs.size() < i.count)
+ {
+ i.bufs.add(current);
+ i.uses++;
+ if (playable)
+ {
+ i.playableUses++;
+ }
+ break;
+ }
+
+ i.overflows++;
+ if (playable)
+ {
+ i.playableOverflows++;
+ // System.err.println("Overflow, size requested: " + size + " playable:"+playable);
+ }
+ }
+ }
+
+ return current;
+ }
+
+ private void dropDebugItem(int itemId, int num, AbstractNodeLoc loc)
+ {
+ final L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
+ item.setCount(num);
+ item.spawnMe(loc.getX(), loc.getY(), loc.getZ());
+ _debugItems.add(item);
+ }
+
+ private static final class BufferInfo
+ {
+ final int mapSize;
+ final int count;
+ ArrayList bufs;
+ int uses = 0;
+ int playableUses = 0;
+ int overflows = 0;
+ int playableOverflows = 0;
+ long elapsed = 0;
+
+ public BufferInfo(int size, int cnt)
+ {
+ mapSize = size;
+ count = cnt;
+ bufs = new ArrayList<>(count);
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder(100);
+ sb.append(mapSize);
+ sb.append("x");
+ sb.append(mapSize);
+ sb.append(" num:");
+ sb.append(bufs.size());
+ sb.append("/");
+ sb.append(count);
+ sb.append(" uses:");
+ sb.append(uses);
+ sb.append("/");
+ sb.append(playableUses);
+ if (uses > 0)
+ {
+ sb.append(" total/avg(ms):");
+ sb.append(elapsed);
+ sb.append("/");
+ sb.append(String.format("%1.2f", (double) elapsed / uses));
+ }
+
+ sb.append(" ovf:");
+ sb.append(overflows);
+ sb.append("/");
+ sb.append(playableOverflows);
+
+ return sb.toString();
+ }
+ }
+
+ @Override
+ public String[] getStat()
+ {
+ final String[] result = new String[_allBuffers.length + 1];
+ for (int i = 0; i < _allBuffers.length; i++)
+ {
+ result[i] = _allBuffers[i].toString();
+ }
+
+ final StringBuilder sb = new StringBuilder(128);
+ sb.append("LOS postfilter uses:");
+ sb.append(_postFilterUses);
+ sb.append("/");
+ sb.append(_postFilterPlayableUses);
+ if (_postFilterUses > 0)
+ {
+ sb.append(" total/avg(ms):");
+ sb.append(_postFilterElapsed);
+ sb.append("/");
+ sb.append(String.format("%1.2f", (double) _postFilterElapsed / _postFilterUses));
+ sb.append(" passes total/avg:");
+ sb.append(_postFilterPasses);
+ sb.append("/");
+ sb.append(String.format("%1.1f", (double) _postFilterPasses / _postFilterUses));
+ sb.append(Config.EOL);
+ }
+ sb.append("Pathfind success/fail:");
+ sb.append(_findSuccess);
+ sb.append("/");
+ sb.append(_findFails);
+ result[result.length - 1] = sb.toString();
+
+ return result;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final CellPathFinding _instance = new CellPathFinding();
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/NodeLoc.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/NodeLoc.java
similarity index 63%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/NodeLoc.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/NodeLoc.java
index f837412e63..f0720ae1ae 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/cellnodes/NodeLoc.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/cellnodes/NodeLoc.java
@@ -1,215 +1,184 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.cellnodes;
-
-import com.l2jmobius.gameserver.GeoData;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-import com.l2jserver.gameserver.geoengine.Direction;
-
-/**
- * @author -Nemesiss-, FBIagent
- */
-public class NodeLoc extends AbstractNodeLoc
-{
- private int _x;
- private int _y;
- private boolean _goNorth;
- private boolean _goEast;
- private boolean _goSouth;
- private boolean _goWest;
- private int _geoHeight;
-
- public NodeLoc(int x, int y, int z)
- {
- set(x, y, z);
- }
-
- public void set(int x, int y, int z)
- {
- _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);
- _geoHeight = GeoData.getInstance().getNearestZ(x, y, z);
- }
-
- public boolean canGoNorth()
- {
- return _goNorth;
- }
-
- public boolean canGoEast()
- {
- return _goEast;
- }
-
- public boolean canGoSouth()
- {
- return _goSouth;
- }
-
- public boolean canGoWest()
- {
- return _goWest;
- }
-
- public boolean canGoNone()
- {
- return !canGoNorth() && !canGoEast() && !canGoSouth() && !canGoWest();
- }
-
- public boolean canGoAll()
- {
- return canGoNorth() && canGoEast() && canGoSouth() && canGoWest();
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getX()
- */
- @Override
- public int getX()
- {
- return GeoData.getInstance().getWorldX(_x);
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getY()
- */
- @Override
- public int getY()
- {
- return GeoData.getInstance().getWorldY(_y);
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getZ()
- */
- @Override
- public int getZ()
- {
- return _geoHeight;
- }
-
- @Override
- public void setZ(short z)
- {
- // do nothing here
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getNodeX()
- */
- @Override
- public int getNodeX()
- {
- return _x;
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getNodeY()
- */
- @Override
- public int getNodeY()
- {
- return _y;
- }
-
- /**
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + _x;
- result = (prime * result) + _y;
-
- byte nswe = 0;
- if (canGoNorth())
- {
- nswe |= 1;
- }
- if (canGoEast())
- {
- nswe |= 1 << 1;
- }
- if (canGoSouth())
- {
- nswe |= 1 << 2;
- }
- if (canGoEast())
- {
- nswe |= 1 << 3;
- }
-
- result = (prime * result) + (((_geoHeight & 0xFFFF) << 1) | nswe);
- return result;
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof NodeLoc))
- {
- return false;
- }
- final NodeLoc other = (NodeLoc) obj;
- if (_x != other._x)
- {
- return false;
- }
- if (_y != other._y)
- {
- return false;
- }
- if (_goNorth != other._goNorth)
- {
- return false;
- }
- if (_goEast != other._goEast)
- {
- return false;
- }
- if (_goSouth != other._goSouth)
- {
- return false;
- }
- if (_goWest != other._goWest)
- {
- return false;
- }
- if (_geoHeight != other._geoHeight)
- {
- return false;
- }
- return true;
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
+
+import com.l2jmobius.gameserver.geodata.GeoData;
+import com.l2jmobius.gameserver.geodata.geodriver.Cell;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
+
+/**
+ * @author -Nemesiss-, HorridoJoho
+ */
+public class NodeLoc extends AbstractNodeLoc
+{
+ private int _x;
+ private int _y;
+ private boolean _goNorth;
+ private boolean _goEast;
+ private boolean _goSouth;
+ private boolean _goWest;
+ private int _geoHeight;
+
+ public NodeLoc(int x, int y, int z)
+ {
+ set(x, y, z);
+ }
+
+ public void set(int x, int y, int z)
+ {
+ _x = x;
+ _y = y;
+ _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);
+ }
+
+ public boolean canGoNorth()
+ {
+ return _goNorth;
+ }
+
+ public boolean canGoEast()
+ {
+ return _goEast;
+ }
+
+ public boolean canGoSouth()
+ {
+ return _goSouth;
+ }
+
+ public boolean canGoWest()
+ {
+ return _goWest;
+ }
+
+ public boolean canGoAll()
+ {
+ return canGoNorth() && canGoEast() && canGoSouth() && canGoWest();
+ }
+
+ @Override
+ public int getX()
+ {
+ return GeoData.getInstance().getWorldX(_x);
+ }
+
+ @Override
+ public int getY()
+ {
+ return GeoData.getInstance().getWorldY(_y);
+ }
+
+ @Override
+ public int getZ()
+ {
+ return _geoHeight;
+ }
+
+ @Override
+ public int getNodeX()
+ {
+ return _x;
+ }
+
+ @Override
+ public int getNodeY()
+ {
+ return _y;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + _x;
+ result = (prime * result) + _y;
+
+ int nswe = 0;
+ if (canGoNorth())
+ {
+ nswe |= Cell.NSWE_NORTH;
+ }
+ if (canGoEast())
+ {
+ nswe |= Cell.NSWE_EAST;
+ }
+ if (canGoSouth())
+ {
+ nswe |= Cell.NSWE_SOUTH;
+ }
+ if (canGoWest())
+ {
+ nswe |= Cell.NSWE_WEST;
+ }
+
+ result = (prime * result) + (((_geoHeight & 0xFFFF) << 1) | nswe);
+ return result;
+ // return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof NodeLoc))
+ {
+ return false;
+ }
+ final NodeLoc other = (NodeLoc) obj;
+ if (_x != other._x)
+ {
+ return false;
+ }
+ if (_y != other._y)
+ {
+ return false;
+ }
+ if (_goNorth != other._goNorth)
+ {
+ return false;
+ }
+ if (_goEast != other._goEast)
+ {
+ return false;
+ }
+ if (_goSouth != other._goSouth)
+ {
+ return false;
+ }
+ if (_goWest != other._goWest)
+ {
+ return false;
+ }
+ if (_geoHeight != other._geoHeight)
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoNode.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoNode.java
similarity index 78%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoNode.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoNode.java
index 5a933e26f4..e9461b122a 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoNode.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoNode.java
@@ -1,63 +1,62 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.geonodes;
-
-import com.l2jmobius.gameserver.pathfinding.AbstractNode;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-
-/**
- * @author -Nemesiss-
- */
-public class GeoNode extends AbstractNode
-{
- private final int _neighborsIdx;
- private short _cost;
- private GeoNode[] _neighbors;
-
- public GeoNode(AbstractNodeLoc Loc, int Neighbors_idx)
- {
- super(Loc);
- _neighborsIdx = Neighbors_idx;
- }
-
- public short getCost()
- {
- return _cost;
- }
-
- public void setCost(int cost)
- {
- _cost = (short) cost;
- }
-
- public GeoNode[] getNeighbors()
- {
- return _neighbors;
- }
-
- public void attachNeighbors()
- {
- if (getLoc() == null)
- {
- _neighbors = null;
- }
- else
- {
- _neighbors = GeoPathFinding.getInstance().readNeighbors(this, _neighborsIdx);
- }
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.geonodes;
+
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
+
+/**
+ * @author -Nemesiss-
+ */
+public class GeoNode extends AbstractNode
+{
+ private final int _neighborsIdx;
+ private short _cost;
+ private GeoNode[] _neighbors;
+
+ public GeoNode(GeoNodeLoc Loc, int Neighbors_idx)
+ {
+ super(Loc);
+ _neighborsIdx = Neighbors_idx;
+ }
+
+ public short getCost()
+ {
+ return _cost;
+ }
+
+ public void setCost(int cost)
+ {
+ _cost = (short) cost;
+ }
+
+ public GeoNode[] getNeighbors()
+ {
+ return _neighbors;
+ }
+
+ public void attachNeighbors()
+ {
+ if (getLoc() == null)
+ {
+ _neighbors = null;
+ }
+ else
+ {
+ _neighbors = GeoPathFinding.getInstance().readNeighbors(this, _neighborsIdx);
+ }
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoNodeLoc.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoNodeLoc.java
similarity index 74%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoNodeLoc.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoNodeLoc.java
index f63e92de85..3721b3a75e 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoNodeLoc.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoNodeLoc.java
@@ -1,130 +1,109 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.geonodes;
-
-import com.l2jmobius.gameserver.model.L2World;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-
-/**
- * @author -Nemesiss-
- */
-public class GeoNodeLoc extends AbstractNodeLoc
-{
- private final short _x;
- private final short _y;
- private final short _z;
-
- public GeoNodeLoc(short x, short y, short z)
- {
- _x = x;
- _y = y;
- _z = z;
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getX()
- */
- @Override
- public int getX()
- {
- return L2World.MAP_MIN_X + (_x * 128) + 48;
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getY()
- */
- @Override
- public int getY()
- {
- return L2World.MAP_MIN_Y + (_y * 128) + 48;
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getZ()
- */
- @Override
- public int getZ()
- {
- return _z;
- }
-
- @Override
- public void setZ(short z)
- {
- // Overriden
- }
-
- @Override
- public int getNodeX()
- {
- return _x;
- }
-
- @Override
- public int getNodeY()
- {
- return _y;
- }
-
- /**
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + _x;
- result = (prime * result) + _y;
- result = (prime * result) + _z;
- return result;
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof GeoNodeLoc))
- {
- return false;
- }
- final GeoNodeLoc other = (GeoNodeLoc) obj;
- if (_x != other._x)
- {
- return false;
- }
- if (_y != other._y)
- {
- return false;
- }
- if (_z != other._z)
- {
- return false;
- }
- return true;
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.geonodes;
+
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
+import com.l2jmobius.gameserver.model.L2World;
+
+/**
+ * @author -Nemesiss-
+ */
+public class GeoNodeLoc extends AbstractNodeLoc
+{
+ private final short _x;
+ private final short _y;
+ private final short _z;
+
+ public GeoNodeLoc(short x, short y, short z)
+ {
+ _x = x;
+ _y = y;
+ _z = z;
+ }
+
+ @Override
+ public int getX()
+ {
+ return L2World.MAP_MIN_X + (_x * 128) + 48;
+ }
+
+ @Override
+ public int getY()
+ {
+ return L2World.MAP_MIN_Y + (_y * 128) + 48;
+ }
+
+ @Override
+ public int getZ()
+ {
+ return _z;
+ }
+
+ @Override
+ public int getNodeX()
+ {
+ return _x;
+ }
+
+ @Override
+ public int getNodeY()
+ {
+ return _y;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + _x;
+ result = (prime * result) + _y;
+ result = (prime * result) + _z;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof GeoNodeLoc))
+ {
+ return false;
+ }
+ final GeoNodeLoc other = (GeoNodeLoc) obj;
+ if (_x != other._x)
+ {
+ return false;
+ }
+ if (_y != other._y)
+ {
+ return false;
+ }
+ if (_z != other._z)
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoPathFinding.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoPathFinding.java
similarity index 71%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoPathFinding.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoPathFinding.java
index c0f5a43d16..c6a4ca3ab7 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/geonodes/GeoPathFinding.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/geonodes/GeoPathFinding.java
@@ -1,470 +1,469 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.geonodes;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.LineNumberReader;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
-import com.l2jmobius.gameserver.model.L2World;
-import com.l2jmobius.gameserver.model.Location;
-import com.l2jmobius.gameserver.pathfinding.AbstractNode;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-import com.l2jmobius.gameserver.pathfinding.PathFinding;
-import com.l2jmobius.gameserver.pathfinding.utils.FastNodeList;
-
-import javolution.util.FastList;
-import javolution.util.FastMap;
-
-/**
- * @author -Nemesiss-
- */
-public class GeoPathFinding extends PathFinding
-{
- private static Logger _log = Logger.getLogger(GeoPathFinding.class.getName());
- private static GeoPathFinding _instance;
- private static Map pathNodes = new FastMap<>();
- private static Map pathNodes_index = new FastMap<>();
-
- public static GeoPathFinding getInstance()
- {
- if (_instance == null)
- {
- _instance = new GeoPathFinding();
- }
- return _instance;
- }
-
- /**
- * @see com.l2jmobius.gameserver.pathfinding.PathFinding#pathNodesExist(short)
- */
- @Override
- public boolean pathNodesExist(short regionoffset)
- {
- return pathNodes_index.containsKey(regionoffset);
- }
-
- @Override
- public List findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
- {
- final int gx = (x - L2World.MAP_MIN_X) >> 4;
- final int gy = (y - L2World.MAP_MIN_Y) >> 4;
- final short gz = (short) z;
- final int gtx = (tx - L2World.MAP_MIN_X) >> 4;
- final int gty = (ty - L2World.MAP_MIN_Y) >> 4;
- final short gtz = (short) tz;
-
- final GeoNode start = readNode(gx, gy, gz);
- final GeoNode end = readNode(gtx, gty, gtz);
-
- if ((start == null) || (end == null))
- {
- return null;
- }
- if (Math.abs(start.getLoc().getZ() - z) > 55)
- {
- return null; // not correct layer
- }
- if (Math.abs(end.getLoc().getZ() - tz) > 55)
- {
- return null; // not correct layer
- }
- if (start == end)
- {
- return null;
- }
- Location temp = GeoData.getInstance().moveCheck(x, y, z, start.getLoc().getX(), start.getLoc().getY(), start.getLoc().getZ());
- if ((temp.getX() != start.getLoc().getX()) || (temp.getY() != start.getLoc().getY()))
- {
- return null; // cannot reach closest...
- }
-
- temp = GeoData.getInstance().moveCheck(tx, ty, tz, end.getLoc().getX(), end.getLoc().getY(), end.getLoc().getZ());
- if ((temp.getX() != end.getLoc().getX()) || (temp.getY() != end.getLoc().getY()))
- {
- return null; // cannot reach closest...
- }
-
- return searchByClosest2(start, end);
- }
-
- public List searchByClosest2(GeoNode start, GeoNode end)
- {
- // Always continues checking from the closest to target non-blocked
- // node from to_visit list. There's extra length in path if needed
- // to go backwards/sideways but when moving generally forwards, this is extra fast
- // and accurate. And can reach insane distances (try it with 800 nodes..).
- // Minimum required node count would be around 300-400.
- // Generally returns a bit (only a bit) more intelligent looking routes than
- // the basic version. Not a true distance image (which would increase CPU
- // load) level of intelligence though.
-
- // List of Visited Nodes
- final FastNodeList visited = new FastNodeList(550);
-
- // List of Nodes to Visit
- final LinkedList to_visit = new LinkedList<>();
- to_visit.add(start);
- final int targetX = end.getLoc().getNodeX();
- final int targetY = end.getLoc().getNodeY();
-
- int dx, dy;
- boolean added;
- int i = 0;
- while (i < 550)
- {
- GeoNode node;
- try
- {
- node = to_visit.removeFirst();
- }
- catch (final Exception e)
- {
- // No Path found
- return null;
- }
-
- if (node.equals(end))
- {
- return constructPath2(node);
- }
-
- i++;
- visited.add(node);
- node.attachNeighbors();
- final GeoNode[] neighbors = node.getNeighbors();
- if (neighbors == null)
- {
- continue;
- }
- for (final GeoNode n : neighbors)
- {
- if (!visited.containsRev(n) && !to_visit.contains(n))
- {
- added = false;
- n.setParent(node);
- dx = targetX - n.getLoc().getNodeX();
- dy = targetY - n.getLoc().getNodeY();
- n.setCost((dx * dx) + (dy * dy));
- for (int index = 0; index < to_visit.size(); index++)
- {
- // supposed to find it quite early..
- if (to_visit.get(index).getCost() > n.getCost())
- {
- to_visit.add(index, n);
- added = true;
- break;
- }
- }
- if (!added)
- {
- to_visit.addLast(n);
- }
- }
- }
- }
- // No Path found
- return null;
- }
-
- public List constructPath2(AbstractNode node)
- {
- final LinkedList path = new LinkedList<>();
- int previousDirectionX = -1000;
- int previousDirectionY = -1000;
- int directionX;
- int directionY;
-
- while (node.getParent() != null)
- {
- // only add a new route point if moving direction changes
- directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
- directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
-
- if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
- {
- previousDirectionX = directionX;
- previousDirectionY = directionY;
- path.addFirst(node.getLoc());
- }
- node = node.getParent();
- }
- return path;
- }
-
- public GeoNode[] readNeighbors(GeoNode n, int idx)
- {
- final int node_x = n.getLoc().getNodeX();
- final int node_y = n.getLoc().getNodeY();
-
- final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
- final ByteBuffer pn = pathNodes.get(regoffset);
-
- final List Neighbors = new FastList<>(8);
-
- GeoNode newNode;
- short new_node_x, new_node_y;
-
- // Region for sure will change, we must read from correct file
- byte neighbor = pn.get(idx); // N
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) node_x;
- new_node_y = (short) (node_y - 1);
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // NE
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) (node_x + 1);
- new_node_y = (short) (node_y - 1);
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // E
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) (node_x + 1);
- new_node_y = (short) node_y;
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // SE
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) (node_x + 1);
- new_node_y = (short) (node_y + 1);
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // S
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) node_x;
- new_node_y = (short) (node_y + 1);
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // SW
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) (node_x - 1);
- new_node_y = (short) (node_y + 1);
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // W
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) (node_x - 1);
- new_node_y = (short) node_y;
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- neighbor = pn.get(idx); // NW
- idx++;
- if (neighbor > 0)
- {
- neighbor--;
- new_node_x = (short) (node_x - 1);
- new_node_y = (short) (node_y - 1);
- newNode = readNode(new_node_x, new_node_y, neighbor);
- if (newNode != null)
- {
- Neighbors.add(newNode);
- }
- }
- final GeoNode[] result = new GeoNode[Neighbors.size()];
- return Neighbors.toArray(result);
- }
-
- private GeoNode readNode(short node_x, short node_y, byte layer)
- {
- final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
- if (!pathNodesExist(regoffset))
- {
- return null;
- }
- final short nbx = getNodeBlock(node_x);
- final short nby = getNodeBlock(node_y);
- int idx = pathNodes_index.get(regoffset).get((nby << 8) + nbx);
- final ByteBuffer pn = pathNodes.get(regoffset);
- // reading
- final byte nodes = pn.get(idx);
- idx += (layer * 10) + 1;// byte + layer*10byte
- if (nodes < layer)
- {
- _log.warning("SmthWrong!");
- }
- final short node_z = pn.getShort(idx);
- idx += 2;
- return new GeoNode(new GeoNodeLoc(node_x, node_y, node_z), idx);
- }
-
- private GeoNode readNode(int gx, int gy, short z)
- {
- final short node_x = getNodePos(gx);
- final short node_y = getNodePos(gy);
- final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
- if (!pathNodesExist(regoffset))
- {
- return null;
- }
- final short nbx = getNodeBlock(node_x);
- final short nby = getNodeBlock(node_y);
- int idx = pathNodes_index.get(regoffset).get((nby << 8) + nbx);
- final ByteBuffer pn = pathNodes.get(regoffset);
- // reading
- byte nodes = pn.get(idx);
- idx++;// byte
- int idx2 = 0; // create index to nearlest node by z
- short last_z = Short.MIN_VALUE;
- while (nodes > 0)
- {
- final short node_z = pn.getShort(idx);
- if (Math.abs(last_z - z) > Math.abs(node_z - z))
- {
- last_z = node_z;
- idx2 = idx + 2;
- }
- idx += 10; // short + 8 byte
- nodes--;
- }
- return new GeoNode(new GeoNodeLoc(node_x, node_y, last_z), idx2);
- }
-
- private GeoPathFinding()
- {
- final File Data = new File(Config.PATHNODE_DIR, "pn_index.txt");
- try (FileReader fr = new FileReader(Data);
- BufferedReader br = new BufferedReader(fr);
- LineNumberReader lnr = new LineNumberReader(br))
- {
- _log.info("PathFinding Engine: - Loading Path Nodes...");
- String line;
-
- while ((line = lnr.readLine()) != null)
- {
- if (line.trim().length() == 0)
- {
- continue;
- }
- final StringTokenizer st = new StringTokenizer(line, "_");
- final byte rx = Byte.parseByte(st.nextToken());
- final byte ry = Byte.parseByte(st.nextToken());
- LoadPathNodeFile(rx, ry);
- }
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- throw new Error("Failed to Read pn_index File.");
- }
- }
-
- private void LoadPathNodeFile(byte rx, byte ry)
- {
- final short regionoffset = getRegionOffset(rx, ry);
- final File pn = new File(Config.PATHNODE_DIR, rx + "_" + ry + ".pn");
- _log.info("PathFinding Engine: - Loading: " + pn.getName() + " -> region offset: " + regionoffset + "X: " + rx + " Y: " + ry);
- int node = 0, size, index = 0;
-
- // Create a read-only memory-mapped file
- try (RandomAccessFile raf = new RandomAccessFile(pn, "r");
- FileChannel roChannel = raf.getChannel())
- {
- size = (int) roChannel.size();
- MappedByteBuffer nodes;
- if (Config.FORCE_GEODATA) // Force O/S to Loads this buffer's content into physical memory.
- {
- // it is not guarantee, because the underlying operating system may have paged out some of the buffer's data
- nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
- }
- else
- {
- nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
- }
-
- // Indexing pathnode files, so we will know where each block starts
- final IntBuffer indexs = IntBuffer.allocate(65536);
-
- while (node < 65536)
- {
- final byte layer = nodes.get(index);
- indexs.put(node, index);
- node++;
- index += (layer * 10) + 1;
- }
- pathNodes_index.put(regionoffset, indexs);
- pathNodes.put(regionoffset, nodes);
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- _log.warning("Failed to Load PathNode File: " + pn.getAbsolutePath() + "\n");
- }
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.geonodes;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.geodata.GeoData;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
+import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author -Nemesiss-
+ */
+public class GeoPathFinding extends PathFinding
+{
+ private static Logger _log = Logger.getLogger(GeoPathFinding.class.getName());
+ private static Map _pathNodes = new ConcurrentHashMap<>();
+ private static Map _pathNodesIndex = new ConcurrentHashMap<>();
+
+ public static GeoPathFinding getInstance()
+ {
+ return SingletonHolder._instance;
+ }
+
+ @Override
+ public boolean pathNodesExist(short regionoffset)
+ {
+ return _pathNodesIndex.containsKey(regionoffset);
+ }
+
+ @Override
+ public List findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
+ {
+ final int gx = (x - L2World.MAP_MIN_X) >> 4;
+ final int gy = (y - L2World.MAP_MIN_Y) >> 4;
+ final short gz = (short) z;
+ final int gtx = (tx - L2World.MAP_MIN_X) >> 4;
+ final int gty = (ty - L2World.MAP_MIN_Y) >> 4;
+ final short gtz = (short) tz;
+
+ final GeoNode start = readNode(gx, gy, gz);
+ final GeoNode end = readNode(gtx, gty, gtz);
+ if ((start == null) || (end == null))
+ {
+ return null;
+ }
+ if (Math.abs(start.getLoc().getZ() - z) > 55)
+ {
+ return null; // not correct layer
+ }
+ if (Math.abs(end.getLoc().getZ() - tz) > 55)
+ {
+ return null; // not correct layer
+ }
+ if (start == end)
+ {
+ return null;
+ }
+
+ // TODO: Find closest path node we CAN access. Now only checks if we can not reach the closest
+ Location temp = GeoData.getInstance().moveCheck(x, y, z, start.getLoc().getX(), start.getLoc().getY(), start.getLoc().getZ());
+ if ((temp.getX() != start.getLoc().getX()) || (temp.getY() != start.getLoc().getY()))
+ {
+ return null; // cannot reach closest...
+ }
+
+ // TODO: Find closest path node around target, now only checks if final location can be reached
+ temp = GeoData.getInstance().moveCheck(tx, ty, tz, end.getLoc().getX(), end.getLoc().getY(), end.getLoc().getZ());
+ if ((temp.getX() != end.getLoc().getX()) || (temp.getY() != end.getLoc().getY()))
+ {
+ return null; // cannot reach closest...
+ }
+
+ // return searchAStar(start, end);
+ return searchByClosest2(start, end);
+ }
+
+ public List searchByClosest2(GeoNode start, GeoNode end)
+ {
+ // Always continues checking from the closest to target non-blocked
+ // node from to_visit list. There's extra length in path if needed
+ // to go backwards/sideways but when moving generally forwards, this is extra fast
+ // and accurate. And can reach insane distances (try it with 800 nodes..).
+ // Minimum required node count would be around 300-400.
+ // Generally returns a bit (only a bit) more intelligent looking routes than
+ // the basic version. Not a true distance image (which would increase CPU
+ // load) level of intelligence though.
+
+ // List of Visited Nodes
+ final List visited = new ArrayList<>(550);
+
+ // List of Nodes to Visit
+ final LinkedList to_visit = new LinkedList<>();
+ to_visit.add(start);
+ final int targetX = end.getLoc().getNodeX();
+ final int targetY = end.getLoc().getNodeY();
+
+ int dx, dy;
+ boolean added;
+ int i = 0;
+ while (i < 550)
+ {
+ GeoNode node;
+ try
+ {
+ node = to_visit.removeFirst();
+ }
+ catch (Exception e)
+ {
+ // No Path found
+ return null;
+ }
+ if (node.equals(end))
+ {
+ return constructPath2(node);
+ }
+
+ i++;
+ visited.add(node);
+ node.attachNeighbors();
+ final GeoNode[] neighbors = node.getNeighbors();
+ if (neighbors == null)
+ {
+ continue;
+ }
+ for (GeoNode n : neighbors)
+ {
+ if ((visited.lastIndexOf(n) == -1) && !to_visit.contains(n))
+ {
+ added = false;
+ n.setParent(node);
+ dx = targetX - n.getLoc().getNodeX();
+ dy = targetY - n.getLoc().getNodeY();
+ n.setCost((dx * dx) + (dy * dy));
+ for (int index = 0; index < to_visit.size(); index++)
+ {
+ // supposed to find it quite early..
+ if (to_visit.get(index).getCost() > n.getCost())
+ {
+ to_visit.add(index, n);
+ added = true;
+ break;
+ }
+ }
+ if (!added)
+ {
+ to_visit.addLast(n);
+ }
+ }
+ }
+ }
+ // No Path found
+ return null;
+ }
+
+ public List constructPath2(AbstractNode node)
+ {
+ final LinkedList path = new LinkedList<>();
+ int previousDirectionX = -1000;
+ int previousDirectionY = -1000;
+ int directionX;
+ int directionY;
+
+ while (node.getParent() != null)
+ {
+ // only add a new route point if moving direction changes
+ directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
+ directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
+
+ if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
+ {
+ previousDirectionX = directionX;
+ previousDirectionY = directionY;
+ path.addFirst(node.getLoc());
+ }
+ node = node.getParent();
+ }
+ return path;
+ }
+
+ public GeoNode[] readNeighbors(GeoNode n, int idx)
+ {
+ final int node_x = n.getLoc().getNodeX();
+ final int node_y = n.getLoc().getNodeY();
+ // short node_z = n.getLoc().getZ();
+
+ final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
+ final ByteBuffer pn = _pathNodes.get(regoffset);
+
+ final List> Neighbors = new ArrayList<>(8);
+ GeoNode newNode;
+ short new_node_x, new_node_y;
+
+ // Region for sure will change, we must read from correct file
+ byte neighbor = pn.get(idx++); // N
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) node_x;
+ new_node_y = (short) (node_y - 1);
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // NE
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) (node_x + 1);
+ new_node_y = (short) (node_y - 1);
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // E
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) (node_x + 1);
+ new_node_y = (short) node_y;
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // SE
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) (node_x + 1);
+ new_node_y = (short) (node_y + 1);
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // S
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) node_x;
+ new_node_y = (short) (node_y + 1);
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // SW
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) (node_x - 1);
+ new_node_y = (short) (node_y + 1);
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // W
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) (node_x - 1);
+ new_node_y = (short) node_y;
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ neighbor = pn.get(idx++); // NW
+ if (neighbor > 0)
+ {
+ neighbor--;
+ new_node_x = (short) (node_x - 1);
+ new_node_y = (short) (node_y - 1);
+ newNode = readNode(new_node_x, new_node_y, neighbor);
+ if (newNode != null)
+ {
+ Neighbors.add(newNode);
+ }
+ }
+ final GeoNode[] result = new GeoNode[Neighbors.size()];
+ return Neighbors.toArray(result);
+ }
+
+ // Private
+
+ private GeoNode readNode(short node_x, short node_y, byte layer)
+ {
+ final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
+ if (!pathNodesExist(regoffset))
+ {
+ return null;
+ }
+ final short nbx = getNodeBlock(node_x);
+ final short nby = getNodeBlock(node_y);
+ int idx = _pathNodesIndex.get(regoffset).get((nby << 8) + nbx);
+ final ByteBuffer pn = _pathNodes.get(regoffset);
+ // reading
+ final byte nodes = pn.get(idx);
+ idx += (layer * 10) + 1; // byte + layer*10byte
+ if (nodes < layer)
+ {
+ _log.warning("SmthWrong!");
+ }
+ final short node_z = pn.getShort(idx);
+ idx += 2;
+ return new GeoNode(new GeoNodeLoc(node_x, node_y, node_z), idx);
+ }
+
+ private GeoNode readNode(int gx, int gy, short z)
+ {
+ final short node_x = getNodePos(gx);
+ final short node_y = getNodePos(gy);
+ final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
+ if (!pathNodesExist(regoffset))
+ {
+ return null;
+ }
+ final short nbx = getNodeBlock(node_x);
+ final short nby = getNodeBlock(node_y);
+ int idx = _pathNodesIndex.get(regoffset).get((nby << 8) + nbx);
+ final ByteBuffer pn = _pathNodes.get(regoffset);
+ // reading
+ byte nodes = pn.get(idx++);
+ int idx2 = 0; // create index to nearlest node by z
+ short last_z = Short.MIN_VALUE;
+ while (nodes > 0)
+ {
+ final short node_z = pn.getShort(idx);
+ if (Math.abs(last_z - z) > Math.abs(node_z - z))
+ {
+ last_z = node_z;
+ idx2 = idx + 2;
+ }
+ idx += 10; // short + 8 byte
+ nodes--;
+ }
+ return new GeoNode(new GeoNodeLoc(node_x, node_y, last_z), idx2);
+ }
+
+ protected GeoPathFinding()
+ {
+ try
+ {
+ _log.info("Path Engine: - Loading Path Nodes...");
+ //@formatter:off
+ Files.lines(Paths.get(Config.PATHNODE_DIR.getPath(), "pn_index.txt"), StandardCharsets.UTF_8)
+ .map(String::trim)
+ .filter(l -> !l.isEmpty())
+ .forEach(line -> {
+ final String[] parts = line.split("_");
+
+ if ((parts.length < 2)
+ || !Util.isDigit(parts[0])
+ || !Util.isDigit(parts[1]))
+ {
+ _log.warning("Invalid pathnode entry: '" + line + "', must be in format 'XX_YY', where X and Y - integers");
+ return;
+ }
+
+ final byte rx = Byte.parseByte(parts[0]);
+ final byte ry = Byte.parseByte(parts[1]);
+ LoadPathNodeFile(rx, ry);
+ });
+ //@formatter:on
+ }
+ catch (IOException e)
+ {
+ _log.log(Level.WARNING, "", e);
+ throw new Error("Failed to read pn_index file.");
+ }
+ }
+
+ private void LoadPathNodeFile(byte rx, byte ry)
+ {
+ if ((rx < L2World.TILE_X_MIN) || (rx > L2World.TILE_X_MAX) || (ry < L2World.TILE_Y_MIN) || (ry > L2World.TILE_Y_MAX))
+ {
+ _log.warning("Failed to Load PathNode File: invalid region " + rx + "," + ry + Config.EOL);
+ return;
+ }
+ final short regionoffset = getRegionOffset(rx, ry);
+ final File file = new File(Config.PATHNODE_DIR, rx + "_" + ry + ".pn");
+ _log.info("Path Engine: - Loading: " + file.getName() + " -> region offset: " + regionoffset + " X: " + rx + " Y: " + ry);
+ int node = 0, size, index = 0;
+
+ // Create a read-only memory-mapped file
+ try (RandomAccessFile raf = new RandomAccessFile(file, "r");
+ FileChannel roChannel = raf.getChannel())
+ {
+ size = (int) roChannel.size();
+ MappedByteBuffer nodes;
+ if (Config.FORCE_GEODATA)
+ {
+ // it is not guarantee, because the underlying operating system may have paged out some of the buffer's data
+ nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
+ }
+ else
+ {
+ nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+ }
+
+ // Indexing pathnode files, so we will know where each block starts
+ final IntBuffer indexs = IntBuffer.allocate(65536);
+
+ while (node < 65536)
+ {
+ final byte layer = nodes.get(index);
+ indexs.put(node++, index);
+ index += (layer * 10) + 1;
+ }
+ _pathNodesIndex.put(regionoffset, indexs);
+ _pathNodes.put(regionoffset, nodes);
+ }
+ catch (Exception e)
+ {
+ _log.log(Level.WARNING, "Failed to Load PathNode File: " + file.getAbsolutePath() + " : " + e.getMessage(), e);
+ }
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final GeoPathFinding _instance = new GeoPathFinding();
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/utils/BinaryNodeHeap.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/utils/BinaryNodeHeap.java
similarity index 90%
rename from L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/utils/BinaryNodeHeap.java
rename to L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/utils/BinaryNodeHeap.java
index 866122a675..a6aae4c662 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/utils/BinaryNodeHeap.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/pathfinding/utils/BinaryNodeHeap.java
@@ -1,124 +1,124 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding.utils;
-
-import com.l2jmobius.gameserver.pathfinding.geonodes.GeoNode;
-
-/**
- * @author -Nemesiss-
- */
-public class BinaryNodeHeap
-{
- private final GeoNode[] _list;
- private int _size;
-
- public BinaryNodeHeap(int size)
- {
- _list = new GeoNode[size + 1];
- _size = 0;
- }
-
- public void add(GeoNode n)
- {
- _size++;
- int pos = _size;
- _list[pos] = n;
- while (pos != 1)
- {
- final int p2 = pos / 2;
- if (_list[pos].getCost() <= _list[p2].getCost())
- {
- final GeoNode temp = _list[p2];
- _list[p2] = _list[pos];
- _list[pos] = temp;
- pos = p2;
- }
- else
- {
- break;
- }
- }
- }
-
- public GeoNode removeFirst()
- {
- final GeoNode first = _list[1];
- _list[1] = _list[_size];
- _list[_size] = null;
- _size--;
- int pos = 1;
- int cpos;
- int dblcpos;
- GeoNode temp;
- while (true)
- {
- cpos = pos;
- dblcpos = cpos * 2;
- if ((dblcpos + 1) <= _size)
- {
- if (_list[cpos].getCost() >= _list[dblcpos].getCost())
- {
- pos = dblcpos;
- }
- if (_list[pos].getCost() >= _list[dblcpos + 1].getCost())
- {
- pos = dblcpos + 1;
- }
- }
- else if (dblcpos <= _size)
- {
- if (_list[cpos].getCost() >= _list[dblcpos].getCost())
- {
- pos = dblcpos;
- }
- }
-
- if (cpos != pos)
- {
- temp = _list[cpos];
- _list[cpos] = _list[pos];
- _list[pos] = temp;
- }
- else
- {
- break;
- }
- }
- return first;
- }
-
- public boolean contains(GeoNode n)
- {
- if (_size == 0)
- {
- return false;
- }
- for (int i = 1; i <= _size; i++)
- {
- if (_list[i].equals(n))
- {
- return true;
- }
- }
- return false;
- }
-
- public boolean isEmpty()
- {
- return _size == 0;
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.geodata.pathfinding.utils;
+
+import com.l2jmobius.gameserver.geodata.pathfinding.geonodes.GeoNode;
+
+/**
+ * @author -Nemesiss-
+ */
+public class BinaryNodeHeap
+{
+ private final GeoNode[] _list;
+ private int _size;
+
+ public BinaryNodeHeap(int size)
+ {
+ _list = new GeoNode[size + 1];
+ _size = 0;
+ }
+
+ public void add(GeoNode n)
+ {
+ _size++;
+ int pos = _size;
+ _list[pos] = n;
+ while (pos != 1)
+ {
+ final int p2 = pos / 2;
+ if (_list[pos].getCost() <= _list[p2].getCost())
+ {
+ final GeoNode temp = _list[p2];
+ _list[p2] = _list[pos];
+ _list[pos] = temp;
+ pos = p2;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public GeoNode removeFirst()
+ {
+ final GeoNode first = _list[1];
+ _list[1] = _list[_size];
+ _list[_size] = null;
+ _size--;
+ int pos = 1;
+ int cpos;
+ int dblcpos;
+ GeoNode temp;
+ while (true)
+ {
+ cpos = pos;
+ dblcpos = cpos * 2;
+ if ((dblcpos + 1) <= _size)
+ {
+ if (_list[cpos].getCost() >= _list[dblcpos].getCost())
+ {
+ pos = dblcpos;
+ }
+ if (_list[pos].getCost() >= _list[dblcpos + 1].getCost())
+ {
+ pos = dblcpos + 1;
+ }
+ }
+ else if (dblcpos <= _size)
+ {
+ if (_list[cpos].getCost() >= _list[dblcpos].getCost())
+ {
+ pos = dblcpos;
+ }
+ }
+
+ if (cpos != pos)
+ {
+ temp = _list[cpos];
+ _list[cpos] = _list[pos];
+ _list[pos] = temp;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return first;
+ }
+
+ public boolean contains(GeoNode n)
+ {
+ if (_size == 0)
+ {
+ return false;
+ }
+ for (int i = 1; i <= _size; i++)
+ {
+ if (_list[i].equals(n))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isEmpty()
+ {
+ return _size == 0;
+ }
+}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geoeditorcon/GeoEditorListener.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geoeditorcon/GeoEditorListener.java
deleted file mode 100644
index f037547a53..0000000000
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geoeditorcon/GeoEditorListener.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.geoeditorcon;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * @author Dezmond
- */
-public class GeoEditorListener extends Thread
-{
- private static GeoEditorListener _instance;
- private static final int PORT = 9011;
- private static Logger _log = Logger.getLogger(GeoEditorListener.class.getName());
- private final ServerSocket _serverSocket;
- private static GeoEditorThread _geoEditor;
-
- public static GeoEditorListener getInstance()
- {
- if (_instance == null)
- {
- try
- {
- _instance = new GeoEditorListener();
- _instance.start();
- _log.info("GeoEditorListener Initialized.");
- }
- catch (final IOException e)
- {
- _log.severe("Error creating geoeditor listener! " + e.getMessage());
- System.exit(1);
- }
- }
- return _instance;
- }
-
- private GeoEditorListener() throws IOException
- {
- _serverSocket = new ServerSocket(PORT);
- }
-
- public GeoEditorThread getThread()
- {
- return _geoEditor;
- }
-
- public String getStatus()
- {
- if ((_geoEditor != null) && _geoEditor.isWorking())
- {
- return "Geoeditor connected.";
- }
-
- return "Geoeditor not connected.";
- }
-
- @Override
- public void run()
- {
- try (Socket connection = _serverSocket.accept())
- {
- while (true)
- {
- if ((_geoEditor != null) && _geoEditor.isWorking())
- {
- _log.warning("Geoeditor already connected!");
- connection.close();
- continue;
- }
-
- _log.info("Received geoeditor connection from: " + connection.getInetAddress().getHostAddress());
- _geoEditor = new GeoEditorThread(connection);
- _geoEditor.start();
- }
- }
- catch (final Exception e)
- {
- _log.info("GeoEditorListener: " + e.getMessage());
- }
- finally
- {
- try
- {
- _serverSocket.close();
- }
- catch (final IOException io)
- {
- _log.log(Level.INFO, "", io);
- }
- _log.warning("GeoEditorListener Closed!");
- }
- }
-}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geoeditorcon/GeoEditorThread.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geoeditorcon/GeoEditorThread.java
deleted file mode 100644
index 04296e371d..0000000000
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/geoeditorcon/GeoEditorThread.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.geoeditorcon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.logging.Logger;
-
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-
-import javolution.util.FastList;
-
-/**
- * @author Luno, Dezmond
- */
-public class GeoEditorThread extends Thread
-{
- private static Logger _log = Logger.getLogger(GeoEditorThread.class.getName());
-
- private boolean _working = false;
-
- private int _mode = 0; // 0 - don't send coords, 1 - send each
-
- // validateposition from client, 2 - send in
- // intervals of _sendDelay ms.
- private int _sendDelay = 1000; // default - once in second
-
- private final Socket _geSocket;
-
- private OutputStream _out;
-
- private final FastList _gms;
-
- public GeoEditorThread(Socket ge)
- {
- _geSocket = ge;
- _working = true;
- _gms = new FastList<>();
- }
-
- @Override
- public void interrupt()
- {
- try
- {
- _geSocket.close();
- }
- catch (final Exception e)
- {
- }
- super.interrupt();
- }
-
- @Override
- public void run()
- {
- try
- {
- _out = _geSocket.getOutputStream();
- int timer = 0;
-
- while (_working)
- {
- if (!isConnected())
- {
- _working = false;
- }
-
- if ((_mode == 2) && (timer > _sendDelay))
- {
- for (final L2PcInstance gm : _gms)
- {
- if (gm == null)
- {
- continue;
- }
-
- if (!gm.getClient().getConnection().isClosed())
- {
- sendGmPosition(gm);
- }
- else
- {
- _gms.remove(gm);
- }
- }
-
- timer = 0;
- }
-
- try
- {
- sleep(100);
- if (_mode == 2)
- {
- timer += 100;
- }
- }
- catch (final Exception e)
- {
- }
- }
- }
- catch (final SocketException e)
- {
- _log.warning("GeoEditor disconnected. " + e.getMessage());
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- }
- finally
- {
- try
- {
- _geSocket.close();
- }
- catch (final Exception e)
- {
- }
- _working = false;
- }
- }
-
- public void sendGmPosition(int gx, int gy, short z)
- {
- if (!isConnected())
- {
- return;
- }
-
- try
- {
- synchronized (_out)
- {
- writeC(0x0b); // length 11 bytes!
- writeC(0x01); // Cmd = save cell;
- writeD(gx); // Global coord X;
- writeD(gy); // Global coord Y;
- writeH(z); // Coord Z;
- _out.flush();
- }
- }
- catch (final SocketException e)
- {
- _log.warning("GeoEditor disconnected. " + e.getMessage());
- _working = false;
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- try
- {
- _geSocket.close();
- }
- catch (final Exception ex)
- {
- }
- _working = false;
- }
- }
-
- public void sendGmPosition(L2PcInstance _gm)
- {
- sendGmPosition(_gm.getX(), _gm.getY(), (short) _gm.getZ());
- }
-
- public void sendPing()
- {
- if (!isConnected())
- {
- return;
- }
-
- try
- {
- synchronized (_out)
- {
- writeC(0x01); // length 1 byte!
- writeC(0x02); // Cmd = ping (dummy packet for connection
- _out.flush();
- }
- }
- catch (final SocketException e)
- {
- _log.warning("GeoEditor disconnected. " + e.getMessage());
- _working = false;
- }
- catch (final Exception e)
- {
- e.printStackTrace();
- try
- {
- _geSocket.close();
- }
- catch (final Exception ex)
- {
- }
- _working = false;
- }
- }
-
- private void writeD(int value) throws IOException
- {
- _out.write(value & 0xff);
- _out.write((value >> 8) & 0xff);
- _out.write((value >> 16) & 0xff);
- _out.write((value >> 24) & 0xff);
- }
-
- private void writeH(int value) throws IOException
- {
- _out.write(value & 0xff);
- _out.write((value >> 8) & 0xff);
- }
-
- private void writeC(int value) throws IOException
- {
- _out.write(value & 0xff);
- }
-
- public void setMode(int value)
- {
- _mode = value;
- }
-
- public void setTimer(int value)
- {
- if (value < 500)
- {
- _sendDelay = 500; // maximum - 2 times per second!
- }
- else if (value > 60000)
- {
- _sendDelay = 60000; // Minimum - 1 time per minute.
- }
- else
- {
- _sendDelay = value;
- }
- }
-
- public void addGM(L2PcInstance gm)
- {
- if (!_gms.contains(gm))
- {
- _gms.add(gm);
- }
- }
-
- public void removeGM(L2PcInstance gm)
- {
- if (_gms.contains(gm))
- {
- _gms.remove(gm);
- }
- }
-
- public boolean isSend(L2PcInstance gm)
- {
- if ((_mode == 1) && _gms.contains(gm))
- {
- return true;
- }
-
- return false;
- }
-
- private boolean isConnected()
- {
- return _geSocket.isConnected() && !_geSocket.isClosed();
- }
-
- public boolean isWorking()
- {
- sendPing();
- return _working;
- }
-
- public int getMode()
- {
- return _mode;
- }
-}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeoEditor.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeoEditor.java
deleted file mode 100644
index 369b76a096..0000000000
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeoEditor.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.handler.admincommandhandlers;
-
-import java.util.StringTokenizer;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.geoeditorcon.GeoEditorListener;
-import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
-import com.l2jmobius.gameserver.model.GMAudit;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-
-/**
- * @author Luno, Dezmond
- */
-public class AdminGeoEditor implements IAdminCommandHandler
-{
- private static String[] _adminCommands =
- {
- "admin_ge_status",
- "admin_ge_mode",
- "admin_ge_join",
- "admin_ge_leave"
- };
-
- private static final int REQUIRED_LEVEL = Config.GM_MIN;
-
- @Override
- public boolean useAdminCommand(String command, L2PcInstance activeChar)
- {
- if (!Config.ALT_PRIVILEGES_ADMIN)
- {
- if (!(checkLevel(activeChar.getAccessLevel()) && activeChar.isGM()))
- {
- return false;
- }
- }
-
- final String target = (activeChar.getTarget() != null) ? activeChar.getTarget().getName() : "no-target";
- GMAudit.auditGMAction(activeChar.getName(), command, target, "");
-
- if (!Config.ACCEPT_GEOEDITOR_CONN)
- {
- activeChar.sendMessage("Server does not accept geoeditor connections now.");
- return true;
- }
-
- if (command.startsWith("admin_ge_status"))
- {
- activeChar.sendMessage(GeoEditorListener.getInstance().getStatus());
- }
- else if (command.startsWith("admin_ge_mode"))
- {
- if (GeoEditorListener.getInstance().getThread() == null)
- {
- activeChar.sendMessage("Geoeditor is not connected.");
- return true;
- }
-
- try
- {
- final String val = command.substring("admin_ge_mode".length());
- final StringTokenizer st = new StringTokenizer(val);
-
- if (st.countTokens() < 1)
- {
- activeChar.sendMessage("Usage: //ge_mode X");
- activeChar.sendMessage("Mode 0: Don't send coordinates to geoeditor.");
- activeChar.sendMessage("Mode 1: Send coordinates at ValidatePosition from clients.");
- activeChar.sendMessage("Mode 2: Send coordinates each second.");
- return true;
- }
-
- final int m = Integer.parseInt(st.nextToken());
- GeoEditorListener.getInstance().getThread().setMode(m);
- activeChar.sendMessage("Geoeditor connection mode set to " + m + ".");
- }
- catch (final Exception e)
- {
- activeChar.sendMessage("Usage: //ge_mode X");
- activeChar.sendMessage("Mode 0: Don't send coordinates to geoeditor.");
- activeChar.sendMessage("Mode 1: Send coordinates at ValidatePosition from clients.");
- activeChar.sendMessage("Mode 2: Send coordinates each second.");
- e.printStackTrace();
- }
- }
- else if (command.equals("admin_ge_join"))
- {
- if (GeoEditorListener.getInstance().getThread() == null)
- {
- activeChar.sendMessage("Geoeditor is not connected.");
- return true;
- }
- GeoEditorListener.getInstance().getThread().addGM(activeChar);
- activeChar.sendMessage("You have been added to geoeditor's list.");
- }
- else if (command.equals("admin_ge_leave"))
- {
- if (GeoEditorListener.getInstance().getThread() == null)
- {
- activeChar.sendMessage("Geoeditor is not connected.");
- return true;
- }
- GeoEditorListener.getInstance().getThread().removeGM(activeChar);
- activeChar.sendMessage("You have been removed from geoeditor's list.");
- }
- return true;
- }
-
- @Override
- public String[] getAdminCommandList()
- {
- return _adminCommands;
- }
-
- private boolean checkLevel(int level)
- {
- return (level >= REQUIRED_LEVEL);
- }
-}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeodata.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeodata.java
index 8d2c01a48c..90046925c9 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeodata.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminGeodata.java
@@ -17,10 +17,12 @@
package com.l2jmobius.gameserver.handler.admincommandhandlers;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.model.L2Object;
+import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.util.GeoUtils;
/**
* @author -Nemesiss-
@@ -32,7 +34,9 @@ public class AdminGeodata implements IAdminCommandHandler
"admin_geo_pos",
"admin_geo_spawn_pos",
"admin_geo_can_move",
- "admin_geo_can_see"
+ "admin_geo_can_see",
+ "admin_geogrid",
+ "admin_geomap"
};
private static final int REQUIRED_LEVEL = Config.GM_MIN;
@@ -75,7 +79,7 @@ public class AdminGeodata implements IAdminCommandHandler
if (GeoData.getInstance().hasGeoPos(geoX, geoY))
{
- activeChar.sendMessage("WorldX: " + worldX + ", WorldY: " + worldY + ", WorldZ: " + worldZ + ", GeoX: " + geoX + ", GeoY: " + geoY + ", GeoZ: " + GeoData.getInstance().getSpawnHeight(worldX, worldY, worldZ, worldZ));
+ activeChar.sendMessage("WorldX: " + worldX + ", WorldY: " + worldY + ", WorldZ: " + worldZ + ", GeoX: " + geoX + ", GeoY: " + geoY + ", GeoZ: " + GeoData.getInstance().getSpawnHeight(worldX, worldY, worldZ));
}
else
{
@@ -120,6 +124,16 @@ public class AdminGeodata implements IAdminCommandHandler
activeChar.sendMessage("Incorrect Target.");
}
}
+ else if (command.equals("admin_geogrid"))
+ {
+ GeoUtils.debugGrid(activeChar);
+ }
+ else if (command.equals("admin_geomap"))
+ {
+ final int x = ((activeChar.getX() - L2World.MAP_MIN_X) >> 15) + L2World.TILE_X_MIN;
+ final int y = ((activeChar.getY() - L2World.MAP_MIN_Y) >> 15) + L2World.TILE_Y_MIN;
+ activeChar.sendMessage("GeoMap: " + x + "_" + y);
+ }
else
{
return false;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminPathNode.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminPathNode.java
index 18fbd4610e..4058a2b5fa 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminPathNode.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/admincommandhandlers/AdminPathNode.java
@@ -19,10 +19,10 @@ package com.l2jmobius.gameserver.handler.admincommandhandlers;
import java.util.List;
import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
+import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-import com.l2jmobius.gameserver.pathfinding.PathFinding;
public class AdminPathNode implements IAdminCommandHandler
{
@@ -79,7 +79,7 @@ public class AdminPathNode implements IAdminCommandHandler
}
else if (command.equals("admin_find_path"))
{
- if (Config.GEODATA < 2)
+ if (Config.PATHFINDING < 2)
{
activeChar.sendMessage("PathFinding has not been enabled.");
return true;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/skillhandlers/Fishing.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/skillhandlers/Fishing.java
index d9084507c2..5f7d40b693 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/skillhandlers/Fishing.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/handler/skillhandlers/Fishing.java
@@ -17,8 +17,8 @@
package com.l2jmobius.gameserver.handler.skillhandlers;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.datatables.ZoneTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.handler.ISkillHandler;
import com.l2jmobius.gameserver.model.Inventory;
import com.l2jmobius.gameserver.model.L2Character;
@@ -169,7 +169,7 @@ public class Fishing implements ISkillHandler
if (aimingTo != null)
{
// fishing zone found, we can fish here
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
// geodata enabled, checking if we can see end of the pole
if (GeoData.getInstance().canSeeTarget(player.getX(), player.getY(), z, x, y, z))
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/Inventory.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/Inventory.java
index fc95817aa5..37ac7552e1 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/Inventory.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/Inventory.java
@@ -72,6 +72,8 @@ public abstract class Inventory extends ItemContainer
// Speed percentage mods
public static final double MAX_ARMOR_WEIGHT = 12000;
+ public static final int ADENA_ID = 57;
+
private final L2ItemInstance[] _paperdoll;
private final List _paperdollListeners;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Character.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Character.java
index 04b9ea93bf..fc34af77c5 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Character.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Character.java
@@ -26,7 +26,6 @@ import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.GameTimeController;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlEvent;
import com.l2jmobius.gameserver.ai.CtrlIntention;
@@ -36,6 +35,9 @@ import com.l2jmobius.gameserver.datatables.DoorTable;
import com.l2jmobius.gameserver.datatables.MapRegionTable;
import com.l2jmobius.gameserver.datatables.MapRegionTable.TeleportWhereType;
import com.l2jmobius.gameserver.datatables.SkillTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
+import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
+import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
import com.l2jmobius.gameserver.handler.ISkillHandler;
import com.l2jmobius.gameserver.handler.SkillHandler;
import com.l2jmobius.gameserver.instancemanager.TownManager;
@@ -80,8 +82,6 @@ import com.l2jmobius.gameserver.network.serverpackets.StatusUpdate;
import com.l2jmobius.gameserver.network.serverpackets.StopMove;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.network.serverpackets.TeleportToLocation;
-import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
-import com.l2jmobius.gameserver.pathfinding.PathFinding;
import com.l2jmobius.gameserver.skills.Calculator;
import com.l2jmobius.gameserver.skills.Formulas;
import com.l2jmobius.gameserver.skills.Stats;
@@ -4407,10 +4407,10 @@ public abstract class L2Character extends L2Object
final boolean isFloating = isFlying() || isInsideZone(L2Character.ZONE_WATER);
// Z coordinate will follow geodata or client values
- if ((Config.GEODATA > 0) && (Config.COORD_SYNCHRONIZE == 2) && !isFloating && !m.disregardingGeodata && !(this instanceof L2BoatInstance) && ((GameTimeController.getGameTicks() % 10) == 0 // once a second to reduce possible cpu load
+ if ((Config.PATHFINDING > 0) && (Config.COORD_SYNCHRONIZE == 2) && !isFloating && !m.disregardingGeodata && !(this instanceof L2BoatInstance) && ((GameTimeController.getGameTicks() % 10) == 0 // once a second to reduce possible cpu load
) && GeoData.getInstance().hasGeo(xPrev, yPrev))
{
- final int geoHeight = GeoData.getInstance().getSpawnHeight(xPrev, yPrev, zPrev - 30, zPrev + 30);
+ final int geoHeight = GeoData.getInstance().getSpawnHeight(xPrev, yPrev, zPrev - 30);
dz = m._zDestination - geoHeight;
// quite a big difference, compare to validatePosition packet
if ((this instanceof L2PcInstance) && (Math.abs(((L2PcInstance) this).getClientZ() - geoHeight) > 200) && (Math.abs(((L2PcInstance) this).getClientZ() - geoHeight) < 1500))
@@ -4650,7 +4650,7 @@ public abstract class L2Character extends L2Object
// make water move short and use no geodata checks for swimming chars
// distance in a click can easily be over 3000
- if ((Config.GEODATA > 0) && !(this instanceof L2BoatInstance) && isInsideZone(ZONE_WATER) && (distance > 700))
+ if ((Config.PATHFINDING > 0) && !(this instanceof L2BoatInstance) && isInsideZone(ZONE_WATER) && (distance > 700))
{
final double divider = 700 / distance;
x = curX + (int) (divider * dx);
@@ -4728,7 +4728,7 @@ public abstract class L2Character extends L2Object
m.onGeodataPathIndex = -1; // Initialize not on geodata path
m.disregardingGeodata = false;
- if ((Config.GEODATA > 0) && !isFlying() // currently flying characters not checked
+ if ((Config.PATHFINDING > 0) && !isFlying() // currently flying characters not checked
&& !(this instanceof L2NpcWalkerInstance) && !(this instanceof L2BoatInstance) && (!isInsideZone(ZONE_WATER) || isInsideZone(ZONE_SIEGE))) // swimming also not checked - but distance is limited
{
final boolean isInBoat = (this instanceof L2PcInstance) && ((L2PcInstance) this).isInBoat();
@@ -4747,12 +4747,7 @@ public abstract class L2Character extends L2Object
// Movement checks:
// when geodata == 2, for all characters except mobs returning home (could be changed later to teleport if pathfinding fails)
// when geodata == 1, for l2playableinstance and l2riftinvaderinstance
- if (((Config.GEODATA == 2) && !((this instanceof L2Attackable) && ((L2Attackable) this).isReturningToSpawnPoint())) || ((this instanceof L2PcInstance) && !(isInBoat && (distance > 1500))) || isAfraid() || (this instanceof L2RiftInvaderInstance) || ((this instanceof L2Summon) && !(getAI().getIntention() == CtrlIntention.AI_INTENTION_FOLLOW))) // assuming
- // intention_follow
- // only
- // when
- // following
- // owner
+ if (((Config.PATHFINDING == 2) && !((this instanceof L2Attackable) && ((L2Attackable) this).isReturningToSpawnPoint())) || ((this instanceof L2PcInstance) && !(isInBoat && (distance > 1500))) || isAfraid() || (this instanceof L2RiftInvaderInstance) || ((this instanceof L2Summon) && !(getAI().getIntention() == CtrlIntention.AI_INTENTION_FOLLOW))) // assuming
{
if (isOnGeodataPath())
{
@@ -4806,7 +4801,7 @@ public abstract class L2Character extends L2Object
// Pathfinding checks. Only when geodata setting is 2, the LoS check gives shorter result
// than the original movement was and the LoS gives a shorter distance than 2000
// This way of detecting need for pathfinding could be changed.
- if ((Config.GEODATA == 2) && ((originalDistance - distance) > 30) && (distance < 2000) && !isAfraid())
+ if ((Config.PATHFINDING == 2) && ((originalDistance - distance) > 30) && (distance < 2000) && !isAfraid())
{
// Path calculation
// Overrides previous movement check
@@ -4876,7 +4871,7 @@ public abstract class L2Character extends L2Object
}
// If no distance to go through, the movement is cancelled
- if ((distance < 1) && ((Config.GEODATA == 2) || (this instanceof L2PlayableInstance) || isAfraid() || (this instanceof L2RiftInvaderInstance)))
+ if ((distance < 1) && ((Config.PATHFINDING == 2) || (this instanceof L2PlayableInstance) || isAfraid() || (this instanceof L2RiftInvaderInstance)))
{
if (this instanceof L2Summon)
{
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2ItemInstance.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2ItemInstance.java
index 02d9a288f0..021f9ad168 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2ItemInstance.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2ItemInstance.java
@@ -27,10 +27,10 @@ import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
import com.l2jmobius.gameserver.instancemanager.MercTicketManager;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
@@ -931,7 +931,7 @@ public final class L2ItemInstance extends L2Object
assert getPosition().getWorldRegion() == null;
}
- if ((Config.GEODATA > 0) && (dropper != null))
+ if ((Config.PATHFINDING > 0) && (dropper != null))
{
final Location dropDest = GeoData.getInstance().moveCheck(dropper.getX(), dropper.getY(), dropper.getZ(), x, y, z);
x = dropDest.getX();
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Skill.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Skill.java
index d5db5a5bdb..8c9949675c 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Skill.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Skill.java
@@ -23,8 +23,8 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.datatables.SkillTreeTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.actor.instance.L2ArtefactInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2ChestInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Spawn.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Spawn.java
index 2c2c124cae..5cfea800b1 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Spawn.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Spawn.java
@@ -22,9 +22,9 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.Territory;
import com.l2jmobius.gameserver.ThreadPoolManager;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
@@ -581,7 +581,7 @@ public class L2Spawn
// don't correct z of flying npc's
if (!mob.isFlying())
{
- newlocz = GeoData.getInstance().getSpawnHeight(newlocx, newlocy, newlocz, newlocz);
+ newlocz = GeoData.getInstance().getSpawnHeight(newlocx, newlocy, newlocz);
}
for (final L2Effect f : mob.getAllEffects())
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Summon.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Summon.java
index 3a637cfcd7..2f71f61025 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Summon.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2Summon.java
@@ -17,11 +17,11 @@
package com.l2jmobius.gameserver.model;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.ai.L2CharacterAI;
import com.l2jmobius.gameserver.ai.L2SummonAI;
import com.l2jmobius.gameserver.datatables.SkillTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.L2Attackable.AggroInfo;
import com.l2jmobius.gameserver.model.L2Skill.SkillTargetType;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
@@ -213,7 +213,7 @@ public abstract class L2Summon extends L2PlayableInstance
player.sendPacket(new ValidateLocation(this));
if (isAutoAttackable(player))
{
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
if (GeoData.getInstance().canSeeTarget(player, this))
{
@@ -231,7 +231,7 @@ public abstract class L2Summon extends L2PlayableInstance
{
// This Action Failed packet avoids player getting stuck when clicking three or more times
player.sendPacket(new ActionFailed());
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
if (GeoData.getInstance().canSeeTarget(player, this))
{
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2World.java
index 3cd4273da3..1eeb6f5151 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2World.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/L2World.java
@@ -47,6 +47,10 @@ public final class L2World
public static final int SHIFT_BY = 12;
/** Map dimensions */
+ public static final int TILE_X_MIN = 11;
+ public static final int TILE_Y_MIN = 10;
+ public static final int TILE_X_MAX = 28;
+ public static final int TILE_Y_MAX = 26;
public static final int MAP_MIN_X = -131072;
public static final int MAP_MAX_X = 228608;
public static final int MAP_MIN_Y = -262144;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2ControlTowerInstance.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2ControlTowerInstance.java
index 3bd56ea966..9f6e842ff4 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2ControlTowerInstance.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2ControlTowerInstance.java
@@ -18,8 +18,8 @@ package com.l2jmobius.gameserver.model.actor.instance;
import java.util.List;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ai.CtrlIntention;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index ccf6abb1a9..de144f5ce5 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -35,7 +35,6 @@ import java.util.logging.Level;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.GameTimeController;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ItemsAutoDestroy;
import com.l2jmobius.gameserver.LoginServerThread;
import com.l2jmobius.gameserver.Olympiad;
@@ -63,6 +62,7 @@ import com.l2jmobius.gameserver.datatables.NobleSkillTable;
import com.l2jmobius.gameserver.datatables.NpcTable;
import com.l2jmobius.gameserver.datatables.SkillTable;
import com.l2jmobius.gameserver.datatables.SkillTreeTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.handler.IItemHandler;
import com.l2jmobius.gameserver.handler.ItemHandler;
import com.l2jmobius.gameserver.instancemanager.CastleManager;
@@ -3996,7 +3996,7 @@ public final class L2PcInstance extends L2PlayableInstance
{
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
@@ -4030,7 +4030,7 @@ public final class L2PcInstance extends L2PlayableInstance
// This Action Failed packet avoids player getting stuck when clicking three or more times
player.sendPacket(new ActionFailed());
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PetInstance.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PetInstance.java
index 034c2e4687..9a3f838879 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PetInstance.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/model/actor/instance/L2PetInstance.java
@@ -24,10 +24,10 @@ import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.datatables.SkillTable;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.handler.IItemHandler;
import com.l2jmobius.gameserver.handler.ItemHandler;
import com.l2jmobius.gameserver.idfactory.IdFactory;
@@ -316,7 +316,7 @@ public class L2PetInstance extends L2Summon
// Check if the pet is attackable (without a forced attack) and isn't dead
if (isAutoAttackable(player) && !isOwner)
{
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
if (GeoData.getInstance().canSeeTarget(player, this))
{
@@ -333,7 +333,7 @@ public class L2PetInstance extends L2Summon
}
else if (!isInsideRadius(player, 150, false, false))
{
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
if (GeoData.getInstance().canSeeTarget(player, this))
{
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/MoveBackwardToLocation.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/MoveBackwardToLocation.java
index 6301a26f95..6ba7b1e74a 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/MoveBackwardToLocation.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/MoveBackwardToLocation.java
@@ -104,7 +104,7 @@ public class MoveBackwardToLocation extends L2GameClientPacket
}
// Disable keyboard movement when geodata is not enabled and player is not flying.
- if ((_moveMovement == 0) && (Config.GEODATA < 1) && !activeChar.isFlying())
+ if ((_moveMovement == 0) && (Config.PATHFINDING < 1) && !activeChar.isFlying())
{
activeChar.sendPacket(new ActionFailed());
}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/ValidatePosition.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/ValidatePosition.java
index 7137d30311..a3b61d335c 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/ValidatePosition.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/clientpackets/ValidatePosition.java
@@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.geoeditorcon.GeoEditorListener;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.GetOnVehicle;
@@ -113,14 +112,6 @@ public class ValidatePosition extends L2GameClientPacket
activeChar.getParty().broadcastToPartyMembers(activeChar, new PartyMemberPosition(activeChar));
}
- if (Config.ACCEPT_GEOEDITOR_CONN)
- {
- if ((GeoEditorListener.getInstance().getThread() != null) && GeoEditorListener.getInstance().getThread().isWorking() && GeoEditorListener.getInstance().getThread().isSend(activeChar))
- {
- GeoEditorListener.getInstance().getThread().sendGmPosition(_x, _y, (short) _z);
- }
- }
-
if (activeChar.isFlying() || activeChar.isInsideZone(L2Character.ZONE_WATER))
{
activeChar.setXYZ(realX, realY, _z);
@@ -165,7 +156,7 @@ public class ValidatePosition extends L2GameClientPacket
// intended for geodata. Sends a validation packet to client
// when too far from server calculated true coordinate.
// Due to geodata "holes", some Z axis checks are made.
- if ((Config.GEODATA > 0) && ((diffSq > 250000) || (Math.abs(dz) > 200)))
+ if ((Config.PATHFINDING > 0) && ((diffSq > 250000) || (Math.abs(dz) > 200)))
{
if ((Math.abs(dz) > 200) && (Math.abs(dz) < 1500) && (Math.abs(_z - activeChar.getClientZ()) < 800))
{
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/serverpackets/ExServerPrimitive.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/serverpackets/ExServerPrimitive.java
new file mode 100644
index 0000000000..0f6089c70f
--- /dev/null
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/network/serverpackets/ExServerPrimitive.java
@@ -0,0 +1,327 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+package com.l2jmobius.gameserver.network.serverpackets;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A packet used to draw points and lines on client.
+ * Note: Names in points and lines are bugged they will appear even when not looking at them.
+ * @author NosBit
+ */
+public class ExServerPrimitive extends L2GameServerPacket
+{
+ private static final String _SM_EX_SERVER_PRIMITIVE = "[S] FE:24 ExServerPrimitive";
+
+ private final String _name;
+ private final int _x;
+ private final int _y;
+ private final int _z;
+ private final List _points = new ArrayList<>();
+ private final List _lines = new ArrayList<>();
+
+ /**
+ * @param name A unique name this will be used to replace lines if second packet is sent
+ * @param x the x coordinate usually middle of drawing area
+ * @param y the y coordinate usually middle of drawing area
+ * @param z the z coordinate usually middle of drawing area
+ */
+ public ExServerPrimitive(String name, int x, int y, int z)
+ {
+ _name = name;
+ _x = x;
+ _y = y;
+ _z = z;
+ }
+
+ /**
+ * Adds a point to be displayed on client.
+ * @param name the name that will be displayed over the point
+ * @param color the color
+ * @param isNameColored if {@code true} name will be colored as well.
+ * @param x the x coordinate for this point
+ * @param y the y coordinate for this point
+ * @param z the z coordinate for this point
+ */
+ public void addPoint(String name, int color, boolean isNameColored, int x, int y, int z)
+ {
+ _points.add(new Point(name, color, isNameColored, x, y, z));
+ }
+
+ /**
+ * Adds a point to be displayed on client.
+ * @param color the color
+ * @param x the x coordinate for this point
+ * @param y the y coordinate for this point
+ * @param z the z coordinate for this point
+ */
+ public void addPoint(int color, int x, int y, int z)
+ {
+ addPoint("", color, false, x, y, z);
+ }
+
+ /**
+ * Adds a point to be displayed on client.
+ * @param name the name that will be displayed over the point
+ * @param color the color
+ * @param isNameColored if {@code true} name will be colored as well.
+ * @param x the x coordinate for this point
+ * @param y the y coordinate for this point
+ * @param z the z coordinate for this point
+ */
+ public void addPoint(String name, Color color, boolean isNameColored, int x, int y, int z)
+ {
+ addPoint(name, color.getRGB(), isNameColored, x, y, z);
+ }
+
+ /**
+ * Adds a point to be displayed on client.
+ * @param color the color
+ * @param x the x coordinate for this point
+ * @param y the y coordinate for this point
+ * @param z the z coordinate for this point
+ */
+ public void addPoint(Color color, int x, int y, int z)
+ {
+ addPoint("", color, false, x, y, z);
+ }
+
+ /**
+ * Adds a line to be displayed on client
+ * @param name the name that will be displayed over the middle of line
+ * @param color the color
+ * @param isNameColored if {@code true} name will be colored as well.
+ * @param x the x coordinate for this line start point
+ * @param y the y coordinate for this line start point
+ * @param z the z coordinate for this line start point
+ * @param x2 the x coordinate for this line end point
+ * @param y2 the y coordinate for this line end point
+ * @param z2 the z coordinate for this line end point
+ */
+ public void addLine(String name, int color, boolean isNameColored, int x, int y, int z, int x2, int y2, int z2)
+ {
+ _lines.add(new Line(name, color, isNameColored, x, y, z, x2, y2, z2));
+ }
+
+ /**
+ * Adds a line to be displayed on client
+ * @param color the color
+ * @param x the x coordinate for this line start point
+ * @param y the y coordinate for this line start point
+ * @param z the z coordinate for this line start point
+ * @param x2 the x coordinate for this line end point
+ * @param y2 the y coordinate for this line end point
+ * @param z2 the z coordinate for this line end point
+ */
+ public void addLine(int color, int x, int y, int z, int x2, int y2, int z2)
+ {
+ addLine("", color, false, x, y, z, x2, y2, z2);
+ }
+
+ /**
+ * Adds a line to be displayed on client
+ * @param name the name that will be displayed over the middle of line
+ * @param color the color
+ * @param isNameColored if {@code true} name will be colored as well.
+ * @param x the x coordinate for this line start point
+ * @param y the y coordinate for this line start point
+ * @param z the z coordinate for this line start point
+ * @param x2 the x coordinate for this line end point
+ * @param y2 the y coordinate for this line end point
+ * @param z2 the z coordinate for this line end point
+ */
+ public void addLine(String name, Color color, boolean isNameColored, int x, int y, int z, int x2, int y2, int z2)
+ {
+ addLine(name, color.getRGB(), isNameColored, x, y, z, x2, y2, z2);
+ }
+
+ /**
+ * Adds a line to be displayed on client
+ * @param color the color
+ * @param x the x coordinate for this line start point
+ * @param y the y coordinate for this line start point
+ * @param z the z coordinate for this line start point
+ * @param x2 the x coordinate for this line end point
+ * @param y2 the y coordinate for this line end point
+ * @param z2 the z coordinate for this line end point
+ */
+ public void addLine(Color color, int x, int y, int z, int x2, int y2, int z2)
+ {
+ addLine("", color, false, x, y, z, x2, y2, z2);
+ }
+
+ @Override
+ protected void writeImpl()
+ {
+ writeC(0xFE);
+ writeH(0x24); // Changed at Kamael to 11
+ writeS(_name);
+ writeD(_x);
+ writeD(_y);
+ writeD(_z);
+ writeD(65535); // has to do something with display range and angle
+ writeD(65535); // has to do something with display range and angle
+
+ writeD(_points.size() + _lines.size());
+
+ for (Point point : _points)
+ {
+ writeC(1); // Its the type in this case Point
+ writeS(point.getName());
+ final int color = point.getColor();
+ writeD((color >> 16) & 0xFF); // R
+ writeD((color >> 8) & 0xFF); // G
+ writeD(color & 0xFF); // B
+ writeD(point.isNameColored() ? 1 : 0);
+ writeD(point.getX());
+ writeD(point.getY());
+ writeD(point.getZ());
+ }
+
+ for (Line line : _lines)
+ {
+ writeC(2); // Its the type in this case Line
+ writeS(line.getName());
+ final int color = line.getColor();
+ writeD((color >> 16) & 0xFF); // R
+ writeD((color >> 8) & 0xFF); // G
+ writeD(color & 0xFF); // B
+ writeD(line.isNameColored() ? 1 : 0);
+ writeD(line.getX());
+ writeD(line.getY());
+ writeD(line.getZ());
+ writeD(line.getX2());
+ writeD(line.getY2());
+ writeD(line.getZ2());
+ }
+ }
+
+ private static class Point
+ {
+ private final String _name;
+ private final int _color;
+ private final boolean _isNameColored;
+ private final int _x;
+ private final int _y;
+ private final int _z;
+
+ public Point(String name, int color, boolean isNameColored, int x, int y, int z)
+ {
+ _name = name;
+ _color = color;
+ _isNameColored = isNameColored;
+ _x = x;
+ _y = y;
+ _z = z;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName()
+ {
+ return _name;
+ }
+
+ /**
+ * @return the color
+ */
+ public int getColor()
+ {
+ return _color;
+ }
+
+ /**
+ * @return the isNameColored
+ */
+ public boolean isNameColored()
+ {
+ return _isNameColored;
+ }
+
+ /**
+ * @return the x
+ */
+ public int getX()
+ {
+ return _x;
+ }
+
+ /**
+ * @return the y
+ */
+ public int getY()
+ {
+ return _y;
+ }
+
+ /**
+ * @return the z
+ */
+ public int getZ()
+ {
+ return _z;
+ }
+ }
+
+ private static class Line extends Point
+ {
+ private final int _x2;
+ private final int _y2;
+ private final int _z2;
+
+ public Line(String name, int color, boolean isNameColored, int x, int y, int z, int x2, int y2, int z2)
+ {
+ super(name, color, isNameColored, x, y, z);
+ _x2 = x2;
+ _y2 = y2;
+ _z2 = z2;
+ }
+
+ /**
+ * @return the x2
+ */
+ public int getX2()
+ {
+ return _x2;
+ }
+
+ /**
+ * @return the y2
+ */
+ public int getY2()
+ {
+ return _y2;
+ }
+
+ /**
+ * @return the z2
+ */
+ public int getZ2()
+ {
+ return _z2;
+ }
+ }
+
+ @Override
+ public String getType()
+ {
+ return _SM_EX_SERVER_PRIMITIVE;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/PathFinding.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/PathFinding.java
deleted file mode 100644
index 94e28bd1a2..0000000000
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/pathfinding/PathFinding.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program 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.
- *
- * This program 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 .
- */
-package com.l2jmobius.gameserver.pathfinding;
-
-import java.util.List;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.model.L2World;
-import com.l2jmobius.gameserver.pathfinding.cellnodes.CellPathFinding;
-import com.l2jmobius.gameserver.pathfinding.geonodes.GeoPathFinding;
-
-/**
- * @author -Nemesiss-
- */
-public abstract class PathFinding
-{
- private static PathFinding _instance;
-
- public static PathFinding getInstance()
- {
- if (_instance == null)
- {
- if (!Config.GEODATA_CELLFINDING)
- {
- // Higher Memory Usage, Smaller Cpu Usage
- return GeoPathFinding.getInstance();
- }
- return CellPathFinding.getInstance();
- }
- return _instance;
- }
-
- public abstract boolean pathNodesExist(short regionoffset);
-
- public abstract List findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable);
-
- /**
- * Convert geodata position to pathnode position
- * @param geo_pos
- * @return pathnode position
- */
- public short getNodePos(int geo_pos)
- {
- return (short) (geo_pos >> 3); // OK?
- }
-
- /**
- * Convert node position to pathnode block position
- * @param node_pos
- * @return pathnode block position (0...255)
- */
- public short getNodeBlock(int node_pos)
- {
- return (short) (node_pos % 256);
- }
-
- public byte getRegionX(int node_pos)
- {
- return (byte) ((node_pos >> 8) + 16);
- }
-
- public byte getRegionY(int node_pos)
- {
- return (byte) ((node_pos >> 8) + 10);
- }
-
- public short getRegionOffset(byte rx, byte ry)
- {
- return (short) ((rx << 5) + ry);
- }
-
- /**
- * Convert pathnode x to World x position
- * @param node_x
- * @return
- */
- public int calculateWorldX(short node_x)
- {
- return L2World.MAP_MIN_X + (node_x * 128) + 48;
- }
-
- /**
- * Convert pathnode y to World y position
- * @param node_y
- * @return
- */
- public int CalculateWorldY(short node_y)
- {
- return L2World.MAP_MIN_Y + (node_y * 128) + 48;
- }
-
- public String[] getStat()
- {
- return null;
- }
-}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectFear.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectFear.java
index 19330a3dca..84a1722456 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectFear.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectFear.java
@@ -17,8 +17,8 @@
package com.l2jmobius.gameserver.skills.effects;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ai.CtrlIntention;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Effect;
import com.l2jmobius.gameserver.model.Location;
@@ -110,7 +110,7 @@ final class EffectFear extends L2Effect
posX += _dX * FEAR_RANGE;
posY += _dY * FEAR_RANGE;
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
final Location destiny = GeoData.getInstance().moveCheck(getEffected().getX(), getEffected().getY(), getEffected().getZ(), posX, posY, posZ);
posX = destiny.getX();
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectThrowUp.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectThrowUp.java
index aaee244d74..04654307da 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectThrowUp.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/skills/effects/EffectThrowUp.java
@@ -19,7 +19,7 @@ package com.l2jmobius.gameserver.skills.effects;
import java.util.logging.Logger;
import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.GeoData;
+import com.l2jmobius.gameserver.geodata.GeoData;
import com.l2jmobius.gameserver.model.L2Effect;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.network.serverpackets.FlyToLocation;
@@ -92,7 +92,7 @@ final class EffectThrowUp extends L2Effect
_y = getEffector().getY() - (int) (offset * sin);
_z = getEffected().getZ();
- if (Config.GEODATA > 0)
+ if (Config.PATHFINDING > 0)
{
final Location destiny = GeoData.getInstance().moveCheck(getEffected().getX(), getEffected().getY(), getEffected().getZ(), _x, _y, _z);
_x = destiny.getX();
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/GeoUtils.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/GeoUtils.java
index 9ea6f3588b..7004d8cccc 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/GeoUtils.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/GeoUtils.java
@@ -16,25 +16,165 @@
*/
package com.l2jmobius.gameserver.util;
-import com.l2jserver.gameserver.geoengine.Direction;
+import java.awt.Color;
+
+import com.l2jmobius.gameserver.geodata.GeoData;
+import com.l2jmobius.gameserver.geodata.geodriver.Cell;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
/**
- * @author FBIagent
+ * @author HorridoJoho
*/
public final class GeoUtils
{
- public interface PointListener
+ public static void debug2DLine(L2PcInstance player, int x, int y, int tx, int ty, int z)
{
- /**
- * @param x
- * @param y
- * @return true proceed, false abort
- */
- boolean onPoint(int x, int y);
+ final int gx = GeoData.getInstance().getGeoX(x);
+ final int gy = GeoData.getInstance().getGeoY(y);
+
+ final int tgx = GeoData.getInstance().getGeoX(tx);
+ final int tgy = GeoData.getInstance().getGeoY(ty);
+
+ final ExServerPrimitive prim = new ExServerPrimitive("Debug2DLine", x, y, z);
+ prim.addLine(Color.BLUE, GeoData.getInstance().getWorldX(gx), GeoData.getInstance().getWorldY(gy), z, GeoData.getInstance().getWorldX(tgx), GeoData.getInstance().getWorldY(tgy), z);
+
+ final LinePointIterator iter = new LinePointIterator(gx, gy, tgx, tgy);
+
+ while (iter.next())
+ {
+ final int wx = GeoData.getInstance().getWorldX(iter.x());
+ final int wy = GeoData.getInstance().getWorldY(iter.y());
+
+ prim.addPoint(Color.RED, wx, wy, z);
+ }
+ player.sendPacket(prim);
+ }
+
+ public static void debug3DLine(L2PcInstance player, int x, int y, int z, int tx, int ty, int tz)
+ {
+ final int gx = GeoData.getInstance().getGeoX(x);
+ final int gy = GeoData.getInstance().getGeoY(y);
+
+ final int tgx = GeoData.getInstance().getGeoX(tx);
+ final int tgy = GeoData.getInstance().getGeoY(ty);
+
+ final ExServerPrimitive prim = new ExServerPrimitive("Debug3DLine", x, y, z);
+ prim.addLine(Color.BLUE, GeoData.getInstance().getWorldX(gx), GeoData.getInstance().getWorldY(gy), z, GeoData.getInstance().getWorldX(tgx), GeoData.getInstance().getWorldY(tgy), tz);
+
+ final LinePointIterator3D iter = new LinePointIterator3D(gx, gy, z, tgx, tgy, tz);
+ iter.next();
+ int prevX = iter.x();
+ int prevY = iter.y();
+ int wx = GeoData.getInstance().getWorldX(prevX);
+ int wy = GeoData.getInstance().getWorldY(prevY);
+ int wz = iter.z();
+ prim.addPoint(Color.RED, wx, wy, wz);
+
+ while (iter.next())
+ {
+ final int curX = iter.x();
+ final int curY = iter.y();
+
+ if ((curX != prevX) || (curY != prevY))
+ {
+ wx = GeoData.getInstance().getWorldX(curX);
+ wy = GeoData.getInstance().getWorldY(curY);
+ wz = iter.z();
+
+ prim.addPoint(Color.RED, wx, wy, wz);
+
+ prevX = curX;
+ prevY = curY;
+ }
+ }
+ player.sendPacket(prim);
+ }
+
+ private static Color getDirectionColor(int x, int y, int z, int nswe)
+ {
+ if (GeoData.getInstance().checkNearestNswe(x, y, z, nswe))
+ {
+ return Color.GREEN;
+ }
+ return Color.RED;
+ }
+
+ public static void debugGrid(L2PcInstance player)
+ {
+ final int geoRadius = 20;
+ final int blocksPerPacket = 40;
+
+ int iBlock = blocksPerPacket;
+ int iPacket = 0;
+
+ ExServerPrimitive exsp = null;
+ final GeoData gd = GeoData.getInstance();
+ final int playerGx = gd.getGeoX(player.getX());
+ final int playerGy = gd.getGeoY(player.getY());
+ for (int dx = -geoRadius; dx <= geoRadius; ++dx)
+ {
+ for (int dy = -geoRadius; dy <= geoRadius; ++dy)
+ {
+ if (iBlock >= blocksPerPacket)
+ {
+ iBlock = 0;
+ if (exsp != null)
+ {
+ ++iPacket;
+ player.sendPacket(exsp);
+ }
+ exsp = new ExServerPrimitive("DebugGrid_" + iPacket, player.getX(), player.getY(), -16000);
+ }
+
+ if (exsp == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ final int gx = playerGx + dx;
+ final int gy = playerGy + dy;
+
+ final int x = gd.getWorldX(gx);
+ final int y = gd.getWorldY(gy);
+ final int z = gd.getNearestZ(gx, gy, player.getZ());
+
+ // north arrow
+ 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, 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, 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, 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);
+ exsp.addLine(col, x - 4, y - 4, z, x - 4, y + 4, z);
+
+ ++iBlock;
+ }
+ }
+
+ player.sendPacket(exsp);
}
/**
- * difference between x values: never abover 1
+ * difference between x values: never above 1
* difference between y values: never above 1
* @param lastX
* @param lastY
@@ -42,36 +182,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
@@ -79,15 +219,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();
}
}
}
diff --git a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Util.java
index 74b5feff6e..c1d30c50b4 100644
--- a/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Util.java
+++ b/L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Util.java
@@ -325,4 +325,24 @@ public final class Util
}
return result;
}
+
+ /**
+ * @param text - the text to check
+ * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise
+ */
+ public static boolean isDigit(String text)
+ {
+ if ((text == null) || text.isEmpty())
+ {
+ return false;
+ }
+ for (char c : text.toCharArray())
+ {
+ if (!Character.isDigit(c))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
}
\ No newline at end of file
diff --git a/L2J_Mobius_C4/launcher/Gameserver.launch b/L2J_Mobius_C4/launcher/Gameserver.launch
index 2418e5fd37..3c9ff6f4d8 100644
--- a/L2J_Mobius_C4/launcher/Gameserver.launch
+++ b/L2J_Mobius_C4/launcher/Gameserver.launch
@@ -7,7 +7,7 @@
-
+
diff --git a/L2J_Mobius_C4/launcher/Loginserver.launch b/L2J_Mobius_C4/launcher/Loginserver.launch
index e5c80b5561..96757f326a 100644
--- a/L2J_Mobius_C4/launcher/Loginserver.launch
+++ b/L2J_Mobius_C4/launcher/Loginserver.launch
@@ -7,7 +7,7 @@
-
+