Replaced GeoData engine with newest version.
This commit is contained in:
@@ -9,8 +9,6 @@
|
|||||||
<classpathentry kind="lib" path="dist/libs/javolution-5.5.1.jar"/>
|
<classpathentry kind="lib" path="dist/libs/javolution-5.5.1.jar"/>
|
||||||
<classpathentry kind="lib" path="dist/libs/jython-engine-2.2.1.jar"/>
|
<classpathentry kind="lib" path="dist/libs/jython-engine-2.2.1.jar"/>
|
||||||
<classpathentry kind="lib" path="dist/libs/jython.jar"/>
|
<classpathentry kind="lib" path="dist/libs/jython.jar"/>
|
||||||
<classpathentry kind="lib" path="dist/libs/L2J_GeoAbstraction.jar"/>
|
|
||||||
<classpathentry kind="lib" path="dist/libs/L2J_GeoDriver.jar"/>
|
|
||||||
<classpathentry kind="lib" path="dist/libs/mchange-commons-0.2.jar"/>
|
<classpathentry kind="lib" path="dist/libs/mchange-commons-0.2.jar"/>
|
||||||
<classpathentry kind="lib" path="dist/libs/mmocore.jar"/>
|
<classpathentry kind="lib" path="dist/libs/mmocore.jar"/>
|
||||||
<classpathentry kind="lib" path="dist/libs/mysql-connector-java-5.1.23-bin.jar"/>
|
<classpathentry kind="lib" path="dist/libs/mysql-connector-java-5.1.23-bin.jar"/>
|
||||||
|
75
L2J_Mobius_C4/dist/game/config/GeoData.ini
vendored
Normal file
75
L2J_Mobius_C4/dist/game/config/GeoData.ini
vendored
Normal file
@@ -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
|
16
L2J_Mobius_C4/dist/game/config/GeoDriver.ini
vendored
16
L2J_Mobius_C4/dist/game/config/GeoDriver.ini
vendored
@@ -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
|
|
@@ -376,9 +376,8 @@ admin_geo_pos = 100
|
|||||||
admin_geo_spawn_pos = 100
|
admin_geo_spawn_pos = 100
|
||||||
admin_geo_can_see = 100
|
admin_geo_can_see = 100
|
||||||
admin_geo_can_move = 100
|
admin_geo_can_move = 100
|
||||||
admin_geoeditor_connect = 100
|
admin_geogrid = 100
|
||||||
admin_geoeditor_join = 100
|
admin_geomap =100
|
||||||
admin_geoeditor_leave = 100
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
### MANOR ###
|
### MANOR ###
|
||||||
|
72
L2J_Mobius_C4/dist/game/config/options.ini
vendored
72
L2J_Mobius_C4/dist/game/config/options.ini
vendored
@@ -5,7 +5,6 @@
|
|||||||
Debug = False
|
Debug = False
|
||||||
Assert = False
|
Assert = False
|
||||||
Developer = False
|
Developer = False
|
||||||
AcceptGeoeditorConn = False
|
|
||||||
# if true the server will be a test server (listed by clients setted up to list testserver)
|
# if true the server will be a test server (listed by clients setted up to list testserver)
|
||||||
TestServer = False
|
TestServer = False
|
||||||
|
|
||||||
@@ -253,77 +252,6 @@ GridsAlwaysOn = False
|
|||||||
GridNeighborTurnOnTime = 1
|
GridNeighborTurnOnTime = 1
|
||||||
GridNeighborTurnOffTime = 90
|
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
|
# Falling Damage
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Allow characters to receive damage from falling.
|
# Allow characters to receive damage from falling.
|
||||||
|
@@ -23,9 +23,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Character;
|
import com.l2jmobius.gameserver.model.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.L2Effect;
|
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);
|
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, loc_x, loc_y, loc_z, heading, false, 0);
|
||||||
GrandBossManager.getInstance().addBoss(baium);
|
GrandBossManager.getInstance().addBoss(baium);
|
||||||
final L2NpcInstance _baium = baium;
|
final L2NpcInstance _baium = baium;
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
|
ThreadPoolManager.getInstance().scheduleGeneral(() ->
|
||||||
{
|
{
|
||||||
@Override
|
try
|
||||||
public void run()
|
|
||||||
{
|
{
|
||||||
try
|
_baium.setCurrentHpMp(hp, mp);
|
||||||
{
|
_baium.setIsInvul(true);
|
||||||
_baium.setCurrentHpMp(hp, mp);
|
_baium.setIsImmobilized(true);
|
||||||
_baium.setIsInvul(true);
|
_baium.setRunning();
|
||||||
_baium.setIsImmobilized(true);
|
_baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
||||||
_baium.setRunning();
|
startQuestTimer("baium_wakeup", 15000, _baium, null);
|
||||||
_baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
}
|
||||||
startQuestTimer("baium_wakeup", 15000, _baium, null);
|
catch (final Exception e)
|
||||||
}
|
{
|
||||||
catch (final Exception e)
|
e.printStackTrace();
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 100L);
|
}, 100L);
|
||||||
}
|
}
|
||||||
@@ -219,20 +215,16 @@ public class Baium extends Quest
|
|||||||
startQuestTimer("baium_despawn", 60000, npc, null, true);
|
startQuestTimer("baium_despawn", 60000, npc, null, true);
|
||||||
startQuestTimer("skill_range", 500, npc, null, true);
|
startQuestTimer("skill_range", 500, npc, null, true);
|
||||||
final L2NpcInstance baium = npc;
|
final L2NpcInstance baium = npc;
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
|
ThreadPoolManager.getInstance().scheduleGeneral(() ->
|
||||||
{
|
{
|
||||||
@Override
|
try
|
||||||
public void run()
|
|
||||||
{
|
{
|
||||||
try
|
baium.setIsInvul(false);
|
||||||
{
|
baium.setIsImmobilized(false);
|
||||||
baium.setIsInvul(false);
|
}
|
||||||
baium.setIsImmobilized(false);
|
catch (final Exception e)
|
||||||
}
|
{
|
||||||
catch (final Exception e)
|
e.printStackTrace();
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 11100L);
|
}, 11100L);
|
||||||
|
|
||||||
@@ -313,23 +305,19 @@ public class Baium extends Quest
|
|||||||
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, npc);
|
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, npc);
|
||||||
GrandBossManager.getInstance().addBoss(baium);
|
GrandBossManager.getInstance().addBoss(baium);
|
||||||
final L2NpcInstance _baium = baium;
|
final L2NpcInstance _baium = baium;
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
|
ThreadPoolManager.getInstance().scheduleGeneral(() ->
|
||||||
{
|
{
|
||||||
@Override
|
try
|
||||||
public void run()
|
|
||||||
{
|
{
|
||||||
try
|
_baium.setIsInvul(true);
|
||||||
{
|
_baium.setIsImmobilized(true);
|
||||||
_baium.setIsInvul(true);
|
_baium.setRunning();
|
||||||
_baium.setIsImmobilized(true);
|
_baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
||||||
_baium.setRunning();
|
startQuestTimer("baium_wakeup", 15000, _baium, null);
|
||||||
_baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
}
|
||||||
startQuestTimer("baium_wakeup", 15000, _baium, null);
|
catch (final Exception e)
|
||||||
}
|
{
|
||||||
catch (final Exception e)
|
e.printStackTrace();
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 100L);
|
}, 100L);
|
||||||
}
|
}
|
||||||
|
@@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
package ai.individual;
|
package ai.individual;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.model.L2CharPosition;
|
import com.l2jmobius.gameserver.model.L2CharPosition;
|
||||||
import com.l2jmobius.gameserver.model.L2Character;
|
import com.l2jmobius.gameserver.model.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.L2Summon;
|
import com.l2jmobius.gameserver.model.L2Summon;
|
||||||
|
BIN
L2J_Mobius_C4/dist/libs/L2J_GeoAbstraction.jar
vendored
BIN
L2J_Mobius_C4/dist/libs/L2J_GeoAbstraction.jar
vendored
Binary file not shown.
BIN
L2J_Mobius_C4/dist/libs/L2J_GeoDriver.jar
vendored
BIN
L2J_Mobius_C4/dist/libs/L2J_GeoDriver.jar
vendored
Binary file not shown.
@@ -22,12 +22,16 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.math.BigInteger;
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.base.Experience;
|
import com.l2jmobius.gameserver.model.base.Experience;
|
||||||
import com.l2jmobius.gameserver.util.FloodProtectorConfig;
|
import com.l2jmobius.gameserver.util.FloodProtectorConfig;
|
||||||
import com.l2jmobius.util.StringUtil;
|
import com.l2jmobius.util.StringUtil;
|
||||||
@@ -46,6 +50,9 @@ import javolution.util.FastMap;
|
|||||||
public final class Config
|
public final class Config
|
||||||
{
|
{
|
||||||
protected static Logger _log = Logger.getLogger(Config.class.getName());
|
protected static Logger _log = Logger.getLogger(Config.class.getName());
|
||||||
|
|
||||||
|
public static final String EOL = System.lineSeparator();
|
||||||
|
|
||||||
/** Debug/release mode */
|
/** Debug/release mode */
|
||||||
public static boolean DEBUG;
|
public static boolean DEBUG;
|
||||||
/** Enable/disable assertions */
|
/** Enable/disable assertions */
|
||||||
@@ -578,8 +585,6 @@ public final class Config
|
|||||||
/** Accept multi-items drop ? */
|
/** Accept multi-items drop ? */
|
||||||
public static boolean MULTIPLE_ITEM_DROP;
|
public static boolean MULTIPLE_ITEM_DROP;
|
||||||
|
|
||||||
/** Coord Synchronization */
|
|
||||||
public static int COORD_SYNCHRONIZE;
|
|
||||||
/** Falling Damage */
|
/** Falling Damage */
|
||||||
public static boolean ENABLE_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";
|
public static final String OLYMPIAD_CONFIGURATION_FILE = "config/olympiad.ini";
|
||||||
/** Properties file for extensions configurations */
|
/** Properties file for extensions configurations */
|
||||||
public static final String EXTENSIONS_CONFIGURATION_FILE = "config/extensions.ini";
|
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 */
|
/** Text file containing hexadecimal value of server ID */
|
||||||
public static final String HEXID_FILE = "./config/hexid.txt";
|
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_SUPPORT3_FEE;
|
||||||
public static int CS_SUPPORT4_FEE;
|
public static int CS_SUPPORT4_FEE;
|
||||||
|
|
||||||
/** GeoData 0/1/2 */
|
/** GeoData Settings */
|
||||||
public static int GEODATA;
|
public static int PATHFINDING;
|
||||||
public static String GEODATA_DRIVER;
|
|
||||||
|
|
||||||
/** Cell PathFinding */
|
|
||||||
public static boolean GEODATA_CELLFINDING;
|
|
||||||
public static File PATHNODE_DIR;
|
public static File PATHNODE_DIR;
|
||||||
public static String PATHFIND_BUFFERS;
|
public static String PATHFIND_BUFFERS;
|
||||||
public static float LOW_WEIGHT;
|
public static float LOW_WEIGHT;
|
||||||
@@ -1284,10 +1287,11 @@ public final class Config
|
|||||||
public static float DIAGONAL_WEIGHT;
|
public static float DIAGONAL_WEIGHT;
|
||||||
public static int MAX_POSTFILTER_PASSES;
|
public static int MAX_POSTFILTER_PASSES;
|
||||||
public static boolean DEBUG_PATH;
|
public static boolean DEBUG_PATH;
|
||||||
|
|
||||||
/** Force loading GeoData to physical memory */
|
|
||||||
public static boolean FORCE_GEODATA;
|
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<String, Boolean> GEODATA_REGIONS;
|
||||||
|
|
||||||
/** Max number of buffs */
|
/** Max number of buffs */
|
||||||
public static byte BUFFS_MAX_AMOUNT;
|
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.");
|
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();
|
final Properties optionsSettings = new Properties();
|
||||||
try (InputStream is = new FileInputStream(new File(OPTIONS_FILE)))
|
try (InputStream is = new FileInputStream(new File(OPTIONS_FILE)))
|
||||||
{
|
{
|
||||||
@@ -1392,7 +1435,6 @@ public final class Config
|
|||||||
DEBUG = Boolean.parseBoolean(optionsSettings.getProperty("Debug", "false"));
|
DEBUG = Boolean.parseBoolean(optionsSettings.getProperty("Debug", "false"));
|
||||||
ASSERT = Boolean.parseBoolean(optionsSettings.getProperty("Assert", "false"));
|
ASSERT = Boolean.parseBoolean(optionsSettings.getProperty("Assert", "false"));
|
||||||
DEVELOPER = Boolean.parseBoolean(optionsSettings.getProperty("Developer", "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"));
|
TEST_SERVER = Boolean.parseBoolean(optionsSettings.getProperty("TestServer", "false"));
|
||||||
SERVER_LIST_TESTSERVER = 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"));
|
MULTIPLE_ITEM_DROP = Boolean.valueOf(optionsSettings.getProperty("MultipleItemDrop", "True"));
|
||||||
|
|
||||||
final String str = optionsSettings.getProperty("EnableFallingDamage", "auto");
|
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"));
|
ALLOW_WAREHOUSE = Boolean.valueOf(optionsSettings.getProperty("AllowWarehouse", "True"));
|
||||||
WAREHOUSE_CACHE = Boolean.valueOf(optionsSettings.getProperty("WarehouseCache", "False"));
|
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_TURNON_TIME = Integer.parseInt(optionsSettings.getProperty("GridNeighborTurnOnTime", "1"));
|
||||||
GRID_NEIGHBOR_TURNOFF_TIME = Integer.parseInt(optionsSettings.getProperty("GridNeighborTurnOffTime", "90"));
|
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
|
// Configuration values not found in config files
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
|
@@ -63,7 +63,8 @@ import com.l2jmobius.gameserver.datatables.StaticObjects;
|
|||||||
import com.l2jmobius.gameserver.datatables.SummonItemsData;
|
import com.l2jmobius.gameserver.datatables.SummonItemsData;
|
||||||
import com.l2jmobius.gameserver.datatables.TeleportLocationTable;
|
import com.l2jmobius.gameserver.datatables.TeleportLocationTable;
|
||||||
import com.l2jmobius.gameserver.datatables.ZoneTable;
|
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.AdminCommandHandler;
|
||||||
import com.l2jmobius.gameserver.handler.ItemHandler;
|
import com.l2jmobius.gameserver.handler.ItemHandler;
|
||||||
import com.l2jmobius.gameserver.handler.SkillHandler;
|
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.AdminEventEngine;
|
||||||
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminExpSp;
|
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminExpSp;
|
||||||
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminFightCalculator;
|
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.AdminGeodata;
|
||||||
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGm;
|
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGm;
|
||||||
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGmChat;
|
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.model.entity.Hero;
|
||||||
import com.l2jmobius.gameserver.network.L2GameClient;
|
import com.l2jmobius.gameserver.network.L2GameClient;
|
||||||
import com.l2jmobius.gameserver.network.L2GamePacketHandler;
|
import com.l2jmobius.gameserver.network.L2GamePacketHandler;
|
||||||
import com.l2jmobius.gameserver.pathfinding.PathFinding;
|
|
||||||
import com.l2jmobius.gameserver.script.faenor.FaenorScriptEngine;
|
import com.l2jmobius.gameserver.script.faenor.FaenorScriptEngine;
|
||||||
import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager;
|
import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager;
|
||||||
import com.l2jmobius.gameserver.taskmanager.AutoAnnounceTaskManager;
|
import com.l2jmobius.gameserver.taskmanager.AutoAnnounceTaskManager;
|
||||||
@@ -359,7 +358,7 @@ public class GameServer
|
|||||||
ClanTable.getInstance();
|
ClanTable.getInstance();
|
||||||
|
|
||||||
GeoData.getInstance();
|
GeoData.getInstance();
|
||||||
if (Config.GEODATA == 2)
|
if (Config.PATHFINDING > 0)
|
||||||
{
|
{
|
||||||
PathFinding.getInstance();
|
PathFinding.getInstance();
|
||||||
}
|
}
|
||||||
@@ -588,7 +587,6 @@ public class GameServer
|
|||||||
_adminCommandHandler.registerAdminCommandHandler(new AdminQuest());
|
_adminCommandHandler.registerAdminCommandHandler(new AdminQuest());
|
||||||
_adminCommandHandler.registerAdminCommandHandler(new AdminZone());
|
_adminCommandHandler.registerAdminCommandHandler(new AdminZone());
|
||||||
_adminCommandHandler.registerAdminCommandHandler(new AdminGeodata());
|
_adminCommandHandler.registerAdminCommandHandler(new AdminGeodata());
|
||||||
_adminCommandHandler.registerAdminCommandHandler(new AdminGeoEditor());
|
|
||||||
_adminCommandHandler.registerAdminCommandHandler(new AdminManor());
|
_adminCommandHandler.registerAdminCommandHandler(new AdminManor());
|
||||||
|
|
||||||
// _adminCommandHandler.registerAdminCommandHandler(new AdminRadar());
|
// _adminCommandHandler.registerAdminCommandHandler(new AdminRadar());
|
||||||
@@ -630,11 +628,6 @@ public class GameServer
|
|||||||
// read pet stats from db
|
// read pet stats from db
|
||||||
L2PetDataTable.getInstance().loadPetsData();
|
L2PetDataTable.getInstance().loadPetsData();
|
||||||
|
|
||||||
if (Config.ACCEPT_GEOEDITOR_CONN)
|
|
||||||
{
|
|
||||||
GeoEditorListener.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
_shutdownHandler = Shutdown.getInstance();
|
_shutdownHandler = Shutdown.getInstance();
|
||||||
Runtime.getRuntime().addShutdownHook(_shutdownHandler);
|
Runtime.getRuntime().addShutdownHook(_shutdownHandler);
|
||||||
|
|
||||||
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -25,9 +25,9 @@ import java.util.concurrent.Future;
|
|||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GameTimeController;
|
import com.l2jmobius.gameserver.GameTimeController;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.Territory;
|
import com.l2jmobius.gameserver.Territory;
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.instancemanager.DimensionalRiftManager;
|
import com.l2jmobius.gameserver.instancemanager.DimensionalRiftManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Attackable;
|
import com.l2jmobius.gameserver.model.L2Attackable;
|
||||||
import com.l2jmobius.gameserver.model.L2CharPosition;
|
import com.l2jmobius.gameserver.model.L2CharPosition;
|
||||||
@@ -976,7 +976,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Considering, if bigger range will be attempted
|
// 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 posX = _actor.getX();
|
||||||
int posY = _actor.getY();
|
int posY = _actor.getY();
|
||||||
|
@@ -24,8 +24,8 @@ import java.util.concurrent.Future;
|
|||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GameTimeController;
|
import com.l2jmobius.gameserver.GameTimeController;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.model.L2Attackable;
|
import com.l2jmobius.gameserver.model.L2Attackable;
|
||||||
import com.l2jmobius.gameserver.model.L2Character;
|
import com.l2jmobius.gameserver.model.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.L2Effect;
|
import com.l2jmobius.gameserver.model.L2Effect;
|
||||||
|
@@ -27,11 +27,11 @@ import java.util.StringTokenizer;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
|
||||||
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
||||||
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
|
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
||||||
import com.l2jmobius.gameserver.model.entity.ClanHall;
|
import com.l2jmobius.gameserver.model.entity.ClanHall;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
|
||||||
import com.l2jmobius.gameserver.templates.L2CharTemplate;
|
import com.l2jmobius.gameserver.templates.L2CharTemplate;
|
||||||
import com.l2jmobius.gameserver.templates.StatsSet;
|
import com.l2jmobius.gameserver.templates.StatsSet;
|
||||||
|
|
||||||
|
559
L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/GeoData.java
Normal file
559
L2J_Mobius_C4/java/com/l2jmobius/gameserver/geodata/GeoData.java
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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<IRegion> _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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -14,50 +14,44 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
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;
|
public static final NullRegion INSTANCE = new NullRegion();
|
||||||
private int _size;
|
|
||||||
|
|
||||||
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;
|
return worldZ;
|
||||||
_size++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(AbstractNode n)
|
@Override
|
||||||
|
public int getNextLowerZ(int geoX, int geoY, int worldZ)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _size; i++)
|
return worldZ;
|
||||||
{
|
|
||||||
if (_list[i].equals(n))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,93 +1,87 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding;
|
package com.l2jmobius.gameserver.geodata.pathfinding;
|
||||||
|
|
||||||
public abstract class AbstractNode
|
public abstract class AbstractNode<T extends AbstractNodeLoc>
|
||||||
{
|
{
|
||||||
private AbstractNodeLoc _loc;
|
private T _loc;
|
||||||
private AbstractNode _parent;
|
private AbstractNode<T> _parent;
|
||||||
|
|
||||||
public AbstractNode(AbstractNodeLoc loc)
|
public AbstractNode(T loc)
|
||||||
{
|
{
|
||||||
_loc = loc;
|
_loc = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParent(AbstractNode p)
|
public void setParent(AbstractNode<T> p)
|
||||||
{
|
{
|
||||||
_parent = p;
|
_parent = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractNode getParent()
|
public AbstractNode<T> getParent()
|
||||||
{
|
{
|
||||||
return _parent;
|
return _parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractNodeLoc getLoc()
|
public T getLoc()
|
||||||
{
|
{
|
||||||
return _loc;
|
return _loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoc(AbstractNodeLoc l)
|
public void setLoc(T l)
|
||||||
{
|
{
|
||||||
_loc = l;
|
_loc = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see java.lang.Object#hashCode()
|
public int hashCode()
|
||||||
*/
|
{
|
||||||
@Override
|
final int prime = 31;
|
||||||
public int hashCode()
|
int result = 1;
|
||||||
{
|
result = (prime * result) + ((_loc == null) ? 0 : _loc.hashCode());
|
||||||
final int prime = 31;
|
return result;
|
||||||
int result = 1;
|
}
|
||||||
result = (prime * result) + ((_loc == null) ? 0 : _loc.hashCode());
|
|
||||||
return result;
|
@Override
|
||||||
}
|
public boolean equals(Object obj)
|
||||||
|
{
|
||||||
/**
|
if (this == obj)
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
{
|
||||||
*/
|
return true;
|
||||||
@Override
|
}
|
||||||
public boolean equals(Object obj)
|
if (obj == null)
|
||||||
{
|
{
|
||||||
if (this == obj)
|
return false;
|
||||||
{
|
}
|
||||||
return true;
|
if (!(obj instanceof AbstractNode))
|
||||||
}
|
{
|
||||||
if (obj == null)
|
return false;
|
||||||
{
|
}
|
||||||
return false;
|
final AbstractNode<?> other = (AbstractNode<?>) obj;
|
||||||
}
|
if (_loc == null)
|
||||||
if (!(obj instanceof AbstractNode))
|
{
|
||||||
{
|
if (other._loc != null)
|
||||||
return false;
|
{
|
||||||
}
|
return false;
|
||||||
final AbstractNode other = (AbstractNode) obj;
|
}
|
||||||
if (_loc == null)
|
}
|
||||||
{
|
else if (!_loc.equals(other._loc))
|
||||||
if (other._loc != null)
|
{
|
||||||
{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
else if (!_loc.equals(other._loc))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -1,35 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding;
|
package com.l2jmobius.gameserver.geodata.pathfinding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author -Nemesiss-
|
* @author -Nemesiss-
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractNodeLoc
|
public abstract class AbstractNodeLoc
|
||||||
{
|
{
|
||||||
public abstract int getX();
|
public abstract int getX();
|
||||||
|
|
||||||
public abstract int getY();
|
public abstract int getY();
|
||||||
|
|
||||||
public abstract int getZ();
|
public abstract int getZ();
|
||||||
|
|
||||||
public abstract void setZ(short z);
|
public abstract int getNodeX();
|
||||||
|
|
||||||
public abstract int getNodeX();
|
public abstract int getNodeY();
|
||||||
|
}
|
||||||
public abstract int getNodeY();
|
|
||||||
}
|
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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<AbstractNodeLoc> findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable);
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
/*
|
||||||
|
public List<AbstractNodeLoc> 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<AbstractNode> visited = new LinkedList<AbstractNode>();
|
||||||
|
|
||||||
|
// List of Nodes to Visit
|
||||||
|
LinkedList<AbstractNode> to_visit = new LinkedList<AbstractNode>();
|
||||||
|
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<AbstractNodeLoc> 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;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,70 +1,69 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.cellnodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNode;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
|
||||||
|
public class CellNode extends AbstractNode<NodeLoc>
|
||||||
public class CellNode extends AbstractNode
|
{
|
||||||
{
|
private CellNode _next = null;
|
||||||
private CellNode _next = null;
|
private boolean _isInUse = true;
|
||||||
private boolean _isInUse = true;
|
private float _cost = -1000;
|
||||||
private float _cost = -1000;
|
|
||||||
|
public CellNode(NodeLoc loc)
|
||||||
public CellNode(AbstractNodeLoc loc)
|
{
|
||||||
{
|
super(loc);
|
||||||
super(loc);
|
}
|
||||||
}
|
|
||||||
|
public boolean isInUse()
|
||||||
public boolean isInUse()
|
{
|
||||||
{
|
return _isInUse;
|
||||||
return _isInUse;
|
}
|
||||||
}
|
|
||||||
|
public void setInUse()
|
||||||
public void setInUse()
|
{
|
||||||
{
|
_isInUse = true;
|
||||||
_isInUse = true;
|
}
|
||||||
}
|
|
||||||
|
public CellNode getNext()
|
||||||
public CellNode getNext()
|
{
|
||||||
{
|
return _next;
|
||||||
return _next;
|
}
|
||||||
}
|
|
||||||
|
public void setNext(CellNode next)
|
||||||
public void setNext(CellNode next)
|
{
|
||||||
{
|
_next = next;
|
||||||
_next = next;
|
}
|
||||||
}
|
|
||||||
|
public float getCost()
|
||||||
public float getCost()
|
{
|
||||||
{
|
return _cost;
|
||||||
return _cost;
|
}
|
||||||
}
|
|
||||||
|
public void setCost(double cost)
|
||||||
public void setCost(double cost)
|
{
|
||||||
{
|
_cost = (float) cost;
|
||||||
_cost = (float) cost;
|
}
|
||||||
}
|
|
||||||
|
public void free()
|
||||||
public void free()
|
{
|
||||||
{
|
setParent(null);
|
||||||
setParent(null);
|
_cost = -1000;
|
||||||
_cost = -1000;
|
_isInUse = false;
|
||||||
_isInUse = false;
|
_next = null;
|
||||||
_next = null;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@@ -1,364 +1,361 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.cellnodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import com.l2jmobius.Config;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import javolution.util.FastList;
|
import com.l2jmobius.Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author DS Credits to Diamond
|
* @author DS Credits to Diamond
|
||||||
*/
|
*/
|
||||||
public class CellNodeBuffer
|
public class CellNodeBuffer
|
||||||
{
|
{
|
||||||
private static final int MAX_ITERATIONS = 3500;
|
private static final int MAX_ITERATIONS = 3500;
|
||||||
|
|
||||||
private final ReentrantLock _lock = new ReentrantLock();
|
private final ReentrantLock _lock = new ReentrantLock();
|
||||||
private final int _mapSize;
|
private final int _mapSize;
|
||||||
private final CellNode[][] _buffer;
|
private final CellNode[][] _buffer;
|
||||||
|
|
||||||
private int _baseX = 0;
|
private int _baseX = 0;
|
||||||
private int _baseY = 0;
|
private int _baseY = 0;
|
||||||
|
|
||||||
private int _targetX = 0;
|
private int _targetX = 0;
|
||||||
private int _targetY = 0;
|
private int _targetY = 0;
|
||||||
private int _targetZ = 0;
|
private int _targetZ = 0;
|
||||||
|
|
||||||
private long _timeStamp = 0;
|
private long _timeStamp = 0;
|
||||||
private long _lastElapsedTime = 0;
|
private long _lastElapsedTime = 0;
|
||||||
|
|
||||||
private CellNode _current = null;
|
private CellNode _current = null;
|
||||||
|
|
||||||
public CellNodeBuffer(int size)
|
public CellNodeBuffer(int size)
|
||||||
{
|
{
|
||||||
_mapSize = size;
|
_mapSize = size;
|
||||||
_buffer = new CellNode[_mapSize][_mapSize];
|
_buffer = new CellNode[_mapSize][_mapSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean lock()
|
public final boolean lock()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CellNode findPath(int x, int y, int z, int tx, int ty, int tz)
|
public final CellNode findPath(int x, int y, int z, int tx, int ty, int tz)
|
||||||
{
|
{
|
||||||
_timeStamp = System.currentTimeMillis();
|
_timeStamp = System.currentTimeMillis();
|
||||||
_baseX = x + ((tx - x - _mapSize) / 2); // middle of the line (x,y) - (tx,ty)
|
_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
|
_baseY = y + ((ty - y - _mapSize) / 2); // will be in the center of the buffer
|
||||||
_targetX = tx;
|
_targetX = tx;
|
||||||
_targetY = ty;
|
_targetY = ty;
|
||||||
_targetZ = tz;
|
_targetZ = tz;
|
||||||
_current = getNode(x, y, z);
|
_current = getNode(x, y, z);
|
||||||
_current.setCost(getCost(x, y, z, Config.HIGH_WEIGHT));
|
_current.setCost(getCost(x, y, z, Config.HIGH_WEIGHT));
|
||||||
|
|
||||||
for (int count = 0; count < MAX_ITERATIONS; count++)
|
for (int count = 0; count < MAX_ITERATIONS; count++)
|
||||||
{
|
{
|
||||||
if ((_current.getLoc().getNodeX() == _targetX) && (_current.getLoc().getNodeY() == _targetY) && (Math.abs(_current.getLoc().getZ() - _targetZ) < 64))
|
if ((_current.getLoc().getNodeX() == _targetX) && (_current.getLoc().getNodeY() == _targetY) && (Math.abs(_current.getLoc().getZ() - _targetZ) < 64))
|
||||||
{
|
{
|
||||||
return _current; // found
|
return _current; // found
|
||||||
}
|
}
|
||||||
|
|
||||||
getNeighbors();
|
getNeighbors();
|
||||||
if (_current.getNext() == null)
|
if (_current.getNext() == null)
|
||||||
{
|
{
|
||||||
return null; // no more ways
|
return null; // no more ways
|
||||||
}
|
}
|
||||||
|
|
||||||
_current = _current.getNext();
|
_current = _current.getNext();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void free()
|
public final void free()
|
||||||
{
|
{
|
||||||
_current = null;
|
_current = null;
|
||||||
|
|
||||||
CellNode node;
|
CellNode node;
|
||||||
for (int i = 0; i < _mapSize; i++)
|
for (int i = 0; i < _mapSize; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < _mapSize; j++)
|
for (int j = 0; j < _mapSize; j++)
|
||||||
{
|
{
|
||||||
node = _buffer[i][j];
|
node = _buffer[i][j];
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
node.free();
|
node.free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lock.unlock();
|
_lock.unlock();
|
||||||
_lastElapsedTime = System.currentTimeMillis() - _timeStamp;
|
_lastElapsedTime = System.currentTimeMillis() - _timeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final long getElapsedTime()
|
public final long getElapsedTime()
|
||||||
{
|
{
|
||||||
return _lastElapsedTime;
|
return _lastElapsedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final FastList<CellNode> debugPath()
|
public final List<CellNode> debugPath()
|
||||||
{
|
{
|
||||||
final FastList<CellNode> result = new FastList<>();
|
final List<CellNode> result = new LinkedList<>();
|
||||||
|
|
||||||
for (CellNode n = _current; n.getParent() != null; n = (CellNode) n.getParent())
|
for (CellNode n = _current; n.getParent() != null; n = (CellNode) n.getParent())
|
||||||
{
|
{
|
||||||
result.add(n);
|
result.add(n);
|
||||||
n.setCost(-n.getCost());
|
n.setCost(-n.getCost());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _mapSize; i++)
|
for (int i = 0; i < _mapSize; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < _mapSize; j++)
|
for (int j = 0; j < _mapSize; j++)
|
||||||
{
|
{
|
||||||
final CellNode n = _buffer[i][j];
|
final CellNode n = _buffer[i][j];
|
||||||
if ((n == null) || !n.isInUse() || (n.getCost() <= 0))
|
if ((n == null) || !n.isInUse() || (n.getCost() <= 0))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(n);
|
result.add(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void getNeighbors()
|
private void getNeighbors()
|
||||||
{
|
{
|
||||||
if (((NodeLoc) _current.getLoc()).canGoNone())
|
if (!_current.getLoc().canGoAll())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int x = _current.getLoc().getNodeX();
|
final int x = _current.getLoc().getNodeX();
|
||||||
final int y = _current.getLoc().getNodeY();
|
final int y = _current.getLoc().getNodeY();
|
||||||
final int z = _current.getLoc().getZ();
|
final int z = _current.getLoc().getZ();
|
||||||
|
|
||||||
CellNode nodeE = null;
|
CellNode nodeE = null;
|
||||||
CellNode nodeS = null;
|
CellNode nodeS = null;
|
||||||
CellNode nodeW = null;
|
CellNode nodeW = null;
|
||||||
CellNode nodeN = null;
|
CellNode nodeN = null;
|
||||||
|
|
||||||
// East
|
// East
|
||||||
if (((NodeLoc) _current.getLoc()).canGoEast())
|
if (_current.getLoc().canGoEast())
|
||||||
{
|
{
|
||||||
nodeE = addNode(x + 1, y, z, false);
|
nodeE = addNode(x + 1, y, z, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// South
|
// South
|
||||||
if (((NodeLoc) _current.getLoc()).canGoSouth())
|
if (_current.getLoc().canGoSouth())
|
||||||
{
|
{
|
||||||
nodeS = addNode(x, y + 1, z, false);
|
nodeS = addNode(x, y + 1, z, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// West
|
// West
|
||||||
if (((NodeLoc) _current.getLoc()).canGoWest())
|
if (_current.getLoc().canGoWest())
|
||||||
{
|
{
|
||||||
nodeW = addNode(x - 1, y, z, false);
|
nodeW = addNode(x - 1, y, z, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// North
|
// North
|
||||||
if (((NodeLoc) _current.getLoc()).canGoNorth())
|
if (_current.getLoc().canGoNorth())
|
||||||
{
|
{
|
||||||
nodeN = addNode(x, y - 1, z, false);
|
nodeN = addNode(x, y - 1, z, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.ADVANCED_DIAGONAL_STRATEGY)
|
if (Config.ADVANCED_DIAGONAL_STRATEGY)
|
||||||
{
|
{
|
||||||
// SouthEast
|
// SouthEast
|
||||||
if ((nodeE != null) && (nodeS != null))
|
if ((nodeE != null) && (nodeS != null))
|
||||||
{
|
{
|
||||||
if (((NodeLoc) nodeE.getLoc()).canGoSouth() && ((NodeLoc) nodeS.getLoc()).canGoEast())
|
if (nodeE.getLoc().canGoSouth() && nodeS.getLoc().canGoEast())
|
||||||
{
|
{
|
||||||
addNode(x + 1, y + 1, z, true);
|
addNode(x + 1, y + 1, z, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SouthWest
|
// SouthWest
|
||||||
if ((nodeS != null) && (nodeW != null))
|
if ((nodeS != null) && (nodeW != null))
|
||||||
{
|
{
|
||||||
if (((NodeLoc) nodeW.getLoc()).canGoSouth() && ((NodeLoc) nodeS.getLoc()).canGoWest())
|
if (nodeW.getLoc().canGoSouth() && nodeS.getLoc().canGoWest())
|
||||||
{
|
{
|
||||||
addNode(x - 1, y + 1, z, true);
|
addNode(x - 1, y + 1, z, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NorthEast
|
// NorthEast
|
||||||
if ((nodeN != null) && (nodeE != null))
|
if ((nodeN != null) && (nodeE != null))
|
||||||
{
|
{
|
||||||
if (((NodeLoc) nodeE.getLoc()).canGoNorth() && ((NodeLoc) nodeN.getLoc()).canGoEast())
|
if (nodeE.getLoc().canGoNorth() && nodeN.getLoc().canGoEast())
|
||||||
{
|
{
|
||||||
addNode(x + 1, y - 1, z, true);
|
addNode(x + 1, y - 1, z, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NorthWest
|
// NorthWest
|
||||||
if ((nodeN != null) && (nodeW != null))
|
if ((nodeN != null) && (nodeW != null))
|
||||||
{
|
{
|
||||||
if (((NodeLoc) nodeW.getLoc()).canGoNorth() && ((NodeLoc) nodeN.getLoc()).canGoWest())
|
if (nodeW.getLoc().canGoNorth() && nodeN.getLoc().canGoWest())
|
||||||
{
|
{
|
||||||
addNode(x - 1, y - 1, z, true);
|
addNode(x - 1, y - 1, z, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final CellNode getNode(int x, int y, int z)
|
private CellNode getNode(int x, int y, int z)
|
||||||
{
|
{
|
||||||
final int aX = x - _baseX;
|
final int aX = x - _baseX;
|
||||||
if ((aX < 0) || (aX >= _mapSize))
|
if ((aX < 0) || (aX >= _mapSize))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int aY = y - _baseY;
|
final int aY = y - _baseY;
|
||||||
if ((aY < 0) || (aY >= _mapSize))
|
if ((aY < 0) || (aY >= _mapSize))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
CellNode result = _buffer[aX][aY];
|
CellNode result = _buffer[aX][aY];
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
result = new CellNode(new NodeLoc(x, y, z));
|
result = new CellNode(new NodeLoc(x, y, z));
|
||||||
_buffer[aX][aY] = result;
|
_buffer[aX][aY] = result;
|
||||||
}
|
}
|
||||||
else if (!result.isInUse())
|
else if (!result.isInUse())
|
||||||
{
|
{
|
||||||
result.setInUse();
|
result.setInUse();
|
||||||
// reinit node if needed
|
// reinit node if needed
|
||||||
if (result.getLoc() != null)
|
if (result.getLoc() != null)
|
||||||
{
|
{
|
||||||
((NodeLoc) result.getLoc()).set(x, y, z);
|
result.getLoc().set(x, y, z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.setLoc(new NodeLoc(x, y, z));
|
result.setLoc(new NodeLoc(x, y, z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final CellNode addNode(int x, int y, int z, boolean diagonal)
|
private CellNode addNode(int x, int y, int z, boolean diagonal)
|
||||||
{
|
{
|
||||||
final CellNode newNode = getNode(x, y, z);
|
final CellNode newNode = getNode(x, y, z);
|
||||||
if (newNode == null)
|
if (newNode == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (newNode.getCost() >= 0)
|
if (newNode.getCost() >= 0)
|
||||||
{
|
{
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int geoZ = newNode.getLoc().getZ();
|
final int geoZ = newNode.getLoc().getZ();
|
||||||
|
|
||||||
final int stepZ = Math.abs(geoZ - _current.getLoc().getZ());
|
final int stepZ = Math.abs(geoZ - _current.getLoc().getZ());
|
||||||
float weight = diagonal ? Config.DIAGONAL_WEIGHT : Config.LOW_WEIGHT;
|
float weight = diagonal ? Config.DIAGONAL_WEIGHT : Config.LOW_WEIGHT;
|
||||||
|
|
||||||
if (!((NodeLoc) newNode.getLoc()).canGoAll() || (stepZ > 16))
|
if (!newNode.getLoc().canGoAll() || (stepZ > 16))
|
||||||
{
|
{
|
||||||
weight = Config.HIGH_WEIGHT;
|
weight = Config.HIGH_WEIGHT;
|
||||||
}
|
}
|
||||||
else
|
else if (isHighWeight(x + 1, y, geoZ))
|
||||||
{
|
{
|
||||||
if (isHighWeight(x + 1, y, geoZ))
|
weight = Config.MEDIUM_WEIGHT;
|
||||||
{
|
}
|
||||||
weight = Config.MEDIUM_WEIGHT;
|
else if (isHighWeight(x - 1, y, geoZ))
|
||||||
}
|
{
|
||||||
else if (isHighWeight(x - 1, y, geoZ))
|
weight = Config.MEDIUM_WEIGHT;
|
||||||
{
|
}
|
||||||
weight = Config.MEDIUM_WEIGHT;
|
else if (isHighWeight(x, y + 1, geoZ))
|
||||||
}
|
{
|
||||||
else if (isHighWeight(x, y + 1, geoZ))
|
weight = Config.MEDIUM_WEIGHT;
|
||||||
{
|
}
|
||||||
weight = Config.MEDIUM_WEIGHT;
|
else if (isHighWeight(x, y - 1, geoZ))
|
||||||
}
|
{
|
||||||
else if (isHighWeight(x, y - 1, geoZ))
|
weight = Config.MEDIUM_WEIGHT;
|
||||||
{
|
}
|
||||||
weight = Config.MEDIUM_WEIGHT;
|
|
||||||
}
|
newNode.setParent(_current);
|
||||||
}
|
newNode.setCost(getCost(x, y, geoZ, weight));
|
||||||
|
|
||||||
newNode.setParent(_current);
|
CellNode node = _current;
|
||||||
newNode.setCost(getCost(x, y, geoZ, weight));
|
int count = 0;
|
||||||
|
while ((node.getNext() != null) && (count < (MAX_ITERATIONS * 4)))
|
||||||
CellNode node = _current;
|
{
|
||||||
int count = 0;
|
count++;
|
||||||
while ((node.getNext() != null) && (count < (MAX_ITERATIONS * 4)))
|
if (node.getNext().getCost() > newNode.getCost())
|
||||||
{
|
{
|
||||||
count++;
|
// insert node into a chain
|
||||||
if (node.getNext().getCost() > newNode.getCost())
|
newNode.setNext(node.getNext());
|
||||||
{
|
break;
|
||||||
// insert node into a chain
|
}
|
||||||
newNode.setNext(node.getNext());
|
node = node.getNext();
|
||||||
break;
|
}
|
||||||
}
|
if (count == (MAX_ITERATIONS * 4))
|
||||||
node = node.getNext();
|
{
|
||||||
}
|
System.err.println("Pathfinding: too long loop detected, cost:" + newNode.getCost());
|
||||||
if (count == (MAX_ITERATIONS * 4))
|
}
|
||||||
{
|
|
||||||
System.err.println("Pathfinding: too long loop detected, cost:" + newNode.getCost());
|
node.setNext(newNode); // add last
|
||||||
}
|
|
||||||
|
return newNode;
|
||||||
node.setNext(newNode); // add last
|
}
|
||||||
|
|
||||||
return newNode;
|
private boolean isHighWeight(int x, int y, int z)
|
||||||
}
|
{
|
||||||
|
final CellNode result = getNode(x, y, z);
|
||||||
private final boolean isHighWeight(int x, int y, int z)
|
if (result == null)
|
||||||
{
|
{
|
||||||
final CellNode result = getNode(x, y, z);
|
return true;
|
||||||
if (result == null)
|
}
|
||||||
{
|
|
||||||
return true;
|
if (!result.getLoc().canGoAll())
|
||||||
}
|
{
|
||||||
|
return true;
|
||||||
if (!((NodeLoc) result.getLoc()).canGoAll())
|
}
|
||||||
{
|
if (Math.abs(result.getLoc().getZ() - z) > 16)
|
||||||
return true;
|
{
|
||||||
}
|
return true;
|
||||||
if (Math.abs(result.getLoc().getZ() - z) > 16)
|
}
|
||||||
{
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
private double getCost(int x, int y, int z, float weight)
|
||||||
}
|
{
|
||||||
|
final int dX = x - _targetX;
|
||||||
private final double getCost(int x, int y, int z, float weight)
|
final int dY = y - _targetY;
|
||||||
{
|
final int dZ = z - _targetZ;
|
||||||
final int dX = x - _targetX;
|
// Math.abs(dx) + Math.abs(dy) + Math.abs(dz) / 16
|
||||||
final int dY = y - _targetY;
|
double result = Math.sqrt((dX * dX) + (dY * dY) + ((dZ * dZ) / 256.0));
|
||||||
final int dZ = z - _targetZ;
|
if (result > weight)
|
||||||
// Math.abs(dx) + Math.abs(dy) + Math.abs(dz) / 16
|
{
|
||||||
double result = Math.sqrt((dX * dX) + (dY * dY) + ((dZ * dZ) / 256));
|
result += weight;
|
||||||
if (result > weight)
|
}
|
||||||
{
|
|
||||||
result += weight;
|
if (result > Float.MAX_VALUE)
|
||||||
}
|
{
|
||||||
|
result = Float.MAX_VALUE;
|
||||||
if (result > Float.MAX_VALUE)
|
}
|
||||||
{
|
|
||||||
result = Float.MAX_VALUE;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -1,413 +1,439 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.cellnodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.LinkedList;
|
||||||
import java.util.ListIterator;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.ListIterator;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import com.l2jmobius.Config;
|
import java.util.logging.Level;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
import java.util.logging.Logger;
|
||||||
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
|
||||||
import com.l2jmobius.gameserver.model.L2ItemInstance;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNode;
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
|
||||||
import com.l2jmobius.gameserver.pathfinding.PathFinding;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
|
||||||
import com.l2jmobius.util.StringUtil;
|
import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
|
||||||
|
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
||||||
import javolution.util.FastList;
|
import com.l2jmobius.gameserver.model.Inventory;
|
||||||
|
import com.l2jmobius.gameserver.model.L2ItemInstance;
|
||||||
/**
|
|
||||||
* @author Sami, DS Credits to Diamond
|
/**
|
||||||
*/
|
* @author Sami, DS Credits to Diamond
|
||||||
public class CellPathFinding extends PathFinding
|
*/
|
||||||
{
|
public class CellPathFinding extends PathFinding
|
||||||
private static final Logger _log = Logger.getLogger(CellPathFinding.class.getName());
|
{
|
||||||
private BufferInfo[] _allBuffers;
|
private static final Logger _log = Logger.getLogger(CellPathFinding.class.getName());
|
||||||
private int _findSuccess = 0;
|
private BufferInfo[] _allBuffers;
|
||||||
private int _findFails = 0;
|
private int _findSuccess = 0;
|
||||||
private int _postFilterUses = 0;
|
private int _findFails = 0;
|
||||||
private int _postFilterPlayableUses = 0;
|
private int _postFilterUses = 0;
|
||||||
private int _postFilterPasses = 0;
|
private int _postFilterPlayableUses = 0;
|
||||||
private long _postFilterElapsed = 0;
|
private int _postFilterPasses = 0;
|
||||||
|
private long _postFilterElapsed = 0;
|
||||||
private FastList<L2ItemInstance> _debugItems = null;
|
|
||||||
|
private List<L2ItemInstance> _debugItems = null;
|
||||||
private static CellPathFinding _instance;
|
|
||||||
|
public static CellPathFinding getInstance()
|
||||||
public static CellPathFinding getInstance()
|
{
|
||||||
{
|
return SingletonHolder._instance;
|
||||||
if (_instance == null)
|
}
|
||||||
{
|
|
||||||
_instance = new CellPathFinding();
|
protected CellPathFinding()
|
||||||
}
|
{
|
||||||
return _instance;
|
try
|
||||||
}
|
{
|
||||||
|
final String[] array = Config.PATHFIND_BUFFERS.split(";");
|
||||||
private CellPathFinding()
|
|
||||||
{
|
_allBuffers = new BufferInfo[array.length];
|
||||||
try
|
|
||||||
{
|
String buf;
|
||||||
final String[] array = Config.PATHFIND_BUFFERS.split(";");
|
String[] args;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
_allBuffers = new BufferInfo[array.length];
|
{
|
||||||
|
buf = array[i];
|
||||||
String buf;
|
args = buf.split("x");
|
||||||
String[] args;
|
if (args.length != 2)
|
||||||
for (int i = 0; i < array.length; i++)
|
{
|
||||||
{
|
throw new Exception("Invalid buffer definition: " + buf);
|
||||||
buf = array[i];
|
}
|
||||||
args = buf.split("x");
|
|
||||||
if (args.length != 2)
|
_allBuffers[i] = new BufferInfo(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
|
||||||
{
|
}
|
||||||
throw new Exception("Invalid buffer definition: " + buf);
|
}
|
||||||
}
|
catch (Exception e)
|
||||||
|
{
|
||||||
_allBuffers[i] = new BufferInfo(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
|
_log.log(Level.WARNING, "CellPathFinding: Problem during buffer init: " + e.getMessage(), e);
|
||||||
}
|
throw new Error("CellPathFinding: load aborted");
|
||||||
}
|
}
|
||||||
catch (final Exception e)
|
}
|
||||||
{
|
|
||||||
_log.warning("CellPathFinding: Problem during buffer init: " + e.getMessage());
|
@Override
|
||||||
throw new Error("CellPathFinding: load aborted");
|
public boolean pathNodesExist(short regionoffset)
|
||||||
}
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.PathFinding#pathNodesExist(short)
|
@Override
|
||||||
*/
|
public List<AbstractNodeLoc> findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
|
||||||
@Override
|
{
|
||||||
public boolean pathNodesExist(short regionoffset)
|
final int gx = GeoData.getInstance().getGeoX(x);
|
||||||
{
|
final int gy = GeoData.getInstance().getGeoY(y);
|
||||||
return false;
|
if (!GeoData.getInstance().hasGeo(x, y))
|
||||||
}
|
{
|
||||||
|
return null;
|
||||||
@Override
|
}
|
||||||
public List<AbstractNodeLoc> findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
|
final int gz = GeoData.getInstance().getHeight(x, y, z);
|
||||||
{
|
final int gtx = GeoData.getInstance().getGeoX(tx);
|
||||||
final int gx = GeoData.getInstance().getGeoX(x);
|
final int gty = GeoData.getInstance().getGeoY(ty);
|
||||||
final int gy = GeoData.getInstance().getGeoY(y);
|
if (!GeoData.getInstance().hasGeo(tx, ty))
|
||||||
if (!GeoData.getInstance().hasGeo(x, y))
|
{
|
||||||
{
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
final int gtz = GeoData.getInstance().getHeight(tx, ty, tz);
|
||||||
final int gz = GeoData.getInstance().getHeight(x, y, z);
|
final CellNodeBuffer buffer = alloc(64 + (2 * Math.max(Math.abs(gx - gtx), Math.abs(gy - gty))), playable);
|
||||||
final int gtx = GeoData.getInstance().getGeoX(tx);
|
if (buffer == null)
|
||||||
final int gty = GeoData.getInstance().getGeoY(ty);
|
{
|
||||||
if (!GeoData.getInstance().hasGeo(tx, ty))
|
return null;
|
||||||
{
|
}
|
||||||
return null;
|
|
||||||
}
|
final boolean debug = playable && Config.DEBUG_PATH;
|
||||||
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 (debug)
|
||||||
if (buffer == null)
|
{
|
||||||
{
|
if (_debugItems == null)
|
||||||
return null;
|
{
|
||||||
}
|
_debugItems = new CopyOnWriteArrayList<>();
|
||||||
|
}
|
||||||
final boolean debug = playable && Config.DEBUG_PATH;
|
else
|
||||||
|
{
|
||||||
if (debug)
|
for (L2ItemInstance item : _debugItems)
|
||||||
{
|
{
|
||||||
if (_debugItems == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
_debugItems = new FastList<>();
|
continue;
|
||||||
}
|
}
|
||||||
else
|
item.decayMe();
|
||||||
{
|
}
|
||||||
for (final L2ItemInstance item : _debugItems)
|
|
||||||
{
|
_debugItems.clear();
|
||||||
if (item == null)
|
}
|
||||||
{
|
}
|
||||||
continue;
|
|
||||||
}
|
List<AbstractNodeLoc> path = null;
|
||||||
item.decayMe();
|
try
|
||||||
}
|
{
|
||||||
|
final CellNode result = buffer.findPath(gx, gy, gz, gtx, gty, gtz);
|
||||||
_debugItems.clear();
|
|
||||||
}
|
if (debug)
|
||||||
}
|
{
|
||||||
|
for (CellNode n : buffer.debugPath())
|
||||||
FastList<AbstractNodeLoc> path = null;
|
{
|
||||||
try
|
if (n.getCost() < 0)
|
||||||
{
|
{
|
||||||
final CellNode result = buffer.findPath(gx, gy, gz, gtx, gty, gtz);
|
dropDebugItem(1831, (int) (-n.getCost() * 10), n.getLoc());
|
||||||
|
}
|
||||||
if (debug)
|
else
|
||||||
{
|
{
|
||||||
for (final CellNode n : buffer.debugPath())
|
// known nodes
|
||||||
{
|
dropDebugItem(Inventory.ADENA_ID, (int) (n.getCost() * 10), n.getLoc());
|
||||||
if (n.getCost() < 0)
|
}
|
||||||
{
|
}
|
||||||
dropDebugItem(1831, (int) (-n.getCost() * 10), n.getLoc());
|
}
|
||||||
}
|
|
||||||
else
|
if (result == null)
|
||||||
{
|
{
|
||||||
dropDebugItem(57, (int) (n.getCost() * 10), n.getLoc());
|
_findFails++;
|
||||||
}
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
path = constructPath(result);
|
||||||
if (result == null)
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
_findFails++;
|
{
|
||||||
return null;
|
_log.log(Level.WARNING, "", e);
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
path = constructPath(result);
|
finally
|
||||||
}
|
{
|
||||||
catch (final Exception e)
|
buffer.free();
|
||||||
{
|
}
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
if ((path.size() < 3) || (Config.MAX_POSTFILTER_PASSES <= 0))
|
||||||
}
|
{
|
||||||
finally
|
_findSuccess++;
|
||||||
{
|
return path;
|
||||||
buffer.free();
|
}
|
||||||
}
|
|
||||||
|
final long timeStamp = System.currentTimeMillis();
|
||||||
if ((path.size() < 3) || (Config.MAX_POSTFILTER_PASSES <= 0))
|
_postFilterUses++;
|
||||||
{
|
if (playable)
|
||||||
_findSuccess++;
|
{
|
||||||
return path;
|
_postFilterPlayableUses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
final long timeStamp = System.currentTimeMillis();
|
int currentX, currentY, currentZ;
|
||||||
_postFilterUses++;
|
ListIterator<AbstractNodeLoc> middlePoint;
|
||||||
if (playable)
|
boolean remove;
|
||||||
{
|
int pass = 0;
|
||||||
_postFilterPlayableUses++;
|
do
|
||||||
}
|
{
|
||||||
|
pass++;
|
||||||
int currentX, currentY, currentZ;
|
_postFilterPasses++;
|
||||||
ListIterator<AbstractNodeLoc> middlePoint, endPoint;
|
|
||||||
AbstractNodeLoc locMiddle, locEnd;
|
remove = false;
|
||||||
boolean remove;
|
middlePoint = path.listIterator();
|
||||||
int pass = 0;
|
currentX = x;
|
||||||
do
|
currentY = y;
|
||||||
{
|
currentZ = z;
|
||||||
pass++;
|
|
||||||
_postFilterPasses++;
|
while (middlePoint.hasNext())
|
||||||
|
{
|
||||||
remove = false;
|
final AbstractNodeLoc locMiddle = middlePoint.next();
|
||||||
middlePoint = path.listIterator();
|
if (!middlePoint.hasNext())
|
||||||
endPoint = path.listIterator(1);
|
{
|
||||||
locEnd = null;
|
break;
|
||||||
currentX = x;
|
}
|
||||||
currentY = y;
|
|
||||||
currentZ = z;
|
final AbstractNodeLoc locEnd = path.get(middlePoint.nextIndex());
|
||||||
|
if (GeoData.getInstance().canMove(currentX, currentY, currentZ, locEnd.getX(), locEnd.getY(), locEnd.getZ()))
|
||||||
while (endPoint.hasNext())
|
{
|
||||||
{
|
middlePoint.remove();
|
||||||
locEnd = endPoint.next();
|
remove = true;
|
||||||
locMiddle = middlePoint.next();
|
if (debug)
|
||||||
if (GeoData.getInstance().canMove(currentX, currentY, currentZ, locEnd.getX(), locEnd.getY(), locEnd.getZ()))
|
{
|
||||||
{
|
dropDebugItem(735, 1, locMiddle);
|
||||||
middlePoint.remove();
|
}
|
||||||
remove = true;
|
}
|
||||||
if (debug)
|
else
|
||||||
{
|
{
|
||||||
dropDebugItem(735, 1, locMiddle);
|
currentX = locMiddle.getX();
|
||||||
}
|
currentY = locMiddle.getY();
|
||||||
}
|
currentZ = locMiddle.getZ();
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
currentX = locMiddle.getX();
|
}
|
||||||
currentY = locMiddle.getY();
|
// only one postfilter pass for AI
|
||||||
currentZ = locMiddle.getZ();
|
while (playable && remove && (path.size() > 2) && (pass < Config.MAX_POSTFILTER_PASSES));
|
||||||
}
|
|
||||||
}
|
if (debug)
|
||||||
}
|
{
|
||||||
// only one postfilter pass for AI
|
path.forEach(n -> dropDebugItem(65, 1, n));
|
||||||
while (playable && remove && (path.size() > 2) && (pass < Config.MAX_POSTFILTER_PASSES));
|
}
|
||||||
|
|
||||||
if (debug)
|
_findSuccess++;
|
||||||
{
|
_postFilterElapsed += System.currentTimeMillis() - timeStamp;
|
||||||
middlePoint = path.listIterator();
|
return path;
|
||||||
while (middlePoint.hasNext())
|
}
|
||||||
{
|
|
||||||
locMiddle = middlePoint.next();
|
private List<AbstractNodeLoc> constructPath(AbstractNode<NodeLoc> node)
|
||||||
dropDebugItem(65, 1, locMiddle);
|
{
|
||||||
}
|
final LinkedList<AbstractNodeLoc> path = new LinkedList<>();
|
||||||
}
|
int previousDirectionX = Integer.MIN_VALUE;
|
||||||
|
int previousDirectionY = Integer.MIN_VALUE;
|
||||||
_findSuccess++;
|
int directionX, directionY;
|
||||||
_postFilterElapsed += System.currentTimeMillis() - timeStamp;
|
|
||||||
return path;
|
while (node.getParent() != null)
|
||||||
}
|
{
|
||||||
|
if (!Config.ADVANCED_DIAGONAL_STRATEGY && (node.getParent().getParent() != null))
|
||||||
private FastList<AbstractNodeLoc> constructPath(AbstractNode node)
|
{
|
||||||
{
|
final int tmpX = node.getLoc().getNodeX() - node.getParent().getParent().getLoc().getNodeX();
|
||||||
final FastList<AbstractNodeLoc> path = new FastList<>();
|
final int tmpY = node.getLoc().getNodeY() - node.getParent().getParent().getLoc().getNodeY();
|
||||||
int previousDirectionX = Integer.MIN_VALUE;
|
if (Math.abs(tmpX) == Math.abs(tmpY))
|
||||||
int previousDirectionY = Integer.MIN_VALUE;
|
{
|
||||||
int directionX, directionY;
|
directionX = tmpX;
|
||||||
|
directionY = tmpY;
|
||||||
while (node.getParent() != null)
|
}
|
||||||
{
|
else
|
||||||
if (!Config.ADVANCED_DIAGONAL_STRATEGY && (node.getParent().getParent() != null))
|
{
|
||||||
{
|
directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
|
||||||
final int tmpX = node.getLoc().getNodeX() - node.getParent().getParent().getLoc().getNodeX();
|
directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
|
||||||
final int tmpY = node.getLoc().getNodeY() - node.getParent().getParent().getLoc().getNodeY();
|
}
|
||||||
if (Math.abs(tmpX) == Math.abs(tmpY))
|
}
|
||||||
{
|
else
|
||||||
directionX = tmpX;
|
{
|
||||||
directionY = tmpY;
|
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();
|
// only add a new route point if moving direction changes
|
||||||
directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
|
if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
|
||||||
}
|
{
|
||||||
}
|
previousDirectionX = directionX;
|
||||||
else
|
previousDirectionY = directionY;
|
||||||
{
|
|
||||||
directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
|
path.addFirst(node.getLoc());
|
||||||
directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
|
node.setLoc(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only add a new route point if moving direction changes
|
node = node.getParent();
|
||||||
if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
|
}
|
||||||
{
|
|
||||||
previousDirectionX = directionX;
|
return path;
|
||||||
previousDirectionY = directionY;
|
}
|
||||||
|
|
||||||
path.addFirst(node.getLoc());
|
private CellNodeBuffer alloc(int size, boolean playable)
|
||||||
node.setLoc(null);
|
{
|
||||||
}
|
CellNodeBuffer current = null;
|
||||||
|
for (BufferInfo i : _allBuffers)
|
||||||
node = node.getParent();
|
{
|
||||||
}
|
if (i.mapSize >= size)
|
||||||
|
{
|
||||||
return path;
|
for (CellNodeBuffer buf : i.bufs)
|
||||||
}
|
{
|
||||||
|
if (buf.lock())
|
||||||
private final CellNodeBuffer alloc(int size, boolean playable)
|
{
|
||||||
{
|
i.uses++;
|
||||||
CellNodeBuffer current = null;
|
if (playable)
|
||||||
for (final BufferInfo i : _allBuffers)
|
{
|
||||||
{
|
i.playableUses++;
|
||||||
if (i.mapSize >= size)
|
}
|
||||||
{
|
i.elapsed += buf.getElapsedTime();
|
||||||
for (final CellNodeBuffer buf : i.bufs)
|
current = buf;
|
||||||
{
|
break;
|
||||||
if (buf.lock())
|
}
|
||||||
{
|
}
|
||||||
i.uses++;
|
if (current != null)
|
||||||
if (playable)
|
{
|
||||||
{
|
break;
|
||||||
i.playableUses++;
|
}
|
||||||
}
|
|
||||||
i.elapsed += buf.getElapsedTime();
|
// not found, allocate temporary buffer
|
||||||
current = buf;
|
current = new CellNodeBuffer(i.mapSize);
|
||||||
break;
|
current.lock();
|
||||||
}
|
if (i.bufs.size() < i.count)
|
||||||
}
|
{
|
||||||
if (current != null)
|
i.bufs.add(current);
|
||||||
{
|
i.uses++;
|
||||||
break;
|
if (playable)
|
||||||
}
|
{
|
||||||
|
i.playableUses++;
|
||||||
// not found, allocate temporary buffer
|
}
|
||||||
current = new CellNodeBuffer(i.mapSize);
|
break;
|
||||||
current.lock();
|
}
|
||||||
if (i.bufs.size() < i.count)
|
|
||||||
{
|
i.overflows++;
|
||||||
i.bufs.add(current);
|
if (playable)
|
||||||
i.uses++;
|
{
|
||||||
if (playable)
|
i.playableOverflows++;
|
||||||
{
|
// System.err.println("Overflow, size requested: " + size + " playable:"+playable);
|
||||||
i.playableUses++;
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
return current;
|
||||||
i.overflows++;
|
}
|
||||||
if (playable)
|
|
||||||
{
|
private void dropDebugItem(int itemId, int num, AbstractNodeLoc loc)
|
||||||
i.playableOverflows++;
|
{
|
||||||
}
|
final L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
|
||||||
}
|
item.setCount(num);
|
||||||
}
|
item.spawnMe(loc.getX(), loc.getY(), loc.getZ());
|
||||||
|
_debugItems.add(item);
|
||||||
return current;
|
}
|
||||||
}
|
|
||||||
|
private static final class BufferInfo
|
||||||
private final void dropDebugItem(int itemId, int num, AbstractNodeLoc loc)
|
{
|
||||||
{
|
final int mapSize;
|
||||||
final L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
|
final int count;
|
||||||
item.setCount(num);
|
ArrayList<CellNodeBuffer> bufs;
|
||||||
item.spawnMe(loc.getX(), loc.getY(), loc.getZ());
|
int uses = 0;
|
||||||
_debugItems.add(item);
|
int playableUses = 0;
|
||||||
}
|
int overflows = 0;
|
||||||
|
int playableOverflows = 0;
|
||||||
private static final class BufferInfo
|
long elapsed = 0;
|
||||||
{
|
|
||||||
final int mapSize;
|
public BufferInfo(int size, int cnt)
|
||||||
final int count;
|
{
|
||||||
ArrayList<CellNodeBuffer> bufs;
|
mapSize = size;
|
||||||
int uses = 0;
|
count = cnt;
|
||||||
int playableUses = 0;
|
bufs = new ArrayList<>(count);
|
||||||
int overflows = 0;
|
}
|
||||||
int playableOverflows = 0;
|
|
||||||
long elapsed = 0;
|
@Override
|
||||||
|
public String toString()
|
||||||
public BufferInfo(int size, int cnt)
|
{
|
||||||
{
|
final StringBuilder sb = new StringBuilder(100);
|
||||||
mapSize = size;
|
sb.append(mapSize);
|
||||||
count = cnt;
|
sb.append("x");
|
||||||
bufs = new ArrayList<>(count);
|
sb.append(mapSize);
|
||||||
}
|
sb.append(" num:");
|
||||||
|
sb.append(bufs.size());
|
||||||
@Override
|
sb.append("/");
|
||||||
public String toString()
|
sb.append(count);
|
||||||
{
|
sb.append(" uses:");
|
||||||
final StringBuilder stat = new StringBuilder(100);
|
sb.append(uses);
|
||||||
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));
|
sb.append("/");
|
||||||
if (uses > 0)
|
sb.append(playableUses);
|
||||||
{
|
if (uses > 0)
|
||||||
StringUtil.append(stat, " total/avg(ms):", String.valueOf(elapsed), "/", String.format("%1.2f", (double) elapsed / uses));
|
{
|
||||||
}
|
sb.append(" total/avg(ms):");
|
||||||
|
sb.append(elapsed);
|
||||||
StringUtil.append(stat, " ovf:", String.valueOf(overflows), "/", String.valueOf(playableOverflows));
|
sb.append("/");
|
||||||
|
sb.append(String.format("%1.2f", (double) elapsed / uses));
|
||||||
return stat.toString();
|
}
|
||||||
}
|
|
||||||
}
|
sb.append(" ovf:");
|
||||||
|
sb.append(overflows);
|
||||||
@Override
|
sb.append("/");
|
||||||
public String[] getStat()
|
sb.append(playableOverflows);
|
||||||
{
|
|
||||||
final String[] result = new String[_allBuffers.length + 1];
|
return sb.toString();
|
||||||
for (int i = 0; i < _allBuffers.length; i++)
|
}
|
||||||
{
|
}
|
||||||
result[i] = _allBuffers[i].toString();
|
|
||||||
}
|
@Override
|
||||||
|
public String[] getStat()
|
||||||
final StringBuilder stat = new StringBuilder(100);
|
{
|
||||||
StringUtil.append(stat, "LOS postfilter uses:", String.valueOf(_postFilterUses), "/", String.valueOf(_postFilterPlayableUses));
|
final String[] result = new String[_allBuffers.length + 1];
|
||||||
if (_postFilterUses > 0)
|
for (int i = 0; i < _allBuffers.length; i++)
|
||||||
{
|
{
|
||||||
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");
|
result[i] = _allBuffers[i].toString();
|
||||||
}
|
}
|
||||||
StringUtil.append(stat, "Pathfind success/fail:", String.valueOf(_findSuccess), "/", String.valueOf(_findFails));
|
|
||||||
result[result.length - 1] = stat.toString();
|
final StringBuilder sb = new StringBuilder(128);
|
||||||
|
sb.append("LOS postfilter uses:");
|
||||||
return result;
|
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();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,215 +1,184 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.cellnodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.cellnodes;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
import com.l2jmobius.gameserver.geodata.geodriver.Cell;
|
||||||
import com.l2jserver.gameserver.geoengine.Direction;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author -Nemesiss-, FBIagent
|
* @author -Nemesiss-, HorridoJoho
|
||||||
*/
|
*/
|
||||||
public class NodeLoc extends AbstractNodeLoc
|
public class NodeLoc extends AbstractNodeLoc
|
||||||
{
|
{
|
||||||
private int _x;
|
private int _x;
|
||||||
private int _y;
|
private int _y;
|
||||||
private boolean _goNorth;
|
private boolean _goNorth;
|
||||||
private boolean _goEast;
|
private boolean _goEast;
|
||||||
private boolean _goSouth;
|
private boolean _goSouth;
|
||||||
private boolean _goWest;
|
private boolean _goWest;
|
||||||
private int _geoHeight;
|
private int _geoHeight;
|
||||||
|
|
||||||
public NodeLoc(int x, int y, int z)
|
public NodeLoc(int x, int y, int z)
|
||||||
{
|
{
|
||||||
set(x, y, z);
|
set(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int x, int y, int z)
|
public void set(int x, int y, int z)
|
||||||
{
|
{
|
||||||
_x = x;
|
_x = x;
|
||||||
_y = y;
|
_y = y;
|
||||||
_goNorth = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.NORTH);
|
_goNorth = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_NORTH);
|
||||||
_goEast = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.EAST);
|
_goEast = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_EAST);
|
||||||
_goSouth = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.SOUTH);
|
_goSouth = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_SOUTH);
|
||||||
_goWest = GeoData.getInstance().canEnterNeighbors(x, y, z, Direction.WEST);
|
_goWest = GeoData.getInstance().checkNearestNswe(x, y, z, Cell.NSWE_WEST);
|
||||||
_geoHeight = GeoData.getInstance().getNearestZ(x, y, z);
|
_geoHeight = GeoData.getInstance().getNearestZ(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canGoNorth()
|
public boolean canGoNorth()
|
||||||
{
|
{
|
||||||
return _goNorth;
|
return _goNorth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canGoEast()
|
public boolean canGoEast()
|
||||||
{
|
{
|
||||||
return _goEast;
|
return _goEast;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canGoSouth()
|
public boolean canGoSouth()
|
||||||
{
|
{
|
||||||
return _goSouth;
|
return _goSouth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canGoWest()
|
public boolean canGoWest()
|
||||||
{
|
{
|
||||||
return _goWest;
|
return _goWest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canGoNone()
|
public boolean canGoAll()
|
||||||
{
|
{
|
||||||
return !canGoNorth() && !canGoEast() && !canGoSouth() && !canGoWest();
|
return canGoNorth() && canGoEast() && canGoSouth() && canGoWest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canGoAll()
|
@Override
|
||||||
{
|
public int getX()
|
||||||
return canGoNorth() && canGoEast() && canGoSouth() && canGoWest();
|
{
|
||||||
}
|
return GeoData.getInstance().getWorldX(_x);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getX()
|
@Override
|
||||||
*/
|
public int getY()
|
||||||
@Override
|
{
|
||||||
public int getX()
|
return GeoData.getInstance().getWorldY(_y);
|
||||||
{
|
}
|
||||||
return GeoData.getInstance().getWorldX(_x);
|
|
||||||
}
|
@Override
|
||||||
|
public int getZ()
|
||||||
/**
|
{
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getY()
|
return _geoHeight;
|
||||||
*/
|
}
|
||||||
@Override
|
|
||||||
public int getY()
|
@Override
|
||||||
{
|
public int getNodeX()
|
||||||
return GeoData.getInstance().getWorldY(_y);
|
{
|
||||||
}
|
return _x;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getZ()
|
@Override
|
||||||
*/
|
public int getNodeY()
|
||||||
@Override
|
{
|
||||||
public int getZ()
|
return _y;
|
||||||
{
|
}
|
||||||
return _geoHeight;
|
|
||||||
}
|
@Override
|
||||||
|
public int hashCode()
|
||||||
@Override
|
{
|
||||||
public void setZ(short z)
|
final int prime = 31;
|
||||||
{
|
int result = 1;
|
||||||
// do nothing here
|
result = (prime * result) + _x;
|
||||||
}
|
result = (prime * result) + _y;
|
||||||
|
|
||||||
/**
|
int nswe = 0;
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getNodeX()
|
if (canGoNorth())
|
||||||
*/
|
{
|
||||||
@Override
|
nswe |= Cell.NSWE_NORTH;
|
||||||
public int getNodeX()
|
}
|
||||||
{
|
if (canGoEast())
|
||||||
return _x;
|
{
|
||||||
}
|
nswe |= Cell.NSWE_EAST;
|
||||||
|
}
|
||||||
/**
|
if (canGoSouth())
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getNodeY()
|
{
|
||||||
*/
|
nswe |= Cell.NSWE_SOUTH;
|
||||||
@Override
|
}
|
||||||
public int getNodeY()
|
if (canGoWest())
|
||||||
{
|
{
|
||||||
return _y;
|
nswe |= Cell.NSWE_WEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
result = (prime * result) + (((_geoHeight & 0xFFFF) << 1) | nswe);
|
||||||
* @see java.lang.Object#hashCode()
|
return result;
|
||||||
*/
|
// return super.hashCode();
|
||||||
@Override
|
}
|
||||||
public int hashCode()
|
|
||||||
{
|
@Override
|
||||||
final int prime = 31;
|
public boolean equals(Object obj)
|
||||||
int result = 1;
|
{
|
||||||
result = (prime * result) + _x;
|
if (this == obj)
|
||||||
result = (prime * result) + _y;
|
{
|
||||||
|
return true;
|
||||||
byte nswe = 0;
|
}
|
||||||
if (canGoNorth())
|
if (obj == null)
|
||||||
{
|
{
|
||||||
nswe |= 1;
|
return false;
|
||||||
}
|
}
|
||||||
if (canGoEast())
|
if (!(obj instanceof NodeLoc))
|
||||||
{
|
{
|
||||||
nswe |= 1 << 1;
|
return false;
|
||||||
}
|
}
|
||||||
if (canGoSouth())
|
final NodeLoc other = (NodeLoc) obj;
|
||||||
{
|
if (_x != other._x)
|
||||||
nswe |= 1 << 2;
|
{
|
||||||
}
|
return false;
|
||||||
if (canGoEast())
|
}
|
||||||
{
|
if (_y != other._y)
|
||||||
nswe |= 1 << 3;
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
result = (prime * result) + (((_geoHeight & 0xFFFF) << 1) | nswe);
|
if (_goNorth != other._goNorth)
|
||||||
return result;
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
/**
|
if (_goEast != other._goEast)
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
{
|
||||||
*/
|
return false;
|
||||||
@Override
|
}
|
||||||
public boolean equals(Object obj)
|
if (_goSouth != other._goSouth)
|
||||||
{
|
{
|
||||||
if (this == obj)
|
return false;
|
||||||
{
|
}
|
||||||
return true;
|
if (_goWest != other._goWest)
|
||||||
}
|
{
|
||||||
if (obj == null)
|
return false;
|
||||||
{
|
}
|
||||||
return false;
|
if (_geoHeight != other._geoHeight)
|
||||||
}
|
{
|
||||||
if (!(obj instanceof NodeLoc))
|
return false;
|
||||||
{
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,63 +1,62 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.geonodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.geonodes;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNode;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
|
||||||
|
/**
|
||||||
/**
|
* @author -Nemesiss-
|
||||||
* @author -Nemesiss-
|
*/
|
||||||
*/
|
public class GeoNode extends AbstractNode<GeoNodeLoc>
|
||||||
public class GeoNode extends AbstractNode
|
{
|
||||||
{
|
private final int _neighborsIdx;
|
||||||
private final int _neighborsIdx;
|
private short _cost;
|
||||||
private short _cost;
|
private GeoNode[] _neighbors;
|
||||||
private GeoNode[] _neighbors;
|
|
||||||
|
public GeoNode(GeoNodeLoc Loc, int Neighbors_idx)
|
||||||
public GeoNode(AbstractNodeLoc Loc, int Neighbors_idx)
|
{
|
||||||
{
|
super(Loc);
|
||||||
super(Loc);
|
_neighborsIdx = Neighbors_idx;
|
||||||
_neighborsIdx = Neighbors_idx;
|
}
|
||||||
}
|
|
||||||
|
public short getCost()
|
||||||
public short getCost()
|
{
|
||||||
{
|
return _cost;
|
||||||
return _cost;
|
}
|
||||||
}
|
|
||||||
|
public void setCost(int cost)
|
||||||
public void setCost(int cost)
|
{
|
||||||
{
|
_cost = (short) cost;
|
||||||
_cost = (short) cost;
|
}
|
||||||
}
|
|
||||||
|
public GeoNode[] getNeighbors()
|
||||||
public GeoNode[] getNeighbors()
|
{
|
||||||
{
|
return _neighbors;
|
||||||
return _neighbors;
|
}
|
||||||
}
|
|
||||||
|
public void attachNeighbors()
|
||||||
public void attachNeighbors()
|
{
|
||||||
{
|
if (getLoc() == null)
|
||||||
if (getLoc() == null)
|
{
|
||||||
{
|
_neighbors = null;
|
||||||
_neighbors = null;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
_neighbors = GeoPathFinding.getInstance().readNeighbors(this, _neighborsIdx);
|
||||||
_neighbors = GeoPathFinding.getInstance().readNeighbors(this, _neighborsIdx);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@@ -1,130 +1,109 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.geonodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.geonodes;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author -Nemesiss-
|
* @author -Nemesiss-
|
||||||
*/
|
*/
|
||||||
public class GeoNodeLoc extends AbstractNodeLoc
|
public class GeoNodeLoc extends AbstractNodeLoc
|
||||||
{
|
{
|
||||||
private final short _x;
|
private final short _x;
|
||||||
private final short _y;
|
private final short _y;
|
||||||
private final short _z;
|
private final short _z;
|
||||||
|
|
||||||
public GeoNodeLoc(short x, short y, short z)
|
public GeoNodeLoc(short x, short y, short z)
|
||||||
{
|
{
|
||||||
_x = x;
|
_x = x;
|
||||||
_y = y;
|
_y = y;
|
||||||
_z = z;
|
_z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getX()
|
public int getX()
|
||||||
*/
|
{
|
||||||
@Override
|
return L2World.MAP_MIN_X + (_x * 128) + 48;
|
||||||
public int getX()
|
}
|
||||||
{
|
|
||||||
return L2World.MAP_MIN_X + (_x * 128) + 48;
|
@Override
|
||||||
}
|
public int getY()
|
||||||
|
{
|
||||||
/**
|
return L2World.MAP_MIN_Y + (_y * 128) + 48;
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getY()
|
}
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int getY()
|
public int getZ()
|
||||||
{
|
{
|
||||||
return L2World.MAP_MIN_Y + (_y * 128) + 48;
|
return _z;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc#getZ()
|
public int getNodeX()
|
||||||
*/
|
{
|
||||||
@Override
|
return _x;
|
||||||
public int getZ()
|
}
|
||||||
{
|
|
||||||
return _z;
|
@Override
|
||||||
}
|
public int getNodeY()
|
||||||
|
{
|
||||||
@Override
|
return _y;
|
||||||
public void setZ(short z)
|
}
|
||||||
{
|
|
||||||
// Overriden
|
@Override
|
||||||
}
|
public int hashCode()
|
||||||
|
{
|
||||||
@Override
|
final int prime = 31;
|
||||||
public int getNodeX()
|
int result = 1;
|
||||||
{
|
result = (prime * result) + _x;
|
||||||
return _x;
|
result = (prime * result) + _y;
|
||||||
}
|
result = (prime * result) + _z;
|
||||||
|
return result;
|
||||||
@Override
|
}
|
||||||
public int getNodeY()
|
|
||||||
{
|
@Override
|
||||||
return _y;
|
public boolean equals(Object obj)
|
||||||
}
|
{
|
||||||
|
if (this == obj)
|
||||||
/**
|
{
|
||||||
* @see java.lang.Object#hashCode()
|
return true;
|
||||||
*/
|
}
|
||||||
@Override
|
if (obj == null)
|
||||||
public int hashCode()
|
{
|
||||||
{
|
return false;
|
||||||
final int prime = 31;
|
}
|
||||||
int result = 1;
|
if (!(obj instanceof GeoNodeLoc))
|
||||||
result = (prime * result) + _x;
|
{
|
||||||
result = (prime * result) + _y;
|
return false;
|
||||||
result = (prime * result) + _z;
|
}
|
||||||
return result;
|
final GeoNodeLoc other = (GeoNodeLoc) obj;
|
||||||
}
|
if (_x != other._x)
|
||||||
|
{
|
||||||
/**
|
return false;
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
}
|
||||||
*/
|
if (_y != other._y)
|
||||||
@Override
|
{
|
||||||
public boolean equals(Object obj)
|
return false;
|
||||||
{
|
}
|
||||||
if (this == obj)
|
if (_z != other._z)
|
||||||
{
|
{
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
if (obj == null)
|
return true;
|
||||||
{
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,470 +1,469 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.geonodes;
|
package com.l2jmobius.gameserver.geodata.pathfinding.geonodes;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.File;
|
||||||
import java.io.File;
|
import java.io.IOException;
|
||||||
import java.io.FileReader;
|
import java.io.RandomAccessFile;
|
||||||
import java.io.LineNumberReader;
|
import java.nio.ByteBuffer;
|
||||||
import java.io.RandomAccessFile;
|
import java.nio.IntBuffer;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.MappedByteBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.MappedByteBuffer;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.file.Files;
|
||||||
import java.util.LinkedList;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.LinkedList;
|
||||||
import java.util.StringTokenizer;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import com.l2jmobius.Config;
|
import java.util.logging.Level;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
import java.util.logging.Logger;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNode;
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNode;
|
||||||
import com.l2jmobius.gameserver.pathfinding.PathFinding;
|
import com.l2jmobius.gameserver.geodata.pathfinding.AbstractNodeLoc;
|
||||||
import com.l2jmobius.gameserver.pathfinding.utils.FastNodeList;
|
import com.l2jmobius.gameserver.geodata.pathfinding.PathFinding;
|
||||||
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import javolution.util.FastList;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import javolution.util.FastMap;
|
import com.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author -Nemesiss-
|
* @author -Nemesiss-
|
||||||
*/
|
*/
|
||||||
public class GeoPathFinding extends PathFinding
|
public class GeoPathFinding extends PathFinding
|
||||||
{
|
{
|
||||||
private static Logger _log = Logger.getLogger(GeoPathFinding.class.getName());
|
private static Logger _log = Logger.getLogger(GeoPathFinding.class.getName());
|
||||||
private static GeoPathFinding _instance;
|
private static Map<Short, ByteBuffer> _pathNodes = new ConcurrentHashMap<>();
|
||||||
private static Map<Short, ByteBuffer> pathNodes = new FastMap<>();
|
private static Map<Short, IntBuffer> _pathNodesIndex = new ConcurrentHashMap<>();
|
||||||
private static Map<Short, IntBuffer> pathNodes_index = new FastMap<>();
|
|
||||||
|
public static GeoPathFinding getInstance()
|
||||||
public static GeoPathFinding getInstance()
|
{
|
||||||
{
|
return SingletonHolder._instance;
|
||||||
if (_instance == null)
|
}
|
||||||
{
|
|
||||||
_instance = new GeoPathFinding();
|
@Override
|
||||||
}
|
public boolean pathNodesExist(short regionoffset)
|
||||||
return _instance;
|
{
|
||||||
}
|
return _pathNodesIndex.containsKey(regionoffset);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see com.l2jmobius.gameserver.pathfinding.PathFinding#pathNodesExist(short)
|
@Override
|
||||||
*/
|
public List<AbstractNodeLoc> findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
|
||||||
@Override
|
{
|
||||||
public boolean pathNodesExist(short regionoffset)
|
final int gx = (x - L2World.MAP_MIN_X) >> 4;
|
||||||
{
|
final int gy = (y - L2World.MAP_MIN_Y) >> 4;
|
||||||
return pathNodes_index.containsKey(regionoffset);
|
final short gz = (short) z;
|
||||||
}
|
final int gtx = (tx - L2World.MAP_MIN_X) >> 4;
|
||||||
|
final int gty = (ty - L2World.MAP_MIN_Y) >> 4;
|
||||||
@Override
|
final short gtz = (short) tz;
|
||||||
public List<AbstractNodeLoc> findPath(int x, int y, int z, int tx, int ty, int tz, boolean playable)
|
|
||||||
{
|
final GeoNode start = readNode(gx, gy, gz);
|
||||||
final int gx = (x - L2World.MAP_MIN_X) >> 4;
|
final GeoNode end = readNode(gtx, gty, gtz);
|
||||||
final int gy = (y - L2World.MAP_MIN_Y) >> 4;
|
if ((start == null) || (end == null))
|
||||||
final short gz = (short) z;
|
{
|
||||||
final int gtx = (tx - L2World.MAP_MIN_X) >> 4;
|
return null;
|
||||||
final int gty = (ty - L2World.MAP_MIN_Y) >> 4;
|
}
|
||||||
final short gtz = (short) tz;
|
if (Math.abs(start.getLoc().getZ() - z) > 55)
|
||||||
|
{
|
||||||
final GeoNode start = readNode(gx, gy, gz);
|
return null; // not correct layer
|
||||||
final GeoNode end = readNode(gtx, gty, gtz);
|
}
|
||||||
|
if (Math.abs(end.getLoc().getZ() - tz) > 55)
|
||||||
if ((start == null) || (end == null))
|
{
|
||||||
{
|
return null; // not correct layer
|
||||||
return null;
|
}
|
||||||
}
|
if (start == end)
|
||||||
if (Math.abs(start.getLoc().getZ() - z) > 55)
|
{
|
||||||
{
|
return null;
|
||||||
return null; // not correct layer
|
}
|
||||||
}
|
|
||||||
if (Math.abs(end.getLoc().getZ() - tz) > 55)
|
// 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());
|
||||||
return null; // not correct layer
|
if ((temp.getX() != start.getLoc().getX()) || (temp.getY() != start.getLoc().getY()))
|
||||||
}
|
{
|
||||||
if (start == end)
|
return null; // cannot reach closest...
|
||||||
{
|
}
|
||||||
return null;
|
|
||||||
}
|
// TODO: Find closest path node around target, now only checks if final location can be reached
|
||||||
Location temp = GeoData.getInstance().moveCheck(x, y, z, start.getLoc().getX(), start.getLoc().getY(), start.getLoc().getZ());
|
temp = GeoData.getInstance().moveCheck(tx, ty, tz, end.getLoc().getX(), end.getLoc().getY(), end.getLoc().getZ());
|
||||||
if ((temp.getX() != start.getLoc().getX()) || (temp.getY() != start.getLoc().getY()))
|
if ((temp.getX() != end.getLoc().getX()) || (temp.getY() != end.getLoc().getY()))
|
||||||
{
|
{
|
||||||
return null; // cannot reach closest...
|
return null; // cannot reach closest...
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = GeoData.getInstance().moveCheck(tx, ty, tz, end.getLoc().getX(), end.getLoc().getY(), end.getLoc().getZ());
|
// return searchAStar(start, end);
|
||||||
if ((temp.getX() != end.getLoc().getX()) || (temp.getY() != end.getLoc().getY()))
|
return searchByClosest2(start, end);
|
||||||
{
|
}
|
||||||
return null; // cannot reach closest...
|
|
||||||
}
|
public List<AbstractNodeLoc> searchByClosest2(GeoNode start, GeoNode end)
|
||||||
|
{
|
||||||
return searchByClosest2(start, 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
|
||||||
public List<AbstractNodeLoc> searchByClosest2(GeoNode start, GeoNode end)
|
// and accurate. And can reach insane distances (try it with 800 nodes..).
|
||||||
{
|
// Minimum required node count would be around 300-400.
|
||||||
// Always continues checking from the closest to target non-blocked
|
// Generally returns a bit (only a bit) more intelligent looking routes than
|
||||||
// node from to_visit list. There's extra length in path if needed
|
// the basic version. Not a true distance image (which would increase CPU
|
||||||
// to go backwards/sideways but when moving generally forwards, this is extra fast
|
// load) level of intelligence though.
|
||||||
// and accurate. And can reach insane distances (try it with 800 nodes..).
|
|
||||||
// Minimum required node count would be around 300-400.
|
// List of Visited Nodes
|
||||||
// Generally returns a bit (only a bit) more intelligent looking routes than
|
final List<GeoNode> visited = new ArrayList<>(550);
|
||||||
// the basic version. Not a true distance image (which would increase CPU
|
|
||||||
// load) level of intelligence though.
|
// List of Nodes to Visit
|
||||||
|
final LinkedList<GeoNode> to_visit = new LinkedList<>();
|
||||||
// List of Visited Nodes
|
to_visit.add(start);
|
||||||
final FastNodeList visited = new FastNodeList(550);
|
final int targetX = end.getLoc().getNodeX();
|
||||||
|
final int targetY = end.getLoc().getNodeY();
|
||||||
// List of Nodes to Visit
|
|
||||||
final LinkedList<GeoNode> to_visit = new LinkedList<>();
|
int dx, dy;
|
||||||
to_visit.add(start);
|
boolean added;
|
||||||
final int targetX = end.getLoc().getNodeX();
|
int i = 0;
|
||||||
final int targetY = end.getLoc().getNodeY();
|
while (i < 550)
|
||||||
|
{
|
||||||
int dx, dy;
|
GeoNode node;
|
||||||
boolean added;
|
try
|
||||||
int i = 0;
|
{
|
||||||
while (i < 550)
|
node = to_visit.removeFirst();
|
||||||
{
|
}
|
||||||
GeoNode node;
|
catch (Exception e)
|
||||||
try
|
{
|
||||||
{
|
// No Path found
|
||||||
node = to_visit.removeFirst();
|
return null;
|
||||||
}
|
}
|
||||||
catch (final Exception e)
|
if (node.equals(end))
|
||||||
{
|
{
|
||||||
// No Path found
|
return constructPath2(node);
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
i++;
|
||||||
if (node.equals(end))
|
visited.add(node);
|
||||||
{
|
node.attachNeighbors();
|
||||||
return constructPath2(node);
|
final GeoNode[] neighbors = node.getNeighbors();
|
||||||
}
|
if (neighbors == null)
|
||||||
|
{
|
||||||
i++;
|
continue;
|
||||||
visited.add(node);
|
}
|
||||||
node.attachNeighbors();
|
for (GeoNode n : neighbors)
|
||||||
final GeoNode[] neighbors = node.getNeighbors();
|
{
|
||||||
if (neighbors == null)
|
if ((visited.lastIndexOf(n) == -1) && !to_visit.contains(n))
|
||||||
{
|
{
|
||||||
continue;
|
added = false;
|
||||||
}
|
n.setParent(node);
|
||||||
for (final GeoNode n : neighbors)
|
dx = targetX - n.getLoc().getNodeX();
|
||||||
{
|
dy = targetY - n.getLoc().getNodeY();
|
||||||
if (!visited.containsRev(n) && !to_visit.contains(n))
|
n.setCost((dx * dx) + (dy * dy));
|
||||||
{
|
for (int index = 0; index < to_visit.size(); index++)
|
||||||
added = false;
|
{
|
||||||
n.setParent(node);
|
// supposed to find it quite early..
|
||||||
dx = targetX - n.getLoc().getNodeX();
|
if (to_visit.get(index).getCost() > n.getCost())
|
||||||
dy = targetY - n.getLoc().getNodeY();
|
{
|
||||||
n.setCost((dx * dx) + (dy * dy));
|
to_visit.add(index, n);
|
||||||
for (int index = 0; index < to_visit.size(); index++)
|
added = true;
|
||||||
{
|
break;
|
||||||
// supposed to find it quite early..
|
}
|
||||||
if (to_visit.get(index).getCost() > n.getCost())
|
}
|
||||||
{
|
if (!added)
|
||||||
to_visit.add(index, n);
|
{
|
||||||
added = true;
|
to_visit.addLast(n);
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!added)
|
}
|
||||||
{
|
// No Path found
|
||||||
to_visit.addLast(n);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
public List<AbstractNodeLoc> constructPath2(AbstractNode<GeoNodeLoc> node)
|
||||||
}
|
{
|
||||||
// No Path found
|
final LinkedList<AbstractNodeLoc> path = new LinkedList<>();
|
||||||
return null;
|
int previousDirectionX = -1000;
|
||||||
}
|
int previousDirectionY = -1000;
|
||||||
|
int directionX;
|
||||||
public List<AbstractNodeLoc> constructPath2(AbstractNode node)
|
int directionY;
|
||||||
{
|
|
||||||
final LinkedList<AbstractNodeLoc> path = new LinkedList<>();
|
while (node.getParent() != null)
|
||||||
int previousDirectionX = -1000;
|
{
|
||||||
int previousDirectionY = -1000;
|
// only add a new route point if moving direction changes
|
||||||
int directionX;
|
directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
|
||||||
int directionY;
|
directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
|
||||||
|
|
||||||
while (node.getParent() != null)
|
if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
|
||||||
{
|
{
|
||||||
// only add a new route point if moving direction changes
|
previousDirectionX = directionX;
|
||||||
directionX = node.getLoc().getNodeX() - node.getParent().getLoc().getNodeX();
|
previousDirectionY = directionY;
|
||||||
directionY = node.getLoc().getNodeY() - node.getParent().getLoc().getNodeY();
|
path.addFirst(node.getLoc());
|
||||||
|
}
|
||||||
if ((directionX != previousDirectionX) || (directionY != previousDirectionY))
|
node = node.getParent();
|
||||||
{
|
}
|
||||||
previousDirectionX = directionX;
|
return path;
|
||||||
previousDirectionY = directionY;
|
}
|
||||||
path.addFirst(node.getLoc());
|
|
||||||
}
|
public GeoNode[] readNeighbors(GeoNode n, int idx)
|
||||||
node = node.getParent();
|
{
|
||||||
}
|
final int node_x = n.getLoc().getNodeX();
|
||||||
return path;
|
final int node_y = n.getLoc().getNodeY();
|
||||||
}
|
// short node_z = n.getLoc().getZ();
|
||||||
|
|
||||||
public GeoNode[] readNeighbors(GeoNode n, int idx)
|
final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
|
||||||
{
|
final ByteBuffer pn = _pathNodes.get(regoffset);
|
||||||
final int node_x = n.getLoc().getNodeX();
|
|
||||||
final int node_y = n.getLoc().getNodeY();
|
final List<AbstractNode<GeoNodeLoc>> Neighbors = new ArrayList<>(8);
|
||||||
|
GeoNode newNode;
|
||||||
final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
|
short new_node_x, new_node_y;
|
||||||
final ByteBuffer pn = pathNodes.get(regoffset);
|
|
||||||
|
// Region for sure will change, we must read from correct file
|
||||||
final List<AbstractNode> Neighbors = new FastList<>(8);
|
byte neighbor = pn.get(idx++); // N
|
||||||
|
if (neighbor > 0)
|
||||||
GeoNode newNode;
|
{
|
||||||
short new_node_x, new_node_y;
|
neighbor--;
|
||||||
|
new_node_x = (short) node_x;
|
||||||
// Region for sure will change, we must read from correct file
|
new_node_y = (short) (node_y - 1);
|
||||||
byte neighbor = pn.get(idx); // N
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
idx++;
|
if (newNode != null)
|
||||||
if (neighbor > 0)
|
{
|
||||||
{
|
Neighbors.add(newNode);
|
||||||
neighbor--;
|
}
|
||||||
new_node_x = (short) node_x;
|
}
|
||||||
new_node_y = (short) (node_y - 1);
|
neighbor = pn.get(idx++); // NE
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
if (neighbor > 0)
|
||||||
if (newNode != null)
|
{
|
||||||
{
|
neighbor--;
|
||||||
Neighbors.add(newNode);
|
new_node_x = (short) (node_x + 1);
|
||||||
}
|
new_node_y = (short) (node_y - 1);
|
||||||
}
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
neighbor = pn.get(idx); // NE
|
if (newNode != null)
|
||||||
idx++;
|
{
|
||||||
if (neighbor > 0)
|
Neighbors.add(newNode);
|
||||||
{
|
}
|
||||||
neighbor--;
|
}
|
||||||
new_node_x = (short) (node_x + 1);
|
neighbor = pn.get(idx++); // E
|
||||||
new_node_y = (short) (node_y - 1);
|
if (neighbor > 0)
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
{
|
||||||
if (newNode != null)
|
neighbor--;
|
||||||
{
|
new_node_x = (short) (node_x + 1);
|
||||||
Neighbors.add(newNode);
|
new_node_y = (short) node_y;
|
||||||
}
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
}
|
if (newNode != null)
|
||||||
neighbor = pn.get(idx); // E
|
{
|
||||||
idx++;
|
Neighbors.add(newNode);
|
||||||
if (neighbor > 0)
|
}
|
||||||
{
|
}
|
||||||
neighbor--;
|
neighbor = pn.get(idx++); // SE
|
||||||
new_node_x = (short) (node_x + 1);
|
if (neighbor > 0)
|
||||||
new_node_y = (short) node_y;
|
{
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
neighbor--;
|
||||||
if (newNode != null)
|
new_node_x = (short) (node_x + 1);
|
||||||
{
|
new_node_y = (short) (node_y + 1);
|
||||||
Neighbors.add(newNode);
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
}
|
if (newNode != null)
|
||||||
}
|
{
|
||||||
neighbor = pn.get(idx); // SE
|
Neighbors.add(newNode);
|
||||||
idx++;
|
}
|
||||||
if (neighbor > 0)
|
}
|
||||||
{
|
neighbor = pn.get(idx++); // S
|
||||||
neighbor--;
|
if (neighbor > 0)
|
||||||
new_node_x = (short) (node_x + 1);
|
{
|
||||||
new_node_y = (short) (node_y + 1);
|
neighbor--;
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
new_node_x = (short) node_x;
|
||||||
if (newNode != null)
|
new_node_y = (short) (node_y + 1);
|
||||||
{
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
Neighbors.add(newNode);
|
if (newNode != null)
|
||||||
}
|
{
|
||||||
}
|
Neighbors.add(newNode);
|
||||||
neighbor = pn.get(idx); // S
|
}
|
||||||
idx++;
|
}
|
||||||
if (neighbor > 0)
|
neighbor = pn.get(idx++); // SW
|
||||||
{
|
if (neighbor > 0)
|
||||||
neighbor--;
|
{
|
||||||
new_node_x = (short) node_x;
|
neighbor--;
|
||||||
new_node_y = (short) (node_y + 1);
|
new_node_x = (short) (node_x - 1);
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
new_node_y = (short) (node_y + 1);
|
||||||
if (newNode != null)
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
{
|
if (newNode != null)
|
||||||
Neighbors.add(newNode);
|
{
|
||||||
}
|
Neighbors.add(newNode);
|
||||||
}
|
}
|
||||||
neighbor = pn.get(idx); // SW
|
}
|
||||||
idx++;
|
neighbor = pn.get(idx++); // W
|
||||||
if (neighbor > 0)
|
if (neighbor > 0)
|
||||||
{
|
{
|
||||||
neighbor--;
|
neighbor--;
|
||||||
new_node_x = (short) (node_x - 1);
|
new_node_x = (short) (node_x - 1);
|
||||||
new_node_y = (short) (node_y + 1);
|
new_node_y = (short) node_y;
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
if (newNode != null)
|
if (newNode != null)
|
||||||
{
|
{
|
||||||
Neighbors.add(newNode);
|
Neighbors.add(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
neighbor = pn.get(idx); // W
|
neighbor = pn.get(idx++); // NW
|
||||||
idx++;
|
if (neighbor > 0)
|
||||||
if (neighbor > 0)
|
{
|
||||||
{
|
neighbor--;
|
||||||
neighbor--;
|
new_node_x = (short) (node_x - 1);
|
||||||
new_node_x = (short) (node_x - 1);
|
new_node_y = (short) (node_y - 1);
|
||||||
new_node_y = (short) node_y;
|
newNode = readNode(new_node_x, new_node_y, neighbor);
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
if (newNode != null)
|
||||||
if (newNode != null)
|
{
|
||||||
{
|
Neighbors.add(newNode);
|
||||||
Neighbors.add(newNode);
|
}
|
||||||
}
|
}
|
||||||
}
|
final GeoNode[] result = new GeoNode[Neighbors.size()];
|
||||||
neighbor = pn.get(idx); // NW
|
return Neighbors.toArray(result);
|
||||||
idx++;
|
}
|
||||||
if (neighbor > 0)
|
|
||||||
{
|
// Private
|
||||||
neighbor--;
|
|
||||||
new_node_x = (short) (node_x - 1);
|
private GeoNode readNode(short node_x, short node_y, byte layer)
|
||||||
new_node_y = (short) (node_y - 1);
|
{
|
||||||
newNode = readNode(new_node_x, new_node_y, neighbor);
|
final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
|
||||||
if (newNode != null)
|
if (!pathNodesExist(regoffset))
|
||||||
{
|
{
|
||||||
Neighbors.add(newNode);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
final short nbx = getNodeBlock(node_x);
|
||||||
final GeoNode[] result = new GeoNode[Neighbors.size()];
|
final short nby = getNodeBlock(node_y);
|
||||||
return Neighbors.toArray(result);
|
int idx = _pathNodesIndex.get(regoffset).get((nby << 8) + nbx);
|
||||||
}
|
final ByteBuffer pn = _pathNodes.get(regoffset);
|
||||||
|
// reading
|
||||||
private GeoNode readNode(short node_x, short node_y, byte layer)
|
final byte nodes = pn.get(idx);
|
||||||
{
|
idx += (layer * 10) + 1; // byte + layer*10byte
|
||||||
final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
|
if (nodes < layer)
|
||||||
if (!pathNodesExist(regoffset))
|
{
|
||||||
{
|
_log.warning("SmthWrong!");
|
||||||
return null;
|
}
|
||||||
}
|
final short node_z = pn.getShort(idx);
|
||||||
final short nbx = getNodeBlock(node_x);
|
idx += 2;
|
||||||
final short nby = getNodeBlock(node_y);
|
return new GeoNode(new GeoNodeLoc(node_x, node_y, node_z), idx);
|
||||||
int idx = pathNodes_index.get(regoffset).get((nby << 8) + nbx);
|
}
|
||||||
final ByteBuffer pn = pathNodes.get(regoffset);
|
|
||||||
// reading
|
private GeoNode readNode(int gx, int gy, short z)
|
||||||
final byte nodes = pn.get(idx);
|
{
|
||||||
idx += (layer * 10) + 1;// byte + layer*10byte
|
final short node_x = getNodePos(gx);
|
||||||
if (nodes < layer)
|
final short node_y = getNodePos(gy);
|
||||||
{
|
final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
|
||||||
_log.warning("SmthWrong!");
|
if (!pathNodesExist(regoffset))
|
||||||
}
|
{
|
||||||
final short node_z = pn.getShort(idx);
|
return null;
|
||||||
idx += 2;
|
}
|
||||||
return new GeoNode(new GeoNodeLoc(node_x, node_y, node_z), idx);
|
final short nbx = getNodeBlock(node_x);
|
||||||
}
|
final short nby = getNodeBlock(node_y);
|
||||||
|
int idx = _pathNodesIndex.get(regoffset).get((nby << 8) + nbx);
|
||||||
private GeoNode readNode(int gx, int gy, short z)
|
final ByteBuffer pn = _pathNodes.get(regoffset);
|
||||||
{
|
// reading
|
||||||
final short node_x = getNodePos(gx);
|
byte nodes = pn.get(idx++);
|
||||||
final short node_y = getNodePos(gy);
|
int idx2 = 0; // create index to nearlest node by z
|
||||||
final short regoffset = getRegionOffset(getRegionX(node_x), getRegionY(node_y));
|
short last_z = Short.MIN_VALUE;
|
||||||
if (!pathNodesExist(regoffset))
|
while (nodes > 0)
|
||||||
{
|
{
|
||||||
return null;
|
final short node_z = pn.getShort(idx);
|
||||||
}
|
if (Math.abs(last_z - z) > Math.abs(node_z - z))
|
||||||
final short nbx = getNodeBlock(node_x);
|
{
|
||||||
final short nby = getNodeBlock(node_y);
|
last_z = node_z;
|
||||||
int idx = pathNodes_index.get(regoffset).get((nby << 8) + nbx);
|
idx2 = idx + 2;
|
||||||
final ByteBuffer pn = pathNodes.get(regoffset);
|
}
|
||||||
// reading
|
idx += 10; // short + 8 byte
|
||||||
byte nodes = pn.get(idx);
|
nodes--;
|
||||||
idx++;// byte
|
}
|
||||||
int idx2 = 0; // create index to nearlest node by z
|
return new GeoNode(new GeoNodeLoc(node_x, node_y, last_z), idx2);
|
||||||
short last_z = Short.MIN_VALUE;
|
}
|
||||||
while (nodes > 0)
|
|
||||||
{
|
protected GeoPathFinding()
|
||||||
final short node_z = pn.getShort(idx);
|
{
|
||||||
if (Math.abs(last_z - z) > Math.abs(node_z - z))
|
try
|
||||||
{
|
{
|
||||||
last_z = node_z;
|
_log.info("Path Engine: - Loading Path Nodes...");
|
||||||
idx2 = idx + 2;
|
//@formatter:off
|
||||||
}
|
Files.lines(Paths.get(Config.PATHNODE_DIR.getPath(), "pn_index.txt"), StandardCharsets.UTF_8)
|
||||||
idx += 10; // short + 8 byte
|
.map(String::trim)
|
||||||
nodes--;
|
.filter(l -> !l.isEmpty())
|
||||||
}
|
.forEach(line -> {
|
||||||
return new GeoNode(new GeoNodeLoc(node_x, node_y, last_z), idx2);
|
final String[] parts = line.split("_");
|
||||||
}
|
|
||||||
|
if ((parts.length < 2)
|
||||||
private GeoPathFinding()
|
|| !Util.isDigit(parts[0])
|
||||||
{
|
|| !Util.isDigit(parts[1]))
|
||||||
final File Data = new File(Config.PATHNODE_DIR, "pn_index.txt");
|
{
|
||||||
try (FileReader fr = new FileReader(Data);
|
_log.warning("Invalid pathnode entry: '" + line + "', must be in format 'XX_YY', where X and Y - integers");
|
||||||
BufferedReader br = new BufferedReader(fr);
|
return;
|
||||||
LineNumberReader lnr = new LineNumberReader(br))
|
}
|
||||||
{
|
|
||||||
_log.info("PathFinding Engine: - Loading Path Nodes...");
|
final byte rx = Byte.parseByte(parts[0]);
|
||||||
String line;
|
final byte ry = Byte.parseByte(parts[1]);
|
||||||
|
LoadPathNodeFile(rx, ry);
|
||||||
while ((line = lnr.readLine()) != null)
|
});
|
||||||
{
|
//@formatter:on
|
||||||
if (line.trim().length() == 0)
|
}
|
||||||
{
|
catch (IOException e)
|
||||||
continue;
|
{
|
||||||
}
|
_log.log(Level.WARNING, "", e);
|
||||||
final StringTokenizer st = new StringTokenizer(line, "_");
|
throw new Error("Failed to read pn_index file.");
|
||||||
final byte rx = Byte.parseByte(st.nextToken());
|
}
|
||||||
final byte ry = Byte.parseByte(st.nextToken());
|
}
|
||||||
LoadPathNodeFile(rx, ry);
|
|
||||||
}
|
private void LoadPathNodeFile(byte rx, byte ry)
|
||||||
}
|
{
|
||||||
catch (final Exception e)
|
if ((rx < L2World.TILE_X_MIN) || (rx > L2World.TILE_X_MAX) || (ry < L2World.TILE_Y_MIN) || (ry > L2World.TILE_Y_MAX))
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
_log.warning("Failed to Load PathNode File: invalid region " + rx + "," + ry + Config.EOL);
|
||||||
throw new Error("Failed to Read pn_index File.");
|
return;
|
||||||
}
|
}
|
||||||
}
|
final short regionoffset = getRegionOffset(rx, ry);
|
||||||
|
final File file = new File(Config.PATHNODE_DIR, rx + "_" + ry + ".pn");
|
||||||
private void LoadPathNodeFile(byte rx, byte ry)
|
_log.info("Path Engine: - Loading: " + file.getName() + " -> region offset: " + regionoffset + " X: " + rx + " Y: " + ry);
|
||||||
{
|
int node = 0, size, index = 0;
|
||||||
final short regionoffset = getRegionOffset(rx, ry);
|
|
||||||
final File pn = new File(Config.PATHNODE_DIR, rx + "_" + ry + ".pn");
|
// Create a read-only memory-mapped file
|
||||||
_log.info("PathFinding Engine: - Loading: " + pn.getName() + " -> region offset: " + regionoffset + "X: " + rx + " Y: " + ry);
|
try (RandomAccessFile raf = new RandomAccessFile(file, "r");
|
||||||
int node = 0, size, index = 0;
|
FileChannel roChannel = raf.getChannel())
|
||||||
|
{
|
||||||
// Create a read-only memory-mapped file
|
size = (int) roChannel.size();
|
||||||
try (RandomAccessFile raf = new RandomAccessFile(pn, "r");
|
MappedByteBuffer nodes;
|
||||||
FileChannel roChannel = raf.getChannel())
|
if (Config.FORCE_GEODATA)
|
||||||
{
|
{
|
||||||
size = (int) roChannel.size();
|
// it is not guarantee, because the underlying operating system may have paged out some of the buffer's data
|
||||||
MappedByteBuffer nodes;
|
nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
|
||||||
if (Config.FORCE_GEODATA) // Force O/S to Loads this buffer's content into physical memory.
|
}
|
||||||
{
|
else
|
||||||
// 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();
|
nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
// Indexing pathnode files, so we will know where each block starts
|
||||||
nodes = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
|
final IntBuffer indexs = IntBuffer.allocate(65536);
|
||||||
}
|
|
||||||
|
while (node < 65536)
|
||||||
// Indexing pathnode files, so we will know where each block starts
|
{
|
||||||
final IntBuffer indexs = IntBuffer.allocate(65536);
|
final byte layer = nodes.get(index);
|
||||||
|
indexs.put(node++, index);
|
||||||
while (node < 65536)
|
index += (layer * 10) + 1;
|
||||||
{
|
}
|
||||||
final byte layer = nodes.get(index);
|
_pathNodesIndex.put(regionoffset, indexs);
|
||||||
indexs.put(node, index);
|
_pathNodes.put(regionoffset, nodes);
|
||||||
node++;
|
}
|
||||||
index += (layer * 10) + 1;
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
pathNodes_index.put(regionoffset, indexs);
|
_log.log(Level.WARNING, "Failed to Load PathNode File: " + file.getAbsolutePath() + " : " + e.getMessage(), e);
|
||||||
pathNodes.put(regionoffset, nodes);
|
}
|
||||||
}
|
}
|
||||||
catch (final Exception e)
|
|
||||||
{
|
private static class SingletonHolder
|
||||||
e.printStackTrace();
|
{
|
||||||
_log.warning("Failed to Load PathNode File: " + pn.getAbsolutePath() + "\n");
|
protected static final GeoPathFinding _instance = new GeoPathFinding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@@ -1,124 +1,124 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the L2J Mobius project.
|
* This file is part of the L2J Mobius project.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.pathfinding.utils;
|
package com.l2jmobius.gameserver.geodata.pathfinding.utils;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.pathfinding.geonodes.GeoNode;
|
import com.l2jmobius.gameserver.geodata.pathfinding.geonodes.GeoNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author -Nemesiss-
|
* @author -Nemesiss-
|
||||||
*/
|
*/
|
||||||
public class BinaryNodeHeap
|
public class BinaryNodeHeap
|
||||||
{
|
{
|
||||||
private final GeoNode[] _list;
|
private final GeoNode[] _list;
|
||||||
private int _size;
|
private int _size;
|
||||||
|
|
||||||
public BinaryNodeHeap(int size)
|
public BinaryNodeHeap(int size)
|
||||||
{
|
{
|
||||||
_list = new GeoNode[size + 1];
|
_list = new GeoNode[size + 1];
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(GeoNode n)
|
public void add(GeoNode n)
|
||||||
{
|
{
|
||||||
_size++;
|
_size++;
|
||||||
int pos = _size;
|
int pos = _size;
|
||||||
_list[pos] = n;
|
_list[pos] = n;
|
||||||
while (pos != 1)
|
while (pos != 1)
|
||||||
{
|
{
|
||||||
final int p2 = pos / 2;
|
final int p2 = pos / 2;
|
||||||
if (_list[pos].getCost() <= _list[p2].getCost())
|
if (_list[pos].getCost() <= _list[p2].getCost())
|
||||||
{
|
{
|
||||||
final GeoNode temp = _list[p2];
|
final GeoNode temp = _list[p2];
|
||||||
_list[p2] = _list[pos];
|
_list[p2] = _list[pos];
|
||||||
_list[pos] = temp;
|
_list[pos] = temp;
|
||||||
pos = p2;
|
pos = p2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeoNode removeFirst()
|
public GeoNode removeFirst()
|
||||||
{
|
{
|
||||||
final GeoNode first = _list[1];
|
final GeoNode first = _list[1];
|
||||||
_list[1] = _list[_size];
|
_list[1] = _list[_size];
|
||||||
_list[_size] = null;
|
_list[_size] = null;
|
||||||
_size--;
|
_size--;
|
||||||
int pos = 1;
|
int pos = 1;
|
||||||
int cpos;
|
int cpos;
|
||||||
int dblcpos;
|
int dblcpos;
|
||||||
GeoNode temp;
|
GeoNode temp;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
cpos = pos;
|
cpos = pos;
|
||||||
dblcpos = cpos * 2;
|
dblcpos = cpos * 2;
|
||||||
if ((dblcpos + 1) <= _size)
|
if ((dblcpos + 1) <= _size)
|
||||||
{
|
{
|
||||||
if (_list[cpos].getCost() >= _list[dblcpos].getCost())
|
if (_list[cpos].getCost() >= _list[dblcpos].getCost())
|
||||||
{
|
{
|
||||||
pos = dblcpos;
|
pos = dblcpos;
|
||||||
}
|
}
|
||||||
if (_list[pos].getCost() >= _list[dblcpos + 1].getCost())
|
if (_list[pos].getCost() >= _list[dblcpos + 1].getCost())
|
||||||
{
|
{
|
||||||
pos = dblcpos + 1;
|
pos = dblcpos + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dblcpos <= _size)
|
else if (dblcpos <= _size)
|
||||||
{
|
{
|
||||||
if (_list[cpos].getCost() >= _list[dblcpos].getCost())
|
if (_list[cpos].getCost() >= _list[dblcpos].getCost())
|
||||||
{
|
{
|
||||||
pos = dblcpos;
|
pos = dblcpos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpos != pos)
|
if (cpos != pos)
|
||||||
{
|
{
|
||||||
temp = _list[cpos];
|
temp = _list[cpos];
|
||||||
_list[cpos] = _list[pos];
|
_list[cpos] = _list[pos];
|
||||||
_list[pos] = temp;
|
_list[pos] = temp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(GeoNode n)
|
public boolean contains(GeoNode n)
|
||||||
{
|
{
|
||||||
if (_size == 0)
|
if (_size == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = 1; i <= _size; i++)
|
for (int i = 1; i <= _size; i++)
|
||||||
{
|
{
|
||||||
if (_list[i].equals(n))
|
if (_list[i].equals(n))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty()
|
public boolean isEmpty()
|
||||||
{
|
{
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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<L2PcInstance> _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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -17,10 +17,12 @@
|
|||||||
package com.l2jmobius.gameserver.handler.admincommandhandlers;
|
package com.l2jmobius.gameserver.handler.admincommandhandlers;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
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.handler.IAdminCommandHandler;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
|
import com.l2jmobius.gameserver.util.GeoUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author -Nemesiss-
|
* @author -Nemesiss-
|
||||||
@@ -32,7 +34,9 @@ public class AdminGeodata implements IAdminCommandHandler
|
|||||||
"admin_geo_pos",
|
"admin_geo_pos",
|
||||||
"admin_geo_spawn_pos",
|
"admin_geo_spawn_pos",
|
||||||
"admin_geo_can_move",
|
"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;
|
private static final int REQUIRED_LEVEL = Config.GM_MIN;
|
||||||
@@ -75,7 +79,7 @@ public class AdminGeodata implements IAdminCommandHandler
|
|||||||
|
|
||||||
if (GeoData.getInstance().hasGeoPos(geoX, geoY))
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -120,6 +124,16 @@ public class AdminGeodata implements IAdminCommandHandler
|
|||||||
activeChar.sendMessage("Incorrect Target.");
|
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
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@@ -19,10 +19,10 @@ package com.l2jmobius.gameserver.handler.admincommandhandlers;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
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.handler.IAdminCommandHandler;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
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
|
public class AdminPathNode implements IAdminCommandHandler
|
||||||
{
|
{
|
||||||
@@ -79,7 +79,7 @@ public class AdminPathNode implements IAdminCommandHandler
|
|||||||
}
|
}
|
||||||
else if (command.equals("admin_find_path"))
|
else if (command.equals("admin_find_path"))
|
||||||
{
|
{
|
||||||
if (Config.GEODATA < 2)
|
if (Config.PATHFINDING < 2)
|
||||||
{
|
{
|
||||||
activeChar.sendMessage("PathFinding has not been enabled.");
|
activeChar.sendMessage("PathFinding has not been enabled.");
|
||||||
return true;
|
return true;
|
||||||
|
@@ -17,8 +17,8 @@
|
|||||||
package com.l2jmobius.gameserver.handler.skillhandlers;
|
package com.l2jmobius.gameserver.handler.skillhandlers;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.datatables.ZoneTable;
|
import com.l2jmobius.gameserver.datatables.ZoneTable;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.handler.ISkillHandler;
|
import com.l2jmobius.gameserver.handler.ISkillHandler;
|
||||||
import com.l2jmobius.gameserver.model.Inventory;
|
import com.l2jmobius.gameserver.model.Inventory;
|
||||||
import com.l2jmobius.gameserver.model.L2Character;
|
import com.l2jmobius.gameserver.model.L2Character;
|
||||||
@@ -169,7 +169,7 @@ public class Fishing implements ISkillHandler
|
|||||||
if (aimingTo != null)
|
if (aimingTo != null)
|
||||||
{
|
{
|
||||||
// fishing zone found, we can fish here
|
// 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
|
// geodata enabled, checking if we can see end of the pole
|
||||||
if (GeoData.getInstance().canSeeTarget(player.getX(), player.getY(), z, x, y, z))
|
if (GeoData.getInstance().canSeeTarget(player.getX(), player.getY(), z, x, y, z))
|
||||||
|
@@ -72,6 +72,8 @@ public abstract class Inventory extends ItemContainer
|
|||||||
// Speed percentage mods
|
// Speed percentage mods
|
||||||
public static final double MAX_ARMOR_WEIGHT = 12000;
|
public static final double MAX_ARMOR_WEIGHT = 12000;
|
||||||
|
|
||||||
|
public static final int ADENA_ID = 57;
|
||||||
|
|
||||||
private final L2ItemInstance[] _paperdoll;
|
private final L2ItemInstance[] _paperdoll;
|
||||||
private final List<PaperdollListener> _paperdollListeners;
|
private final List<PaperdollListener> _paperdollListeners;
|
||||||
|
|
||||||
|
@@ -26,7 +26,6 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GameTimeController;
|
import com.l2jmobius.gameserver.GameTimeController;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
import com.l2jmobius.gameserver.ai.CtrlEvent;
|
import com.l2jmobius.gameserver.ai.CtrlEvent;
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
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;
|
||||||
import com.l2jmobius.gameserver.datatables.MapRegionTable.TeleportWhereType;
|
import com.l2jmobius.gameserver.datatables.MapRegionTable.TeleportWhereType;
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
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.ISkillHandler;
|
||||||
import com.l2jmobius.gameserver.handler.SkillHandler;
|
import com.l2jmobius.gameserver.handler.SkillHandler;
|
||||||
import com.l2jmobius.gameserver.instancemanager.TownManager;
|
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.StopMove;
|
||||||
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||||
import com.l2jmobius.gameserver.network.serverpackets.TeleportToLocation;
|
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.Calculator;
|
||||||
import com.l2jmobius.gameserver.skills.Formulas;
|
import com.l2jmobius.gameserver.skills.Formulas;
|
||||||
import com.l2jmobius.gameserver.skills.Stats;
|
import com.l2jmobius.gameserver.skills.Stats;
|
||||||
@@ -4407,10 +4407,10 @@ public abstract class L2Character extends L2Object
|
|||||||
final boolean isFloating = isFlying() || isInsideZone(L2Character.ZONE_WATER);
|
final boolean isFloating = isFlying() || isInsideZone(L2Character.ZONE_WATER);
|
||||||
|
|
||||||
// Z coordinate will follow geodata or client values
|
// 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))
|
) && 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;
|
dz = m._zDestination - geoHeight;
|
||||||
// quite a big difference, compare to validatePosition packet
|
// 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))
|
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
|
// make water move short and use no geodata checks for swimming chars
|
||||||
// distance in a click can easily be over 3000
|
// 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;
|
final double divider = 700 / distance;
|
||||||
x = curX + (int) (divider * dx);
|
x = curX + (int) (divider * dx);
|
||||||
@@ -4728,7 +4728,7 @@ public abstract class L2Character extends L2Object
|
|||||||
m.onGeodataPathIndex = -1; // Initialize not on geodata path
|
m.onGeodataPathIndex = -1; // Initialize not on geodata path
|
||||||
m.disregardingGeodata = false;
|
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
|
&& !(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();
|
final boolean isInBoat = (this instanceof L2PcInstance) && ((L2PcInstance) this).isInBoat();
|
||||||
@@ -4747,12 +4747,7 @@ public abstract class L2Character extends L2Object
|
|||||||
// Movement checks:
|
// Movement checks:
|
||||||
// when geodata == 2, for all characters except mobs returning home (could be changed later to teleport if pathfinding fails)
|
// 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
|
// 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
|
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
|
||||||
// intention_follow
|
|
||||||
// only
|
|
||||||
// when
|
|
||||||
// following
|
|
||||||
// owner
|
|
||||||
{
|
{
|
||||||
if (isOnGeodataPath())
|
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
|
// 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
|
// than the original movement was and the LoS gives a shorter distance than 2000
|
||||||
// This way of detecting need for pathfinding could be changed.
|
// 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
|
// Path calculation
|
||||||
// Overrides previous movement check
|
// 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 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)
|
if (this instanceof L2Summon)
|
||||||
{
|
{
|
||||||
|
@@ -27,10 +27,10 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.L2DatabaseFactory;
|
import com.l2jmobius.L2DatabaseFactory;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import com.l2jmobius.gameserver.datatables.ItemTable;
|
import com.l2jmobius.gameserver.datatables.ItemTable;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
|
||||||
import com.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
import com.l2jmobius.gameserver.instancemanager.MercTicketManager;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
@@ -931,7 +931,7 @@ public final class L2ItemInstance extends L2Object
|
|||||||
assert getPosition().getWorldRegion() == null;
|
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);
|
final Location dropDest = GeoData.getInstance().moveCheck(dropper.getX(), dropper.getY(), dropper.getZ(), x, y, z);
|
||||||
x = dropDest.getX();
|
x = dropDest.getX();
|
||||||
|
@@ -23,8 +23,8 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTreeTable;
|
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.L2ArtefactInstance;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2ChestInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2ChestInstance;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
||||||
|
@@ -22,9 +22,9 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.Territory;
|
import com.l2jmobius.gameserver.Territory;
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||||
@@ -581,7 +581,7 @@ public class L2Spawn
|
|||||||
// don't correct z of flying npc's
|
// don't correct z of flying npc's
|
||||||
if (!mob.isFlying())
|
if (!mob.isFlying())
|
||||||
{
|
{
|
||||||
newlocz = GeoData.getInstance().getSpawnHeight(newlocx, newlocy, newlocz, newlocz);
|
newlocz = GeoData.getInstance().getSpawnHeight(newlocx, newlocy, newlocz);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final L2Effect f : mob.getAllEffects())
|
for (final L2Effect f : mob.getAllEffects())
|
||||||
|
@@ -17,11 +17,11 @@
|
|||||||
package com.l2jmobius.gameserver.model;
|
package com.l2jmobius.gameserver.model;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import com.l2jmobius.gameserver.ai.L2CharacterAI;
|
import com.l2jmobius.gameserver.ai.L2CharacterAI;
|
||||||
import com.l2jmobius.gameserver.ai.L2SummonAI;
|
import com.l2jmobius.gameserver.ai.L2SummonAI;
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.model.L2Attackable.AggroInfo;
|
import com.l2jmobius.gameserver.model.L2Attackable.AggroInfo;
|
||||||
import com.l2jmobius.gameserver.model.L2Skill.SkillTargetType;
|
import com.l2jmobius.gameserver.model.L2Skill.SkillTargetType;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
||||||
@@ -213,7 +213,7 @@ public abstract class L2Summon extends L2PlayableInstance
|
|||||||
player.sendPacket(new ValidateLocation(this));
|
player.sendPacket(new ValidateLocation(this));
|
||||||
if (isAutoAttackable(player))
|
if (isAutoAttackable(player))
|
||||||
{
|
{
|
||||||
if (Config.GEODATA > 0)
|
if (Config.PATHFINDING > 0)
|
||||||
{
|
{
|
||||||
if (GeoData.getInstance().canSeeTarget(player, this))
|
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
|
// This Action Failed packet avoids player getting stuck when clicking three or more times
|
||||||
player.sendPacket(new ActionFailed());
|
player.sendPacket(new ActionFailed());
|
||||||
if (Config.GEODATA > 0)
|
if (Config.PATHFINDING > 0)
|
||||||
{
|
{
|
||||||
if (GeoData.getInstance().canSeeTarget(player, this))
|
if (GeoData.getInstance().canSeeTarget(player, this))
|
||||||
{
|
{
|
||||||
|
@@ -47,6 +47,10 @@ public final class L2World
|
|||||||
public static final int SHIFT_BY = 12;
|
public static final int SHIFT_BY = 12;
|
||||||
|
|
||||||
/** Map dimensions */
|
/** 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_MIN_X = -131072;
|
||||||
public static final int MAP_MAX_X = 228608;
|
public static final int MAP_MAX_X = 228608;
|
||||||
public static final int MAP_MIN_Y = -262144;
|
public static final int MAP_MIN_Y = -262144;
|
||||||
|
@@ -18,8 +18,8 @@ package com.l2jmobius.gameserver.model.actor.instance;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.model.L2Character;
|
import com.l2jmobius.gameserver.model.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.L2Spawn;
|
import com.l2jmobius.gameserver.model.L2Spawn;
|
||||||
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
|
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
|
||||||
|
@@ -35,7 +35,6 @@ import java.util.logging.Level;
|
|||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.L2DatabaseFactory;
|
import com.l2jmobius.L2DatabaseFactory;
|
||||||
import com.l2jmobius.gameserver.GameTimeController;
|
import com.l2jmobius.gameserver.GameTimeController;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ItemsAutoDestroy;
|
import com.l2jmobius.gameserver.ItemsAutoDestroy;
|
||||||
import com.l2jmobius.gameserver.LoginServerThread;
|
import com.l2jmobius.gameserver.LoginServerThread;
|
||||||
import com.l2jmobius.gameserver.Olympiad;
|
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.NpcTable;
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTreeTable;
|
import com.l2jmobius.gameserver.datatables.SkillTreeTable;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.handler.IItemHandler;
|
import com.l2jmobius.gameserver.handler.IItemHandler;
|
||||||
import com.l2jmobius.gameserver.handler.ItemHandler;
|
import com.l2jmobius.gameserver.handler.ItemHandler;
|
||||||
import com.l2jmobius.gameserver.instancemanager.CastleManager;
|
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
|
// This Action Failed packet avoids player getting stuck when clicking three or more times
|
||||||
|
|
||||||
player.sendPacket(new ActionFailed());
|
player.sendPacket(new ActionFailed());
|
||||||
if (Config.GEODATA > 0)
|
if (Config.PATHFINDING > 0)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@@ -24,10 +24,10 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.L2DatabaseFactory;
|
import com.l2jmobius.L2DatabaseFactory;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.handler.IItemHandler;
|
import com.l2jmobius.gameserver.handler.IItemHandler;
|
||||||
import com.l2jmobius.gameserver.handler.ItemHandler;
|
import com.l2jmobius.gameserver.handler.ItemHandler;
|
||||||
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
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
|
// Check if the pet is attackable (without a forced attack) and isn't dead
|
||||||
if (isAutoAttackable(player) && !isOwner)
|
if (isAutoAttackable(player) && !isOwner)
|
||||||
{
|
{
|
||||||
if (Config.GEODATA > 0)
|
if (Config.PATHFINDING > 0)
|
||||||
{
|
{
|
||||||
if (GeoData.getInstance().canSeeTarget(player, this))
|
if (GeoData.getInstance().canSeeTarget(player, this))
|
||||||
{
|
{
|
||||||
@@ -333,7 +333,7 @@ public class L2PetInstance extends L2Summon
|
|||||||
}
|
}
|
||||||
else if (!isInsideRadius(player, 150, false, false))
|
else if (!isInsideRadius(player, 150, false, false))
|
||||||
{
|
{
|
||||||
if (Config.GEODATA > 0)
|
if (Config.PATHFINDING > 0)
|
||||||
{
|
{
|
||||||
if (GeoData.getInstance().canSeeTarget(player, this))
|
if (GeoData.getInstance().canSeeTarget(player, this))
|
||||||
{
|
{
|
||||||
|
@@ -104,7 +104,7 @@ public class MoveBackwardToLocation extends L2GameClientPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable keyboard movement when geodata is not enabled and player is not flying.
|
// 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());
|
activeChar.sendPacket(new ActionFailed());
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.network.clientpackets;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.geoeditorcon.GeoEditorListener;
|
|
||||||
import com.l2jmobius.gameserver.model.L2Character;
|
import com.l2jmobius.gameserver.model.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
import com.l2jmobius.gameserver.network.serverpackets.GetOnVehicle;
|
import com.l2jmobius.gameserver.network.serverpackets.GetOnVehicle;
|
||||||
@@ -113,14 +112,6 @@ public class ValidatePosition extends L2GameClientPacket
|
|||||||
activeChar.getParty().broadcastToPartyMembers(activeChar, new PartyMemberPosition(activeChar));
|
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))
|
if (activeChar.isFlying() || activeChar.isInsideZone(L2Character.ZONE_WATER))
|
||||||
{
|
{
|
||||||
activeChar.setXYZ(realX, realY, _z);
|
activeChar.setXYZ(realX, realY, _z);
|
||||||
@@ -165,7 +156,7 @@ public class ValidatePosition extends L2GameClientPacket
|
|||||||
// intended for geodata. Sends a validation packet to client
|
// intended for geodata. Sends a validation packet to client
|
||||||
// when too far from server calculated true coordinate.
|
// when too far from server calculated true coordinate.
|
||||||
// Due to geodata "holes", some Z axis checks are made.
|
// 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))
|
if ((Math.abs(dz) > 200) && (Math.abs(dz) < 1500) && (Math.abs(_z - activeChar.getClientZ()) < 800))
|
||||||
{
|
{
|
||||||
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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.<br/>
|
||||||
|
* <b>Note:</b> 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<Point> _points = new ArrayList<>();
|
||||||
|
private final List<Line> _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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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<AbstractNodeLoc> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -17,8 +17,8 @@
|
|||||||
package com.l2jmobius.gameserver.skills.effects;
|
package com.l2jmobius.gameserver.skills.effects;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
import com.l2jmobius.Config;
|
||||||
import com.l2jmobius.gameserver.GeoData;
|
|
||||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
|
import com.l2jmobius.gameserver.geodata.GeoData;
|
||||||
import com.l2jmobius.gameserver.model.L2CharPosition;
|
import com.l2jmobius.gameserver.model.L2CharPosition;
|
||||||
import com.l2jmobius.gameserver.model.L2Effect;
|
import com.l2jmobius.gameserver.model.L2Effect;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
@@ -110,7 +110,7 @@ final class EffectFear extends L2Effect
|
|||||||
posX += _dX * FEAR_RANGE;
|
posX += _dX * FEAR_RANGE;
|
||||||
posY += _dY * 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);
|
final Location destiny = GeoData.getInstance().moveCheck(getEffected().getX(), getEffected().getY(), getEffected().getZ(), posX, posY, posZ);
|
||||||
posX = destiny.getX();
|
posX = destiny.getX();
|
||||||
|
@@ -19,7 +19,7 @@ package com.l2jmobius.gameserver.skills.effects;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.l2jmobius.Config;
|
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.L2Effect;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.network.serverpackets.FlyToLocation;
|
import com.l2jmobius.gameserver.network.serverpackets.FlyToLocation;
|
||||||
@@ -92,7 +92,7 @@ final class EffectThrowUp extends L2Effect
|
|||||||
_y = getEffector().getY() - (int) (offset * sin);
|
_y = getEffector().getY() - (int) (offset * sin);
|
||||||
_z = getEffected().getZ();
|
_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);
|
final Location destiny = GeoData.getInstance().moveCheck(getEffected().getX(), getEffected().getY(), getEffected().getZ(), _x, _y, _z);
|
||||||
_x = destiny.getX();
|
_x = destiny.getX();
|
||||||
|
@@ -16,25 +16,165 @@
|
|||||||
*/
|
*/
|
||||||
package com.l2jmobius.gameserver.util;
|
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 final class GeoUtils
|
||||||
{
|
{
|
||||||
public interface PointListener
|
public static void debug2DLine(L2PcInstance player, int x, int y, int tx, int ty, int z)
|
||||||
{
|
{
|
||||||
/**
|
final int gx = GeoData.getInstance().getGeoX(x);
|
||||||
* @param x
|
final int gy = GeoData.getInstance().getGeoY(y);
|
||||||
* @param y
|
|
||||||
* @return true proceed, false abort
|
final int tgx = GeoData.getInstance().getGeoX(tx);
|
||||||
*/
|
final int tgy = GeoData.getInstance().getGeoY(ty);
|
||||||
boolean onPoint(int x, int y);
|
|
||||||
|
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<br>
|
* difference between x values: never above 1<br>
|
||||||
* difference between y values: never above 1
|
* difference between y values: never above 1
|
||||||
* @param lastX
|
* @param lastX
|
||||||
* @param lastY
|
* @param lastY
|
||||||
@@ -42,36 +182,36 @@ public final class GeoUtils
|
|||||||
* @param y
|
* @param y
|
||||||
* @return
|
* @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 (x > lastX) // east
|
||||||
{
|
{
|
||||||
if (y > lastY)
|
if (y > lastY)
|
||||||
{
|
{
|
||||||
return Direction.SOUTH_EAST;
|
return Cell.NSWE_SOUTH_EAST; // Direction.SOUTH_EAST;
|
||||||
}
|
}
|
||||||
else if (y < lastY)
|
else if (y < lastY)
|
||||||
{
|
{
|
||||||
return Direction.NORTH_EAST;
|
return Cell.NSWE_NORTH_EAST; // Direction.NORTH_EAST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Direction.EAST;
|
return Cell.NSWE_EAST; // Direction.EAST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (x < lastX) // west
|
else if (x < lastX) // west
|
||||||
{
|
{
|
||||||
if (y > lastY)
|
if (y > lastY)
|
||||||
{
|
{
|
||||||
return Direction.SOUTH_WEST;
|
return Cell.NSWE_SOUTH_WEST; // Direction.SOUTH_WEST;
|
||||||
}
|
}
|
||||||
else if (y < lastY)
|
else if (y < lastY)
|
||||||
{
|
{
|
||||||
return Direction.NORTH_WEST;
|
return Cell.NSWE_NORTH_WEST; // Direction.NORTH_WEST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Direction.WEST;
|
return Cell.NSWE_WEST; // Direction.WEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -79,15 +219,15 @@ public final class GeoUtils
|
|||||||
{
|
{
|
||||||
if (y > lastY)
|
if (y > lastY)
|
||||||
{
|
{
|
||||||
return Direction.SOUTH;
|
return Cell.NSWE_SOUTH; // Direction.SOUTH;
|
||||||
}
|
}
|
||||||
else if (y < lastY)
|
else if (y < lastY)
|
||||||
{
|
{
|
||||||
return Direction.NORTH;
|
return Cell.NSWE_NORTH; // Direction.NORTH;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return null;// error, should never happen, TODO: Logging
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -325,4 +325,24 @@ public final class Util
|
|||||||
}
|
}
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user