Added a target coordinate finder.

Implemented DFS name changes.
This commit is contained in:
2020-04-20 23:24:12 -05:00
parent cf6a371428
commit f5e3435d8b
5 changed files with 231 additions and 93 deletions

View File

@@ -0,0 +1,11 @@
package ca.recrown.islandsurvivalcraft.pathfinding;
public interface CoordinateTargetValidatable {
/**
* Is the current coordinate the objective?
* @param x the x of the coordinate.
* @param y the y of the coordinate.
* @return true if this is the objective coordinate.
*/
public boolean isCoordinateTarget(int x, int y);
}

View File

@@ -1,35 +1,44 @@
package ca.recrown.islandsurvivalcraft.pathfinding;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
public class DepthFirstSearch {
private PriorityQueue<Node> queue;
private Queue<Node> queue;
private CoordinateValidatable validatable;
private Node startNode;
private Node endNode;
private ArrayList<Node> checkedNodes;
public DepthFirstSearch(CoordinateValidatable validatable) {
queue = new PriorityQueue<>();
this.validatable = validatable;
public DepthFirstSearch() {
checkedNodes = new ArrayList<>();
}
public void Setup(int xGoal, int yGoal, int x, int y) {
startNode = new Node(null, xGoal, yGoal, x, y);
public DepthFirstSearch(CoordinateValidatable validatable) {
this();
this.validatable = validatable;
}
public Node getTree() {
return startNode;
public void setValidatable(CoordinateValidatable validatable) {
this.validatable = validatable;
}
public void setStartPosition(int x, int y) {
startNode = new Node(null, x, y);
}
public Node getEndNode() {
return endNode;
public void setEndPosition(int x, int y) {
endNode = new Node(null, x, y);
}
public Node getParentOfNode(Node node) {
return node.parent;
public int getEndX() {
return endNode.x;
}
public int getEndY() {
return endNode.y;
}
public void deleteTree() {
@@ -37,14 +46,49 @@ public class DepthFirstSearch {
endNode = null;
}
public boolean buildTree() {
public boolean buildPathToEndNode() {
queue = new PriorityQueue<>();
checkedNodes.clear();
queue.clear();
Node begin = startNode;
queue.add(begin);
while (!queue.isEmpty()) {
Node n = queue.poll();
if (!(n.x == n.xGoal && n.y == n.yGoal)) {
if (!n.equals(endNode)) {
n.child[0] = new Node(n, n.x + 1, n.y);
n.child[1] = new Node(n, n.x - 1, n.y);
n.child[2] = new Node(n, n.x, n.y + 1);
n.child[3] = new Node(n, n.x, n.y - 1);
} else {
n.shallowCopyTo(endNode);
return true;
}
if (!n.check()) {
for (int i = 0; i < n.child.length; i++) {
Node child = n.child[i];
if (validatable.validate(child.x, child.y)) {
queue.add(child);
}
}
}
}
return false;
}
/**
* Finds the end node.
* Will not set end node if one wasn't found,
* therefore, previous end node data is kept.
* @param targetValidator
* @return
*/
public boolean findEndNode(CoordinateTargetValidatable targetValidator) {
queue = new LinkedList<>();
checkedNodes.clear();
Node begin = startNode;
queue.add(begin);
while (!queue.isEmpty()) {
Node n = queue.poll();
if (!targetValidator.isCoordinateTarget(n.x, n.y)) {
n.child[0] = new Node(n, n.x + 1, n.y);
n.child[1] = new Node(n, n.x - 1, n.y);
n.child[2] = new Node(n, n.x, n.y + 1);
@@ -55,8 +99,9 @@ public class DepthFirstSearch {
}
if (!n.check()) {
for (int i = 0; i < n.child.length; i++) {
if (validatable.validate(n.child[i].x, n.child[i].y)) {
queue.add(n.child[i]);
Node child = n.child[i];
if (validatable.validate(child.x, child.y)) {
queue.add(child);
}
}
}
@@ -66,49 +111,35 @@ public class DepthFirstSearch {
private class Node implements Comparable<Node> {
public Node[] child;
public final Node parent;
public Node parent;
public int x;
public int y;
private boolean checked = false;
private final int xGoal;
private final int yGoal;
public Node(Node parent, int xGoal, int yGoal, int x, int y) {
public Node(Node parent, int x, int y) {
this.parent = parent;
child = new Node[4];
this.xGoal = xGoal;
this.yGoal = yGoal;
this.x = x;
this.y = y;
}
public Node(Node parent, int x, int y) {
this(parent, parent.xGoal, parent.yGoal, x, y);
}
@Override
public int compareTo(Node o) {
return Math.round(distanceToGoal() - o.distanceToGoal());
return Math.round(distanceToGoal(endNode) - o.distanceToGoal(endNode));
}
public float distanceToGoal() {
float distanceX = xGoal - this.x;
float distanceY = yGoal - this.y;
public float distanceToGoal(Node goal) {
float distanceX = goal.x - this.x;
float distanceY = goal.y - this.y;
float distance = (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
return distance;
}
public boolean check() {
if (!checked) {
checked = true;
if (checkedNodes.contains(this)) {
return true;
}
checkedNodes.add(this);
return false;
if (checkedNodes.contains(this)) {
return true;
}
return true;
checkedNodes.add(this);
return false;
}
@Override
@@ -121,5 +152,12 @@ public class DepthFirstSearch {
}
return false;
}
public void shallowCopyTo(Node node) {
node.child = this.child;
node.parent = this.parent;
node.x = this.x;
node.y = this.y;
}
}
}

View File

@@ -1,5 +1,6 @@
package ca.recrown.islandsurvivalcraft.worldgeneration;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
@@ -9,12 +10,13 @@ import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandOwnerMetadata;
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandShoreBiomeMetadata;
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandTUIDMetadata;
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandTemperatureMetadata;
import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateTargetValidatable;
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandBedrockMetadataHelper;
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandMainBiomeMetadata;
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandMetadataPack;
public class BiomePerIslandGenerator implements IslandBiomeGenerator {
public class BiomePerIslandGenerator implements IslandBiomeGenerator, CoordinateTargetValidatable {
private IslandMapGenerator mapGenerator;
private Biome currentIslandBiome;
private float currentIslandTemperature;
@@ -42,7 +44,7 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
int worldZ = chunkZ * 16 + localZ;
if (mapGenerator.isIsland(worldX, worldZ)) {
IslandMetadataPack sameIslandPack = getSurroundingIslandData(world, worldX, worldZ);
IslandMetadataPack sameIslandPack = getSurroundingIslandData(worldX, worldZ);
if (sameIslandPack != null) {
//Old island
currentIslandBiome = sameIslandPack.mainBiomeMetadata.getMainBiome();
@@ -50,6 +52,8 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
currentIslandTemperature = sameIslandPack.temperatureMetadata.getTemperature();
currentTUID = sameIslandPack.islandTIUDMetadata.getIUID();
} else {
//New island
currentIslandTemperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
currentIslandBiome = biomeSelector.getLandBiome(currentIslandTemperature);
@@ -67,16 +71,46 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
current.setTUID(currentTUID, plugin);
metadataHelper.setIslandBedrockMetadataPack(worldX, worldZ, current);
//Set the biome information for the chunk
if (mapGenerator.isShore(worldX, worldZ)) {
setBiome(localX, localZ, biome, currentIslandShoreBiome);
} else {
setBiome(localX, localZ, biome, currentIslandBiome);
}
//Check if island besides this one need to be generated.
if (localX == 0 && mapGenerator.isSameIsland(worldX, worldZ, worldX - 1, worldZ)) {
if (!world.isChunkGenerated(chunkX - 1, chunkZ)) {
Chunk chunk = world.getChunkAt(chunkX - 1, chunkZ);
chunk.load(true);
chunk.unload(true);
}
} else if (localX == 15 && mapGenerator.isSameIsland(worldX, worldZ, worldX + 1, worldZ)) {
if (!world.isChunkGenerated(chunkX + 1, chunkZ)) {
Chunk chunk = world.getChunkAt(chunkX + 1, chunkZ);
chunk.load(true);
chunk.unload(true);
}
}
if (localZ == 0 && mapGenerator.isSameIsland(worldX, worldZ, worldX, worldZ - 1)) {
if (!world.isChunkGenerated(chunkX, chunkZ - 1)) {
Chunk chunk = world.getChunkAt(chunkX, chunkZ - 1);
chunk.load(true);
chunk.unload(true);
}
} else if (localZ == 15 && mapGenerator.isSameIsland(worldX, worldZ, worldX, worldZ + 1)) {
if (!world.isChunkGenerated(chunkX, chunkZ + 1)) {
Chunk chunk = world.getChunkAt(chunkX, chunkZ + 1);
chunk.load(true);
chunk.unload(true);
}
}
}
}
private IslandMetadataPack getSurroundingIslandData(World world, int worldX, int worldZ) {
private IslandMetadataPack getSurroundingIslandData(int worldX, int worldZ) {
IslandMetadataPack data = null;
if (mapGenerator.isSameIsland(worldX, worldZ, worldX + 1, worldZ)) {
data = getMetadataPackAt(worldX + 1, worldZ, world);
@@ -114,4 +148,10 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
biomeGrid.setBiome(localX, y, localZ, biome);
}
}
@Override
public boolean isCoordinateTarget(int x, int y) {
return false;
}
}

View File

@@ -140,8 +140,9 @@ public class IslandMapGenerator implements CoordinateValidatable {
public boolean isSameIsland(int firstBlockX, int firstBlockZ, int secondBlockX, int secondBlockZ) {
if (!isIsland(firstBlockX, firstBlockZ)) return false;
if (!isIsland(secondBlockX, secondBlockZ)) return false;
dfs.Setup(secondBlockX, secondBlockZ, firstBlockX, firstBlockZ);
boolean res = dfs.buildTree();
dfs.setStartPosition(firstBlockX, firstBlockZ);
dfs.setEndPosition(secondBlockX, secondBlockZ);
boolean res = dfs.buildPathToEndNode();
dfs.deleteTree();
return res;
}