diff --git a/build/resources/main/maps/lobby/region/r.-1.-1.mca b/build/resources/main/maps/lobby/region/r.-1.-1.mca index decb6ba..c2ab205 100644 Binary files a/build/resources/main/maps/lobby/region/r.-1.-1.mca and b/build/resources/main/maps/lobby/region/r.-1.-1.mca differ diff --git a/build/resources/main/maps/lobby/region/r.-1.0.mca b/build/resources/main/maps/lobby/region/r.-1.0.mca index 8ec79aa..4f3d1a9 100644 Binary files a/build/resources/main/maps/lobby/region/r.-1.0.mca and b/build/resources/main/maps/lobby/region/r.-1.0.mca differ diff --git a/build/resources/main/maps/lobby/region/r.0.-1.mca b/build/resources/main/maps/lobby/region/r.0.-1.mca index 139a2b1..ca9ce8c 100644 Binary files a/build/resources/main/maps/lobby/region/r.0.-1.mca and b/build/resources/main/maps/lobby/region/r.0.-1.mca differ diff --git a/build/resources/main/maps/lobby/region/r.0.0.mca b/build/resources/main/maps/lobby/region/r.0.0.mca index 41b3321..bbed565 100644 Binary files a/build/resources/main/maps/lobby/region/r.0.0.mca and b/build/resources/main/maps/lobby/region/r.0.0.mca differ diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF index 59499bc..6fd6a28 100644 --- a/build/tmp/jar/MANIFEST.MF +++ b/build/tmp/jar/MANIFEST.MF @@ -1,2 +1,4 @@ Manifest-Version: 1.0 +Main-Class: eu.mhsl.minenet.minigames.Main +Multi-Release: true diff --git a/resources/maps/lobby/region/r.-1.-1.mca b/resources/maps/lobby/region/r.-1.-1.mca index decb6ba..c2ab205 100644 Binary files a/resources/maps/lobby/region/r.-1.-1.mca and b/resources/maps/lobby/region/r.-1.-1.mca differ diff --git a/resources/maps/lobby/region/r.-1.0.mca b/resources/maps/lobby/region/r.-1.0.mca index 8ec79aa..4f3d1a9 100644 Binary files a/resources/maps/lobby/region/r.-1.0.mca and b/resources/maps/lobby/region/r.-1.0.mca differ diff --git a/resources/maps/lobby/region/r.0.-1.mca b/resources/maps/lobby/region/r.0.-1.mca index 139a2b1..ca9ce8c 100644 Binary files a/resources/maps/lobby/region/r.0.-1.mca and b/resources/maps/lobby/region/r.0.-1.mca differ diff --git a/resources/maps/lobby/region/r.0.0.mca b/resources/maps/lobby/region/r.0.0.mca index 41b3321..bbed565 100644 Binary files a/resources/maps/lobby/region/r.0.0.mca and b/resources/maps/lobby/region/r.0.0.mca differ diff --git a/src/main/java/eu/mhsl/minenet/minigames/Main.java b/src/main/java/eu/mhsl/minenet/minigames/Main.java index 645ba9b..427397a 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/Main.java +++ b/src/main/java/eu/mhsl/minenet/minigames/Main.java @@ -8,6 +8,7 @@ import eu.mhsl.minenet.minigames.server.provider.ByPlayerNameUuidProvider; import io.github.bloepiloepi.pvp.PvpExtension; import net.minestom.server.MinecraftServer; import net.minestom.server.extras.lan.OpenToLAN; +import net.minestom.server.extras.velocity.VelocityProxy; import net.minestom.server.timer.TaskSchedule; import java.util.logging.Logger; @@ -41,6 +42,7 @@ public class Main { logger.info("Starting Minecraft server ... "); OpenToLAN.open(); //MojangAuth.init(); LET NON MIGRATORS PLAY! + VelocityProxy.enable("sKkDO9lGfpS7"); server.start("0.0.0.0", 25565); System.gc(); diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java b/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java index ec15e96..860b2c3 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java +++ b/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java @@ -1,5 +1,6 @@ package eu.mhsl.minenet.minigames.command; +import eu.mhsl.minenet.minigames.command.anonymous.SkinCommand; import eu.mhsl.minenet.minigames.command.privileged.*; import eu.mhsl.minenet.minigames.command.anonymous.HubCommand; import eu.mhsl.minenet.minigames.command.anonymous.LeaveCommand; @@ -22,6 +23,7 @@ public enum Commands { OP(new OpCommand()), FAKEPLAYER(new FakeplayerCommand()), KICK(new KickCommand()), + SKIN(new SkinCommand()), SETOWNER(new SetRoomOwnerCommand()); Commands(Command handler) { diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/anonymous/SkinCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/anonymous/SkinCommand.java new file mode 100644 index 0000000..9f4ffe1 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/anonymous/SkinCommand.java @@ -0,0 +1,18 @@ +package eu.mhsl.minenet.minigames.command.anonymous; + +import net.minestom.server.command.builder.Command; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.PlayerSkin; + +public class SkinCommand extends Command { + public SkinCommand() { + super("skin"); + + addSyntax((sender, context) -> { + if(sender instanceof Player p) { + p.setSkin(PlayerSkin.fromUsername(context.getRaw("target"))); + } + }, ArgumentType.Entity("target").onlyPlayers(true).onlyPlayers(true)); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java b/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java index 7e632cb..c2a86c9 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java @@ -2,6 +2,7 @@ package eu.mhsl.minenet.minigames.handler; import eu.mhsl.minenet.minigames.handler.global.AddEntityToInstanceEventListener; import eu.mhsl.minenet.minigames.handler.global.PlayerChatHandler; +import eu.mhsl.minenet.minigames.handler.global.PlayerLeaveHandler; import eu.mhsl.minenet.minigames.handler.global.PlayerLoginHandler; import net.minestom.server.MinecraftServer; import net.minestom.server.event.EventListener; @@ -9,7 +10,8 @@ import net.minestom.server.event.EventListener; public enum Listeners { SPAWN(new AddEntityToInstanceEventListener()), CHAT(new PlayerChatHandler()), - LOGIN(new PlayerLoginHandler()); + LOGIN(new PlayerLoginHandler()), + LEAVE(new PlayerLeaveHandler()); Listeners(EventListener event) { MinecraftServer.getGlobalEventHandler().addListener(event); diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java new file mode 100644 index 0000000..7a9658f --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java @@ -0,0 +1,23 @@ +package eu.mhsl.minenet.minigames.handler.global; + +import eu.mhsl.minenet.minigames.message.Icon; +import eu.mhsl.minenet.minigames.message.type.ChatMessage; +import net.minestom.server.MinecraftServer; +import net.minestom.server.entity.Player; +import net.minestom.server.event.EventListener; +import net.minestom.server.event.player.PlayerDisconnectEvent; +import org.jetbrains.annotations.NotNull; + +public class PlayerLeaveHandler implements EventListener { + @Override + public @NotNull Class eventType() { + return PlayerDisconnectEvent.class; + } + + @Override + public @NotNull Result run(@NotNull PlayerDisconnectEvent event) { + Player p = event.getPlayer(); + new ChatMessage(Icon.SCIENCE).appendStatic("unübersetzter Leavetext: ").appendStatic(p.getDisplayName()).send(MinecraftServer.getConnectionManager().getOnlinePlayers()); + return Result.SUCCESS; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java index e64ea10..1f27c45 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java @@ -1,6 +1,8 @@ package eu.mhsl.minenet.minigames.handler.global; import eu.mhsl.minenet.minigames.instance.room.Room; +import eu.mhsl.minenet.minigames.message.Icon; +import eu.mhsl.minenet.minigames.message.type.ChatMessage; import eu.mhsl.minenet.minigames.skin.SkinCache; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; @@ -34,6 +36,8 @@ public class PlayerLoginHandler implements EventListener { Logger.getLogger("user").info(p.getUsername() + " joined"); + new ChatMessage(Icon.SCIENCE).appendStatic("unübersetzter Jointext: ").appendStatic(p.getUsername()).send(MinecraftServer.getConnectionManager().getOnlinePlayers()); + return Result.SUCCESS; } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java index dbed6ec..8f9b9d1 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java @@ -1,6 +1,8 @@ package eu.mhsl.minenet.minigames.instance.game; import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef.BowSpleefFactory; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace.ElytraRaceFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.backrooms.BackroomsFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars.BedwarsFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.acidRain.AcidRainFactory; @@ -21,8 +23,10 @@ public enum GameList { BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE), BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE), TNTRUN(new TntRunFactory(), GameType.OTHER), - BLIZZARD(new AcidRainFactory(), GameType.PVE), - SPLEEF(new SpleefFactory(), GameType.PVP); + ACIDRAIN(new AcidRainFactory(), GameType.PVE), + ELYTRARACE(new ElytraRaceFactory(), GameType.PVP), + SPLEEF(new SpleefFactory(), GameType.PVP), + BOWSPLEEF(new BowSpleefFactory(), GameType.PVP); private final GameFactory factory; private final GameType type; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/acidRain/AcidRain.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/acidRain/AcidRain.java index b36706b..924910e 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/acidRain/AcidRain.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/acidRain/AcidRain.java @@ -5,9 +5,9 @@ import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.score.LastWinsScore; import eu.mhsl.minenet.minigames.util.BatchUtil; -import eu.mhsl.minenet.minigames.util.RangeMap; +import eu.mhsl.minenet.minigames.util.NumberUtil; import eu.mhsl.minenet.minigames.util.WeatherUtils; -import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator; import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Pos; @@ -75,7 +75,7 @@ public class AcidRain extends StatelessGame { generatePlatform(generationOffset); if(!isRunning) return TaskSchedule.stop(); - return TaskSchedule.millis(RangeMap.map(50 - difficulty, 0, 50, 100, 1000)); + return TaskSchedule.millis((long) NumberUtil.map(50 - difficulty, 0, 50, 100, 1000)); }, ExecutionType.ASYNC); MinecraftServer.getSchedulerManager().submitTask(() -> { diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/bowSpleef/BowSpleef.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/bowSpleef/BowSpleef.java new file mode 100644 index 0000000..e0d4a7b --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/bowSpleef/BowSpleef.java @@ -0,0 +1,158 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef; + +import eu.mhsl.minenet.minigames.instance.Dimension; +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import eu.mhsl.minenet.minigames.score.LastWinsScore; +import eu.mhsl.minenet.minigames.util.BatchUtil; +import eu.mhsl.minenet.minigames.util.GeneratorUtils; +import io.github.bloepiloepi.pvp.events.ProjectileHitEvent; +import io.github.bloepiloepi.pvp.projectile.CustomEntityProjectile; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.*; +import net.minestom.server.entity.metadata.arrow.ArrowMeta; +import net.minestom.server.entity.metadata.other.PrimedTntMeta; +import net.minestom.server.event.EventListener; +import net.minestom.server.event.item.ItemUpdateStateEvent; +import net.minestom.server.event.player.PlayerItemAnimationEvent; +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.item.Enchantment; +import net.minestom.server.item.ItemHideFlag; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.tag.Tag; +import net.minestom.server.utils.MathUtils; +import net.minestom.server.utils.time.TimeUnit; +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +public class BowSpleef extends StatelessGame { + private static final Tag CHARGE_BOW_SINCE = Tag.Long("CHARGE_BOW_SINCE"); + private static final Tag ARROW_FIRST_HIT = Tag.Boolean("ARROW_ALREADY_LIT"); + private final int radius = 30; + private final int totalElevation = 50; + public BowSpleef() { + super(Dimension.OVERWORLD.DIMENSION, "bowSpleef", new LastWinsScore()); + + eventNode().addListener( + EventListener + .builder(PlayerItemAnimationEvent.class) + .handler(playerItemAnimationEvent -> playerItemAnimationEvent.getPlayer().setTag(CHARGE_BOW_SINCE, System.currentTimeMillis())) + .filter(playerItemAnimationEvent -> playerItemAnimationEvent.getItemAnimationType() == PlayerItemAnimationEvent.ItemAnimationType.BOW) + .build() + ); + + eventNode().addListener( + EventListener + .builder(ItemUpdateStateEvent.class) + .handler(event -> { + final Player player = event.getPlayer(); + final double chargedFor = (System.currentTimeMillis() - player.getTag(CHARGE_BOW_SINCE)) / 1000D; + final double power = MathUtils.clamp((chargedFor * chargedFor + 2 * chargedFor) / 2D, 0, 1); + + if (power > 0.2) { + final CustomEntityProjectile projectile = new CustomEntityProjectile(player, EntityType.ARROW, true); + final ArrowMeta meta = (ArrowMeta) projectile.getEntityMeta(); + meta.setCritical(power >= 0.9); + projectile.scheduleRemove(Duration.of(100, TimeUnit.SERVER_TICK)); + projectile.setOnFire(true); + + final Pos position = player.getPosition().add(0, player.getEyeHeight(), 0); + projectile.setInstance(Objects.requireNonNull(player.getInstance()), position); + + final Vec direction = projectile.getPosition().direction(); + projectile.shoot(position.add(direction).sub(0, 0.2, 0), power * 3, 1.0); + projectile.setTag(ARROW_FIRST_HIT, true); + } + }) + .filter(itemUpdateStateEvent -> itemUpdateStateEvent.getItemStack().material() == Material.BOW) + .build() + ); + + eventNode().addListener( + EventListener + .builder(ProjectileHitEvent.ProjectileBlockHitEvent.class) + .handler(projectileBlockHitEvent -> { + CustomEntityProjectile projectile = projectileBlockHitEvent.getEntity(); + if(!projectile.getTag(ARROW_FIRST_HIT)) { + projectile.remove(); + return; + } + + float radius = 0.5F; + Point arrowPos = projectile.getPosition(); + GeneratorUtils.foreachXZ(arrowPos.add(radius), arrowPos.sub(radius), point -> { + Point location = point.add(projectile.getVelocity().mul(0.04)).withY(totalElevation); + if(!getBlock(location).isAir()) { + setBlock(location, Block.AIR); + + Entity fallingTnt = new Entity(EntityType.TNT); + PrimedTntMeta fallingTntMeta = (PrimedTntMeta) fallingTnt.getEntityMeta(); + fallingTntMeta.setFuseTime(20); + fallingTnt.setInstance(this, location); + fallingTnt.setVelocity(new Vec(0, 3, 0)); + } + }); + + projectile.setTag(ARROW_FIRST_HIT, false); + }) + .build() + ); + + eventNode().addListener( + EventListener + .builder(ProjectileHitEvent.ProjectileEntityHitEvent.class) + .handler(projectileEntityHitEvent -> projectileEntityHitEvent.setCancelled(true)) + .build() + ); + + } + + @Override + protected void onLoad(@NotNull CompletableFuture callback) { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + for(int x = -radius; x <= radius; x++) { + for(int z = -radius; z <= radius; z++) { + if(new Pos(x, 0, z).distance(new Pos(0, 0, 0)) > radius) continue; + + batch.setBlock(x, totalElevation, z, Block.TNT); + } + } + BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); + } + + @Override + protected void onStart() { + getPlayers().forEach(player -> { + player.getInventory().setItemStack( + 0, + ItemStack + .builder(Material.BOW) + .displayName(TranslatedComponent.byId("bow").getAssembled(player)) + .meta(builder -> builder.enchantment(Enchantment.FLAME, (short) 1).build()) + .meta(builder -> builder.hideFlag(ItemHideFlag.HIDE_ENCHANTS)) + .build() + ); + }); + } + + @Override + protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { + if(playerMoveEvent.getNewPosition().y() < totalElevation) { + getScore().insertResult(playerMoveEvent.getPlayer()); + playerMoveEvent.getPlayer().setGameMode(GameMode.SPECTATOR); + } + } + + @Override + public Pos getSpawn() { + return new Pos(0, totalElevation + 1, 0); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/bowSpleef/BowSpleefFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/bowSpleef/BowSpleefFactory.java new file mode 100644 index 0000000..1e69a08 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/bowSpleef/BowSpleefFactory.java @@ -0,0 +1,26 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef; + +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.Option; +import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import net.minestom.server.item.Material; + +import java.util.Map; + +public class BowSpleefFactory implements GameFactory { + @Override + public TranslatedComponent name() { + return TranslatedComponent.byId(""); + } + + @Override + public Material symbol() { + return Material.BOW; + } + + @Override + public StatelessGame manufacture(Map> configuration) throws Exception { + return new BowSpleef(); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/deathcube/Deathcube.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/deathcube/Deathcube.java index 5edec6e..dff508d 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/deathcube/Deathcube.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/deathcube/Deathcube.java @@ -4,7 +4,7 @@ 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.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator; import io.github.bloepiloepi.pvp.config.AttackConfig; import io.github.bloepiloepi.pvp.config.DamageConfig; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/elytraRace/ElytraRace.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/elytraRace/ElytraRace.java new file mode 100644 index 0000000..29acf12 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/elytraRace/ElytraRace.java @@ -0,0 +1,254 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace; + +import eu.mhsl.minenet.minigames.instance.Dimension; +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.message.Countdown; +import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import eu.mhsl.minenet.minigames.message.type.TitleMessage; +import eu.mhsl.minenet.minigames.score.FirstWinsScore; +import eu.mhsl.minenet.minigames.util.*; +import eu.mhsl.minenet.minigames.world.BlockPallet; +import eu.mhsl.minenet.minigames.world.generator.featureEnriched.ValeGenerator; +import eu.mhsl.minenet.minigames.world.generator.terrain.PlaneTerrainGenerator; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.Player; +import net.minestom.server.event.player.*; +import net.minestom.server.instance.batch.AbsoluteBlockBatch; +import net.minestom.server.instance.block.Block; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.network.packet.server.play.ParticlePacket; +import net.minestom.server.particle.Particle; +import net.minestom.server.particle.ParticleCreator; +import net.minestom.server.sound.SoundEvent; +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + + +public class ElytraRace extends StatelessGame { + private final ValeGenerator vale = new ValeGenerator(); + + private final int gameHeight = 0; + private final int ringSpacing = 100; + private final int ringCount; + + private final Material boostMaterial = Material.FIREWORK_ROCKET; + private final Material resetMaterial = Material.RED_DYE; + private final int boostMultiplier = 50; + private final Material ringMaterial = Material.GOLD_BLOCK; + private int generatedUntil = 0; + + private record CheckPointData(int currentCheckpoint, int nextCheckpoint) { + public CheckPointData next(int spacing) { + return new CheckPointData(nextCheckpoint, nextCheckpoint + spacing); + } + } + private final Map playerCheckpoints = new HashMap<>(); + + public ElytraRace(int ringCount) { + super(Dimension.OVERWORLD.DIMENSION, "ElytraRace", new FirstWinsScore()); + + this.ringCount = ringCount; + + setGenerator(vale); + vale.setCalculateSeaLevel(point -> -55); + vale.setXShiftMultiplier(integer -> NumberUtil.map(integer, 50, 500, 0, 1)); + vale.addMixIn(new PlaneTerrainGenerator(gameHeight, Block.BARRIER)); + + eventNode().addListener(PlayerUseItemEvent.class, playerUseItemEvent -> { + Player player = playerUseItemEvent.getPlayer(); + Material usedMaterial = playerUseItemEvent.getItemStack().material(); + + if(usedMaterial.equals(boostMaterial)) { + if(!player.isFlyingWithElytra()) return; + + boost(player); + InventoryUtil.removeItemFromPlayer(player, boostMaterial, 1); + } else if(usedMaterial.equals(resetMaterial)) { + toCheckpoint(player); + InventoryUtil.removeItemFromPlayer(player, resetMaterial, 1); + } + }); + + eventNode().addListener(PlayerStopFlyingWithElytraEvent.class, playerStopFlyingWithElytraEvent -> { + Player player = playerStopFlyingWithElytraEvent.getPlayer(); + if(Position.blocksBelowPlayer(this, player).contains(ringMaterial.block())) { + player.setFlyingWithElytra(true); + boost(player); + } else { + toCheckpoint(player); +// getScore().insertResult(playerStopFlyingWithElytraEvent.getPlayer()); +// playerStopFlyingWithElytraEvent.getPlayer().setGameMode(GameMode.SPECTATOR); + } + }); + + eventNode().addListener(PlayerStartFlyingWithElytraEvent.class, playerStartFlyingWithElytraEvent -> { + if(!isRunning) { + playerStartFlyingWithElytraEvent.getPlayer().setFlyingWithElytra(false); + return; + } + + boost(playerStartFlyingWithElytraEvent.getPlayer()); + }); + } + + @Override + protected void onLoad(@NotNull CompletableFuture callback) { + Point spawnpoint = new Pos(vale.getXShiftAtZ(0), -46, 0); + GeneratorUtils.iterateArea(spawnpoint.sub(2, 0, 2), spawnpoint.add(2, 0, 2), point -> { + setBlock(point, BlockPallet.STREET.rnd()); + }); + + generateRing(ringSpacing); + generateRing(ringSpacing * 2); + callback.complete(null); + } + + @Override + protected void onStart() { + getPlayers().forEach(player -> { + player.getInventory().setChestplate(ItemStack.of(Material.ELYTRA)); + for(int i = 0; i < 3; i++) { + player.getInventory().setItemStack(i, ItemStack.builder(boostMaterial).displayName(TranslatedComponent.byId("boost").getAssembled(player)).build()); + } + addResetItemToPlayer(player); + }); + } + + @Override + protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { + Player player = playerMoveEvent.getPlayer(); + Point newPos = playerMoveEvent.getNewPosition(); + + playerCheckpoints.putIfAbsent(player, new CheckPointData(ringSpacing, ringSpacing * 2)); + + if(newPos.z() > generatedUntil - ringSpacing) { + generateRing(generatedUntil + ringSpacing); + } + + if(newPos.z() > playerCheckpoints.get(player).nextCheckpoint) { + playerCheckpoints.put(player, playerCheckpoints.get(player).next(ringSpacing)); + boost(player); + } + + if(newPos.y() > gameHeight - 5) { + Point particlePoint = newPos.withY(gameHeight); + ParticlePacket particle = ParticleCreator.createParticlePacket( + Particle.WAX_ON, + particlePoint.blockX(), + particlePoint.blockY(), + particlePoint.withZ(z -> z+10).blockZ(), + 20, + 0, + 30, + Math.toIntExact((long) NumberUtil.map(newPos.y(), gameHeight - 5, gameHeight, 50, 500)) + ); + player.sendPacket(particle); + } + + if(getBlock(player.getPosition()).equals(Block.WATER)) { + toCheckpoint(player); + } + + if(newPos.z() > ringCount * ringSpacing) { + getScore().insertResult(player); + player.setGameMode(GameMode.SPECTATOR); + } + } + + @Override + public Pos getSpawn() { + return new Pos(vale.getXShiftAtZ(0), -45, 0); + } + + private void addResetItemToPlayer(Player p) { + p.getInventory().setItemStack(8, ItemStack.builder(resetMaterial).displayName(TranslatedComponent.byId("reset").getAssembled(p)).build()); + } + + private Point getRingPositionAtZ(int z) { + return new Pos(vale.getXShiftAtZ(z), -45, z); + } + + private CompletableFuture generateRing(int zPos) { + if(zPos > ringCount * ringSpacing) return null; + boolean isLast = (zPos == ringCount * ringSpacing); + + generatedUntil = zPos; + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + + Point ringPos = getRingPositionAtZ(zPos); + GeneratorUtils.iterateArea( + ringPos.sub(100, 0, 0).withY(getDimensionType().getMinY()), + ringPos.add(100, 0, 0).withY(gameHeight), + point -> batch.setBlock(point, Block.BARRIER) + ); + GeneratorUtils.iterateArea( + ringPos.sub(3, 3, 0), + ringPos.add(3, 3, 0), + point -> batch.setBlock(point, isLast ? Block.DIAMOND_BLOCK : ringMaterial.block()) + ); + GeneratorUtils.iterateArea( + ringPos.sub(2, 2, 0), + ringPos.add(2, 2, 0), + point -> batch.setBlock(point, Block.AIR) + ); + + BatchUtil.loadAndApplyBatch(batch, this, () -> {}); + return null; + } + + private void boost(Player player) { + player.playSound(Sound.sound(SoundEvent.ENTITY_FIREWORK_ROCKET_LAUNCH, Sound.Source.VOICE, 1f, 1f)); + + Vec playerVelocity = player.getPosition().direction(); + player.setVelocity( + player.getVelocity().add(playerVelocity.mul(boostMultiplier)) + .withY(playerVelocity.withY(v -> v * boostMultiplier).y()) + ); + } + + private void toCheckpoint(Player p) { + Point checkpointPos = getRingPositionAtZ(playerCheckpoints.get(p).currentCheckpoint); + p.setVelocity(Vec.ZERO); + p.setFlyingWithElytra(false); + p.teleport(Pos.fromPoint(checkpointPos).add(0.5, 0, 0.5)); + + p.setFlying(true); + p.setFlyingSpeed(0); + + new Countdown(TitleMessage.class) + .countdown( + Audience.audience(p), + 3, + countdownModifier -> + countdownModifier.message = new TitleMessage( + Duration.ofMillis(300), + Duration.ofMillis(700) + ) + .subtitle( + subtitleMessage -> + subtitleMessage + .appendStatic(Component.text("Launch in ", NamedTextColor.DARK_GREEN)) + .appendStatic(Component.text(countdownModifier.timeLeft, NamedTextColor.GREEN)) + .appendStatic(Component.text(" seconds", NamedTextColor.DARK_GREEN)) + ) + ).thenRun(() -> { + p.setFlying(false); + p.setFlyingSpeed(1); + p.setFlyingWithElytra(true); + boost(p); + addResetItemToPlayer(p); + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/elytraRace/ElytraRaceFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/elytraRace/ElytraRaceFactory.java new file mode 100644 index 0000000..04533f8 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/elytraRace/ElytraRaceFactory.java @@ -0,0 +1,34 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace; + +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory; +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; + +import java.util.Map; + +public class ElytraRaceFactory implements GameFactory { + @Override + public TranslatedComponent name() { + return TranslatedComponent.byId(""); + } + + @Override + public Material symbol() { + return Material.ELYTRA; + } + + @Override + public ConfigManager configuration() { + return new ConfigManager() + .addOption(new NumericOption("ringCount", Material.DIAMOND_BLOCK, TranslatedComponent.byId("ringCount"), 5, 10, 20, 30, 40, 50)); + } + + @Override + public StatelessGame manufacture(Map> configuration) throws Exception { + return new ElytraRace(configuration.get("ringCount").getAsInt()); + } +} 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 4f35b5f..421384a 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 @@ -1,19 +1,17 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.minerun; 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; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.terrain.SquarePlateTerrainGenerator; import net.kyori.adventure.sound.Sound; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Entity; +import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.event.player.PlayerMoveEvent; import net.minestom.server.instance.batch.AbsoluteBlockBatch; @@ -36,7 +34,7 @@ class Minerun extends StatelessGame { public Minerun(int width, int length, int minePercentage) { super(Dimension.THE_END.DIMENSION, "Minerun", new FirstWinsScore()); - setGenerator(new SquarePlateTerrainGenerator(width, length + preRun + afterFinishLine).setPlateHeight(50)); + setGenerator(new SquarePlateTerrainGenerator(width, length + preRun + afterFinishLine).setPlateHeight(50).setGenerateBorders(true)); this.width = width; this.length = length; @@ -83,28 +81,19 @@ class Minerun extends StatelessGame { Player p = playerMoveEvent.getPlayer(); Pos middle = playerMoveEvent.getNewPosition(); - if(middle.x() < 0 || middle.x() > width) { //player cannot go sidewards + if(isBeforeBeginning && middle.z() > preRun+0.5) { //player cannot go forward before the game start playerMoveEvent.setCancelled(true); - new ActionBarMessage().appendStatic(Component.text("Please stay in line!", NamedTextColor.RED)).send(p); - } - - if(!isRunning && middle.z() > preRun+0.5) { //player cannot go forward before the game start - playerMoveEvent.setCancelled(true); - } - - if(middle.z() < preRun + length + afterMines && getScore().hasResult(p)) { // player cannot go back after winning - playerMoveEvent.setCancelled(true); - new ActionBarMessage().appendStatic(Component.text("You cannot go back on the Field!", NamedTextColor.RED)).send(p); } if(Intersect.withPressurePlate(this, BlockPallet.PRESSURE_PLATES, middle)) { //Player died + p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.PLAYER, 1f, 1f)); p.setPose(Entity.Pose.DYING); p.teleport(new Pos(p.getPosition().x(), getSpawn().y(), getSpawn().z())); - p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.PLAYER, 1f, 1f)); } if(middle.z() > preRun + length + afterMines) { // Player finished getScore().insertResult(p); + p.setGameMode(GameMode.SPECTATOR); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spleef/Spleef.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spleef/Spleef.java index 58a71c8..86cf18c 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spleef/Spleef.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spleef/Spleef.java @@ -5,7 +5,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; import eu.mhsl.minenet.minigames.score.LastWinsScore; import eu.mhsl.minenet.minigames.util.BatchUtil; -import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.GameMode; 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 667bc0f..a4e467e 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 @@ -6,7 +6,7 @@ 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.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.terrain.SquarePlateTerrainGenerator; import net.kyori.adventure.sound.Sound; import net.minestom.server.coordinate.Pos; 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 19f4641..36a77fd 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 @@ -75,7 +75,7 @@ public class Room extends MineNetInstance implements Spawnable { construct(); setOwner(owner); this.gameSelector = new GameSelector(); - this.gameSelector.setInstance(this, new Pos(0.5, 16, 9.5)); + this.gameSelector.setInstance(this, new Pos(0.5, 50, 19.5)); } protected Room() { @@ -141,6 +141,6 @@ public class Room extends MineNetInstance implements Spawnable { @Override public Pos getSpawn() { - return new Pos(0.5, 16, 0.5); + return new Pos(0.5, 50, 0.5); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/message/Sendable.java b/src/main/java/eu/mhsl/minenet/minigames/message/Sendable.java index 2be3a28..4201711 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/message/Sendable.java +++ b/src/main/java/eu/mhsl/minenet/minigames/message/Sendable.java @@ -3,7 +3,7 @@ package eu.mhsl.minenet.minigames.message; import net.kyori.adventure.audience.Audience; import net.minestom.server.entity.Player; -import java.util.List; +import java.util.Collection; import java.util.Set; //TODO maybe async large batches @@ -14,7 +14,7 @@ public interface Sendable { players.forEachAudience(audience -> this.send((Player) audience)); } - default void send(List players) { + default void send(Collection players) { players.forEach(this::send); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/message/TranslatableMessage.java b/src/main/java/eu/mhsl/minenet/minigames/message/TranslatableMessage.java index 70e3e1c..855ee5c 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/message/TranslatableMessage.java +++ b/src/main/java/eu/mhsl/minenet/minigames/message/TranslatableMessage.java @@ -7,6 +7,7 @@ import net.kyori.adventure.text.ComponentBuilder; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import net.minestom.server.entity.Player; import java.util.ArrayList; @@ -94,8 +95,8 @@ public abstract class TranslatableMessage implements Sendable { public Component build(Player p) { ComponentBuilder out = Component.text(); chain.forEach(componentLike -> { + if(componentLike == null) componentLike = Component.text("NULL", NamedTextColor.RED, TextDecoration.ITALIC); if(componentLike instanceof Translatable t) t.assemble(p); - out.append(componentLike); }); return out.build(); diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/BatchUtil.java b/src/main/java/eu/mhsl/minenet/minigames/util/BatchUtil.java index a8adcbc..225b115 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/util/BatchUtil.java +++ b/src/main/java/eu/mhsl/minenet/minigames/util/BatchUtil.java @@ -2,14 +2,15 @@ package eu.mhsl.minenet.minigames.util; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minestom.server.instance.InstanceContainer; -import net.minestom.server.instance.batch.AbsoluteBlockBatch; +import net.minestom.server.instance.batch.Batch; import net.minestom.server.instance.batch.ChunkBatch; import net.minestom.server.utils.chunk.ChunkUtils; import java.lang.reflect.Field; +import java.util.concurrent.CompletableFuture; public class BatchUtil { - public static long[] getAffectedChunks(AbsoluteBlockBatch batch) { + public static long[] getAffectedChunks(Batch batch) { try { Field field = batch.getClass().getDeclaredField("chunkBatchesMap"); field.setAccessible(true); @@ -23,10 +24,33 @@ public class BatchUtil { } } - public static void loadAndApplyBatch(AbsoluteBlockBatch batch, InstanceContainer instance, Runnable onFinish) { + public static void loadAndApplyBatch(Batch batch, InstanceContainer instance, Runnable onFinish) { batch.awaitReady(); long[] affectedChunks = BatchUtil.getAffectedChunks(batch); ChunkUtils.optionalLoadAll(instance, affectedChunks, null).thenRun(() -> batch.apply(instance, onFinish)); } + public static void loadAndApplyBatchBlocking(Batch batch, InstanceContainer instance) { + CompletableFuture future = new CompletableFuture<>(); + batch.awaitReady(); + long[] affectedChunks = BatchUtil.getAffectedChunks(batch); + CompletableFuture loadChunksTask = ChunkUtils.optionalLoadAll(instance, affectedChunks, null); + + Runnable completerTask = () -> { + System.out.println("COMPLETE"); + future.complete(null); + }; + + loadChunksTask.thenRun(() -> { + System.out.println("BEGIN"); + batch.apply(instance, completerTask); + }); + + try { + future.get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/GeneratorUtils.java b/src/main/java/eu/mhsl/minenet/minigames/util/GeneratorUtils.java new file mode 100644 index 0000000..6b7c5cc --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/util/GeneratorUtils.java @@ -0,0 +1,81 @@ +package eu.mhsl.minenet.minigames.util; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.function.Consumer; + + +public class GeneratorUtils { + public static void foreachXZ(GenerationUnit unit, Consumer bottomPoint) { + double startX = unit.absoluteStart().x(); + double endX = unit.absoluteEnd().x() - 1; + double startZ = unit.absoluteStart().z(); + double endZ = unit.absoluteEnd().z() - 1; + + for (double x = startX; x <= endX; x++) { + for (double z = startZ; z <= endZ; z++) { + Point currentPoint = new Pos(x, unit.absoluteStart().y(), z); + bottomPoint.accept(currentPoint); + } + } + } + + public static void foreachXZ(Point start, Point end, Consumer callback) { + double startX = Math.min(start.x(), end.x()); + double endX = Math.max(start.x(), end.x()); + double startZ = Math.min(start.z(), end.z()); + double endZ = Math.max(start.z(), end.z()); + + for (double x = startX; x <= endX; x++) { + for (double z = startZ; z <= endZ; z++) { + Point currentPoint = new Pos(x, start.y(), z); + callback.accept(currentPoint); + } + } + } + + public static void iterateArea(Point pos1, Point pos2, Consumer callback) { + int minX = (int) Math.min(pos1.x(), pos2.x()); + int maxX = (int) Math.max(pos1.x(), pos2.x()); + int minY = (int) Math.min(pos1.y(), pos2.y()); + int maxY = (int) Math.max(pos1.y(), pos2.y()); + int minZ = (int) Math.min(pos1.z(), pos2.z()); + int maxZ = (int) Math.max(pos1.z(), pos2.z()); + + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + Point point = new Pos(x, y, z); + callback.accept(point); + } + } + } + } + + public static void outline(Point pos1, Point pos2, Consumer outline) { + outline(pos1, pos2, outline, point -> {}); + } + + public static void outline(Point pos1, Point pos2, Consumer outline, Consumer innerFill) { + int minX = (int) Math.min(pos1.x(), pos2.x()); + int minY = (int) Math.min(pos1.y(), pos2.y()); + int minZ = (int) Math.min(pos1.z(), pos2.z()); + + int maxX = (int) Math.max(pos1.x(), pos2.x()); + int maxY = (int) Math.max(pos1.y(), pos2.y()); + int maxZ = (int) Math.max(pos1.z(), pos2.z()); + + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + Point blockPos = new Pos(x, y, z); + if (x == minX || x == maxX || y == minY || y == maxY || z == minZ || z == maxZ) { + outline.accept(blockPos); + } + } + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/Intersect.java b/src/main/java/eu/mhsl/minenet/minigames/util/Intersect.java index 8327b2d..a3e9cb3 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/util/Intersect.java +++ b/src/main/java/eu/mhsl/minenet/minigames/util/Intersect.java @@ -1,6 +1,6 @@ package eu.mhsl.minenet.minigames.util; -import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.world.BlockPallet; import net.minestom.server.coordinate.Pos; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/InventoryUtil.java b/src/main/java/eu/mhsl/minenet/minigames/util/InventoryUtil.java new file mode 100644 index 0000000..b47f1a3 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/util/InventoryUtil.java @@ -0,0 +1,24 @@ +package eu.mhsl.minenet.minigames.util; + +import net.minestom.server.entity.Player; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; + +public class InventoryUtil { + public static void removeItemFromPlayer(Player player, Material material, int amount) { + ItemStack[] items = player.getInventory().getItemStacks(); + for (int i = 0; i < items.length; i++) { + ItemStack item = items[i]; + if (item.material() != material) continue; + + int stackSize = item.amount(); + if (stackSize < amount) { + amount -= stackSize; + player.getInventory().setItemStack(i, ItemStack.AIR); + } else { + player.getInventory().setItemStack(i, item.withAmount(stackSize - amount)); + break; + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/NumberUtil.java b/src/main/java/eu/mhsl/minenet/minigames/util/NumberUtil.java new file mode 100644 index 0000000..714a144 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/util/NumberUtil.java @@ -0,0 +1,17 @@ +package eu.mhsl.minenet.minigames.util; + +public class NumberUtil { + public static double map(double oldValue, double oldMin, double oldMax, double newMin, double newMax) { + double out = (((oldValue - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin; + if(out > newMax) out = newMax; + if(out < newMin) out = newMin; + + return out; + } + + public static > T clamp(T val, T min, T max) { + if (val.compareTo(min) < 0) return min; + else if (val.compareTo(max) > 0) return max; + else return val; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/Position.java b/src/main/java/eu/mhsl/minenet/minigames/util/Position.java index ab9bd02..4dd189f 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/util/Position.java +++ b/src/main/java/eu/mhsl/minenet/minigames/util/Position.java @@ -1,8 +1,14 @@ package eu.mhsl.minenet.minigames.util; +import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.Instance; +import net.minestom.server.instance.block.Block; +import java.util.ArrayList; import java.util.InputMismatchException; +import java.util.List; public class Position { public static final double PIXEL = 0.0625; @@ -23,4 +29,13 @@ public class Position { return new Pos(x, y, z); } + + public static List blocksBelowPlayer(Instance instance, Player p) { + Point playerPos = p.getPosition(); + List blocks = new ArrayList<>(); + GeneratorUtils.foreachXZ(playerPos.sub(0.5, 1, 0.5), playerPos.add(0.5, -1, 0.5), point -> { + blocks.add(instance.getBlock(point)); + }); + return blocks.stream().distinct().toList(); + } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/RangeMap.java b/src/main/java/eu/mhsl/minenet/minigames/util/RangeMap.java deleted file mode 100644 index b793f83..0000000 --- a/src/main/java/eu/mhsl/minenet/minigames/util/RangeMap.java +++ /dev/null @@ -1,11 +0,0 @@ -package eu.mhsl.minenet.minigames.util; - -public class RangeMap { - public static long map(double oldValue, double oldMin, double oldMax, double newMin, double newMax) { - double out = (((oldValue - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin; - if(out > newMax) out = newMax; - if(out < newMin) out = newMin; - - return (long) out; - } -} diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/SingleExecution.java b/src/main/java/eu/mhsl/minenet/minigames/util/SingleExecution.java new file mode 100644 index 0000000..db78c4f --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/util/SingleExecution.java @@ -0,0 +1,19 @@ +package eu.mhsl.minenet.minigames.util; + +public class SingleExecution { + public static SingleExecution make() { + return new SingleExecution(); + } + + private boolean wasExecuted = false; + + public void reset() { + this.wasExecuted = false; + } + + public void singleRun(Runnable task) { + if(wasExecuted) return; + task.run(); + this.wasExecuted = true; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java b/src/main/java/eu/mhsl/minenet/minigames/world/BlockPallet.java similarity index 96% rename from src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java rename to src/main/java/eu/mhsl/minenet/minigames/world/BlockPallet.java index c3ee1e4..72bbc3a 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/BlockPallet.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/BlockPallet.java @@ -1,4 +1,4 @@ -package eu.mhsl.minenet.minigames.world.generator; +package eu.mhsl.minenet.minigames.world; import net.minestom.server.instance.block.Block; diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlaneGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlaneGenerator.java deleted file mode 100644 index 5ff4599..0000000 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlaneGenerator.java +++ /dev/null @@ -1,15 +0,0 @@ -package eu.mhsl.minenet.minigames.world.generator; - -import net.minestom.server.instance.block.Block; -import net.minestom.server.instance.generator.GenerationUnit; -import net.minestom.server.instance.generator.Generator; -import org.jetbrains.annotations.NotNull; - -public class PlaneGenerator implements Generator { - @Override - public void generate(@NotNull GenerationUnit unit) { - unit.modifier() - .fillHeight(0, 5, Block.STONE); - - } -} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlateTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlateTerrainGenerator.java index a0db1a5..2e265b2 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlateTerrainGenerator.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/PlateTerrainGenerator.java @@ -1,5 +1,6 @@ package eu.mhsl.minenet.minigames.world.generator; +import eu.mhsl.minenet.minigames.world.BlockPallet; import net.minestom.server.instance.generator.Generator; public abstract class PlateTerrainGenerator implements Generator { diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/featureEnriched/CircularPlateGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/featureEnriched/CircularPlateGenerator.java new file mode 100644 index 0000000..a838212 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/featureEnriched/CircularPlateGenerator.java @@ -0,0 +1,60 @@ +package eu.mhsl.minenet.minigames.world.generator.featureEnriched; + +import eu.mhsl.minenet.minigames.util.GeneratorUtils; +import eu.mhsl.minenet.minigames.util.SingleExecution; +import eu.mhsl.minenet.minigames.world.BlockPallet; +import eu.mhsl.minenet.minigames.world.generator.terrain.HeightTerrainGenerator; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; +import org.jetbrains.annotations.NotNull; + +public class CircularPlateGenerator extends HeightTerrainGenerator { + private final SingleExecution execution = SingleExecution.make(); + private final int radius; + private final int height; + private BlockPallet blockPallet = BlockPallet.GROUND; + + private int centerX = 0; + private int centerZ = 0; + + private boolean generated = false; + + public CircularPlateGenerator(int radius, int height) { + setCalculateHeight(point -> (int) ((point.distance(new Pos(0, point.y(), 0)) / 2) - radius)); + this.radius = radius; + this.height = height; + } + + public CircularPlateGenerator setBlockPallet(BlockPallet pallet) { + this.blockPallet = pallet; + return this; + } + + public CircularPlateGenerator setCenter(int x, int z) { + this.centerX = x; + this.centerZ = z; + return this; + } + + @Override + public void generate(@NotNull GenerationUnit unit) { + execution.singleRun(() -> unit.fork(setter -> { + System.out.println(new Pos(-(radius + centerX), unit.absoluteStart().y(), -(radius + centerZ))); + System.out.println(new Pos(radius + centerX, height, radius + centerZ)); + GeneratorUtils.foreachXZ( + new Pos(-(radius + centerX), unit.absoluteStart().y(), -(radius + centerZ)), + new Pos(radius + centerX, height, radius + centerZ), + point -> { + double distance = point.distance(new Pos(centerX, point.y(), centerZ)); + + if(distance <= this.radius) { + setter.setBlock(point.add(1, height, 1), Block.GOLD_BLOCK); + } + } + ); + })); + + super.generate(unit); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/featureEnriched/ValeGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/featureEnriched/ValeGenerator.java new file mode 100644 index 0000000..6ece504 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/featureEnriched/ValeGenerator.java @@ -0,0 +1,41 @@ +package eu.mhsl.minenet.minigames.world.generator.featureEnriched; + +import de.articdive.jnoise.JNoise; +import eu.mhsl.minenet.minigames.util.NumberUtil; +import eu.mhsl.minenet.minigames.world.generator.terrain.HeightTerrainGenerator; +import net.minestom.server.coordinate.Point; + +import java.util.function.Function; + +public class ValeGenerator extends HeightTerrainGenerator { + private final JNoise curves = JNoise.newBuilder() + .fastSimplex() + .setSeed(rnd.nextLong()) + .setFrequency(0.01) + .build(); + + private final JNoise largeCurves = JNoise.newBuilder() + .fastSimplex() + .setSeed(rnd.nextLong()) + .setFrequency(0.001) + .build(); + + private Function xShiftMultiplier = multiplier -> 1d; + + public ValeGenerator() { + setCalculateHeight(this::calculateY); + setHeightNoiseMultiplier(point -> (int) NumberUtil.map(calculateY(point), -64, 100, 0, 16)); + } + + private int calculateY(Point point) { + return (int) (Math.abs(point.blockX() - getXShiftAtZ(point.blockZ())) / 1.5); + } + + public int getXShiftAtZ(int z) { + return (int) ((curves.getNoise(z) * 32 + largeCurves.getNoise(z) * 64) * xShiftMultiplier.apply(z)); + } + + public void setXShiftMultiplier(Function xShiftMultiplier) { + this.xShiftMultiplier = xShiftMultiplier; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/PeakRock.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/PeakRock.java index c453f60..8fe0130 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/PeakRock.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/PeakRock.java @@ -1,6 +1,6 @@ package eu.mhsl.minenet.minigames.world.generator.structures.generatable; -import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.structures.Structure; import net.minestom.server.coordinate.Point; import net.minestom.server.instance.block.Block; diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/Tree.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/Tree.java index c8e5ff5..2196b76 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/Tree.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/structures/generatable/Tree.java @@ -13,6 +13,27 @@ public class Tree extends Structure { @Override public void generateStructure(Block.Setter setter) { + int trunkX = position.blockX(); + int trunkBottomY = position.blockY(); + int trunkZ = position.blockZ(); + for (int i = 0; i < 2; i++) { + setter.setBlock(trunkX + 1, trunkBottomY + 3 + i, trunkZ, Block.OAK_LEAVES); + setter.setBlock(trunkX - 1, trunkBottomY + 3 + i, trunkZ, Block.OAK_LEAVES); + setter.setBlock(trunkX, trunkBottomY + 3 + i, trunkZ + 1, Block.OAK_LEAVES); + setter.setBlock(trunkX, trunkBottomY + 3 + i, trunkZ - 1, Block.OAK_LEAVES); + + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + setter.setBlock(trunkX + x, trunkBottomY + 2 + i, trunkZ - z, Block.OAK_LEAVES); + } + } + } + + setter.setBlock(trunkX, trunkBottomY, trunkZ, Block.OAK_LOG); + setter.setBlock(trunkX, trunkBottomY + 1, trunkZ, Block.OAK_LOG); + setter.setBlock(trunkX, trunkBottomY + 2, trunkZ, Block.OAK_LOG); + setter.setBlock(trunkX, trunkBottomY + 3, trunkZ, Block.OAK_LOG); + setter.setBlock(trunkX, trunkBottomY + 4, trunkZ, Block.OAK_LEAVES); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/BaseGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/BaseGenerator.java new file mode 100644 index 0000000..a5348a9 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/BaseGenerator.java @@ -0,0 +1,32 @@ +package eu.mhsl.minenet.minigames.world.generator.terrain; + +import eu.mhsl.minenet.minigames.world.generator.structures.Structure; +import net.minestom.server.instance.generator.GenerationUnit; +import net.minestom.server.instance.generator.Generator; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseGenerator implements Generator { + private final List structures = new ArrayList<>(); + private final List mixIns = new ArrayList<>(); + + public void addStructure(Structure structure) { + this.structures.add(structure); + } + + public void addMixIn(Generator mixIn) { + this.mixIns.add(mixIn); + } + + protected void applyStructures(GenerationUnit unit) { + structures.forEach(structure -> unit.fork(structure::generateStructure)); + } + + + @Override + public void generate(@NotNull GenerationUnit unit) { + mixIns.forEach(generator -> generator.generate(unit)); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/CircularPlateTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/CircularPlateTerrainGenerator.java index f0b44bf..6f97ba5 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/CircularPlateTerrainGenerator.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/CircularPlateTerrainGenerator.java @@ -1,8 +1,8 @@ package eu.mhsl.minenet.minigames.world.generator.terrain; import de.articdive.jnoise.JNoise; -import eu.mhsl.minenet.minigames.util.RangeMap; -import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.util.NumberUtil; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.PlateTerrainGenerator; import eu.mhsl.minenet.minigames.world.generator.structures.generatable.PeakRock; import net.minestom.server.coordinate.Point; @@ -61,7 +61,7 @@ public class CircularPlateTerrainGenerator extends PlateTerrainGenerator { synchronized (base) { double baseNoise = base.getNoise(bottom.x(), bottom.z()); - double currentHeight = minTwo(RangeMap.map(distance, 0, 400, -((double) this.size / 5), 200)) + baseNoise * 8; + double currentHeight = minTwo(NumberUtil.map(distance, 0, 400, -((double) this.size / 5), 200)) + baseNoise * 8; synchronized (batches) { double elementNoise = batches.getNoise(bottom.x(), bottom.z()); diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/FlatTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/FlatTerrainGenerator.java new file mode 100644 index 0000000..07bde3f --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/FlatTerrainGenerator.java @@ -0,0 +1,26 @@ +package eu.mhsl.minenet.minigames.world.generator.terrain; + +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; +import net.minestom.server.instance.generator.Generator; +import org.jetbrains.annotations.NotNull; + +public class FlatTerrainGenerator implements Generator { + private final int height; + private final Block block; + + public FlatTerrainGenerator(int height, Block block) { + this.height = height; + this.block = block; + } + + FlatTerrainGenerator() { + this.height = 5; + this.block = Block.GRASS_BLOCK; + } + + @Override + public void generate(@NotNull GenerationUnit unit) { + unit.modifier().fillHeight(0, height, block); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/HeightTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/HeightTerrainGenerator.java new file mode 100644 index 0000000..362d3fe --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/HeightTerrainGenerator.java @@ -0,0 +1,97 @@ +package eu.mhsl.minenet.minigames.world.generator.terrain; + +import de.articdive.jnoise.JNoise; +import eu.mhsl.minenet.minigames.util.GeneratorUtils; +import eu.mhsl.minenet.minigames.util.NumberUtil; +import eu.mhsl.minenet.minigames.world.BlockPallet; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Random; +import java.util.function.Function; + +public class HeightTerrainGenerator extends BaseGenerator { + protected final Random rnd = new Random(); + private Function calculateHeight = (Point) -> 0; + protected Function heightNoiseMultiplier = (Point) -> 16; + protected Function calculateSeaLevel = null; + + private final JNoise base = JNoise.newBuilder() + .fastSimplex() + .setSeed(rnd.nextLong()) + .setFrequency(0.01) + .build(); + + private final JNoise batches = JNoise.newBuilder() + .fastSimplex() + .setSeed(rnd.nextLong()) + .setFrequency(0.05) + .build(); + + private final JNoise peaks = JNoise.newBuilder() + .fastSimplex() + .setSeed(rnd.nextLong()) + .setFrequency(0.1) + .build(); + + private final BlockPallet blockPallet = BlockPallet.STONE; + + @Override + public void generate(@NotNull GenerationUnit unit) { + super.generate(unit); + GeneratorUtils.foreachXZ(unit, bottomPoint -> { + unit.modifier().setBlock(bottomPoint, blockPallet.rnd()); + + synchronized (base) { + double heightNoise = base.getNoise(bottomPoint.x(), bottomPoint.z()); + double noiseModifier = heightNoise * heightNoiseMultiplier.apply(bottomPoint); + double heightModifier = NumberUtil.clamp(calculateHeight.apply(bottomPoint) + noiseModifier, 1d, unit.size().y()); + if(heightModifier < 1) System.out.println("HEIGHT MODIFIER ILLEGAL"); + + synchronized (batches) { + double batchNoise = batches.getNoise(bottomPoint.x(), bottomPoint.z()); + + unit.modifier().fill(bottomPoint, bottomPoint.add(1, heightModifier, 1), batchNoise < 0.9 ? batchNoise > 0 ? Block.GRASS_BLOCK : Block.SOUL_SAND : Block.STONE); + + if(calculateSeaLevel != null) { + Point absoluteHeight = bottomPoint.add(0, heightModifier, 0); + int seaLevel = calculateSeaLevel.apply(bottomPoint); + if(absoluteHeight.y() < seaLevel) { +// System.out.println("HM:" + absoluteHeight.y() + " SL:" + seaLevel); +// System.out.println("Filling from " + bottomPoint.y() + " to " + absoluteHeight.withY(seaLevel).y()); + unit.modifier().fill(bottomPoint.withY(v -> v+heightModifier), absoluteHeight.add(1, 0, 1).withY(seaLevel), Block.WATER); + } + } + } + + synchronized (peaks) { + double peakNoise = peaks.getNoise(bottomPoint.x(), bottomPoint.z()); + + if(peakNoise > 0.97 && bottomPoint.distance(new Pos(0, 0, 0)) > (50 + 20)) { + + Point center = bottomPoint.add(1, heightModifier, 1); +// unit.fork(setter -> new PeakRock(center, BlockPallet.STONE).generateStructure(setter)); + +// unit.fork(setter -> new Tree(center).generateStructure(setter)); + } + } + } + }); + } + + public void setCalculateHeight(Function calculateHeight) { + this.calculateHeight = calculateHeight; + } + + public void setHeightNoiseMultiplier(Function heightNoiseMultiplier) { + this.heightNoiseMultiplier = heightNoiseMultiplier; + } + + public void setCalculateSeaLevel(@Nullable Function calculateSeaLevel) { + this.calculateSeaLevel = calculateSeaLevel; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/PlaneTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/PlaneTerrainGenerator.java new file mode 100644 index 0000000..9694799 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/PlaneTerrainGenerator.java @@ -0,0 +1,26 @@ +package eu.mhsl.minenet.minigames.world.generator.terrain; + +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; +import net.minestom.server.instance.generator.Generator; +import org.jetbrains.annotations.NotNull; + +public class PlaneTerrainGenerator implements Generator { + private final int height; + private final Block block; + + public PlaneTerrainGenerator(int height, Block block) { + this.height = height; + this.block = block; + } + + PlaneTerrainGenerator() { + this.height = 5; + this.block = Block.GRASS_BLOCK; + } + + @Override + public void generate(@NotNull GenerationUnit unit) { + unit.modifier().fillHeight(height-1, height, block); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquarePlateTerrainGenerator.java b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquarePlateTerrainGenerator.java index ed6414f..2ca083b 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquarePlateTerrainGenerator.java +++ b/src/main/java/eu/mhsl/minenet/minigames/world/generator/terrain/SquarePlateTerrainGenerator.java @@ -1,8 +1,8 @@ package eu.mhsl.minenet.minigames.world.generator.terrain; import de.articdive.jnoise.JNoise; -import eu.mhsl.minenet.minigames.util.RangeMap; -import eu.mhsl.minenet.minigames.world.generator.BlockPallet; +import eu.mhsl.minenet.minigames.util.NumberUtil; +import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.PlateTerrainGenerator; import eu.mhsl.minenet.minigames.world.generator.structures.generatable.PeakRock; import net.minestom.server.coordinate.Point; @@ -84,10 +84,10 @@ public class SquarePlateTerrainGenerator extends PlateTerrainGenerator { synchronized (base) { double baseNoise = base.getNoise(bottom.x(), bottom.z()); 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 + minTwo(NumberUtil.map(bottom.distance(new Pos(0, 0, 0)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, + minTwo(NumberUtil.map(bottom.distance(new Pos(width, 0, 0)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, + minTwo(NumberUtil.map(bottom.distance(new Pos(0, 0, length)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, + minTwo(NumberUtil.map(bottom.distance(new Pos(width, 0, length)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8 }; double currentHeight = Arrays.stream(possibleHeights).min().getAsDouble(); diff --git a/src/main/resources/maps/lobby/region/r.-1.-1.mca b/src/main/resources/maps/lobby/region/r.-1.-1.mca index decb6ba..c2ab205 100644 Binary files a/src/main/resources/maps/lobby/region/r.-1.-1.mca and b/src/main/resources/maps/lobby/region/r.-1.-1.mca differ diff --git a/src/main/resources/maps/lobby/region/r.-1.0.mca b/src/main/resources/maps/lobby/region/r.-1.0.mca index 8ec79aa..4f3d1a9 100644 Binary files a/src/main/resources/maps/lobby/region/r.-1.0.mca and b/src/main/resources/maps/lobby/region/r.-1.0.mca differ diff --git a/src/main/resources/maps/lobby/region/r.0.-1.mca b/src/main/resources/maps/lobby/region/r.0.-1.mca index 139a2b1..ca9ce8c 100644 Binary files a/src/main/resources/maps/lobby/region/r.0.-1.mca and b/src/main/resources/maps/lobby/region/r.0.-1.mca differ diff --git a/src/main/resources/maps/lobby/region/r.0.0.mca b/src/main/resources/maps/lobby/region/r.0.0.mca index 41b3321..bbed565 100644 Binary files a/src/main/resources/maps/lobby/region/r.0.0.mca and b/src/main/resources/maps/lobby/region/r.0.0.mca differ