Fixed NodeBuffer exhaustion.
This commit is contained in:
		@@ -19,8 +19,8 @@ GeoDataType = L2J
 | 
			
		||||
# an alternative path (e.g. walk around obstacle), default: True
 | 
			
		||||
PathFinding = True
 | 
			
		||||
 | 
			
		||||
# Pathfinding array buffers configuration, default: 500x10;1000x10;3000x5;5000x3;10000x3
 | 
			
		||||
PathFindBuffers = 500x10;1000x10;3000x5;5000x3;10000x3
 | 
			
		||||
# Pathfinding array buffers configuration, default: 1200x10;2000x10;3000x5;5000x3;10000x3
 | 
			
		||||
PathFindBuffers = 1200x10;2000x10;3000x5;5000x3;10000x3
 | 
			
		||||
 | 
			
		||||
# Movement weight, when moving from one to another axially and diagonally, default: 10 and 14
 | 
			
		||||
MoveWeight = 10
 | 
			
		||||
 
 | 
			
		||||
@@ -979,6 +979,7 @@ public class Config
 | 
			
		||||
	public static int MOVE_WEIGHT;
 | 
			
		||||
	public static int MOVE_WEIGHT_DIAG;
 | 
			
		||||
	public static int OBSTACLE_WEIGHT;
 | 
			
		||||
	public static int OBSTACLE_WEIGHT_DIAG;
 | 
			
		||||
	public static int HEURISTIC_WEIGHT;
 | 
			
		||||
	public static int HEURISTIC_WEIGHT_DIAG;
 | 
			
		||||
	public static int MAX_ITERATIONS;
 | 
			
		||||
@@ -2583,10 +2584,11 @@ public class Config
 | 
			
		||||
		GEODATA_PATH = Paths.get(geoengineConfig.getString("GeoDataPath", "./data/geodata"));
 | 
			
		||||
		GEODATA_TYPE = Enum.valueOf(GeoType.class, geoengineConfig.getString("GeoDataType", "L2J"));
 | 
			
		||||
		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_DIAG = geoengineConfig.getInt("MoveWeightDiag", 14);
 | 
			
		||||
		OBSTACLE_WEIGHT = geoengineConfig.getInt("ObstacleWeight", 30);
 | 
			
		||||
		OBSTACLE_WEIGHT_DIAG = (int) (OBSTACLE_WEIGHT * Math.sqrt(2));
 | 
			
		||||
		HEURISTIC_WEIGHT = geoengineConfig.getInt("HeuristicWeight", 12);
 | 
			
		||||
		HEURISTIC_WEIGHT_DIAG = geoengineConfig.getInt("HeuristicWeightDiag", 18);
 | 
			
		||||
		MAX_ITERATIONS = geoengineConfig.getInt("MaxIterations", 3500);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,11 @@ import java.nio.MappedByteBuffer;
 | 
			
		||||
import java.nio.channels.FileChannel;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.ListIterator;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
import org.l2jmobius.Config;
 | 
			
		||||
