diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/IslandSurvivalCraft.java b/src/main/java/ca/recrown/islandsurvivalcraft/IslandSurvivalCraft.java index f3e1930..6087f8a 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/IslandSurvivalCraft.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/IslandSurvivalCraft.java @@ -44,7 +44,7 @@ public class IslandSurvivalCraft extends JavaPlugin implements Listener { } catch (NullPointerException | IllegalArgumentException e) { gID = GeneratorModes.UNIQUE; } - return worldInfoManager.getChunkGenerator(getServer().getWorld(worldName), gID); + return worldInfoManager.getChunkGenerator(worldName, gID); } /** diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/Commands.java b/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/Commands.java index f419829..fc63d12 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/Commands.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/Commands.java @@ -5,12 +5,12 @@ import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.HighlightIs import org.bukkit.command.CommandSender; import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft; -import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.CommandRunnable; -import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.HelpCommand; +import ca.recrown.islandsurvivalcraft.interaction.commands.runnables.*; public enum Commands implements CommandRunnable { HIGHLIGHT(new HighlightIslandCommand()), HELP(new HelpCommand()), + VALUE(new ValueRunnable()), ; private final CommandRunnable commandRunnable; diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/HighlightIslandCommand.java b/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/HighlightIslandCommand.java index c9b4706..0ea0b62 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/HighlightIslandCommand.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/HighlightIslandCommand.java @@ -2,7 +2,9 @@ package ca.recrown.islandsurvivalcraft.interaction.commands.runnables; import java.util.ArrayList; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedList; +import java.util.Set; import java.util.concurrent.CompletableFuture; import org.bukkit.Bukkit; @@ -16,12 +18,12 @@ import org.bukkit.entity.Player; import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft; import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2; import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch; -import ca.recrown.islandsurvivalcraft.world.IslandWorldMap; import ca.recrown.islandsurvivalcraft.world.WorldInfo; +import ca.recrown.islandsurvivalcraft.world.Information.IslandInformation; public class HighlightIslandCommand implements CommandRunnable { 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 EXTRA = 0d; HashSet playersHighlighting = new HashSet<>(); @@ -74,20 +76,28 @@ public class HighlightIslandCommand implements CommandRunnable { return; } World world = player.getWorld(); - WorldInfo worldInfo = islandsurvivalcraft.getWorldInfoManager().retrieve(world); + WorldInfo worldInfo = islandsurvivalcraft.getWorldInfoManager().retrieve(world.getName()); Location playerLocation = player.getLocation(); int playerX = playerLocation.getBlockX(), playerY = playerLocation.getBlockY(), playerZ = playerLocation.getBlockZ(); - IslandWorldMap map = worldInfo.getIslandMap(); - - //TODO SPAWN HIGHLIGHTING PARTICLES. + Point2 playerCoords = new Point2(playerX, playerZ); + IslandInformation islandInfo = worldInfo.getIslandInfoManager().getIslandInformation(playerCoords); + if (islandInfo != null) { + Set islandBorder = islandInfo.getEdgeCoordinates(); + Iterator 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); } - }, 0, 8); + }, 0, 10); } 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 @@ -97,6 +107,7 @@ public class HighlightIslandCommand implements CommandRunnable { private class PlayerIslandHighlighter { private final int MAX_SEARCH = 0; + private IslandInformation lastIsland; private final Player player; private DepthFirstSearch dfs; @@ -104,30 +115,12 @@ public class HighlightIslandCommand implements CommandRunnable { this.player = player; } - public CompletableFuture> update(Point2 playerLocation, IslandWorldMap islandWorldMap, IslandSurvivalCraft isc) { - CompletableFuture> completableFuture = new CompletableFuture<>(); - Bukkit.getScheduler().runTaskAsynchronously(isc, () -> { - ArrayList border = new ArrayList<>(64); - while (dfs == null || dfs.step(islandWorldMap.islandValidator, (p) -> false)) { - dfs = new DepthFirstSearch(playerLocation, null, (p1, p2) -> { - 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; + public boolean hasUpdated(IslandInformation islandInformation) { + if (lastIsland == null || !(lastIsland.hashCode() == islandInformation.hashCode() && lastIsland.equals(islandInformation))) { + lastIsland = islandInformation; + return true; + } + return false; } } } \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/ValueRunnable.java b/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/ValueRunnable.java new file mode 100644 index 0000000..5db50d2 --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/interaction/commands/runnables/ValueRunnable.java @@ -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; + } + +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/utilities/datatypes/Point2.java b/src/main/java/ca/recrown/islandsurvivalcraft/utilities/datatypes/Point2.java index ba3b6e5..5496ea6 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/utilities/datatypes/Point2.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/utilities/datatypes/Point2.java @@ -42,4 +42,8 @@ public class Point2 { public String toString() { return String.format("(%d, %d)", x, y); } + + public Point2 shift(int x, int y) { + return new Point2(this.x + x, this.y + y); + } } \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformation.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformation.java new file mode 100644 index 0000000..2879bad --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformation.java @@ -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 chunkSpan; + private final Set islandCoordinates; + private final Set edgeCoordinates; + private final Point2 islandOrigin; + private UUID ownerUUID; + + public IslandInformation(Point2 islandOrigin, Set islandCoordinates, Set edgeCoordinates, Set 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 getIslandCoordinates() { + return islandCoordinates; + } + + /** + * @return a set of chunks that this island spans. + */ + public Set getChunkSpan() { + return chunkSpan; + } + + /** + * @return a set of points that represent all the edges of this island. + */ + public Set 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; + } +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformationBuilder.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformationBuilder.java new file mode 100644 index 0000000..ea200fe --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformationBuilder.java @@ -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 islandCoordinates = new HashSet<>(); + private final HashSet edgeCoordinates = new HashSet<>(); + private final HashSet 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 getChunksUsed() { + return chunksUsed; + } +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformationManager.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformationManager.java new file mode 100644 index 0000000..281c5eb --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/Information/IslandInformationManager.java @@ -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> 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 checkedCoordinates = new HashSet<>(); + for (Point2 chunk : surrounding) { + HashSet 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 getChunkIslandInformationSet(Point2 chunkCoords) { + if (!islandSets.containsKey(chunkCoords)) islandSets.put(chunkCoords, new HashSet<>()); + return islandSets.get(chunkCoords); + } + + public IslandInformation getIslandInformation(Point2 coords) { + HashSet chunkIslandSet = getChunkIslandInformationSet(GeneralUtilities.worldToChunkCoordinates(coords)); + for (IslandInformation islandInformation : chunkIslandSet) { + if (islandInformation.isWithinIsland(coords)) return islandInformation; + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/IslandWorldMap.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/IslandWorldMap.java index 5ee1dc3..3ff09b7 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/IslandWorldMap.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/IslandWorldMap.java @@ -11,6 +11,7 @@ import ca.recrown.islandsurvivalcraft.utilities.pathfinding.CoordinateValidatabl import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch; public class IslandWorldMap { + private final float SHALLOW_PORTION = 0.06f; private final float TRANSITION_DEPTH_PORTION = 0.1f; private final float DEEP_OCEAN_PORTION = 0.5f; private final float HILL_PORTION = 0.4f; @@ -23,7 +24,6 @@ public class IslandWorldMap { private final float ISLAND_PERCENT = 0.36f; private final double NOISE_FREQ = 1.78D; private final double NOISE_AMP = 0.47D; - private final float SHALLOW_PORTION = 0.06f; private final double SCALE = 0.005D; public IslandWorldMap(Random random) { @@ -70,6 +70,13 @@ public class IslandWorldMap { 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) { 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 worldZ The y coordinate of the island block in question. * @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) { if (!isIsland(worldX, worldZ)) throw new IllegalArgumentException("The given coordinates are not part is an island."); diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java index d9e1b8f..5d41e32 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java @@ -4,10 +4,12 @@ import java.util.Random; import org.bukkit.World; +import ca.recrown.islandsurvivalcraft.world.Information.IslandInformationManager; import ca.recrown.islandsurvivalcraft.world.generation.chunks.IslandWorldChunkGenerator; public class WorldInfo { private final WorldInfoManager manager; + private volatile IslandInformationManager islandInfoManager; private volatile Random random; private volatile int seaLevel; 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 * non-initialized info object. */ - public WorldInfo(WorldInfoManager manager, World world) { + public WorldInfo(WorldInfoManager manager) { this.manager = manager; - if (world != null) { - initialize(world, null); - } + this.generator = new IslandWorldChunkGenerator(this); } - public void initialize(World world, IslandWorldChunkGenerator chunkGenerator) { + public void initialize(World world) { if (initialized) throw new IllegalStateException("This world information object has already been initialized."); this.initialized = true; @@ -42,15 +42,9 @@ public class WorldInfo { this.biomeMap = new BiomeMap(random); this.tempMap = new TemperatureMap(random); this.islandMap = new IslandWorldMap(random); + this.islandInfoManager = new IslandInformationManager(islandMap); this.worldHeight = world.getMaxHeight(); 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 the islandInfoManager + */ + public IslandInformationManager getIslandInfoManager() { + return islandInfoManager; + } + /** * @return the biomeMap */ diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java index 77b0962..4941e7c 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java @@ -1,18 +1,25 @@ package ca.recrown.islandsurvivalcraft.world; +import java.security.InvalidParameterException; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang.NullArgumentException; +import org.bukkit.Chunk; import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; 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.chunks.IslandWorldChunkGenerator; public class WorldInfoManager implements Listener { - public final ConcurrentHashMap worldInformation = new ConcurrentHashMap<>(); + public final ConcurrentHashMap worldInformation = new ConcurrentHashMap<>(); /** * 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. * @return The world info. */ - public WorldInfo retrieve(World world) { - if (world == null) throw new NullArgumentException("world"); - return worldInformation.computeIfAbsent(world.getUID(), (worldInfo) -> { - return new WorldInfo(this, world); + public WorldInfo retrieve(String worldName) { + if (worldName == null) throw new NullArgumentException("world"); + return worldInformation.computeIfAbsent(worldName, (name) -> { + 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. */ @@ -34,29 +47,21 @@ public class WorldInfoManager implements Listener { worldInformation.clear(); } - /** - * Returns a chunk generator. - * @param world The world the chunk generator is for. If it does not yet exist, it will be created. - * @return The chunk generator associated with the given world. - */ - public ChunkGenerator getChunkGenerator(World world, GeneratorModes mode) { - WorldInfo worldInfo = null; - 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; - } + @EventHandler(priority = EventPriority.MONITOR) + public void onChunkLoad(ChunkLoadEvent 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().loadChunkIslandInformation(new Point2(chunk.getX(), chunk.getZ())); } - protected void register(World world, WorldInfo worldInfo) { - worldInformation.put(world.getUID(), worldInfo); + @EventHandler(priority = EventPriority.MONITOR) + 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())); } } \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/chunks/IslandWorldChunkGenerator.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/chunks/IslandWorldChunkGenerator.java index acf3a10..1e906aa 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/chunks/IslandWorldChunkGenerator.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/chunks/IslandWorldChunkGenerator.java @@ -74,8 +74,9 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene @Override public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { if (!worldInfo.isInitialized()) { - worldInfo.initialize(world, this); + worldInfo.initialize(world); } + if (!isInitialized()) initialize(); if (!initialized) throw new IllegalStateException("This generator has not been initialized."); Future preLoader = exAlpha.submit(() -> { 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(); } else if (islandMap.isShore(worldX, worldZ)) { currentBiome = ((LandBiomeInfo) biomeInfo).getShoreBiome(); + } else if (islandMap.isShallowPortion(worldX, worldZ)) { + currentBiome = ((LandBiomeInfo) biomeInfo).getShoreBiome(); } else if (islandMap.isLand(worldX, worldZ)) { currentBiome = biomeInfo.getMainBiome(); } else if (islandMap.isTransitional(worldX, worldZ)) { diff --git a/test-server/load_latest_build.ps1 b/test-server/load_build.ps1 similarity index 59% rename from test-server/load_latest_build.ps1 rename to test-server/load_build.ps1 index d07c3a6..87a205c 100644 --- a/test-server/load_latest_build.ps1 +++ b/test-server/load_build.ps1 @@ -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..." copy-Item -Path "..\target\IslandSurvivalCraft*.jar" -Destination "plugins\IslandSurvivalCraft.jar"