Island info data structure added.
In addition: changed the world info management to use world name as key.
This commit is contained in:
parent
44518270e1
commit
bd7f591f36
@ -44,7 +44,7 @@ public class IslandSurvivalCraft extends JavaPlugin implements Listener {
|
|||||||
} catch (NullPointerException | IllegalArgumentException e) {
|
} catch (NullPointerException | IllegalArgumentException e) {
|
||||||
gID = GeneratorModes.UNIQUE;
|
gID = GeneratorModes.UNIQUE;
|
||||||
}
|
}
|
||||||
return worldInfoManager.getChunkGenerator(getServer().getWorld(worldName), gID);
|
return worldInfoManager.getChunkGenerator(worldName, gID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,12 +5,12 @@ import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.HighlightIs
|
|||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
||||||
import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.CommandRunnable;
|
import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.*;
|
||||||
import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.HelpCommand;
|
|
||||||
|
|
||||||
public enum Commands implements CommandRunnable {
|
public enum Commands implements CommandRunnable {
|
||||||
HIGHLIGHT(new HighlightIslandCommand()),
|
HIGHLIGHT(new HighlightIslandCommand()),
|
||||||
HELP(new HelpCommand()),
|
HELP(new HelpCommand()),
|
||||||
|
VALUE(new ValueRunnable()),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final CommandRunnable commandRunnable;
|
private final CommandRunnable commandRunnable;
|
||||||
|
@ -2,7 +2,9 @@ package ca.recrown.islandsurvivalcraft.interaction.commands.runnables;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -16,12 +18,12 @@ import org.bukkit.entity.Player;
|
|||||||
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
||||||
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
|
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
|
||||||
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch;
|
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch;
|
||||||
import ca.recrown.islandsurvivalcraft.world.IslandWorldMap;
|
|
||||||
import ca.recrown.islandsurvivalcraft.world.WorldInfo;
|
import ca.recrown.islandsurvivalcraft.world.WorldInfo;
|
||||||
|
import ca.recrown.islandsurvivalcraft.world.Information.IslandInformation;
|
||||||
|
|
||||||
public class HighlightIslandCommand implements CommandRunnable {
|
public class HighlightIslandCommand implements CommandRunnable {
|
||||||
private final Particle.DustOptions OPTIONS = new Particle.DustOptions(Color.RED, 1f);
|
private final Particle.DustOptions OPTIONS = new Particle.DustOptions(Color.RED, 1f);
|
||||||
private final int PARTICLE_AMOUNT = 3;
|
private final int PARTICLE_AMOUNT = 1;
|
||||||
private final double OFFSET_X = 0.0d, OFFSET_Y = 6.0d, OFFSET_Z = 0.0d;
|
private final double OFFSET_X = 0.0d, OFFSET_Y = 6.0d, OFFSET_Z = 0.0d;
|
||||||
private final double EXTRA = 0d;
|
private final double EXTRA = 0d;
|
||||||
HashSet<Player> playersHighlighting = new HashSet<>();
|
HashSet<Player> playersHighlighting = new HashSet<>();
|
||||||
@ -74,20 +76,28 @@ public class HighlightIslandCommand implements CommandRunnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
World world = player.getWorld();
|
World world = player.getWorld();
|
||||||
WorldInfo worldInfo = islandsurvivalcraft.getWorldInfoManager().retrieve(world);
|
WorldInfo worldInfo = islandsurvivalcraft.getWorldInfoManager().retrieve(world.getName());
|
||||||
Location playerLocation = player.getLocation();
|
Location playerLocation = player.getLocation();
|
||||||
int playerX = playerLocation.getBlockX(), playerY = playerLocation.getBlockY(), playerZ = playerLocation.getBlockZ();
|
int playerX = playerLocation.getBlockX(), playerY = playerLocation.getBlockY(), playerZ = playerLocation.getBlockZ();
|
||||||
IslandWorldMap map = worldInfo.getIslandMap();
|
Point2 playerCoords = new Point2(playerX, playerZ);
|
||||||
|
IslandInformation islandInfo = worldInfo.getIslandInfoManager().getIslandInformation(playerCoords);
|
||||||
//TODO SPAWN HIGHLIGHTING PARTICLES.
|
if (islandInfo != null) {
|
||||||
|
Set<Point2> islandBorder = islandInfo.getEdgeCoordinates();
|
||||||
|
Iterator<Point2> islandborderIterable = islandBorder.iterator();
|
||||||
|
for (int i = 0; i < islandBorder.size(); i+= 2) {
|
||||||
|
Point2 current = islandborderIterable.next();
|
||||||
|
spawnParticle(world, current.x, playerY, current.y);
|
||||||
|
islandborderIterable.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
waitingList.add(highlighter);
|
waitingList.add(highlighter);
|
||||||
}
|
}
|
||||||
}, 0, 8);
|
}, 0, 10);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void spawnParticle(World world, double x, double y, double z) {
|
private void spawnParticle(World world, double x, double y, double z) {
|
||||||
world.spawnParticle(Particle.REDSTONE, x, y, z, PARTICLE_AMOUNT, OFFSET_X, OFFSET_Y, OFFSET_Z, EXTRA, OPTIONS, true);
|
world.spawnParticle(Particle.REDSTONE, x, y, z, PARTICLE_AMOUNT, OFFSET_X, OFFSET_Y, OFFSET_Z, EXTRA, OPTIONS, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -97,6 +107,7 @@ public class HighlightIslandCommand implements CommandRunnable {
|
|||||||
|
|
||||||
private class PlayerIslandHighlighter {
|
private class PlayerIslandHighlighter {
|
||||||
private final int MAX_SEARCH = 0;
|
private final int MAX_SEARCH = 0;
|
||||||
|
private IslandInformation lastIsland;
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private DepthFirstSearch dfs;
|
private DepthFirstSearch dfs;
|
||||||
|
|
||||||
@ -104,30 +115,12 @@ public class HighlightIslandCommand implements CommandRunnable {
|
|||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<ArrayList<Point2>> update(Point2 playerLocation, IslandWorldMap islandWorldMap, IslandSurvivalCraft isc) {
|
public boolean hasUpdated(IslandInformation islandInformation) {
|
||||||
CompletableFuture<ArrayList<Point2>> completableFuture = new CompletableFuture<>();
|
if (lastIsland == null || !(lastIsland.hashCode() == islandInformation.hashCode() && lastIsland.equals(islandInformation))) {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(isc, () -> {
|
lastIsland = islandInformation;
|
||||||
ArrayList<Point2> border = new ArrayList<>(64);
|
return true;
|
||||||
while (dfs == null || dfs.step(islandWorldMap.islandValidator, (p) -> false)) {
|
}
|
||||||
dfs = new DepthFirstSearch(playerLocation, null, (p1, p2) -> {
|
return false;
|
||||||
double diff = islandWorldMap.getWorldValue(p1.x, p1.y) - islandWorldMap.getWorldValue(p2.x, p2.y);
|
|
||||||
if (diff == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (diff > 0) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}, MAX_SEARCH);
|
|
||||||
Point2 currentPoint = dfs.getCurrentNode();
|
|
||||||
if (currentPoint != null && islandWorldMap.isEdgeOfIsland(currentPoint.x, currentPoint.y)) {
|
|
||||||
border.add(currentPoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completableFuture.complete(border);
|
|
||||||
});
|
|
||||||
|
|
||||||
return completableFuture;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package ca.recrown.islandsurvivalcraft.interaction.commands.runnables;
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
||||||
|
import ca.recrown.islandsurvivalcraft.world.IslandWorldMap;
|
||||||
|
|
||||||
|
public class ValueRunnable implements CommandRunnable {
|
||||||
|
private IslandSurvivalCraft isc;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Gives the world value this plugin is using.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDetailedDescription() {
|
||||||
|
return "Player only command. Usage: \"IslandSurvivalCraft value [x] [z]\". Gives the current world value at the given x and z coordinates. If the two coordinates are not provided, player location is used.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean invoke(CommandSender sender, String[] args) {
|
||||||
|
if (!(sender instanceof Player)) return false;
|
||||||
|
Player p = (Player) sender;
|
||||||
|
int worldX = 0, worldZ = 0;
|
||||||
|
if (args.length > 0) {
|
||||||
|
if (args.length != 2) return false;
|
||||||
|
try {
|
||||||
|
worldX = Integer.valueOf(args[0]);
|
||||||
|
worldZ = Integer.valueOf(args[1]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
worldX = p.getLocation().getBlockX();
|
||||||
|
worldZ = p.getLocation().getBlockZ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IslandWorldMap map = isc.getWorldInfoManager().retrieve(p.getWorld().getName()).getIslandMap();
|
||||||
|
p.sendMessage(String.format("world: %s, World value (%d, %d): %s",
|
||||||
|
p.getWorld().getName(),
|
||||||
|
worldX, worldZ,
|
||||||
|
map.getWorldValue(worldX, worldZ)));
|
||||||
|
|
||||||
|
p.sendMessage(String.format("Terrain: \nIsland: %b, Shallow: %b, Hill: %b, Land: %b, Shore: %b, Edge: %b, Transitional: %b, Deep: %b",
|
||||||
|
map.isIsland(worldX, worldZ),
|
||||||
|
map.isShallowPortion(worldX, worldZ),
|
||||||
|
map.isHill(worldX, worldZ),
|
||||||
|
map.isLand(worldX, worldZ),
|
||||||
|
map.isShore(worldX, worldZ),
|
||||||
|
map.isEdgeOfIsland(worldX, worldZ),
|
||||||
|
map.isTransitional(worldX, worldZ),
|
||||||
|
map.isDeep(worldX, worldZ)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(IslandSurvivalCraft islandSurvivalCraft) {
|
||||||
|
isc = islandSurvivalCraft;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -42,4 +42,8 @@ public class Point2 {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("(%d, %d)", x, y);
|
return String.format("(%d, %d)", x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Point2 shift(int x, int y) {
|
||||||
|
return new Point2(this.x + x, this.y + y);
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package ca.recrown.islandsurvivalcraft.world.Information;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
|
||||||
|
|
||||||
|
public class IslandInformation {
|
||||||
|
private final Set<Point2> chunkSpan;
|
||||||
|
private final Set<Point2> islandCoordinates;
|
||||||
|
private final Set<Point2> edgeCoordinates;
|
||||||
|
private final Point2 islandOrigin;
|
||||||
|
private UUID ownerUUID;
|
||||||
|
|
||||||
|
public IslandInformation(Point2 islandOrigin, Set<Point2> islandCoordinates, Set<Point2> edgeCoordinates, Set<Point2> chunksUsed) {
|
||||||
|
this.islandCoordinates = Collections.unmodifiableSet(islandCoordinates);
|
||||||
|
this.chunkSpan = Collections.unmodifiableSet(chunksUsed);
|
||||||
|
this.edgeCoordinates = Collections.unmodifiableSet(edgeCoordinates);
|
||||||
|
this.islandOrigin = islandOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a set that represents all coordinates within this island.
|
||||||
|
*/
|
||||||
|
public Set<Point2> getIslandCoordinates() {
|
||||||
|
return islandCoordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a set of chunks that this island spans.
|
||||||
|
*/
|
||||||
|
public Set<Point2> getChunkSpan() {
|
||||||
|
return chunkSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a set of points that represent all the edges of this island.
|
||||||
|
*/
|
||||||
|
public Set<Point2> getEdgeCoordinates() {
|
||||||
|
return edgeCoordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ownerUUID the UUID of the player owner of this island. May be null.
|
||||||
|
*/
|
||||||
|
public void setOwnerUUID(UUID ownerUUID) {
|
||||||
|
this.ownerUUID = ownerUUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the islandOrigin
|
||||||
|
*/
|
||||||
|
public Point2 getIslandOrigin() {
|
||||||
|
return islandOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the UUID of the player owner of this island. May be null.
|
||||||
|
*/
|
||||||
|
public UUID getOwnerUUID() {
|
||||||
|
return ownerUUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWithinIsland(Point2 coordinates) {
|
||||||
|
return islandCoordinates.contains(coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEdgeOfIsland(Point2 coordinates) {
|
||||||
|
return edgeCoordinates.contains(coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIslandInChunk(Point2 chunkCoords) {
|
||||||
|
return chunkSpan.contains(chunkCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return islandOrigin.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof IslandInformation) {
|
||||||
|
return islandOrigin.equals(((IslandInformation) obj).getIslandOrigin());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package ca.recrown.islandsurvivalcraft.world.Information;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
|
||||||
|
|
||||||
|
public class IslandInformationBuilder {
|
||||||
|
private final HashSet<Point2> islandCoordinates = new HashSet<>();
|
||||||
|
private final HashSet<Point2> edgeCoordinates = new HashSet<>();
|
||||||
|
private final HashSet<Point2> chunksUsed = new HashSet<>();
|
||||||
|
private boolean built = false;
|
||||||
|
|
||||||
|
public boolean addCoordinate(Point2 coordinate, boolean isEdge) {
|
||||||
|
if (coordinate == null) throw new NullPointerException("Coordinate cannot be null!");
|
||||||
|
if (built) throw new IllegalStateException("Island information has already been built!");
|
||||||
|
if (isEdge) edgeCoordinates.add(coordinate);
|
||||||
|
return islandCoordinates.add(coordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addChunk(Point2 chunkCoordinate) {
|
||||||
|
if (chunkCoordinate == null) throw new NullPointerException("Chunk coordinate cannot be null!");
|
||||||
|
if (built) throw new IllegalStateException("Island information has already been built!");
|
||||||
|
return chunksUsed.add(chunkCoordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IslandInformation build(Point2 islandOrigin) {
|
||||||
|
if (islandOrigin == null) throw new NullPointerException("IslandOrigin cannot be null.");
|
||||||
|
if (built) throw new IllegalStateException("This island informationh as already been built!");
|
||||||
|
built = true;
|
||||||
|
return new IslandInformation(islandOrigin, islandCoordinates, edgeCoordinates, chunksUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the chunksUsed
|
||||||
|
*/
|
||||||
|
public HashSet<Point2> getChunksUsed() {
|
||||||
|
return chunksUsed;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package ca.recrown.islandsurvivalcraft.world.Information;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import ca.recrown.islandsurvivalcraft.utilities.GeneralUtilities;
|
||||||
|
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
|
||||||
|
import ca.recrown.islandsurvivalcraft.world.IslandWorldMap;
|
||||||
|
|
||||||
|
public class IslandInformationManager {
|
||||||
|
private final IslandWorldMap islandMap;
|
||||||
|
private final ConcurrentHashMap<Point2, HashSet<IslandInformation>> islandSets = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public IslandInformationManager(IslandWorldMap islandWorldMap) {
|
||||||
|
this.islandMap = islandWorldMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadChunkIslandInformation(Point2 chunkCoords) {
|
||||||
|
Point2[] surrounding = new Point2[4];
|
||||||
|
surrounding[0] = chunkCoords.shift(1, 0);
|
||||||
|
surrounding[1] = chunkCoords.shift(-1, 0);
|
||||||
|
surrounding[2] = chunkCoords.shift(0, -1);
|
||||||
|
surrounding[3] = chunkCoords.shift(0, 1);
|
||||||
|
HashSet<Point2> checkedCoordinates = new HashSet<>();
|
||||||
|
for (Point2 chunk : surrounding) {
|
||||||
|
HashSet<IslandInformation> chunkIslandSet = getChunkIslandInformationSet(chunk);
|
||||||
|
for (IslandInformation islandInformation : chunkIslandSet) {
|
||||||
|
if (islandInformation.isIslandInChunk(chunkCoords)) {
|
||||||
|
checkedCoordinates.addAll(islandInformation.getIslandCoordinates());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int x = 0; x < GeneralUtilities.CHUNK_SIZE; x++) {
|
||||||
|
for (int z = 0; z < GeneralUtilities.CHUNK_SIZE; z++) {
|
||||||
|
int worldX = chunkCoords.x * GeneralUtilities.CHUNK_SIZE + x;
|
||||||
|
int worldZ = chunkCoords.y * GeneralUtilities.CHUNK_SIZE + z;
|
||||||
|
if (islandMap.isIsland(worldX, worldZ)) {
|
||||||
|
IslandInformationBuilder infoBuilder = new IslandInformationBuilder();
|
||||||
|
Point2 origin = islandMap.findIslandOrigin(worldX, worldZ, (p) -> {
|
||||||
|
if (!checkedCoordinates.add(p)) return true;
|
||||||
|
infoBuilder.addCoordinate(p, islandMap.isEdgeOfIsland(p.x, p.y));
|
||||||
|
infoBuilder.addChunk(GeneralUtilities.worldToChunkCoordinates(p));
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (origin != null) {
|
||||||
|
IslandInformation islandInfo = infoBuilder.build(origin);
|
||||||
|
for (Point2 chunk : infoBuilder.getChunksUsed()) {
|
||||||
|
getChunkIslandInformationSet(chunk).add(islandInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unloadChunkIslandInformation(Point2 chunkCoords) {
|
||||||
|
islandSets.remove(chunkCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<IslandInformation> getChunkIslandInformationSet(Point2 chunkCoords) {
|
||||||
|
if (!islandSets.containsKey(chunkCoords)) islandSets.put(chunkCoords, new HashSet<>());
|
||||||
|
return islandSets.get(chunkCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IslandInformation getIslandInformation(Point2 coords) {
|
||||||
|
HashSet<IslandInformation> chunkIslandSet = getChunkIslandInformationSet(GeneralUtilities.worldToChunkCoordinates(coords));
|
||||||
|
for (IslandInformation islandInformation : chunkIslandSet) {
|
||||||
|
if (islandInformation.isWithinIsland(coords)) return islandInformation;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import ca.recrown.islandsurvivalcraft.utilities.pathfinding.CoordinateValidatabl
|
|||||||
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch;
|
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch;
|
||||||
|
|
||||||
public class IslandWorldMap {
|
public class IslandWorldMap {
|
||||||
|
private final float SHALLOW_PORTION = 0.06f;
|
||||||
private final float TRANSITION_DEPTH_PORTION = 0.1f;
|
private final float TRANSITION_DEPTH_PORTION = 0.1f;
|
||||||
private final float DEEP_OCEAN_PORTION = 0.5f;
|
private final float DEEP_OCEAN_PORTION = 0.5f;
|
||||||
private final float HILL_PORTION = 0.4f;
|
private final float HILL_PORTION = 0.4f;
|
||||||
@ -23,7 +24,6 @@ public class IslandWorldMap {
|
|||||||
private final float ISLAND_PERCENT = 0.36f;
|
private final float ISLAND_PERCENT = 0.36f;
|
||||||
private final double NOISE_FREQ = 1.78D;
|
private final double NOISE_FREQ = 1.78D;
|
||||||
private final double NOISE_AMP = 0.47D;
|
private final double NOISE_AMP = 0.47D;
|
||||||
private final float SHALLOW_PORTION = 0.06f;
|
|
||||||
private final double SCALE = 0.005D;
|
private final double SCALE = 0.005D;
|
||||||
|
|
||||||
public IslandWorldMap(Random random) {
|
public IslandWorldMap(Random random) {
|
||||||
@ -70,6 +70,13 @@ public class IslandWorldMap {
|
|||||||
return isLand(worldX, worldZ) || isShallowPortion(worldX, worldZ);
|
return isLand(worldX, worldZ) || isShallowPortion(worldX, worldZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks coordinates for if this location is a hill.
|
||||||
|
* It is considered a hill when its world value is greater than the HILL_PORTION.
|
||||||
|
* @param worldX
|
||||||
|
* @param worldZ
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public boolean isHill(int worldX, int worldZ) {
|
public boolean isHill(int worldX, int worldZ) {
|
||||||
return getWorldValue(worldX, worldZ) >= HILL_PORTION;
|
return getWorldValue(worldX, worldZ) >= HILL_PORTION;
|
||||||
}
|
}
|
||||||
@ -152,7 +159,7 @@ public class IslandWorldMap {
|
|||||||
* @param worldX The x coordinate of the island block in question.
|
* @param worldX The x coordinate of the island block in question.
|
||||||
* @param worldZ The y coordinate of the island block in question.
|
* @param worldZ The y coordinate of the island block in question.
|
||||||
* @param targetValidator The coordinate target validator to use. Optional and is null.
|
* @param targetValidator The coordinate target validator to use. Optional and is null.
|
||||||
* @return The island origin point.
|
* @return The island origin point. Will be null if the passed target target validator stops search prematurely.
|
||||||
*/
|
*/
|
||||||
public Point2 findIslandOrigin(int worldX, int worldZ, CoordinateValidatable targetValidator) {
|
public Point2 findIslandOrigin(int worldX, int worldZ, CoordinateValidatable targetValidator) {
|
||||||
if (!isIsland(worldX, worldZ)) throw new IllegalArgumentException("The given coordinates are not part is an island.");
|
if (!isIsland(worldX, worldZ)) throw new IllegalArgumentException("The given coordinates are not part is an island.");
|
||||||
|
@ -4,10 +4,12 @@ import java.util.Random;
|
|||||||
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import ca.recrown.islandsurvivalcraft.world.Information.IslandInformationManager;
|
||||||
import ca.recrown.islandsurvivalcraft.world.generation.chunks.IslandWorldChunkGenerator;
|
import ca.recrown.islandsurvivalcraft.world.generation.chunks.IslandWorldChunkGenerator;
|
||||||
|
|
||||||
public class WorldInfo {
|
public class WorldInfo {
|
||||||
private final WorldInfoManager manager;
|
private final WorldInfoManager manager;
|
||||||
|
private volatile IslandInformationManager islandInfoManager;
|
||||||
private volatile Random random;
|
private volatile Random random;
|
||||||
private volatile int seaLevel;
|
private volatile int seaLevel;
|
||||||
private volatile int worldHeight;
|
private volatile int worldHeight;
|
||||||
@ -26,14 +28,12 @@ public class WorldInfo {
|
|||||||
* @param world The world this object is describing. May be null to create a
|
* @param world The world this object is describing. May be null to create a
|
||||||
* non-initialized info object.
|
* non-initialized info object.
|
||||||
*/
|
*/
|
||||||
public WorldInfo(WorldInfoManager manager, World world) {
|
public WorldInfo(WorldInfoManager manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
if (world != null) {
|
this.generator = new IslandWorldChunkGenerator(this);
|
||||||
initialize(world, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(World world, IslandWorldChunkGenerator chunkGenerator) {
|
public void initialize(World world) {
|
||||||
if (initialized)
|
if (initialized)
|
||||||
throw new IllegalStateException("This world information object has already been initialized.");
|
throw new IllegalStateException("This world information object has already been initialized.");
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
@ -42,15 +42,9 @@ public class WorldInfo {
|
|||||||
this.biomeMap = new BiomeMap(random);
|
this.biomeMap = new BiomeMap(random);
|
||||||
this.tempMap = new TemperatureMap(random);
|
this.tempMap = new TemperatureMap(random);
|
||||||
this.islandMap = new IslandWorldMap(random);
|
this.islandMap = new IslandWorldMap(random);
|
||||||
|
this.islandInfoManager = new IslandInformationManager(islandMap);
|
||||||
this.worldHeight = world.getMaxHeight();
|
this.worldHeight = world.getMaxHeight();
|
||||||
this.seaLevel = world.getSeaLevel();
|
this.seaLevel = world.getSeaLevel();
|
||||||
if (chunkGenerator != null) {
|
|
||||||
this.generator = chunkGenerator;
|
|
||||||
this.generator.initialize();
|
|
||||||
this.manager.register(world, this);
|
|
||||||
} else {
|
|
||||||
generator = new IslandWorldChunkGenerator(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,6 +54,13 @@ public class WorldInfo {
|
|||||||
return initialized;
|
return initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the islandInfoManager
|
||||||
|
*/
|
||||||
|
public IslandInformationManager getIslandInfoManager() {
|
||||||
|
return islandInfoManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the biomeMap
|
* @return the biomeMap
|
||||||
*/
|
*/
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
package ca.recrown.islandsurvivalcraft.world;
|
package ca.recrown.islandsurvivalcraft.world;
|
||||||
|
|
||||||
|
import java.security.InvalidParameterException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.apache.commons.lang.NullArgumentException;
|
import org.apache.commons.lang.NullArgumentException;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.world.ChunkLoadEvent;
|
||||||
|
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
|
||||||
|
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
|
||||||
import ca.recrown.islandsurvivalcraft.world.generation.GeneratorModes;
|
import ca.recrown.islandsurvivalcraft.world.generation.GeneratorModes;
|
||||||
import ca.recrown.islandsurvivalcraft.world.generation.chunks.IslandWorldChunkGenerator;
|
import ca.recrown.islandsurvivalcraft.world.generation.chunks.IslandWorldChunkGenerator;
|
||||||
|
|
||||||
public class WorldInfoManager implements Listener {
|
public class WorldInfoManager implements Listener {
|
||||||
public final ConcurrentHashMap<UUID, WorldInfo> worldInformation = new ConcurrentHashMap<>();
|
public final ConcurrentHashMap<String, WorldInfo> worldInformation = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the world info requested for the given world.
|
* Return the world info requested for the given world.
|
||||||
@ -20,13 +27,19 @@ public class WorldInfoManager implements Listener {
|
|||||||
* @param world The world the associated info is to be requested for.
|
* @param world The world the associated info is to be requested for.
|
||||||
* @return The world info.
|
* @return The world info.
|
||||||
*/
|
*/
|
||||||
public WorldInfo retrieve(World world) {
|
public WorldInfo retrieve(String worldName) {
|
||||||
if (world == null) throw new NullArgumentException("world");
|
if (worldName == null) throw new NullArgumentException("world");
|
||||||
return worldInformation.computeIfAbsent(world.getUID(), (worldInfo) -> {
|
return worldInformation.computeIfAbsent(worldName, (name) -> {
|
||||||
return new WorldInfo(this, world);
|
return new WorldInfo(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChunkGenerator getChunkGenerator(String worldName, GeneratorModes mode) {
|
||||||
|
IslandWorldChunkGenerator islandWorldChunkGenerator = retrieve(worldName).getGenerator();
|
||||||
|
if (!islandWorldChunkGenerator.isInitialized()) islandWorldChunkGenerator.setGeneratorType(mode);
|
||||||
|
return islandWorldChunkGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the manager deleting all currently loaded world info from memory.
|
* Resets the manager deleting all currently loaded world info from memory.
|
||||||
*/
|
*/
|
||||||
@ -34,29 +47,21 @@ public class WorldInfoManager implements Listener {
|
|||||||
worldInformation.clear();
|
worldInformation.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
* Returns a chunk generator.
|
public void onChunkLoad(ChunkLoadEvent event) {
|
||||||
* @param world The world the chunk generator is for. If it does not yet exist, it will be created.
|
Chunk chunk = event.getChunk();
|
||||||
* @return The chunk generator associated with the given world.
|
if (!worldInformation.containsKey(event.getWorld().getName())) return;
|
||||||
*/
|
WorldInfo worldInfo = retrieve(event.getWorld().getName());
|
||||||
public ChunkGenerator getChunkGenerator(World world, GeneratorModes mode) {
|
if (!worldInfo.isInitialized()) worldInfo.initialize(event.getWorld());
|
||||||
WorldInfo worldInfo = null;
|
worldInfo.getIslandInfoManager().loadChunkIslandInformation(new Point2(chunk.getX(), chunk.getZ()));
|
||||||
if (world != null) {
|
|
||||||
worldInfo = retrieve(world);
|
|
||||||
if (!worldInfo.getGenerator().isInitialized()) {
|
|
||||||
worldInfo.getGenerator().setGeneratorType(mode);
|
|
||||||
worldInfo.getGenerator().initialize();
|
|
||||||
}
|
|
||||||
return worldInfo.getGenerator();
|
|
||||||
} else {
|
|
||||||
worldInfo = new WorldInfo(this, null);
|
|
||||||
IslandWorldChunkGenerator generator = new IslandWorldChunkGenerator(worldInfo);
|
|
||||||
generator.setGeneratorType(mode);
|
|
||||||
return generator;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void register(World world, WorldInfo worldInfo) {
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
worldInformation.put(world.getUID(), worldInfo);
|
public void onChunkUnload(ChunkUnloadEvent event) {
|
||||||
|
Chunk chunk = event.getChunk();
|
||||||
|
if (!worldInformation.containsKey(event.getWorld().getName())) return;
|
||||||
|
WorldInfo worldInfo = retrieve(event.getWorld().getName());
|
||||||
|
if (!worldInfo.isInitialized()) worldInfo.initialize(event.getWorld());
|
||||||
|
worldInfo.getIslandInfoManager().unloadChunkIslandInformation(new Point2(chunk.getX(), chunk.getZ()));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -74,8 +74,9 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
|
|||||||
@Override
|
@Override
|
||||||
public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) {
|
public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) {
|
||||||
if (!worldInfo.isInitialized()) {
|
if (!worldInfo.isInitialized()) {
|
||||||
worldInfo.initialize(world, this);
|
worldInfo.initialize(world);
|
||||||
}
|
}
|
||||||
|
if (!isInitialized()) initialize();
|
||||||
if (!initialized) throw new IllegalStateException("This generator has not been initialized.");
|
if (!initialized) throw new IllegalStateException("This generator has not been initialized.");
|
||||||
Future<Boolean> preLoader = exAlpha.submit(() -> {
|
Future<Boolean> preLoader = exAlpha.submit(() -> {
|
||||||
for (int x = GeneralUtilities.CHUNK_SIZE - 1; x >= 0; x--) {
|
for (int x = GeneralUtilities.CHUNK_SIZE - 1; x >= 0; x--) {
|
||||||
@ -108,6 +109,8 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
|
|||||||
currentBiome = ((LandBiomeInfo) biomeInfo).getHillBiome();
|
currentBiome = ((LandBiomeInfo) biomeInfo).getHillBiome();
|
||||||
} else if (islandMap.isShore(worldX, worldZ)) {
|
} else if (islandMap.isShore(worldX, worldZ)) {
|
||||||
currentBiome = ((LandBiomeInfo) biomeInfo).getShoreBiome();
|
currentBiome = ((LandBiomeInfo) biomeInfo).getShoreBiome();
|
||||||
|
} else if (islandMap.isShallowPortion(worldX, worldZ)) {
|
||||||
|
currentBiome = ((LandBiomeInfo) biomeInfo).getShoreBiome();
|
||||||
} else if (islandMap.isLand(worldX, worldZ)) {
|
} else if (islandMap.isLand(worldX, worldZ)) {
|
||||||
currentBiome = biomeInfo.getMainBiome();
|
currentBiome = biomeInfo.getMainBiome();
|
||||||
} else if (islandMap.isTransitional(worldX, worldZ)) {
|
} else if (islandMap.isTransitional(worldX, worldZ)) {
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
write-Output "Deleting previous world if there was one..."
|
|
||||||
remove-Item -Recurse world* -Force -ErrorAction Ignore
|
|
||||||
write-Output "Attempting to copy plugin jar to plugins folder..."
|
write-Output "Attempting to copy plugin jar to plugins folder..."
|
||||||
copy-Item -Path "..\target\IslandSurvivalCraft*.jar" -Destination "plugins\IslandSurvivalCraft.jar"
|
copy-Item -Path "..\target\IslandSurvivalCraft*.jar" -Destination "plugins\IslandSurvivalCraft.jar"
|
Loading…
Reference in New Issue
Block a user