@@ -151,22 +152,12 @@ public class GeoEngine
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			// Find unlocked NodeBuffer.
 | 
			
		||||
			for (NodeBuffer buffer : holder._buffer)
 | 
			
		||||
			// Get NodeBuffer.
 | 
			
		||||
			current = holder.getBuffer();
 | 
			
		||||
			if (current != null)
 | 
			
		||||
			{
 | 
			
		||||
				if (!buffer.isLocked())
 | 
			
		||||
				{
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				return buffer;
 | 
			
		||||
				return current;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			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;
 | 
			
		||||
@@ -948,7 +939,12 @@ public class GeoEngine
 | 
			
		||||
		int gtz = getHeightNearest(gtx, gty, tz);
 | 
			
		||||
		
 | 
			
		||||
		// 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)
 | 
			
		||||
		{
 | 
			
		||||
			return Collections.emptyList();
 | 
			
		||||
@@ -1025,18 +1021,51 @@ public class GeoEngine
 | 
			
		||||
	private static class BufferHolder
 | 
			
		||||
	{
 | 
			
		||||
		final int _size;
 | 
			
		||||
		final List<NodeBuffer> _buffer;
 | 
			
		||||
		final int _count;
 | 
			
		||||
		final Set<NodeBuffer> _buffer;
 | 
			
		||||
		
 | 
			
		||||
		public BufferHolder(int size, int count)
 | 
			
		||||
		{
 | 
			
		||||
			_size = size;
 | 
			
		||||
			_buffer = new ArrayList<>(count);
 | 
			
		||||
			_count = count * 4;
 | 
			
		||||
			_buffer = ConcurrentHashMap.newKeySet(_count);
 | 
			
		||||
			
 | 
			
		||||
			for (int i = 0; i < count; i++)
 | 
			
		||||
			{
 | 
			
		||||
				_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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,24 @@ public final class GeoStructure
 | 
			
		||||
	public static final byte CELL_FLAG_W = 0x02;
 | 
			
		||||
	public static final byte CELL_FLAG_S = 0x04;
 | 
			
		||||
	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;
 | 
			
		||||
	
 | 
			
		||||
	// 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.
 | 
			
		||||
	public static final int CELL_SIZE = 16;
 | 
			
		||||
	public static final int CELL_HEIGHT = 8;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ public class Node extends Location implements Comparable<Node>
 | 
			
		||||
	private int _geoX;
 | 
			
		||||
	private int _geoY;
 | 
			
		||||
	private byte _nswe;
 | 
			
		||||
	private byte _nsweExpand;
 | 
			
		||||
	
 | 
			
		||||
	// The cost G (movement cost done) and cost H (estimated cost to target).
 | 
			
		||||
	private int _costG;
 | 
			
		||||
@@ -48,6 +49,7 @@ public class Node extends Location implements Comparable<Node>
 | 
			
		||||
		_geoX = 0;
 | 
			
		||||
		_geoY = 0;
 | 
			
		||||
		_nswe = GeoStructure.CELL_FLAG_NONE;
 | 
			
		||||
		_nsweExpand = GeoStructure.CELL_FLAG_NONE;
 | 
			
		||||
		
 | 
			
		||||
		_costG = 0;
 | 
			
		||||
		_costH = 0;
 | 
			
		||||
@@ -56,13 +58,14 @@ public class Node extends Location implements Comparable<Node>
 | 
			
		||||
		_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);
 | 
			
		||||
		
 | 
			
		||||
		_geoX = gx;
 | 
			
		||||
		_geoY = gy;
 | 
			
		||||
		_nswe = nswe;
 | 
			
		||||
		_nsweExpand = nsweExpand;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setCost(Node parent, int weight, int costH)
 | 
			
		||||
@@ -93,6 +96,11 @@ public class Node extends Location implements Comparable<Node>
 | 
			
		||||
		return _nswe;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public byte getNsweExpand()
 | 
			
		||||
	{
 | 
			
		||||
		return _nsweExpand;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public int getCostF()
 | 
			
		||||
	{
 | 
			
		||||
		return _costF;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.l2jmobius.gameserver.geoengine.pathfinding;
 | 
			
		||||
 | 
			
		||||
import java.awt.Color;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
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.GeoStructure;
 | 
			
		||||
import org.l2jmobius.gameserver.model.Location;
 | 
			
		||||
import org.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
 | 
			
		||||
 | 
			
		||||
public class NodeBuffer
 | 
			
		||||
{
 | 
			
		||||
@@ -97,7 +95,7 @@ public class NodeBuffer
 | 
			
		||||
		_current = _buffer[_bufferIndex++];
 | 
			
		||||
		
 | 
			
		||||
		// 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));
 | 
			
		||||
		
 | 
			
		||||
		int count = 0;
 | 
			
		||||
@@ -166,25 +164,6 @@ public class NodeBuffer
 | 
			
		||||
		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()
 | 
			
		||||
	{
 | 
			
		||||
		return _lock.tryLock();
 | 
			
		||||
@@ -219,7 +198,8 @@ public class NodeBuffer
 | 
			
		||||
	{
 | 
			
		||||
		// Movement is blocked, skip.
 | 
			
		||||
		final byte nswe = _current.getNSWE();
 | 
			
		||||
		if (nswe == GeoStructure.CELL_FLAG_NONE)
 | 
			
		||||
		byte expand = _current.getNsweExpand();
 | 
			
		||||
		if ((nswe & expand) == GeoStructure.CELL_FLAG_NONE)
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
@@ -235,53 +215,230 @@ public class NodeBuffer
 | 
			
		||||
		byte nsweW = GeoStructure.CELL_FLAG_NONE;
 | 
			
		||||
		byte nsweE = GeoStructure.CELL_FLAG_NONE;
 | 
			
		||||
		
 | 
			
		||||
		// Can move north, expand.
 | 
			
		||||
		if ((nswe & GeoStructure.CELL_FLAG_N) != 0)
 | 
			
		||||
		switch (expand)
 | 
			
		||||
		{
 | 
			
		||||
			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.
 | 
			
		||||
		if ((nswe & GeoStructure.CELL_FLAG_S) != 0)
 | 
			
		||||
		// Get geodata block and check if there is a layer at given coordinates.
 | 
			
		||||
		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.
 | 
			
		||||
		if ((nswe & GeoStructure.CELL_FLAG_W) != 0)
 | 
			
		||||
		{
 | 
			
		||||
			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);
 | 
			
		||||
		}
 | 
			
		||||
		// Get node geodata nswe.
 | 
			
		||||
		return block.getNswe(index);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
@@ -289,10 +446,11 @@ public class NodeBuffer
 | 
			
		||||
	 * @param gx : The new node X geodata coordinate.
 | 
			
		||||
	 * @param gy : The new node Y 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.
 | 
			
		||||
	 */
 | 
			
		||||
	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).
 | 
			
		||||
		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).
 | 
			
		||||
		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.
 | 
			
		||||
		node.setGeo(gx, gy, gz, nswe);
 | 
			
		||||
		node.setGeo(gx, gy, gz, nswe, nsweExpand);
 | 
			
		||||
		
 | 
			
		||||
		// Node is already added to opened list, return.
 | 
			
		||||
		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.
 | 
			
		||||
		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);
 | 
			
		||||
		_bufferIndex++;
 | 
			
		||||
		return nswe;
 | 
			
		||||
@@ -354,15 +523,34 @@ public class NodeBuffer
 | 
			
		||||
	private int getCostH(int gx, int gy, int gz)
 | 
			
		||||
	{
 | 
			
		||||
		// Get differences to the target.
 | 
			
		||||
		final int dx = Math.abs(gx - _gtx);
 | 
			
		||||
		final int dy = Math.abs(gy - _gty);
 | 
			
		||||
		final int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
 | 
			
		||||
		int dx = Math.abs(gx - _gtx);
 | 
			
		||||
		int dy = Math.abs(gy - _gty);
 | 
			
		||||
		int dz = Math.abs(gz - _gtz) / GeoStructure.CELL_HEIGHT;
 | 
			
		||||
		
 | 
			
		||||
		// Get diagonal and axial differences to the target.
 | 
			
		||||
		final int dd = Math.min(dx, dy);
 | 
			
		||||
		final int da = Math.max(dx, dy) - dd;
 | 
			
		||||
		final int ds = Math.min(dx, Math.min(dy, dz));
 | 
			
		||||
		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.
 | 
			
		||||
		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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user