package com.hypixel.hytale.server.npc.navigation;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import java.util.List;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AStarDebugBase {
public static final char CENTER = ' ';
public static final char CROSS = '┼';
public static final char HLINE = '─';
public static final char VLINE = '│';
public static final char OPEN_NODE = '◆';
public static final char CLOSED_NODE = '◇';
public static final char CLOSED_PATH_NODE = '◯';
public static final char OPEN_PATH_NODE = '◉';
public static final char BLOCKED_NODE = '×';
public static final char START_POSITION = '@';
public static final char END_POSITION = 'Ω';
public static final String BORDER_PATTERN = "─┼".repeat(1025);
public static final String CENTER_PATTERN = " │".repeat(1025);
protected AStarBase aStarBase;
protected HytaleLogger logger;
protected HytaleLogger.Api loggerInfo;
public AStarDebugBase(AStarBase base, @Nonnull HytaleLogger logger) {
this.aStarBase = base;
this.logger = logger;
this.loggerInfo = logger.at(Level.INFO);
}
public void dumpOpens(MotionController controller) {
int openCount = this.aStarBase.getOpenCount();
List<AStarNode> openNodes = this.aStarBase.getOpenNodes();
int maxLength = -1;
for(int i = 0; i < openCount; ++i) {
int length = ((AStarNode)openNodes.get(i)).getLength();
if (length > maxLength) {
maxLength = length;
}
}
this.loggerInfo.log("== A* iter=%s opens=%s total=%s maxLength=%s %s", this.aStarBase.getIterations(), openCount, this.aStarBase.getVisitedBlocks().size(), maxLength, this.getExtraLogString(controller));
for(int i = 0; i < openCount; ++i) {
this.loggerInfo.log("%2d %s", i, ((AStarNode)openNodes.get(i)).toString());
}
}
public void dumpPath() {
AStarNode node = this.aStarBase.getPath();
this.loggerInfo.log("== A* Path iter=%s opens=%s total=%s", this.aStarBase.getIterations(), this.aStarBase.getOpenCount(), this.aStarBase.getVisitedBlocks().size());
while(node != null) {
this.loggerInfo.log("%s", node.toString());
node = node.getNextPathNode();
}
}
public void dumpMap(boolean drawPath, MotionController controller) {
int openCount = this.aStarBase.getOpenCount();
List<AStarNode> openNodes = this.aStarBase.getOpenNodes();
AStarNode start = null;
boolean finalPath = false;
if (drawPath) {
AStarNode path = this.aStarBase.getPath();
if (path != null) {
start = path;
finalPath = true;
} else if (openCount > 0) {
start = (AStarNode)openNodes.get(openCount - 1);
}
}
this.dumpMap(start, finalPath, controller);
}
public void dumpMap(@Nullable AStarNode pathNode, boolean isFinalPath, MotionController controller) {
long startPositionIndex = this.aStarBase.getStartPositionIndex();
Long2ObjectMap<AStarNode> visitedBlocks = this.aStarBase.getVisitedBlocks();
int s = AStarBase.xFromIndex(startPositionIndex);
int e = this.getDumpMapRegionX(s);
int minX;
int maxX;
if (s < e) {
minX = s;
maxX = e;
} else {
minX = e;
maxX = s;
}
s = AStarBase.zFromIndex(startPositionIndex);
e = this.getDumpMapRegionZ(s);
int minZ;
int maxZ;
if (s < e) {
minZ = s;
maxZ = e;
} else {
minZ = e;
maxZ = s;
}
ObjectIterator<Long2ObjectMap.Entry<AStarNode>> fastIterator = Long2ObjectMaps.fastIterator(visitedBlocks);
while(fastIterator.hasNext()) {
AStarNode node = (AStarNode)((Long2ObjectMap.Entry)fastIterator.next()).getValue();
int x = AStarBase.xFromIndex(node.getPositionIndex());
int z = AStarBase.zFromIndex(node.getPositionIndex());
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
if (z < minZ) {
minZ = z;
}
if (z > maxZ) {
maxZ = z;
}
}
int rows = maxZ - minZ + 1;
int columns = maxX - minX + 1;
int offset = minX & 1;
boolean evenStart = (minZ & 1) == 0;
String var10000 = (evenStart ? CENTER_PATTERN : BORDER_PATTERN).substring(offset, offset + columns);
String first = "'" + var10000 + "'";
var10000 = (evenStart ? BORDER_PATTERN : CENTER_PATTERN).substring(offset, offset + columns);
String second = "'" + var10000 + "'";
StringBuilder[] map = new StringBuilder[rows];
for(int i = 0; i < rows; i += 2) {
map[i] = new StringBuilder(first);
if (i + 1 < rows) {
map[i + 1] = new StringBuilder(second);
}
}
fastIterator = Long2ObjectMaps.fastIterator(visitedBlocks);
while(fastIterator.hasNext()) {
AStarNode node = (AStarNode)((Long2ObjectMap.Entry)fastIterator.next()).getValue();
this.plot(node.getPositionIndex(), (char)(node.isInvalid() ? '×' : (node.isOpen() ? '◆' : '◇')), map, minX, minZ);
}
int openCount = this.aStarBase.getOpenCount();
int maxLength;
if (pathNode != null) {
for(maxLength = pathNode.getLength(); pathNode != null; pathNode = isFinalPath ? pathNode.getNextPathNode() : pathNode.getPredecessor()) {
this.plot(pathNode.getPositionIndex(), (char)(pathNode.isOpen() ? '◉' : '◯'), map, minX, minZ);
}
} else {
List<AStarNode> openNodes = this.aStarBase.getOpenNodes();
int index = openCount;
maxLength = 0;
while(true) {
--index;
if (index < 0) {
break;
}
int pos = openCount - index;
if (pos > 51) {
break;
}
this.plot(((AStarNode)openNodes.get(index)).getPositionIndex(), (char)(pos >= 26 ? pos - 26 + 97 : pos + 65), map, minX, minZ);
}
}
this.plot(startPositionIndex, '@', map, minX, minZ);
this.drawMapFinish(map, minX, minZ);
this.loggerInfo.log("== A* iter=%s, opens=%s total=%s maxLength=%s %s", this.aStarBase.getIterations(), openCount, visitedBlocks.size(), maxLength, this.getExtraLogString(controller));
for(StringBuilder stringBuilder : map) {
this.loggerInfo.log(stringBuilder.toString());
}
}
protected void plot(long positionIndex, char character, @Nonnull StringBuilder[] map, int minX, int minZ) {
int row = AStarBase.zFromIndex(positionIndex) - minZ;
int column = AStarBase.xFromIndex(positionIndex) - minX + 1;
map[row].setCharAt(column, character);
}
protected void drawMapFinish(StringBuilder[] map, int minX, int minZ) {
}
protected int getDumpMapRegionZ(int def) {
return def;
}
protected int getDumpMapRegionX(int def) {
return def;
}
@Nonnull
protected String getExtraLogString(MotionController controller) {
return "";
}
}