Fixed NodeBuffer exhaustion.
This commit is contained in:
+2
-2
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -941,6 +941,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2483,10 +2484,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -951,6 +951,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2505,10 +2506,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -964,6 +964,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2527,10 +2528,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -951,6 +951,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2502,10 +2503,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -946,6 +946,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2502,10 +2503,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -953,6 +953,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2514,10 +2515,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -965,6 +965,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2557,10 +2558,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -971,6 +971,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2569,10 +2570,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -969,6 +969,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2565,10 +2566,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -969,6 +969,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2565,10 +2566,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -969,6 +969,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2565,10 +2566,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -943,6 +943,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2520,10 +2521,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(geoengineConfig.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(geoengineConfig.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, geoengineConfig.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, geoengineConfig.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = geoengineConfig.getBoolean("PathFinding", true);
|
PATHFINDING = geoengineConfig.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = geoengineConfig.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = geoengineConfig.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = geoengineConfig.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = geoengineConfig.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = geoengineConfig.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = geoengineConfig.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = geoengineConfig.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = geoengineConfig.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = geoengineConfig.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = geoengineConfig.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = geoengineConfig.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = geoengineConfig.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = geoengineConfig.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = geoengineConfig.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -151,22 +152,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -948,7 +939,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1025,18 +1021,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -979,6 +979,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2583,10 +2584,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(geoengineConfig.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(geoengineConfig.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, geoengineConfig.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, geoengineConfig.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = geoengineConfig.getBoolean("PathFinding", true);
|
PATHFINDING = geoengineConfig.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = geoengineConfig.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = geoengineConfig.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = geoengineConfig.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = geoengineConfig.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = geoengineConfig.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = geoengineConfig.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = geoengineConfig.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = geoengineConfig.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = geoengineConfig.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = geoengineConfig.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = geoengineConfig.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = geoengineConfig.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = geoengineConfig.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = geoengineConfig.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -151,22 +152,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -948,7 +939,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1025,18 +1021,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -1069,6 +1069,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2599,10 +2600,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -151,22 +152,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -948,7 +939,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1025,18 +1021,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -1069,6 +1069,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2608,10 +2609,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -151,22 +152,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -948,7 +939,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1025,18 +1021,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -900,6 +900,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2411,10 +2412,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
+9
-1
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
private int _geoX;
|
private int _geoX;
|
||||||
private int _geoY;
|
private int _geoY;
|
||||||
private byte _nswe;
|
private byte _nswe;
|
||||||
|
private byte _nsweExpand;
|
||||||
|
|
||||||
// The cost G (movement cost done) and cost H (estimated cost to target).
|
// The cost G (movement cost done) and cost H (estimated cost to target).
|
||||||
private int _costG;
|
private int _costG;
|
||||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_geoX = 0;
|
_geoX = 0;
|
||||||
_geoY = 0;
|
_geoY = 0;
|
||||||
_nswe = GeoStructure.CELL_FLAG_NONE;
|
_nswe = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
_nsweExpand = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
_costG = 0;
|
_costG = 0;
|
||||||
_costH = 0;
|
_costH = 0;
|
||||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(int gx, int gy, int gz, byte nswe)
|
public void setGeo(int gx, int gy, int gz, byte nswe, byte nsweExpand)
|
||||||
{
|
{
|
||||||
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
super.setXYZ(GeoEngine.getWorldX(gx), GeoEngine.getWorldY(gy), gz);
|
||||||
|
|
||||||
_geoX = gx;
|
_geoX = gx;
|
||||||
_geoY = gy;
|
_geoY = gy;
|
||||||
_nswe = nswe;
|
_nswe = nswe;
|
||||||
|
_nsweExpand = nsweExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(Node parent, int weight, int costH)
|
public void setCost(Node parent, int weight, int costH)
|
||||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
|
|||||||
return _nswe;
|
return _nswe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getNsweExpand()
|
||||||
|
{
|
||||||
|
return _nsweExpand;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCostF()
|
public int getCostF()
|
||||||
{
|
{
|
||||||
return _costF;
|
return _costF;
|
||||||
|
|||||||
+262
-74
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
package org.l2jmobius.gameserver.geoengine.pathfinding;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -29,7 +28,6 @@ import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
|||||||
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
import org.l2jmobius.gameserver.geoengine.geodata.ABlock;
|
||||||
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import org.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
|
|
||||||
|
|
||||||
public class NodeBuffer
|
public class NodeBuffer
|
||||||
{
|
{
|
||||||
@@ -97,7 +95,7 @@ public class NodeBuffer
|
|||||||
_current = _buffer[_bufferIndex++];
|
_current = _buffer[_bufferIndex++];
|
||||||
|
|
||||||
// Set node geodata coordinates and movement cost.
|
// Set node geodata coordinates and movement cost.
|
||||||
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz));
|
_current.setGeo(gox, goy, goz, GeoEngine.getInstance().getNsweNearest(gox, goy, goz), GeoStructure.CELL_EXPANSION_ALL);
|
||||||
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
_current.setCost(null, 0, getCostH(gox, goy, goz));
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -166,25 +164,6 @@ public class NodeBuffer
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates list of Nodes to show debug path.
|
|
||||||
* @param debug : The debug packet to add debug informations in.
|
|
||||||
*/
|
|
||||||
public void debugPath(ExServerPrimitive debug)
|
|
||||||
{
|
|
||||||
// Add all opened node as yellow points.
|
|
||||||
for (Node n : _opened)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.YELLOW, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all opened node as blue points.
|
|
||||||
for (Node n : _closed)
|
|
||||||
{
|
|
||||||
debug.addPoint(String.valueOf(n.getCostF()), Color.BLUE, true, n.getX(), n.getY(), n.getZ() - 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.tryLock();
|
return _lock.tryLock();
|
||||||
@@ -219,7 +198,8 @@ public class NodeBuffer
|
|||||||
{
|
{
|
||||||
// Movement is blocked, skip.
|
// Movement is blocked, skip.
|
||||||
final byte nswe = _current.getNSWE();
|
final byte nswe = _current.getNSWE();
|
||||||
if (nswe == GeoStructure.CELL_FLAG_NONE)
|
byte expand = _current.getNsweExpand();
|
||||||
|
if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,53 +215,230 @@ public class NodeBuffer
|
|||||||
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
byte nsweW = GeoStructure.CELL_FLAG_NONE;
|
||||||
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
byte nsweE = GeoStructure.CELL_FLAG_NONE;
|
||||||
|
|
||||||
// Can move north, expand.
|
switch (expand)
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
|
||||||
{
|
{
|
||||||
nsweN = addNode(x, y - 1, z, Config.MOVE_WEIGHT);
|
case GeoStructure.CELL_EXPANSION_N:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_S:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_W) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x - 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_E) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x + 1, y, z) & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_W:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweW & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweW & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_E:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_N) != 0) && ((nsweE & GeoStructure.CELL_FLAG_N) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y - 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nswe & GeoStructure.CELL_FLAG_S) != 0) && ((nsweE & GeoStructure.CELL_FLAG_S) != 0))
|
||||||
|
{
|
||||||
|
if ((getNodeNswe(x, y + 1, z) & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_NE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SW:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_SE:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeoStructure.CELL_EXPANSION_ALL:
|
||||||
|
{
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
|
||||||
|
{
|
||||||
|
nsweN = addNode(x, y - 1, z, GeoStructure.CELL_EXPANSION_N, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
||||||
|
{
|
||||||
|
nsweS = addNode(x, y + 1, z, GeoStructure.CELL_EXPANSION_S, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
||||||
|
{
|
||||||
|
nsweW = addNode(x - 1, y, z, GeoStructure.CELL_EXPANSION_W, false);
|
||||||
|
}
|
||||||
|
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
||||||
|
{
|
||||||
|
nsweE = addNode(x + 1, y, z, GeoStructure.CELL_EXPANSION_E, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y - 1, z, GeoStructure.CELL_EXPANSION_NW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y - 1, z, GeoStructure.CELL_EXPANSION_NE, true);
|
||||||
|
}
|
||||||
|
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
||||||
|
{
|
||||||
|
addNode(x - 1, y + 1, z, GeoStructure.CELL_EXPANSION_SW, true);
|
||||||
|
}
|
||||||
|
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
||||||
|
{
|
||||||
|
addNode(x + 1, y + 1, z, GeoStructure.CELL_EXPANSION_SE, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getNodeNswe(int gx, int gy, int gz)
|
||||||
|
{
|
||||||
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
|
{
|
||||||
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move south, expand.
|
// Get geodata block and check if there is a layer at given coordinates.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
|
ABlock block = GeoEngine.getInstance().getBlock(gx, gy);
|
||||||
|
final int index = block.getIndexBelow(gx, gy, gz);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
nsweS = addNode(x, y + 1, z, Config.MOVE_WEIGHT);
|
return GeoStructure.CELL_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can move west, expand.
|
// Get node geodata nswe.
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
|
return block.getNswe(index);
|
||||||
{
|
|
||||||
nsweW = addNode(x - 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move east, expand.
|
|
||||||
if ((nswe & GeoStructure.CELL_FLAG_E) != 0)
|
|
||||||
{
|
|
||||||
nsweE = addNode(x + 1, y, z, Config.MOVE_WEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move north-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_N) != 0) && ((nsweN & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y - 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-west, expand.
|
|
||||||
if (((nsweW & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_W) != 0))
|
|
||||||
{
|
|
||||||
addNode(x - 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can move south-east, expand.
|
|
||||||
if (((nsweE & GeoStructure.CELL_FLAG_S) != 0) && ((nsweS & GeoStructure.CELL_FLAG_E) != 0))
|
|
||||||
{
|
|
||||||
addNode(x + 1, y + 1, z, Config.MOVE_WEIGHT_DIAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +446,11 @@ public class NodeBuffer
|
|||||||
* @param gx : The new node X geodata coordinate.
|
* @param gx : The new node X geodata coordinate.
|
||||||
* @param gy : The new node Y geodata coordinate.
|
* @param gy : The new node Y geodata coordinate.
|
||||||
* @param gzValue : The new node Z geodata coordinate.
|
* @param gzValue : The new node Z geodata coordinate.
|
||||||
* @param weight : The weight of movement to the new node.
|
* @param nsweExpand : The allowed directions to be expanded on the new node.
|
||||||
|
* @param diagonal : The new node is being explored in diagonal direction.
|
||||||
* @return The nswe of the added node. Blank, if not added.
|
* @return The nswe of the added node. Blank, if not added.
|
||||||
*/
|
*/
|
||||||
private byte addNode(int gx, int gy, int gzValue, int weight)
|
private byte addNode(int gx, int gy, int gzValue, byte nsweExpand, boolean diagonal)
|
||||||
{
|
{
|
||||||
// Check new node is out of geodata grid (world coordinates).
|
// Check new node is out of geodata grid (world coordinates).
|
||||||
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
if ((gx < 0) || (gx >= GeoStructure.GEO_CELLS_X) || (gy < 0) || (gy >= GeoStructure.GEO_CELLS_Y))
|
||||||
@@ -321,8 +479,19 @@ public class NodeBuffer
|
|||||||
// Get node from current index (don't move index yet).
|
// Get node from current index (don't move index yet).
|
||||||
Node node = _buffer[_bufferIndex];
|
Node node = _buffer[_bufferIndex];
|
||||||
|
|
||||||
|
// Calculate node weight.
|
||||||
|
int weight;
|
||||||
|
if (nswe == GeoStructure.CELL_FLAG_ALL)
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.MOVE_WEIGHT_DIAG : Config.MOVE_WEIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = diagonal ? Config.OBSTACLE_WEIGHT_DIAG : Config.OBSTACLE_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node geodata coordinates.
|
// Set node geodata coordinates.
|
||||||
node.setGeo(gx, gy, gz, nswe);
|
node.setGeo(gx, gy, gz, nswe, nsweExpand);
|
||||||
|
|
||||||
// Node is already added to opened list, return.
|
// Node is already added to opened list, return.
|
||||||
if (_opened.contains(node))
|
if (_opened.contains(node))
|
||||||
@@ -337,7 +506,7 @@ public class NodeBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
// The node is to be used. Set node movement cost and add it to opened list. Move the buffer index.
|
||||||
node.setCost(_current, nswe != GeoStructure.CELL_FLAG_ALL ? Config.OBSTACLE_WEIGHT : weight, getCostH(gx, gy, gz));
|
node.setCost(_current, weight, getCostH(gx, gy, gz));
|
||||||
_opened.add(node);
|
_opened.add(node);
|
||||||
_bufferIndex++;
|
_bufferIndex++;
|
||||||
return nswe;
|
return nswe;
|
||||||
@@ -354,15 +523,34 @@ public class NodeBuffer
|
|||||||
private int getCostH(int gx, int gy, int gz)
|
private int getCostH(int gx, int gy, int gz)
|
||||||
{
|
{
|
||||||
// Get differences to the target.
|
// Get differences to the target.
|
||||||
final int dx = Math.abs(gx - _gtx);
|
int dx = Math.abs(gx - _gtx);
|
||||||
final int dy = Math.abs(gy - _gty);
|
int dy = Math.abs(gy - _gty);
|
||||||
final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
|
||||||
|
|
||||||
// Get diagonal and axial differences to the target.
|
// Get diagonal and axial differences to the target.
|
||||||
final int dd = Math.min(dx, dy);
|
final int ds = Math.min(dx, Math.min(dy, dz));
|
||||||
final int da = Math.max(dx, dy) - dd;
|
dx -= ds;
|
||||||
|
dy -= ds;
|
||||||
|
dz -= ds;
|
||||||
|
int dd;
|
||||||
|
int d;
|
||||||
|
if (dx == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dy, dz);
|
||||||
|
d = Math.max(dy, dz) - dd;
|
||||||
|
}
|
||||||
|
else if (dy == 0)
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dz);
|
||||||
|
d = Math.max(dx, dz) - dd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = Math.min(dx, dy);
|
||||||
|
d = Math.max(dx, dy) - dd;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the diagonal distance of the node to the target.
|
// Calculate the diagonal distance of the node to the target.
|
||||||
return (dd * Config.HEURISTIC_WEIGHT_DIAG) + ((da + dz) * Config.HEURISTIC_WEIGHT);
|
return (int) (((int) (ds * Math.sqrt(3)) + (dd * Config.HEURISTIC_WEIGHT_DIAG) + (d * Config.HEURISTIC_WEIGHT)) * 1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ GeoDataType = L2J
|
|||||||
# an alternative path (e.g. walk around obstacle), default: True
|
# an alternative path (e.g. walk around obstacle), default: True
|
||||||
PathFinding = True
|
PathFinding = True
|
||||||
|
|
||||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
|
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
|
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
|
||||||
|
|
||||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
|
||||||
MoveWeight = 10
|
MoveWeight = 10
|
||||||
|
|||||||
@@ -904,6 +904,7 @@ public class Config
|
|||||||
public static int MOVE_WEIGHT;
|
public static int MOVE_WEIGHT;
|
||||||
public static int MOVE_WEIGHT_DIAG;
|
public static int MOVE_WEIGHT_DIAG;
|
||||||
public static int OBSTACLE_WEIGHT;
|
public static int OBSTACLE_WEIGHT;
|
||||||
|
public static int OBSTACLE_WEIGHT_DIAG;
|
||||||
public static int HEURISTIC_WEIGHT;
|
public static int HEURISTIC_WEIGHT;
|
||||||
public static int HEURISTIC_WEIGHT_DIAG;
|
public static int HEURISTIC_WEIGHT_DIAG;
|
||||||
public static int MAX_ITERATIONS;
|
public static int MAX_ITERATIONS;
|
||||||
@@ -2417,10 +2418,11 @@ public class Config
|
|||||||
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
GEODATA_PATH = Paths.get(GeoEngine.getString("GeoDataPath", "./data/geodata"));
|
||||||
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
GEODATA_TYPE = Enum.valueOf(GeoType.class, GeoEngine.getString("GeoDataType", "L2J"));
|
||||||
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
PATHFINDING = GeoEngine.getBoolean("PathFinding", true);
|
||||||
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "500x10;1000x10;3000x5;5000x3;10000x3");
|
PATHFIND_BUFFERS = GeoEngine.getString("PathFindBuffers", "1200x10;2000x10;3000x5;5000x3;10000x3");
|
||||||
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
MOVE_WEIGHT = GeoEngine.getInt("MoveWeight", 10);
|
||||||
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
MOVE_WEIGHT_DIAG = GeoEngine.getInt("MoveWeightDiag", 14);
|
||||||
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
OBSTACLE_WEIGHT = GeoEngine.getInt("ObstacleWeight", 30);
|
||||||
|
OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
|
||||||
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
HEURISTIC_WEIGHT = GeoEngine.getInt("HeuristicWeight", 12);
|
||||||
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
HEURISTIC_WEIGHT_DIAG = GeoEngine.getInt("HeuristicWeightDiag", 18);
|
||||||
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
MAX_ITERATIONS = GeoEngine.getInt("MaxIterations", 3500);
|
||||||
|
|||||||
+47
-18
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
|
|||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
@@ -152,22 +153,12 @@ public class GeoEngine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unlocked NodeBuffer.
|
// Get NodeBuffer.
|
||||||
for (NodeBuffer buffer : holder._buffer)
|
current = holder.getBuffer();
|
||||||
|
if (current != null)
|
||||||
{
|
{
|
||||||
if (!buffer.isLocked())
|
return current;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.warning("Creating new NodeBuffer " + size + " size, as no buffer empty or out of size.");
|
|
||||||
|
|
||||||
// NodeBuffer not found, allocate temporary buffer.
|
|
||||||
current = new NodeBuffer(holder._size);
|
|
||||||
current.isLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
@@ -949,7 +940,12 @@ public class GeoEngine
|
|||||||
int gtz = getHeightNearest(gtx, gty, tz);
|
int gtz = getHeightNearest(gtx, gty, tz);
|
||||||
|
|
||||||
// Prepare buffer for pathfinding calculations.
|
// Prepare buffer for pathfinding calculations.
|
||||||
NodeBuffer buffer = getBuffer(300 + (10 * (Math.abs(gox - gtx) + Math.abs(goy - gty) + Math.abs(goz - gtz))));
|
int dx = Math.abs(gox - gtx);
|
||||||
|
int dy = Math.abs(goy - gty);
|
||||||
|
int dz = Math.abs(goz - gtz) / 8;
|
||||||
|
int total = dx + dy + dz;
|
||||||
|
int size = 1000 + (10 * total);
|
||||||
|
NodeBuffer buffer = getBuffer(size);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -1026,18 +1022,51 @@ public class GeoEngine
|
|||||||
private static class BufferHolder
|
private static class BufferHolder
|
||||||
{
|
{
|
||||||
final int _size;
|
final int _size;
|
||||||
final List<NodeBuffer> _buffer;
|
final int _count;
|
||||||
|
final Set<NodeBuffer> _buffer;
|
||||||
|
|
||||||
public BufferHolder(int size, int count)
|
public BufferHolder(int size, int count)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_buffer = new ArrayList<>(count);
|
_count = count * 4;
|
||||||
|
_buffer = ConcurrentHashMap.newKeySet(_count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_buffer.add(new NodeBuffer(size));
|
_buffer.add(new NodeBuffer(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeBuffer getBuffer()
|
||||||
|
{
|
||||||
|
// Get available free NodeBuffer.
|
||||||
|
for (NodeBuffer buffer : _buffer)
|
||||||
|
{
|
||||||
|
if (!buffer.isLocked())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No free NodeBuffer found, try allocate new buffer.
|
||||||
|
if (_buffer.size() < _count)
|
||||||
|
{
|
||||||
|
NodeBuffer buffer = new NodeBuffer(_size);
|
||||||
|
buffer.isLocked();
|
||||||
|
_buffer.add(buffer);
|
||||||
|
|
||||||
|
if (_buffer.size() == _count)
|
||||||
|
{
|
||||||
|
LOGGER.warning("NodeBuffer holder with " + _size + " size reached max capacity.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
@@ -26,8 +26,24 @@ public final class GeoStructure
|
|||||||
public static final byte CELL_FLAG_W = 0x02;
|
public static final byte CELL_FLAG_W = 0x02;
|
||||||
public static final byte CELL_FLAG_S = 0x04;
|
public static final byte CELL_FLAG_S = 0x04;
|
||||||
public static final byte CELL_FLAG_N = 0x08;
|
public static final byte CELL_FLAG_N = 0x08;
|
||||||
|
public static final byte CELL_FLAG_SE = 0x10;
|
||||||
|
public static final byte CELL_FLAG_SW = 0x20;
|
||||||
|
public static final byte CELL_FLAG_NE = 0x40;
|
||||||
|
public static final byte CELL_FLAG_NW = (byte) 0x80;
|
||||||
public static final byte CELL_FLAG_ALL = 0x0F;
|
public static final byte CELL_FLAG_ALL = 0x0F;
|
||||||
|
|
||||||
|
// Geo cell expansion flags
|
||||||
|
public static final byte CELL_EXPANSION_E = CELL_FLAG_E | CELL_FLAG_NE | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_W = CELL_FLAG_W | CELL_FLAG_NW | CELL_FLAG_SW;
|
||||||
|
public static final byte CELL_EXPANSION_S = CELL_FLAG_S | CELL_FLAG_SW | CELL_FLAG_SE;
|
||||||
|
public static final byte CELL_EXPANSION_N = CELL_FLAG_N | CELL_FLAG_NW | CELL_FLAG_NE;
|
||||||
|
public static final byte CELL_EXPANSION_SE = CELL_FLAG_SE | CELL_FLAG_S | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_SW = CELL_FLAG_SW | CELL_FLAG_S | CELL_FLAG_W;
|
||||||
|
public static final byte CELL_EXPANSION_NE = CELL_FLAG_NE | CELL_FLAG_N | CELL_FLAG_E;
|
||||||
|
public static final byte CELL_EXPANSION_NW = CELL_FLAG_NW | CELL_FLAG_N | CELL_FLAG_W;
|
||||||
|
// public static final byte CELL_EXPANSION_MASK = CELL_FLAG_SE | CELL_FLAG_SW | CELL_FLAG_NE | CELL_FLAG_NW;
|
||||||
|
public static final byte CELL_EXPANSION_ALL = (byte) 0xFF;
|
||||||
|
|
||||||
// Geo cell height constants.
|
// Geo cell height constants.
|
||||||
public static final int CELL_SIZE = 16;
|
public static final int CELL_SIZE = 16;
|
||||||
public static final int CELL_HEIGHT = 8;
|
public static final int CELL_HEIGHT = 8;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user