From b9b683dcde91c5d04d8bd8a86b5e32c405462acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Tue, 3 Oct 2023 16:50:59 +0200 Subject: [PATCH] Polished TrafficLightRace --- .../minenet/minigames/instance/game/Game.java | 7 +- .../game/stateless/types/minerun/Minerun.java | 20 +-- .../types/trafficlightrace/LightPhase.java | 4 +- .../trafficlightrace/TrafficLightRace.java | 127 ++++++++++++++++-- .../TrafficLightRaceFactory.java | 7 +- .../minenet/minigames/instance/room/Room.java | 4 + .../inventory/MinigameSelectInventory.java | 4 +- .../component/TranslatedComponent.java | 34 ++++- .../minigames/util/CommonProperties.java | 13 ++ .../world/generator/BlockPallet.java | 1 + .../terrain/SquareTerrainGenerator.java | 45 +++++-- 11 files changed, 216 insertions(+), 50 deletions(-) create mode 100644 src/main/java/eu/mhsl/minenet/minigames/util/CommonProperties.java diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java index 07bcba2..b4c5646 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java @@ -52,12 +52,13 @@ public abstract class Game extends MineNetInstance implements Spawnable { try { Game game = factory.manufacture(options); - Room.getRoom(owner).orElseThrow().moveMembersToGame(game); game.load(); + Room.getRoom(owner).orElseThrow().moveMembersToGame(game); } catch (Exception e) { - new ChatMessage(Icon.ERROR).appendStatic("Instance crashed:" + e.getMessage()).send(owner); - e.printStackTrace(); + new ChatMessage(Icon.ERROR).appendStatic("Instance crashed: " + e.getMessage()).send(owner); + MinecraftServer.getSchedulerManager().scheduleNextTick(() -> Room.getRoom(owner).orElseThrow().moveMembersToRoomLobby()); + e.printStackTrace(System.err); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/minerun/Minerun.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/minerun/Minerun.java index e7da287..4e60542 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/minerun/Minerun.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/minerun/Minerun.java @@ -4,6 +4,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.message.type.ActionBarMessage; import eu.mhsl.minenet.minigames.score.FirstWinsScore; import eu.mhsl.minenet.minigames.util.BatchUtil; +import eu.mhsl.minenet.minigames.util.CommonProperties; import eu.mhsl.minenet.minigames.util.Intersect; import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.world.generator.BlockPallet; @@ -25,9 +26,9 @@ import java.util.concurrent.CompletableFuture; class Minerun extends StatelessGame { - private int minePercentage; - private int width; - private int length; + private final int minePercentage; + private final int width; + private final int length; private final int preRun = 5; private final int afterMines = 2; @@ -35,7 +36,7 @@ class Minerun extends StatelessGame { public Minerun(int width, int length, int minePercentage) { super(Dimension.THE_END.DIMENSION, "Minerun", new FirstWinsScore()); - setGenerator(new SquareTerrainGenerator(width, length + preRun + afterFinishLine, true)); + setGenerator(new SquareTerrainGenerator(width, length + preRun + afterFinishLine).withPlate(50)); this.width = width; this.length = length; @@ -58,17 +59,10 @@ class Minerun extends StatelessGame { } } - Map properties = new HashMap<>() { - { - put("west", "true"); - put("east", "true"); - } - }; - for(int x = 0; x <= width; x++) { batch.setBlock(x, 49, spawnToFinishLine, Block.GOLD_BLOCK); batch.setBlock(x, 49, preRun, Block.GOLD_BLOCK); - batch.setBlock(x, 50, preRun, Block.OAK_FENCE.withProperties(properties)); + batch.setBlock(x, 50, preRun, Block.OAK_FENCE.withProperties(CommonProperties.fenceEastWest)); } BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); } @@ -116,6 +110,6 @@ class Minerun extends StatelessGame { @Override public Pos getSpawn() { - return new Pos(width/2, 50, 3); + return new Pos((double) width /2, 50, 3); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/LightPhase.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/LightPhase.java index f75ce82..9cd6d34 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/LightPhase.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/LightPhase.java @@ -8,8 +8,8 @@ import java.util.Random; enum LightPhase { RED(Material.RED_WOOL, 1000, 5000), - YELLOW(Material.YELLOW_WOOL, 1000, 2000), - GREEN(Material.GREEN_WOOL, 1000, 5000); + YELLOW(Material.YELLOW_WOOL, 500, 1500), + GREEN(Material.GREEN_WOOL, 2000, 5000); public final ItemStack item; private final int minDuration; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java index 3f29679..872aa73 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java @@ -1,51 +1,141 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace; +import de.articdive.jnoise.JNoise; import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.score.FirstWinsScore; import eu.mhsl.minenet.minigames.util.BatchUtil; import eu.mhsl.minenet.minigames.instance.Dimension; +import eu.mhsl.minenet.minigames.util.CommonProperties; +import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.world.generator.terrain.SquareTerrainGenerator; +import net.kyori.adventure.sound.Sound; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.GameMode; import net.minestom.server.event.player.PlayerMoveEvent; import net.minestom.server.instance.batch.AbsoluteBlockBatch; import net.minestom.server.instance.block.Block; +import net.minestom.server.sound.SoundEvent; import net.minestom.server.timer.ExecutionType; import net.minestom.server.timer.TaskSchedule; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; class TrafficLightRace extends StatelessGame { private LightPhase phase = LightPhase.RED; - private int phaseCounter = 1; + private int phaseCounter = 0; - public TrafficLightRace() { + private final int width; + private final int length; + private final int preRun = 10; + private final int afterRun = 10; + + private final List trafficLights = new ArrayList<>(); + + public TrafficLightRace(int width, int length) { super(Dimension.THE_END.DIMENSION, "Ampelrennen", new FirstWinsScore()); + this.width = width; + this.length = length; + + setGenerator( + new SquareTerrainGenerator(width, length + preRun + afterRun) + .withPlate(50) + .withBorders() + ); } @Override protected void onLoad(@NotNull CompletableFuture callback) { + final JNoise slowBatches = JNoise.newBuilder() + .fastSimplex() + .setSeed(rnd.nextLong()) + .setFrequency(0.1) + .build(); + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); - for (int x = -10; x <= 10; x++) { - for (int z = 0; z <= 100; z++) { - batch.setBlock(x, 5, z, super.rnd.nextInt(0, 100) > 90 ? Block.SOUL_SAND : Block.BLACK_CONCRETE_POWDER); + + for (int x = 0; x <= width; x++) { + for (int z = 0; z <= preRun; z++) { + batch.setBlock(x, 50, z, BlockPallet.GROUND.rnd()); + } + + for (int z = preRun; z <= length + preRun; z++) { + batch.setBlock(x, 50, z, slowBatches.getNoise(x, z) > 0.6 ? Block.SOUL_SAND : BlockPallet.STREET.rnd()); + } + + for (int z = preRun + length; z <= preRun + length + afterRun; z++) { + batch.setBlock(x, 50, z, BlockPallet.GROUND.rnd()); + } + + batch.setBlock(x, 51, preRun-1, Block.OAK_FENCE.withProperties(CommonProperties.fenceEastWest)); + batch.setBlock(x, 50, preRun + length, Block.GOLD_BLOCK); + } + + record TrafficLightsInput(int x, int z) {} + + Consumer generateTrafficLight = (input) -> { + batch.setBlock(input.x, 51, input.z, Block.ANVIL); + + for(int y = 52; y <= 59; y++) { + batch.setBlock(input.x, y, input.z, Block.ANDESITE_WALL); + } + + for (int x = input.x-3; x <= input.x+3; x++) { + batch.setBlock(x, 60, input.z, Block.SMOOTH_STONE_SLAB); + } + + batch.setBlock(input.x-2, 59, input.z, Block.STONE_BRICK_WALL); + trafficLights.add(new Pos(input.x-2, 58, input.z)); + trafficLights.add(new Pos(input.x-2, 57, input.z)); + + batch.setBlock(input.x+2, 59, input.z, Block.STONE_BRICK_WALL); + trafficLights.add(new Pos(input.x+2, 58, input.z)); + trafficLights.add(new Pos(input.x+2, 57, input.z)); + + for (Pos trafficLight : trafficLights) { + batch.setBlock(trafficLight, Block.WHITE_WOOL); + } + }; + + for (int count = 0; count <= this.rnd.nextInt(1, 2); count++) { + generateTrafficLight.accept(new TrafficLightsInput(0, this.rnd.nextInt(preRun + 10, length + preRun - 10))); + generateTrafficLight.accept(new TrafficLightsInput(width, this.rnd.nextInt(preRun + 10, length + preRun - 10))); + } + + if(width > 30) { + for (int count = 0; count <= this.rnd.nextInt(1, 2); count++) { + generateTrafficLight.accept(new TrafficLightsInput(width/2, this.rnd.nextInt(preRun, length + preRun))); } } + generateTrafficLight.accept(new TrafficLightsInput(0, length + preRun)); + generateTrafficLight.accept(new TrafficLightsInput(width, length + preRun)); + BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); } @Override protected void onStart() { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + for(int x = 0; x <= width; x++) { + batch.setBlock(x, 51, preRun-1, Block.AIR); + } + + BatchUtil.loadAndApplyBatch(batch, this, () -> playSound(Sound.sound(SoundEvent.BLOCK_WOOD_BREAK, Sound.Source.BLOCK, 1f, 1f))); + scheduler().submitTask(() -> { if(!super.isRunning) return TaskSchedule.stop(); phaseCounter++; - if(phaseCounter >= 4) phaseCounter = 0; + if(phaseCounter >= 3) phaseCounter = 0; if(phaseCounter == 0) phase = LightPhase.RED; - if(phaseCounter == 1 || phaseCounter == 3) phase = LightPhase.YELLOW; - if(phaseCounter == 2) phase = LightPhase.GREEN; + if(phaseCounter == 1) phase = LightPhase.GREEN; + if(phaseCounter == 2) phase = LightPhase.YELLOW; getPlayers().forEach(player -> { for(int i = 0; i < 9; i++) { @@ -53,23 +143,34 @@ class TrafficLightRace extends StatelessGame { } }); + AbsoluteBlockBatch changeLightsBatch = new AbsoluteBlockBatch(); + for (Pos trafficLight : trafficLights) { + changeLightsBatch.setBlock(trafficLight, phase.item.material().block()); + } + BatchUtil.loadAndApplyBatch(changeLightsBatch, this, () -> {}); + return phase.taskScheduleRandomDuration(); }, ExecutionType.SYNC); } @Override protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { - super.onPlayerMove(playerMoveEvent); + if(isBeforeBeginning) return; - if(playerMoveEvent.getNewPosition().z() > 110) stop(); + if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z()-0.01 > playerMoveEvent.getPlayer().getPosition().z()) { + playerMoveEvent.getPlayer().setVelocity(new Vec(0, 8, -15)); + playerMoveEvent.getPlayer().playSound(Sound.sound(SoundEvent.ENTITY_BLAZE_SHOOT, Sound.Source.PLAYER, 1f, 1f)); + } - if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z() > playerMoveEvent.getPlayer().getPosition().z()) { - playerMoveEvent.getPlayer().setVelocity(new Vec(0, 5, -10)); + if(playerMoveEvent.getNewPosition().z() > preRun+length) { + getScore().insertResult(playerMoveEvent.getPlayer()); + playerMoveEvent.getPlayer().getInventory().clear(); + playerMoveEvent.getPlayer().setGameMode(GameMode.SPECTATOR); } } @Override public Pos getSpawn() { - return new Pos(0, 6, 10); + return new Pos((double) width/2, 51, 3); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRaceFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRaceFactory.java index a628fe8..22f7884 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRaceFactory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRaceFactory.java @@ -4,6 +4,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager; import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption; import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; import net.minestom.server.item.Material; @@ -17,12 +18,14 @@ public class TrafficLightRaceFactory implements GameFactory { @Override public ConfigManager configuration() { - return null; + return new ConfigManager() + .addOption(new NumericOption("width", Material.OAK_FENCE, TranslatedComponent.byId("game_TrafficlightRace#width"), 20, 30, 40)) + .addOption(new NumericOption("length", Material.BLACK_CONCRETE_POWDER, TranslatedComponent.byId("game_TrafficlightRace#length"), 50, 80, 100, 120, 150)); } @Override public StatelessGame manufacture(Map> configuration) { - return new TrafficLightRace(); + return new TrafficLightRace(configuration.get("width").getAsInt(), configuration.get("length").getAsInt()); } @Override diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java b/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java index 6640a2a..19f4641 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java @@ -123,6 +123,10 @@ public class Room extends MineNetInstance implements Spawnable { this.getAllMembers().forEach(player -> MoveInstance.move(player, game)); } + public void moveMembersToRoomLobby() { + this.getAllMembers().forEach(player -> MoveInstance.move(player, this)); + } + public Set getAllMembers() { return rooms.keySet().stream() .filter(player -> getRoom(player).orElse(null) == this) diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/room/inventory/MinigameSelectInventory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/room/inventory/MinigameSelectInventory.java index a13f800..1123176 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/room/inventory/MinigameSelectInventory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/room/inventory/MinigameSelectInventory.java @@ -30,7 +30,7 @@ public class MinigameSelectInventory extends InteractableInventory { setClickableItem( ItemStack.builder(type.getIcon()) .displayName(type.getTitle().getAssembled(p)) - .lore(type.getDescription().getAssembled(p)) + .lore(type.getDescription().addWrap().getWrappedAssembled(p)) .build(), itemAlignment.next().get(), itemClick -> drawGames(type) @@ -59,7 +59,7 @@ public class MinigameSelectInventory extends InteractableInventory { setClickableItem( ItemStack.builder(gameFactory.symbol()) .displayName(gameFactory.name().getAssembled(p)) - .lore(gameFactory.description().getAssembled(p)) + .lore(gameFactory.description().addWrap().getWrappedAssembled(p)) .meta(metaBuilder -> metaBuilder.hideFlag(ItemHideFlag.HIDE_ATTRIBUTES)) .build(), offset + itemAlignment.next().get(), diff --git a/src/main/java/eu/mhsl/minenet/minigames/message/component/TranslatedComponent.java b/src/main/java/eu/mhsl/minenet/minigames/message/component/TranslatedComponent.java index 75d04ab..311635f 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/message/component/TranslatedComponent.java +++ b/src/main/java/eu/mhsl/minenet/minigames/message/component/TranslatedComponent.java @@ -5,13 +5,18 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.entity.Player; +import org.apache.commons.text.WordUtils; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; +import java.util.List; + public class TranslatedComponent implements ComponentLike, Translatable { private final String mapId; private String result; private NamedTextColor color; + private int wrap = 0; public static TranslatedComponent byId(String mapId) { return new TranslatedComponent(mapId); @@ -27,10 +32,17 @@ public class TranslatedComponent implements ComponentLike, Translatable { public void assemble(Player p) { result = Languages.getInstance().getLanguage(p).getEntry(mapId); + if(wrap > 0) { + result = WordUtils.wrap(result, wrap, "\n", false); + } } - public void assemble(String language) { - result = Languages.getInstance().getLanguage(language).getEntry(mapId); + public TranslatedComponent addWrap() { + return this.addWrap(30); + } + public TranslatedComponent addWrap(int wrap) { + this.wrap = wrap; + return this; } public Component getAssembled(Player p) { @@ -38,6 +50,11 @@ public class TranslatedComponent implements ComponentLike, Translatable { return asComponent(); } + public List getWrappedAssembled(Player p) { + this.assemble(p); + return asWrappedComponent(); + } + public TranslatedComponent setColor(NamedTextColor color) { this.color = color; return this; @@ -45,10 +62,17 @@ public class TranslatedComponent implements ComponentLike, Translatable { @Override public @NotNull Component asComponent() { - //assemble(Languages.getInstance().getLanguage(Languages.defaultLanguage).getEntry(mapId)); + return this.componentFromString(result); + } + + public List asWrappedComponent() { + return Arrays.stream(result.split("\n")).map(this::componentFromString).toList(); + } + + private Component componentFromString(String data) { if(color != null) - return Component.text(result, color); + return Component.text(data, color); else - return Component.text(result); + return Component.text(data); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/CommonProperties.java b/src/main/java/eu/mhsl/minenet/minigames/util/CommonProperties.java new file mode 100644 index 0000000..588cf66 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/util/CommonProperties.java @@ -0,0 +1,13 @@ +package eu.mhsl.minenet.minigames.util; + +import java.util.HashMap; +import java.util.Map; + +public class CommonProperties { + public static Map fenceEastWest = new HashMap<>() { + { + put("west", "true"); + put("east", "true"); + } + }; +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java index 6fae143..c3ee1e4 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java @@ -11,6 +11,7 @@ public enum BlockPallet { WOOD(new Block[] {Block.ACACIA_WOOD, Block.BIRCH_WOOD, Block.JUNGLE_WOOD, Block.OAK_WOOD, Block.DARK_OAK_WOOD, Block.SPRUCE_WOOD}), STONE(new Block[] {Block.CHISELED_STONE_BRICKS, Block.STONE_BRICKS, Block.POLISHED_ANDESITE, Block.POLISHED_BLACKSTONE, Block.POLISHED_DIORITE}), WINTER(new Block[] {Block.SNOW_BLOCK, Block.ICE, Block.PACKED_ICE, Block.BLUE_CONCRETE, Block.SEA_LANTERN}), + STREET(new Block[] {Block.BLACK_CONCRETE_POWDER, Block.GRAY_CONCRETE_POWDER, Block.GRAVEL, Block.BLACK_CONCRETE, Block.GRAY_CONCRETE}), PRESSURE_PLATES(new Block[] {Block.ACACIA_PRESSURE_PLATE, Block.BIRCH_PRESSURE_PLATE, Block.CRIMSON_PRESSURE_PLATE, Block.JUNGLE_PRESSURE_PLATE, Block.OAK_PRESSURE_PLATE, Block.DARK_OAK_PRESSURE_PLATE, Block.HEAVY_WEIGHTED_PRESSURE_PLATE, Block.HEAVY_WEIGHTED_PRESSURE_PLATE, Block.POLISHED_BLACKSTONE_PRESSURE_PLATE, Block.SPRUCE_PRESSURE_PLATE, Block.STONE_PRESSURE_PLATE, Block.WARPED_PRESSURE_PLATE}); diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquareTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquareTerrainGenerator.java index d929859..c7dadb5 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquareTerrainGenerator.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquareTerrainGenerator.java @@ -9,6 +9,7 @@ import net.minestom.server.coordinate.Pos; import net.minestom.server.instance.block.Block; import net.minestom.server.instance.generator.GenerationUnit; import net.minestom.server.instance.generator.Generator; +import net.minestom.server.world.DimensionType; import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -19,14 +20,25 @@ public class SquareTerrainGenerator implements Generator { private final int width; private final int length; + private int plateHeight = 0; + private boolean withBorder = false; - private final boolean generatePlate; - public SquareTerrainGenerator(int width, int length, boolean generatePlate) { + public SquareTerrainGenerator(int width, int length) { this.width = width; this.length = length; - this.generatePlate = generatePlate; } + + public SquareTerrainGenerator withPlate(int plateHeight) { + this.plateHeight = plateHeight; + return this; + } + + public SquareTerrainGenerator withBorders() { + this.withBorder = true; + return this; + } + private final JNoise base = JNoise.newBuilder() .fastSimplex() .setSeed(rnd.nextLong()) @@ -59,22 +71,35 @@ public class SquareTerrainGenerator implements Generator { for (int z = 0; z < unit.size().z(); z++) { Point bottom = start.add(x, 0, z); - if(generatePlate) { + if(plateHeight > 0) { if(bottom.x() <= width && bottom.x() >= 0 && bottom.z() <= length && bottom.z() >= 0) { - unit.modifier().fill(bottom, bottom.add(1, 50, 1), BlockPallet.GROUND.rnd()); + unit.modifier().fill(bottom, bottom.add(1, plateHeight, 1), BlockPallet.GROUND.rnd()); continue; } } + if(withBorder) { + Runnable generateBorder = () -> unit.modifier().fill(bottom, bottom.add(1, DimensionType.OVERWORLD.getMaxY(), 1), Block.BARRIER); + + if(bottom.z() <= length+1 && bottom.z() >= -1 && bottom.x() >= -1 && bottom.x() <= width+1) { + if(bottom.x() == -1 || bottom.x() == width+1) { + generateBorder.run(); + } + if(bottom.z() == -1 || bottom.z() == length + 1) { + generateBorder.run(); + } + } + } + unit.modifier().setBlock(bottom, Block.GRASS_BLOCK); synchronized (base) { double baseNoise = base.getNoise(bottom.x(), bottom.z()); - double possibleHeights[] = { - minTwo(RangeMap.map(bottom.distance(new Pos(0, 0, 0)), 0, 400, -(this.width / 5), 200)) + baseNoise * 8, - minTwo(RangeMap.map(bottom.distance(new Pos(width, 0, 0)), 0, 400, -(this.width / 5), 200)) + baseNoise * 8, - minTwo(RangeMap.map(bottom.distance(new Pos(0, 0, length)), 0, 400, -(this.width / 5), 200)) + baseNoise * 8, - minTwo(RangeMap.map(bottom.distance(new Pos(width, 0, length)), 0, 400, -(this.width / 5), 200)) + baseNoise * 8 + double[] possibleHeights = { + minTwo(RangeMap.map(bottom.distance(new Pos(0, 0, 0)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, + minTwo(RangeMap.map(bottom.distance(new Pos(width, 0, 0)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, + minTwo(RangeMap.map(bottom.distance(new Pos(0, 0, length)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, + minTwo(RangeMap.map(bottom.distance(new Pos(width, 0, length)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8 }; double currentHeight = Arrays.stream(possibleHeights).min().getAsDouble();