diff --git a/.idea/misc.xml b/.idea/misc.xml index 03872dd..0a6f7f2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5613c8c..a216060 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'java' - id "com.github.johnrengelman.shadow" version "7.1.0" + id "com.gradleup.shadow" version "9.6.0" } group 'eu.mhsl.minenet' @@ -11,58 +11,33 @@ version '1.0-SNAPSHOT' repositories { mavenCentral() - google() - - maven { - url 'https://jitpack.io' - } - - maven { - url "https://repo.unnamed.team/repository/unnamed-public/" - } - - maven { - url 'https://oss.sonatype.org/content/repositories/snapshots' - } } -allprojects { - repositories { - maven { url "https://jitpack.io" } - } -} - - java { toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) } } dependencies { - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' + testImplementation 'org.junit.jupiter:junit-jupiter:6.1.2' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - //https://jitpack.io/#Minestom/Minestom - implementation 'net.minestom:minestom-snapshots:fd51c8d17a' + //https://mvnrepository.com/artifact/net.minestom/minestom + implementation 'net.minestom:minestom:2026.07.12-26.2' //Tools - implementation 'de.articdive:jnoise:3.0.2' + implementation 'de.articdive:jnoise-pipeline:4.1.0' + compileOnly 'it.unimi.dsi:fastutil:8.5.18' // von Minestom nur zur Laufzeit bereitgestellt, fuer BatchUtil-Reflection benoetigt implementation 'net.md-5:bungeecord-config:1.21-R0.3' - implementation 'org.apache.commons:commons-text:1.10.0' - implementation 'org.spongepowered:configurate-yaml:4.1.2' + implementation 'org.apache.commons:commons-text:1.15.0' + implementation 'org.spongepowered:configurate-yaml:4.2.0' implementation 'com.sparkjava:spark-core:2.9.4' - implementation 'com.google.code.gson:gson:2.10.1' - implementation 'com.google.guava:guava:32.0.1-android' - + implementation 'com.google.code.gson:gson:2.14.0' + implementation 'com.google.guava:guava:33.4.8-jre' //PvP - implementation 'io.github.TogAr2:MinestomPvP:PR62-SNAPSHOT' - - // Hephaestus engine -// implementation("team.unnamed:hephaestus-api:0.2.1-SNAPSHOT") -// implementation("team.unnamed:hephaestus-reader-blockbench:0.2.1-SNAPSHOT") -// implementation("team.unnamed:hephaestus-runtime-minestom:0.2.1-SNAPSHOT") + implementation 'io.github.togar2:MinestomPvP:2026.05.30-26.1.1' } tasks { @@ -71,8 +46,6 @@ tasks { attributes 'Main-Class': 'eu.mhsl.minenet.minigames.Main' attributes 'Multi-Release': true } - duplicatesStrategy = 'exclude' - from configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } } build { dependsOn(shadowJar) @@ -89,3 +62,7 @@ tasks.register('copyJarToServer', Exec) { commandLine 'scp', 'build/libs/Minigames-1.0-SNAPSHOT.jar', 'root@10.20.6.5:/root/minigames' } + +tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:deprecation" +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9..b1b8ef5 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b41..a9db115 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index f5feea6..249efbb 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..a51ec4f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,30 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/src/main/java/eu/mhsl/minenet/minigames/Main.java b/src/main/java/eu/mhsl/minenet/minigames/Main.java index 6ed8de0..5d147fc 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/Main.java +++ b/src/main/java/eu/mhsl/minenet/minigames/Main.java @@ -3,12 +3,12 @@ package eu.mhsl.minenet.minigames; import eu.mhsl.minenet.minigames.api.HttpServer; import eu.mhsl.minenet.minigames.command.Commands; import eu.mhsl.minenet.minigames.handler.Listeners; +import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.lang.Languages; import eu.mhsl.minenet.minigames.server.tasks.TablistUpdateTask; +import net.minestom.server.Auth; import net.minestom.server.MinecraftServer; -import net.minestom.server.extras.bungee.BungeeCordProxy; import net.minestom.server.extras.lan.OpenToLAN; -import net.minestom.server.extras.velocity.VelocityProxy; import net.minestom.server.timer.TaskSchedule; import org.spongepowered.configurate.ConfigurateException; import org.spongepowered.configurate.ConfigurationNode; @@ -25,7 +25,7 @@ public class Main { public static ConfigurationNode globalConfig; @SuppressWarnings("ResultOfMethodCallIgnored") - public static void main(String[] args) throws ConfigurateException { + static void main(String[] args) throws ConfigurateException { //noinspection ResultOfMethodCallIgnored Resource.values(); // This initializes and preloads the enum and extracts the resources Languages.getInstance(); //Preload languages into the jvm @@ -38,14 +38,31 @@ public class Main { ConfigurationNode serverConfig = globalConfig.node("server"); + // muss vor MinecraftServer.init() gesetzt werden: ServerFlag liest die Properties statisch beim Klassenladen; + // bei fehlendem/ungueltigem Config-Wert den Minestom-Default behalten (0 wuerde keine Chunks senden) + int viewDistance = serverConfig.node("view-distance").getInt(0); + if(viewDistance > 0) { + System.setProperty("minestom.chunk-view-distance", String.valueOf(viewDistance)); + } + logger.info("Initialize Minecraft server..."); - MinecraftServer server = MinecraftServer.init(); + Auth auth = new Auth.Offline(); + if(globalConfig.node("bungeecord", "enabled").getBoolean()) { + auth = new Auth.Bungee(); + } else if(globalConfig.node("velocity", "enabled").getBoolean()) { + auth = new Auth.Velocity(Objects.requireNonNull(globalConfig.node("velocity", "secret").getString())); + } + + MinecraftServer server = MinecraftServer.init(auth); // MinestomPvP.init(); + // Dimensionen muessen vor server.start() registriert werden: + // seit Minestom 26.x sind die dynamischen Registries nach dem Start eingefroren + Dimension.values(); + MinecraftServer.setBrandName("mhsl.eu - minenet - credits to minestom"); MinecraftServer.setCompressionThreshold(serverConfig.node("compression-threshold").getInt(0)); - System.setProperty("minestom.chunk-view-distance", String.valueOf(serverConfig.node("view-distance").getInt())); Commands.values(); Listeners.values(); @@ -57,12 +74,6 @@ public class Main { if(serverConfig.node("open-to-lan").getBoolean()) OpenToLAN.open(); - if(globalConfig.node("bungeecord", "enabled").getBoolean()) BungeeCordProxy.enable(); - - if(globalConfig.node("velocity", "enabled").getBoolean()) { - VelocityProxy.enable(Objects.requireNonNull(globalConfig.node("velocity", "secret").getString())); - } - server.start("0.0.0.0", serverConfig.node("port").getInt(25565)); System.gc(); diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java index 7724d7e..2592123 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java @@ -35,7 +35,7 @@ public class SetMemorialCommand extends PrivilegedCommand { .getTournament() .setMemorialConfiguration( new MemorialConfiguration( - Material.fromNamespaceId(context.get(materialArgument)), + Material.fromKey(context.get(materialArgument)), context.get(titleArgument), context.get(loreArgument) ) diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java index 3e058e5..52e2396 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java @@ -37,7 +37,7 @@ public class SetRewardCommand extends PrivilegedCommand { .getTournament() .setRewardConfiguration( new RewardConfiguration( - Material.fromNamespaceId(context.get(materialArgument)), + Material.fromKey(context.get(materialArgument)), Arrays.stream(context.get(amountsArgument)).map(Integer::valueOf).collect(Collectors.toList()) ) ); 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 fbeba80..5590cc2 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.ChatFormatHandler; +import eu.mhsl.minenet.minigames.handler.global.PlayerFreezeHandler; import eu.mhsl.minenet.minigames.handler.global.PlayerLeaveHandler; import eu.mhsl.minenet.minigames.handler.global.PlayerLoginHandler; import net.minestom.server.MinecraftServer; @@ -11,6 +12,7 @@ public enum Listeners { SPAWN(new AddEntityToInstanceEventListener()), LOGIN(new PlayerLoginHandler()), LEAVE(new PlayerLeaveHandler()), + FREEZE(new PlayerFreezeHandler()), CHAT(new ChatFormatHandler()); Listeners(EventListener event) { diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerFreezeHandler.java b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerFreezeHandler.java new file mode 100644 index 0000000..8845d89 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerFreezeHandler.java @@ -0,0 +1,43 @@ +package eu.mhsl.minenet.minigames.handler.global; + +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.event.EventListener; +import net.minestom.server.event.player.PlayerTickEvent; +import net.minestom.server.instance.Instance; +import net.minestom.server.instance.block.Block; +import org.jetbrains.annotations.NotNull; + +/** + * Weder Minestom noch MinestomPvP verwalten die TICKS_FROZEN-Metadata. Der 26.x-Client baut das + * Freeze-Overlay bei Powder-Snow-Kontakt zwar selbst auf, der Abbau ist aber server-authoritative — + * ohne diese Vanilla-Logik bleibt das Overlay dauerhaft haengen (auch ueber Instanzwechsel hinweg). + */ +public class PlayerFreezeHandler implements EventListener { + private static final int TICKS_REQUIRED_TO_FREEZE = 140; + + @Override + public @NotNull Class eventType() { + return PlayerTickEvent.class; + } + + @Override + public @NotNull Result run(@NotNull PlayerTickEvent event) { + Player p = event.getPlayer(); + Instance instance = p.getInstance(); + if(instance == null) return Result.SUCCESS; + + Pos pos = p.getPosition(); + boolean inPowderSnow = instance.getBlock(pos).compare(Block.POWDER_SNOW) + || instance.getBlock(pos.add(0, 1, 0)).compare(Block.POWDER_SNOW); + + int ticksFrozen = p.getEntityMeta().getTickFrozen(); + if(inPowderSnow) { + p.getEntityMeta().setTickFrozen(Math.min(TICKS_REQUIRED_TO_FREEZE, ticksFrozen + 1)); + } else if(ticksFrozen > 0) { + p.getEntityMeta().setTickFrozen(Math.max(0, ticksFrozen - 2)); + } + + return Result.SUCCESS; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/Dimension.java b/src/main/java/eu/mhsl/minenet/minigames/instance/Dimension.java index cf5085c..1741355 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/Dimension.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/Dimension.java @@ -1,45 +1,66 @@ package eu.mhsl.minenet.minigames.instance; +import net.kyori.adventure.key.Key; import net.minestom.server.MinecraftServer; -import net.minestom.server.registry.DynamicRegistry; -import net.minestom.server.utils.NamespaceID; +import net.minestom.server.registry.RegistryKey; +import net.minestom.server.registry.RegistryTag; +import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.world.DimensionType; +import net.minestom.server.world.attribute.EnvironmentAttribute; +import net.minestom.server.world.clock.WorldClock; +import net.minestom.server.world.timeline.Timeline; /** * Prebuilt dimensions */ public enum Dimension { OVERWORLD( - NamespaceID.from("minenet:fullbright_overworld"), + Key.key("minenet:fullbright_overworld"), DimensionType .builder() - .ambientLight(2.0f) + // Fullbright: seit MC 26.1 laeuft die Grundhelligkeit ueber das Environment-Attribut + // AMBIENT_LIGHT_COLOR (Vanilla-Overworld: #0A0A0A); der alte ambientLight-2.0-Hack + // liegt ausserhalb der validen Range und bricht das Client-Rendering + .setAttribute(EnvironmentAttribute.AMBIENT_LIGHT_COLOR, NamedTextColor.WHITE) + // defaultClock noetig, damit Instance#setTime/#defaultClock funktionieren (sonst null); Timelines wie Vanilla-Overworld + .defaultClock(WorldClock.OVERWORLD) + .timelines(RegistryTag.direct(Timeline.DAY, Timeline.MOON, Timeline.EARLY_GAME, Timeline.VILLAGER_SCHEDULE)) .build() ), NETHER( - NamespaceID.from("minenet:fullbright_nether"), + Key.key("minenet:fullbright_nether"), DimensionType .builder() - .ambientLight(2.0f) - .effects("minecraft:the_nether") + // Fullbright: seit MC 26.1 laeuft die Grundhelligkeit ueber das Environment-Attribut + // AMBIENT_LIGHT_COLOR (Vanilla-Overworld: #0A0A0A); der alte ambientLight-2.0-Hack + // liegt ausserhalb der validen Range und bricht das Client-Rendering + .setAttribute(EnvironmentAttribute.AMBIENT_LIGHT_COLOR, NamedTextColor.WHITE) + .skybox(DimensionType.Skybox.NONE) + .defaultClock(WorldClock.OVERWORLD) + .timelines(RegistryTag.direct(Timeline.VILLAGER_SCHEDULE)) .build() ), THE_END( - NamespaceID.from("minenet:fullbright_end"), + Key.key("minenet:fullbright_end"), DimensionType .builder() - .ambientLight(2.0f) - .effects("minecraft:the_end") + // Fullbright: seit MC 26.1 laeuft die Grundhelligkeit ueber das Environment-Attribut + // AMBIENT_LIGHT_COLOR (Vanilla-Overworld: #0A0A0A); der alte ambientLight-2.0-Hack + // liegt ausserhalb der validen Range und bricht das Client-Rendering + .setAttribute(EnvironmentAttribute.AMBIENT_LIGHT_COLOR, NamedTextColor.WHITE) + .skybox(DimensionType.Skybox.END) + .defaultClock(WorldClock.THE_END) + .timelines(RegistryTag.direct(Timeline.VILLAGER_SCHEDULE)) .build() ); public final DimensionType DIMENSION; - public final NamespaceID namespaceID; - public final DynamicRegistry.Key key; + public final Key namespaceID; + public final RegistryKey key; - Dimension(NamespaceID namespaceID, DimensionType dimType) { + Dimension(Key namespaceID, DimensionType dimType) { this.DIMENSION = dimType; this.namespaceID = namespaceID; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/MineNetInstance.java b/src/main/java/eu/mhsl/minenet/minigames/instance/MineNetInstance.java index 45a47c6..7900dad 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/MineNetInstance.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/MineNetInstance.java @@ -1,21 +1,29 @@ package eu.mhsl.minenet.minigames.instance; import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import net.kyori.adventure.key.Key; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.event.instance.AddEntityToInstanceEvent; import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent; import net.minestom.server.instance.Instance; import net.minestom.server.instance.InstanceContainer; -import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.RegistryKey; import net.minestom.server.timer.TaskSchedule; import net.minestom.server.world.DimensionType; import java.util.UUID; public class MineNetInstance extends InstanceContainer { - public MineNetInstance(DynamicRegistry.Key type) { - super(UUID.randomUUID(), type); + public MineNetInstance(RegistryKey type) { + this(UUID.randomUUID(), type); + } + + // Eindeutiger Dimension-Name pro Instanz: Minestom entscheidet anhand dieses Namens (nicht des + // DimensionTypes), ob beim setInstance das volle Respawn-Protokoll gefahren wird. Ohne den Reset + // rendert der 26.x-Client nach einem Wechsel zwischen Instanzen gleicher Dimension keine Chunks. + private MineNetInstance(UUID uuid, RegistryKey type) { + super(uuid, type, Key.key("minenet", "instance-" + uuid)); MinecraftServer.getInstanceManager().registerInstance(this); this.eventNode() 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 1a9581a..eb62945 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 @@ -16,7 +16,7 @@ import net.minestom.server.event.item.ItemDropEvent; import net.minestom.server.event.player.PlayerBlockBreakEvent; import net.minestom.server.event.player.PlayerBlockPlaceEvent; import net.minestom.server.event.player.PlayerMoveEvent; -import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.RegistryKey; import net.minestom.server.timer.ExecutionType; import net.minestom.server.timer.TaskSchedule; import net.minestom.server.world.DimensionType; @@ -34,7 +34,7 @@ public abstract class Game extends MineNetInstance implements Spawnable { protected boolean isRunning = false; protected boolean isBeforeBeginning = true; - public Game(DynamicRegistry.Key dimensionType) { + public Game(RegistryKey dimensionType) { super(dimensionType); MinecraftServer.getInstanceManager().registerInstance(this); 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 d160948..504a143 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 @@ -17,6 +17,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.highGround.HighGr import eu.mhsl.minenet.minigames.instance.game.stateless.types.jumpDive.JumpDiveFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.minerun.MinerunFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.pillars.PillarsFactory; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.PlayerRaceFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.spaceSnake.SpaceSnakeFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.spleef.SpleefFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.stickfight.StickFightFactory; @@ -52,7 +53,8 @@ public enum GameList { BOATRACE(new BoatRaceFactory(), GameType.OTHER), PILLARS(new PillarsFactory(), GameType.PROTOTYPE), BLOCKBATTLE(new BlockBattleFactory(), GameType.PVP), - COLORJUMP(new ColorJumpFactory(), GameType.JUMPNRUN); + COLORJUMP(new ColorJumpFactory(), GameType.JUMPNRUN), + PLAYERRACE(new PlayerRaceFactory(), GameType.JUMPNRUN); private final GameFactory factory; private final GameType type; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java index 846d143..566701a 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java @@ -9,7 +9,7 @@ import eu.mhsl.minenet.minigames.score.Score; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.RegistryKey; import net.minestom.server.timer.ExecutionType; import net.minestom.server.timer.Task; import net.minestom.server.timer.TaskSchedule; @@ -26,7 +26,7 @@ public class StatelessGame extends Game { private int timeLimit = 0; private int timePlayed = 0; - public StatelessGame(DynamicRegistry.Key dimensionType, String gameName, Score score) { + public StatelessGame(RegistryKey dimensionType, String gameName, Score score) { super(dimensionType); this.score = score; this.name = gameName; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/config/GameConfigurationInventory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/config/GameConfigurationInventory.java index 5f8d0c3..590926c 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/config/GameConfigurationInventory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/config/GameConfigurationInventory.java @@ -14,9 +14,9 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.event.instance.AddEntityToInstanceEvent; import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent; +import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.inventory.click.ClickType; -import net.minestom.server.inventory.condition.InventoryConditionResult; +import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.sound.SoundEvent; @@ -106,8 +106,8 @@ public class GameConfigurationInventory extends InteractableInventory { } @Override - protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) { - inventoryConditionResult.setCancel(true); + protected void onClick(Player player, int slot, Click click, InventoryPreClickEvent event) { + event.setCancelled(true); if(!this.map.containsKey(slot)) return; 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 a123979..8bdfb7d 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 @@ -1,6 +1,7 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.acidRain; -import de.articdive.jnoise.JNoise; +import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.score.LastWinsScore; @@ -28,9 +29,8 @@ import java.util.concurrent.CompletableFuture; public class AcidRain extends StatelessGame { final JNoise noise = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.09) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.09) .build(); final private int radius = 20; final private int roofHeight = 55; @@ -105,7 +105,7 @@ public class AcidRain extends StatelessGame { for(int z = -radius; z <= radius; z++) { batch.setBlock(x, this.roofHeight, z, Block.AIR); if(new Pos(x, 0, z).distance(new Pos(0, 0, 0)) > radius) continue; - if(this.noise.getNoise(x + offset, z + offset) > 0.4) continue; + if(this.noise.evaluateNoise(x + offset, z + offset) > 0.4) continue; batch.setBlock(x, this.roofHeight, z, Block.OAK_PLANKS); } 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 index 1dfffc5..a355839 100644 --- 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 @@ -24,6 +24,7 @@ import net.minestom.server.event.player.PlayerMoveEvent; import net.minestom.server.event.player.PlayerStartFlyingWithElytraEvent; import net.minestom.server.event.player.PlayerStopFlyingWithElytraEvent; import net.minestom.server.event.player.PlayerUseItemEvent; +import net.minestom.server.instance.Chunk; import net.minestom.server.instance.batch.AbsoluteBlockBatch; import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; @@ -209,7 +210,16 @@ public class ElytraRace extends StatelessGame { point -> batch.setBlock(point, Block.AIR) ); + int minChunkX = (ringPos.blockX() - 100) >> 4; + int maxChunkX = (ringPos.blockX() + 100) >> 4; + int chunkZ = ringPos.blockZ() >> 4; + BatchUtil.loadAndApplyBatch(batch, this, () -> { + for(int cx = minChunkX; cx <= maxChunkX; cx++) { + Chunk chunk = this.getChunk(cx, chunkZ); + if(chunk == null) continue; + this.getPlayers().forEach(chunk::sendChunk); + } }); } @@ -229,7 +239,7 @@ public class ElytraRace extends StatelessGame { if(data.currentCheckpoint == 0) checkpointPos = this.getSpawn().add(0, 3, 0); p.setVelocity(Vec.ZERO); p.setFlyingWithElytra(false); - p.teleport(Pos.fromPoint(checkpointPos).add(0.5, 0, 0.5)); + p.teleport(new Pos(checkpointPos).add(0.5, 0, 0.5)); p.setFlying(true); p.setFlyingSpeed(0); diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/highGround/HighGround.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/highGround/HighGround.java index 319a936..193ec36 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/highGround/HighGround.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/highGround/HighGround.java @@ -8,6 +8,7 @@ import io.github.togar2.pvp.events.EntityKnockbackEvent; import io.github.togar2.pvp.events.FinalAttackEvent; import io.github.togar2.pvp.events.PrepareAttackEvent; import io.github.togar2.pvp.feature.CombatFeatures; +import io.github.togar2.pvp.feature.knockback.KnockbackSettings; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Player; import net.minestom.server.event.instance.InstanceTickEvent; @@ -50,7 +51,15 @@ class HighGround extends StatelessGame { this.eventNode().addListener( EntityKnockbackEvent.class, - entityKnockbackEvent -> entityKnockbackEvent.setStrength(1.1f) + entityKnockbackEvent -> entityKnockbackEvent.setSettings( + KnockbackSettings.builder() + .horizontal(1.1) + .vertical(KnockbackSettings.DEFAULT.vertical()) + .verticalLimit(KnockbackSettings.DEFAULT.verticalLimit()) + .extraHorizontal(KnockbackSettings.DEFAULT.extraHorizontal()) + .extraVertical(KnockbackSettings.DEFAULT.extraVertical()) + .build() + ) ); this.eventNode().addListener(InstanceTickEvent.class, instanceTickEvent -> { diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/pillars/Pillars.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/pillars/Pillars.java index 7c3e68d..53d6ef6 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/pillars/Pillars.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/pillars/Pillars.java @@ -19,7 +19,9 @@ import net.minestom.server.item.Material; import net.minestom.server.timer.TaskSchedule; import org.jetbrains.annotations.NotNull; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ThreadLocalRandom; class Pillars extends StatelessGame { @@ -27,6 +29,43 @@ class Pillars extends StatelessGame { private int spawnPosz = 0; private final int pillarSpacing = 10; private final int pillarRowCount = 5; + private final int timeToNextItem = 5; + + private static final Set IGNORED_SUFFIXES = Set.of( + "_SWORD", "_PICKAXE", "_AXE", "_SHOVEL", "_HOE", + "_HELMET", "_CHESTPLATE", "_LEGGINGS", "_BOOTS", + "_BOAT", "_MINECART", "_BUCKET", "_SPAWN_EGG", + "_BANNER", "_CANDLE", "_PRESSURE_PLATE", "_TEMPLATE", + "_BUTTON", "_HARNESS" + ); + + private static final Set IGNORED_EXACT = Set.of( + Material.BOW, Material.CROSSBOW, Material.TRIDENT, Material.MACE, Material.SHIELD, + Material.SHEARS, Material.FLINT_AND_STEEL, Material.FISHING_ROD, Material.SADDLE, + Material.TURTLE_HELMET, Material.ELYTRA, + Material.LADDER, Material.VINE, Material.SCAFFOLDING, Material.TWISTING_VINES, Material.WEEPING_VINES, + Material.BAMBOO_RAFT, + Material.TNT, Material.SPAWNER, Material.END_PORTAL_FRAME, + Material.COMMAND_BLOCK, Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, + Material.STRUCTURE_BLOCK, Material.STRUCTURE_VOID, Material.JIGSAW, + Material.BARRIER, Material.LIGHT, Material.DEBUG_STICK, Material.KNOWLEDGE_BOOK, + Material.BEDROCK, Material.AIR + ); + + private static final Set IGNORED_MATERIALS = new HashSet<>(); + + static { + for (Material material : Material.values()) { + String id = material.key().asString(); + + for (String suffix : IGNORED_SUFFIXES) { + if (id.endsWith(suffix.toLowerCase())) { + IGNORED_MATERIALS.add(material); + break; + } + } + } + } public Pillars() { super(Dimension.THE_END.key, "Pillars", new LastWinsScore()); @@ -90,14 +129,15 @@ class Pillars extends StatelessGame { MinecraftServer.getSchedulerManager().submitTask(() -> { List materials = Material.values().stream() - .filter(material -> !material.equals(Material.AIR)) + .filter(material -> !IGNORED_EXACT.contains(material)) + .filter(material -> !IGNORED_MATERIALS.contains(material)) .toList(); this.getPlayers().forEach(player -> { - ItemStack item = ItemStack.of(materials.get(ThreadLocalRandom.current().nextInt(Material.values().toArray().length))); + ItemStack item = ItemStack.of(materials.get(ThreadLocalRandom.current().nextInt(materials.size()))); player.getInventory().addItemStack(item); }); - return TaskSchedule.seconds(5); + return TaskSchedule.seconds(this.timeToNextItem); }); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRace.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRace.java new file mode 100644 index 0000000..be6480f --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRace.java @@ -0,0 +1,86 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace; + +import eu.mhsl.minenet.minigames.instance.Dimension; +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.util.CommonProperties; +import net.minestom.server.coordinate.Pos; +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; +import net.minestom.server.instance.block.Block; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.CompletableFuture; + +public class PlayerRace extends StatelessGame { + private final int height = 64; + private final Map zLine = new WeakHashMap<>(); + private final Map zSpawnPoint = new WeakHashMap<>(); + private final int obstacleCount; + + public PlayerRace(int obstacleCount) { + super(Dimension.THE_END.key, "PlayerRace", new FirstWinsScore()); + this.setGenerator(new PlayerRaceChunkgenerator(this.height, obstacleCount)); + this.obstacleCount = obstacleCount; + } + + @Override + protected boolean onPlayerJoin(Player p) { + p.setGameMode(GameMode.ADVENTURE); + this.zLine.put(p, 32.0); + this.zSpawnPoint.put(p, 14.5); + return false; + } + + @Override + protected void onLoad(@NotNull CompletableFuture callback) { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + for(int x = 0; x < 16; x++) { + batch.setBlock(x,this.height + 1, 15, Block.OAK_FENCE.withProperties(CommonProperties.fenceEastWest)); + }BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); + } + + @Override + protected void onStart() { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + for(int x = 0; x < 16; x++) { + batch.setBlock(x,this.height + 1, 15, Block.AIR); + }BatchUtil.loadAndApplyBatch(batch, this, () -> {}); + } + + @Override + public Pos getSpawn() { + return new Pos(8, this.height + 1.5, 8); + } + + public Pos getNewSpawn(Player player) { + return new Pos(8, this.height + 1.5, this.zSpawnPoint.get(player)); + } + + @Override + protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { + var player = playerMoveEvent.getPlayer(); + if(playerMoveEvent.getNewPosition().y() < this.height - 5) { + player.teleport(this.isBeforeBeginning ? this.getSpawn() : this.getNewSpawn(player)); + return; + } + + if(playerMoveEvent.getNewPosition().z() >= this.zLine.get(player) && this.isRunning) { + this.zLine.merge(player, 19.0, Double::sum); + this.zSpawnPoint.merge(player, 19.0, Double::sum); + } + + if(playerMoveEvent.getNewPosition().z() >= 16 + this.obstacleCount * 19 && this.isRunning) { + this.getScore().insertResult(player); + player.setGameMode(GameMode.SPECTATOR); + } + + if(playerMoveEvent.getNewPosition().z() >= 16 && this.isBeforeBeginning) + player.teleport(this.getSpawn()); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRaceChunkgenerator.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRaceChunkgenerator.java new file mode 100644 index 0000000..16342cb --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRaceChunkgenerator.java @@ -0,0 +1,61 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace; + +import eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles.Obstacle; +import eu.mhsl.minenet.minigames.util.GeneratorUtils; +import eu.mhsl.minenet.minigames.world.BlockPallet; +import eu.mhsl.minenet.minigames.world.generator.featureEnriched.ValeGenerator; +import eu.mhsl.minenet.minigames.world.generator.terrain.BaseGenerator; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +public class PlayerRaceChunkgenerator extends BaseGenerator { + private static final int START_LENGTH = 16; + private static final int GAP_LENGTH = 3; + private static final int PERIOD = Obstacle.LENGTH + GAP_LENGTH; + + public PlayerRaceChunkgenerator(int height, int obstacleCount) { + ValeGenerator vale = new ValeGenerator(); + vale.setXShiftMultiplier(integer -> 0.5d); + vale.setHeightNoiseMultiplier(integer -> 2); + this.addMixIn(vale); + + int finishStart = START_LENGTH + obstacleCount * PERIOD; + int finishEnd = finishStart + 16; + + this.addMixIn(unit -> { + Point chunkStart = unit.absoluteStart(); + if( + chunkStart.chunkX() != 0 || + chunkStart.blockZ() + 16 <= 0 || + chunkStart.blockZ() >= finishEnd + ) return; + + GeneratorUtils.foreachXZ(unit, point -> { + Block ground = groundBlockAt(point.blockZ(), finishStart, finishEnd); + if(ground != null) unit.modifier().setBlock(point.withY(height), ground); + }); + + for(int i = 0; i < obstacleCount; i++) { + int obstacleZ = START_LENGTH + i * PERIOD; + if(obstacleZ < chunkStart.blockZ() || obstacleZ >= chunkStart.blockZ() + 16) continue; + + GenerationUnit fork = unit.fork( + new Vec(chunkStart.blockX(), height - 8, obstacleZ), + new Vec(chunkStart.blockX() + 16, height + 16, obstacleZ + Obstacle.LENGTH) + ); + Obstacle.getRandomObstacle().generate(fork, new Vec(chunkStart.blockX(), height, obstacleZ)); + } + }); + } + + private static Block groundBlockAt(int z, int finishStart, int finishEnd) { + if(z < 0 || z >= finishEnd) return null; + if(z < START_LENGTH) return BlockPallet.GROUND.rnd(); + if(z >= finishStart) return Block.DIAMOND_BLOCK; + + int relative = (z - START_LENGTH) % PERIOD; + return relative >= Obstacle.LENGTH ? BlockPallet.GROUND.rnd() : null; + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRaceFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRaceFactory.java new file mode 100644 index 0000000..0c0816d --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/PlayerRaceFactory.java @@ -0,0 +1,40 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace; + +import eu.mhsl.minenet.minigames.instance.game.Game; +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.instance.room.Room; +import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import net.minestom.server.item.Material; + +import java.util.Map; + +public class PlayerRaceFactory implements GameFactory { + @Override + public TranslatedComponent name() { + return TranslatedComponent.byId("game_PlayerRace#name"); + } + + @Override + public ConfigManager configuration() { + return new ConfigManager() + .addOption(new NumericOption("length", Material.RAIL, TranslatedComponent.byId("optionCommon#length"), 8, 12, 16, 20)); + } + + @Override + public Game manufacture(Room parent, Map> configuration) throws Exception { + return new PlayerRace(configuration.get("length").getAsInt()).setParent(parent); + } + + @Override + public Material symbol() { + return Material.DIRT_PATH; + } + + @Override + public TranslatedComponent description() { + return TranslatedComponent.byId("game_PlayerRace#description"); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BambooThicket.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BambooThicket.java new file mode 100644 index 0000000..13fe528 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BambooThicket.java @@ -0,0 +1,30 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class BambooThicket extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + unit.modifier().setBlock(point.withY(start.blockY()), rnd.nextInt(3) == 0 ? Block.PODZOL : Block.GRASS_BLOCK); + + int z = relZ(point, start); + if(z < 2 || z > 13 || rnd.nextInt(100) >= 45) return; + + int height = 3 + rnd.nextInt(3); + for(int y = 1; y <= height; y++) { + String leaves = y == height ? "large" : y == height - 1 ? "small" : "none"; + unit.modifier().setBlock( + point.withY(start.blockY() + y), + Block.BAMBOO.withProperty("age", "1").withProperty("leaves", leaves) + ); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BasaltPillars.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BasaltPillars.java new file mode 100644 index 0000000..121d0f7 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BasaltPillars.java @@ -0,0 +1,44 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class BasaltPillars extends Obstacle { + private final JNoise ground = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.13) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + double noise = this.ground.evaluateNoise(point.blockX(), point.blockZ()); + Block floor = noise > 0.4 ? Block.SOUL_SOIL : noise < -0.4 ? Block.BASALT : Block.BLACKSTONE; + unit.modifier().setBlock(point.withY(start.blockY()), floor); + }); + + for(int i = 0; i < 16; i++) { + int x = rnd.nextInt(16); + int z = 2 + rnd.nextInt(12); + int height = 2 + rnd.nextInt(3); + boolean thick = rnd.nextInt(3) == 0 && x < 15; + Block pillar = rnd.nextInt(3) == 0 ? Block.POLISHED_BASALT : Block.BASALT; + for(int y = 1; y <= height; y++) { + unit.modifier().setBlock(start.add(x, y, z), pillar); + if(thick) { + unit.modifier().setBlock(start.add(x + 1, y, z), pillar); + } + } + if(rnd.nextInt(3) == 0) { + unit.modifier().setBlock(start.add(x, height + 1, z), Block.SOUL_LANTERN); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BerryPatch.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BerryPatch.java new file mode 100644 index 0000000..be68a5b --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BerryPatch.java @@ -0,0 +1,28 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class BerryPatch extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + int z = relZ(point, start); + int pathX = 7 + (int) Math.round(5 * Math.sin(z * Math.PI / 7.5)); + boolean onPath = relX(point, start) == pathX || relX(point, start) == pathX + 1; + boolean overgrown = z == 8; + + unit.modifier().setBlock(point.withY(start.blockY()), onPath ? Block.DIRT_PATH : Block.GRASS_BLOCK); + + boolean bush = onPath ? overgrown : z >= 1 && z <= 14 && rnd.nextInt(100) < 45; + if(bush) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.SWEET_BERRY_BUSH.withProperty("age", "3")); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BoulderTrench.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BoulderTrench.java new file mode 100644 index 0000000..ada9800 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/BoulderTrench.java @@ -0,0 +1,40 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class BoulderTrench extends Obstacle { + private static final int[] DEPTHS = {0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0}; + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + int depth = DEPTHS[relZ(point, start)]; + for(int y = start.blockY() - 2; y < start.blockY() - depth; y++) { + unit.modifier().setBlock(point.withY(y), Block.STONE); + } + Block floor = depth == 0 + ? Block.GRASS_BLOCK + : rnd.nextBoolean() ? Block.COARSE_DIRT : Block.GRAVEL; + unit.modifier().setBlock(point.withY(start.blockY() - depth), floor); + }); + + for(int i = 0; i < 10; i++) { + int x = rnd.nextInt(16); + int z = 6 + rnd.nextInt(4); + unit.modifier().setBlock(start.add(x, -1, z), rnd.nextBoolean() ? Block.MOSSY_COBBLESTONE : Block.COBBLESTONE); + if(rnd.nextInt(3) == 0) { + unit.modifier().setBlock(start.add(x, 0, z), Block.MOSSY_COBBLESTONE); + } + } + + for(int i = 0; i < 4; i++) { + unit.modifier().setBlock(start.add(rnd.nextInt(16), -1, 6 + rnd.nextInt(4)), Block.COBWEB); + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/ChorusGrove.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/ChorusGrove.java new file mode 100644 index 0000000..dea7dd2 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/ChorusGrove.java @@ -0,0 +1,65 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class ChorusGrove extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + Block floor = rnd.nextInt(14) == 0 ? Block.PURPUR_BLOCK : Block.END_STONE; + unit.modifier().setBlock(point.withY(start.blockY()), floor); + }); + + int[] rows = {5, 10}; + for(int i = 0; i < rows.length; i++) { + int gapStart = i % 2 == 0 ? 1 + rnd.nextInt(4) : 10 + rnd.nextInt(4); + + boolean[] hasWall = new boolean[16]; + for(int x = 0; x < 16; x++) { + hasWall[x] = x < gapStart || x >= gapStart + 2; + } + + for(int x = 0; x < 16; x++) { + if(!hasWall[x]) continue; + boolean westConnected = x > 0 && hasWall[x - 1]; + boolean eastConnected = x < 15 && hasWall[x + 1]; + Block wall = Block.END_STONE_BRICK_WALL + .withProperty("west", westConnected ? "low" : "none") + .withProperty("east", eastConnected ? "low" : "none") + .withProperty("up", String.valueOf(!westConnected || !eastConnected || x % 4 == 0)); + unit.modifier().setBlock(start.add(x, 1, rows[i]), wall); + + if(rnd.nextInt(6) == 0) { + unit.modifier().setBlock(start.add(x, 2, rows[i]), Block.END_ROD); + } + } + } + + for(int i = 0; i < 15; i++) { + int x = rnd.nextInt(16); + int z = 2 + rnd.nextInt(12); + if(z == 5 || z == 10) continue; + int height = 1 + rnd.nextInt(3); + for(int y = 1; y <= height; y++) { + unit.modifier().setBlock(start.add(x, y, z), Block.CHORUS_PLANT); + } + unit.modifier().setBlock(start.add(x, height + 1, z), Block.CHORUS_FLOWER.withProperty("age", "5")); + } + + for(int i = 0; i < 5; i++) { + int x = rnd.nextInt(16); + int z = 2 + rnd.nextInt(12); + if(z == 5 || z == 10) continue; + unit.modifier().setBlock(start.add(x, 1, z), Block.PURPUR_BLOCK); + if(rnd.nextBoolean()) { + unit.modifier().setBlock(start.add(x, 2, z), Block.PURPUR_BLOCK); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/CobwebGrove.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/CobwebGrove.java new file mode 100644 index 0000000..a16231d --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/CobwebGrove.java @@ -0,0 +1,46 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class CobwebGrove extends Obstacle { + private final JNoise soil = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.12) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + Block floor = this.soil.evaluateNoise(point.blockX(), point.blockZ()) > 0 ? Block.PODZOL : Block.COARSE_DIRT; + unit.modifier().setBlock(point.withY(start.blockY()), floor); + + int z = relZ(point, start); + if(z < 2 || z > 13) return; + + int roll = rnd.nextInt(100); + if(roll < 28) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.COBWEB); + if(roll < 8) unit.modifier().setBlock(point.withY(start.blockY() + 2), Block.COBWEB); + } else if(roll < 36) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.FERN); + } + }); + + for(int i = 0; i < 4; i++) { + int x = rnd.nextInt(16); + int z = 3 + rnd.nextInt(10); + int height = 1 + rnd.nextInt(2); + for(int y = 1; y <= height; y++) { + unit.modifier().setBlock(start.add(x, y, z), Block.SPRUCE_LOG); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/DripstoneSpikes.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/DripstoneSpikes.java new file mode 100644 index 0000000..e198d55 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/DripstoneSpikes.java @@ -0,0 +1,46 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class DripstoneSpikes extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> + unit.modifier().setBlock(point.withY(start.blockY()), rnd.nextInt(6) == 0 ? Block.STONE : Block.DRIPSTONE_BLOCK)); + + int[] rows = {4, 8, 12}; + for(int i = 0; i < rows.length; i++) { + int gapStart = i % 2 == 0 ? 2 + rnd.nextInt(4) : 9 + rnd.nextInt(4); + for(int x = 0; x < 16; x++) { + if(x >= gapStart && x < gapStart + 2) continue; + unit.modifier().setBlock(start.add(x, 1, rows[i]), Block.DRIPSTONE_BLOCK); + this.placeSpike(unit, start.add(0, 1, 0), x, rows[i], 1 + rnd.nextInt(2)); + } + } + + for(int i = 0; i < 12; i++) { + int x = rnd.nextInt(16); + int z = 2 + rnd.nextInt(12); + if(z == 4 || z == 8 || z == 12) continue; + this.placeSpike(unit, start, x, z, 1 + rnd.nextInt(3)); + } + } + + private void placeSpike(GenerationUnit unit, Point start, int x, int z, int height) { + for(int y = 1; y <= height; y++) { + String thickness = y == height ? "tip" : y == height - 1 ? "frustum" : "base"; + unit.modifier().setBlock( + start.add(x, y, z), + Block.POINTED_DRIPSTONE + .withProperty("thickness", thickness) + .withProperty("vertical_direction", "up") + ); + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/GlassPaneWeave.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/GlassPaneWeave.java new file mode 100644 index 0000000..17c4166 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/GlassPaneWeave.java @@ -0,0 +1,36 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class GlassPaneWeave extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> + unit.modifier().setBlock(point.withY(start.blockY()), rnd.nextInt(5) == 0 ? Block.CALCITE : Block.QUARTZ_BLOCK)); + + int[] rows = {4, 8, 12}; + for(int i = 0; i < rows.length; i++) { + int gapStart = i % 2 == 0 ? 2 + rnd.nextInt(3) : 11 + rnd.nextInt(3); + + boolean[] hasPane = new boolean[16]; + for(int x = 0; x < 16; x++) { + hasPane[x] = x < gapStart || x >= gapStart + 2; + } + + for(int x = 0; x < 16; x++) { + if(!hasPane[x]) continue; + Block pane = (rnd.nextInt(6) == 0 ? Block.GRAY_STAINED_GLASS_PANE : Block.WHITE_STAINED_GLASS_PANE) + .withProperty("west", String.valueOf(x > 0 && hasPane[x - 1])) + .withProperty("east", String.valueOf(x < 15 && hasPane[x + 1])); + unit.modifier().setBlock(start.add(x, 1, rows[i]), pane); + unit.modifier().setBlock(start.add(x, 2, rows[i]), pane); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/HayHurdles.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/HayHurdles.java new file mode 100644 index 0000000..be3134f --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/HayHurdles.java @@ -0,0 +1,35 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class HayHurdles extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + unit.modifier().setBlock(point.withY(start.blockY()), Block.GRASS_BLOCK); + if(relZ(point, start) % 3 != 0 && rnd.nextInt(8) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.SHORT_GRASS); + } + }); + + int[] rows = {3, 6, 9, 12}; + for(int i = 0; i < rows.length; i++) { + boolean tall = i % 2 == 1; + int gapStart = rnd.nextInt(14); + for(int x = 0; x < 16; x++) { + if(tall && (x == gapStart || x == gapStart + 1)) continue; + Block block = rnd.nextInt(12) == 0 ? Block.CARVED_PUMPKIN : Block.HAY_BLOCK; + unit.modifier().setBlock(start.add(x, 1, rows[i]), block); + if(tall) { + unit.modifier().setBlock(start.add(x, 2, rows[i]), Block.HAY_BLOCK); + } + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/HoneyField.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/HoneyField.java new file mode 100644 index 0000000..daf2cb0 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/HoneyField.java @@ -0,0 +1,35 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class HoneyField extends Obstacle { + private final JNoise sticky = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.2) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + boolean stickyFloor = this.sticky.evaluateNoise(point.blockX(), point.blockZ()) > 0.35; + unit.modifier().setBlock(point.withY(start.blockY()), stickyFloor ? Block.HONEY_BLOCK : Block.HONEYCOMB_BLOCK); + }); + + for(int wallZ : new int[]{5, 10}) { + int gapStart = wallZ == 5 ? 1 + rnd.nextInt(5) : 8 + rnd.nextInt(5); + for(int x = 0; x < 16; x++) { + if(x >= gapStart && x < gapStart + 2) continue; + unit.modifier().setBlock(start.add(x, 1, wallZ), Block.HONEY_BLOCK); + unit.modifier().setBlock(start.add(x, 2, wallZ), Block.HONEY_BLOCK); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/IceRink.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/IceRink.java new file mode 100644 index 0000000..a704570 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/IceRink.java @@ -0,0 +1,54 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class IceRink extends Obstacle { + private final JNoise streaks = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.15) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + double noise = this.streaks.evaluateNoise(point.blockX(), point.blockZ()); + Block floor = noise > 0.45 ? Block.BLUE_ICE : noise < -0.55 ? Block.ICE : Block.PACKED_ICE; + unit.modifier().setBlock(point.withY(start.blockY()), floor); + + if(relZ(point, start) >= 2 && relZ(point, start) <= 13 && rnd.nextInt(14) == 0) { + unit.modifier().setBlock( + point.withY(start.blockY() + 1), + Block.SNOW.withProperty("layers", String.valueOf(1 + rnd.nextInt(2))) + ); + } + }); + + for(int wallZ : new int[]{5, 10}) { + int gapStart = wallZ == 5 ? 1 + rnd.nextInt(4) : 9 + rnd.nextInt(4); + for(int x = 0; x < 16; x++) { + if(x >= gapStart && x < gapStart + 3) continue; + unit.modifier().setBlock(start.add(x, 1, wallZ), Block.PACKED_ICE); + unit.modifier().setBlock(start.add(x, 2, wallZ), Block.ICE); + if(rnd.nextInt(4) == 0) { + unit.modifier().setBlock(start.add(x, 3, wallZ), Block.SNOW.withProperty("layers", "1")); + } + } + } + + for(int i = 0; i < 5; i++) { + int x = rnd.nextInt(16); + int z = 2 + rnd.nextInt(12); + if(z == 5 || z == 10) continue; + unit.modifier().setBlock(start.add(x, 1, z), Block.PACKED_ICE); + unit.modifier().setBlock(start.add(x, 2, z), Block.SNOW.withProperty("layers", "1")); + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LadderWall.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LadderWall.java new file mode 100644 index 0000000..f1a2468 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LadderWall.java @@ -0,0 +1,36 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import eu.mhsl.minenet.minigames.world.BlockPallet; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class LadderWall extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> + unit.modifier().setBlock(point.withY(start.blockY()), BlockPallet.STONE.rnd())); + + for(int x = 0; x < 16; x++) { + boolean hasLadder = rnd.nextInt(3) != 0; + for(int y = 1; y <= 3; y++) { + for(int z = 7; z <= 8; z++) { + Block block = rnd.nextInt(3) == 0 ? Block.MOSSY_STONE_BRICKS : Block.STONE_BRICKS; + unit.modifier().setBlock(start.add(x, y, z), block); + } + if(hasLadder) { + unit.modifier().setBlock(start.add(x, y, 6), Block.LADDER.withProperty("facing", "north")); + } + unit.modifier().setBlock(start.add(x, y, 9), Block.LADDER.withProperty("facing", "south")); + } + + if(x % 5 == 2) { + unit.modifier().setBlock(start.add(x, 4, 7), Block.LANTERN); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LadderWall2.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LadderWall2.java new file mode 100644 index 0000000..b8fc13d --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LadderWall2.java @@ -0,0 +1,48 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import eu.mhsl.minenet.minigames.world.BlockPallet; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.*; + +class LadderWall2 extends Obstacle{ + @Override + public void generate(GenerationUnit unit, Point start) { + forEachColumn(start, point -> + unit.modifier().setBlock(point.withY(start.blockY()), BlockPallet.STREET.rnd())); + + this.buildWall(unit, start,4, 4, false); + this.buildWall(unit, start,10, 8, true); + } + + private void buildWall(GenerationUnit unit, Point start, int z, int height, boolean lastRow) { + Random random = new Random(); + int y = 1; + for(int x = 0; x < 16; x++) { + for(int wy = 0; wy <= height; wy++) { + unit.modifier().setBlock(start.add(x, y + wy, z), BlockPallet.STONE.rnd()); + } + } + + for(int wy = lastRow ? 2 : 0; wy <= height; wy++) { + + Set noLadder = new HashSet<>(); + for(int i = 0; i < 5; i++) { + noLadder.add(random.nextInt(16)); + } + + for(int x = 0; x < 16; x++) { + if(!noLadder.contains(x)) + unit.modifier().setBlock(start.add(x, y + wy, z - 1), Block.LADDER); + } + + if(!lastRow) { + for(int x = 7; x < 9; x++) { + unit.modifier().setBlock(start.add(x, y + wy, z + 1), Block.LADDER.withProperty("facing", "south")); + } + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LeafHedges.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LeafHedges.java new file mode 100644 index 0000000..04f51f0 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/LeafHedges.java @@ -0,0 +1,35 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import eu.mhsl.minenet.minigames.world.BlockPallet; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class LeafHedges extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + unit.modifier().setBlock(point.withY(start.blockY()), Block.GRASS_BLOCK); + int z = relZ(point, start); + if(z % 4 != 0 && z >= 1 && z <= 14 && rnd.nextInt(10) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), BlockPallet.FLOWER.rnd()); + } + }); + + int[] rows = {4, 8, 12}; + for(int i = 0; i < rows.length; i++) { + int gapStart = i % 2 == 0 ? 11 + rnd.nextInt(3) : 1 + rnd.nextInt(3); + for(int x = 0; x < 16; x++) { + if(x >= gapStart && x < gapStart + 2) continue; + Block leaves = (rnd.nextInt(10) < 3 ? Block.FLOWERING_AZALEA_LEAVES : Block.AZALEA_LEAVES) + .withProperty("persistent", "true"); + unit.modifier().setBlock(start.add(x, 1, rows[i]), leaves); + unit.modifier().setBlock(start.add(x, 2, rows[i]), leaves); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/MudPools.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/MudPools.java new file mode 100644 index 0000000..9695713 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/MudPools.java @@ -0,0 +1,40 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class MudPools extends Obstacle { + private final JNoise pools = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.11) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + int z = relZ(point, start); + double noise = this.pools.evaluateNoise(point.blockX(), point.blockZ()); + boolean pool = z >= 1 && z <= 14 && noise > 0.05; + + if(pool) { + unit.modifier().setBlock(point.withY(start.blockY() - 1), Block.MUD); + return; + } + + Block floor = noise > -0.3 ? Block.MUDDY_MANGROVE_ROOTS : Block.GRASS_BLOCK; + unit.modifier().setBlock(point.withY(start.blockY() - 1), Block.MUD); + unit.modifier().setBlock(point.withY(start.blockY()), floor); + + if(z >= 2 && z <= 13 && rnd.nextInt(6) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.MANGROVE_ROOTS); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/Mudpit.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/Mudpit.java new file mode 100644 index 0000000..0e677a8 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/Mudpit.java @@ -0,0 +1,25 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +class Mudpit extends Obstacle { + private final JNoise curves = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.1) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + forEachColumn(start, point -> { + double relative = relZ(point, start); + double modifier = -1.5 * Math.cos(relative * Math.PI/7.5) + 1.5; + double heightAtBlock = start.blockY() + this.curves.evaluateNoise(point.blockX(), point.blockZ()) * modifier; + unit.modifier().setBlock(point.withY(heightAtBlock), Block.SOUL_SAND); + unit.modifier().setBlock(point.withY(heightAtBlock-1), Block.SOUL_SAND); + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/MushroomRoofs.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/MushroomRoofs.java new file mode 100644 index 0000000..a0dc290 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/MushroomRoofs.java @@ -0,0 +1,37 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class MushroomRoofs extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + unit.modifier().setBlock(point.withY(start.blockY()), Block.MYCELIUM); + int z = relZ(point, start); + if(z >= 1 && z <= 14 && rnd.nextInt(20) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), rnd.nextBoolean() ? Block.RED_MUSHROOM : Block.BROWN_MUSHROOM); + } + }); + + for(int stemZ : new int[]{4, 8, 12}) { + int x = 4 + rnd.nextInt(8); + Block cap = rnd.nextBoolean() ? Block.RED_MUSHROOM_BLOCK : Block.BROWN_MUSHROOM_BLOCK; + + unit.modifier().setBlock(start.add(x, 1, stemZ), Block.MUSHROOM_STEM); + + for(int capX = x - 3; capX <= x + 3; capX++) { + for(int capZ = stemZ - 1; capZ <= stemZ + 1; capZ++) { + if(capX < 0 || capX > 15 || capZ < 0 || capZ > 15) continue; + if(Math.abs(capX - x) == 3 && Math.abs(capZ - stemZ) == 1) continue; + unit.modifier().setBlock(start.add(capX, 2, capZ), cap); + } + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/Obstacle.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/Obstacle.java new file mode 100644 index 0000000..c092b83 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/Obstacle.java @@ -0,0 +1,69 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import eu.mhsl.minenet.minigames.util.GeneratorUtils; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; + +public abstract class Obstacle { + public static final int LENGTH = 16; + + @SuppressWarnings("StaticInitializerReferencesSubClass") + private static final List obstacles = List.of( + new Mudpit(), + new IceRink(), + new HoneyField(), + new CobwebGrove(), + new BerryPatch(), + new WaterChannel(), + new HayHurdles(), + new SlimePatches(), + new MudPools(), + new PowderSnowField(), + new DripstoneSpikes(), + new ChorusGrove(), + new BasaltPillars(), + new WallSlalom(), + new LeafHedges(), + new MushroomRoofs(), + new SandDunes(), + new LadderWall(), + new LadderWall2(), + new GlassPaneWeave(), + new BoulderTrench(), + new BambooThicket() + ); + + public abstract void generate(GenerationUnit unit, Point start); + + private static final List remaining = new ArrayList<>(); + + public static synchronized Obstacle getRandomObstacle() { + if(remaining.isEmpty()) { + remaining.addAll(obstacles); + } + int index = ThreadLocalRandom.current().nextInt(remaining.size()); + return remaining.remove(index); + } + + protected static void forEachColumn(Point start, Consumer callback) { + GeneratorUtils.foreachXZ(start, start.add(15, 0, LENGTH - 1), callback); + } + + protected static int relX(Point point, Point start) { + return point.blockX() - start.blockX(); + } + + protected static int relZ(Point point, Point start) { + return point.blockZ() - start.blockZ(); + } + + protected static Random seededRandom(Point start) { + return new Random(start.blockX() * 341873128712L + start.blockZ() * 132897987541L); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/PowderSnowField.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/PowderSnowField.java new file mode 100644 index 0000000..a843a40 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/PowderSnowField.java @@ -0,0 +1,40 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class PowderSnowField extends Obstacle { + private final JNoise drifts = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.14) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + int z = relZ(point, start); + int laneX = 7 + (int) Math.round(3 * Math.sin(z * Math.PI / 7.5)); + boolean onLane = relX(point, start) == laneX || relX(point, start) == laneX + 1; + double noise = this.drifts.evaluateNoise(point.blockX(), point.blockZ()); + boolean drift = z >= 2 && z <= 13 && noise > (onLane ? 0.45 : 0.0); + + unit.modifier().setBlock(point.withY(start.blockY()), onLane ? Block.PACKED_ICE : Block.SNOW_BLOCK); + + if(drift) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.POWDER_SNOW); + if(noise > 0.6) { + unit.modifier().setBlock(point.withY(start.blockY() + 2), Block.POWDER_SNOW); + } + } else if(!onLane && rnd.nextInt(6) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.SNOW.withProperty("layers", "1")); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/SandDunes.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/SandDunes.java new file mode 100644 index 0000000..bcad507 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/SandDunes.java @@ -0,0 +1,41 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class SandDunes extends Obstacle { + private final JNoise dunes = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.08) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + double taper = -1.25 * Math.cos(relZ(point, start) * Math.PI / 7.5) + 1.25; + double noise = (this.dunes.evaluateNoise(point.blockX(), point.blockZ()) + 1) / 2; + int top = start.blockY() + (int) Math.round(noise * taper); + + for(int y = start.blockY() - 1; y < top; y++) { + unit.modifier().setBlock(point.withY(y), Block.SANDSTONE); + } + unit.modifier().setBlock(point.withY(top), Block.SAND); + + if(top > start.blockY() + 1 && rnd.nextInt(14) == 0) { + unit.modifier().setBlock(point.withY(top + 1), Block.DEAD_BUSH); + } else if(top == start.blockY() && relZ(point, start) >= 2 && relZ(point, start) <= 13 && rnd.nextInt(22) == 0) { + int cactusHeight = 1 + rnd.nextInt(2); + for(int y = 1; y <= cactusHeight; y++) { + unit.modifier().setBlock(point.withY(top + y), Block.CACTUS); + } + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/SlimePatches.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/SlimePatches.java new file mode 100644 index 0000000..95031fe --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/SlimePatches.java @@ -0,0 +1,31 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import de.articdive.jnoise.generators.noisegen.perlin.PerlinNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class SlimePatches extends Obstacle { + private final JNoise blobs = JNoise.newBuilder() + .perlin(PerlinNoiseGenerator.newBuilder().build()) + .scale(0.18) + .build(); + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + int z = relZ(point, start); + boolean slime = z >= 1 && z <= 14 && this.blobs.evaluateNoise(point.blockX(), point.blockZ()) > -0.2; + unit.modifier().setBlock(point.withY(start.blockY()), slime ? Block.SLIME_BLOCK : Block.MOSS_BLOCK); + + if(!slime && z >= 2 && z <= 13 && rnd.nextInt(18) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.AZALEA); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/WallSlalom.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/WallSlalom.java new file mode 100644 index 0000000..0517deb --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/WallSlalom.java @@ -0,0 +1,38 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class WallSlalom extends Obstacle { + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> + unit.modifier().setBlock(point.withY(start.blockY()), rnd.nextInt(4) == 0 ? Block.ANDESITE : Block.STONE)); + + int[] rows = {4, 8, 12}; + for(int i = 0; i < rows.length; i++) { + int gapStart = i % 2 == 0 ? 1 + rnd.nextInt(3) : 10 + rnd.nextInt(3); + + boolean[] hasWall = new boolean[16]; + for(int x = 0; x < 16; x++) { + hasWall[x] = x < gapStart || x >= gapStart + 2; + } + + for(int x = 0; x < 16; x++) { + if(!hasWall[x]) continue; + boolean westConnected = x > 0 && hasWall[x - 1]; + boolean eastConnected = x < 15 && hasWall[x + 1]; + Block wall = Block.STONE_BRICK_WALL + .withProperty("west", westConnected ? "low" : "none") + .withProperty("east", eastConnected ? "low" : "none") + .withProperty("up", String.valueOf(!westConnected || !eastConnected || x % 4 == 0)); + unit.modifier().setBlock(start.add(x, 1, rows[i]), wall); + } + } + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/WaterChannel.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/WaterChannel.java new file mode 100644 index 0000000..c29b6bb --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/playerRace/obstacles/WaterChannel.java @@ -0,0 +1,37 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.generator.GenerationUnit; + +import java.util.Random; + +class WaterChannel extends Obstacle { + private static final int[] DEPTHS = {0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0}; + + @Override + public void generate(GenerationUnit unit, Point start) { + Random rnd = seededRandom(start); + + forEachColumn(start, point -> { + int depth = DEPTHS[relZ(point, start)]; + if(depth == 0) { + unit.modifier().setBlock(point.withY(start.blockY()), rnd.nextInt(3) == 0 ? Block.SMOOTH_SANDSTONE : Block.SAND); + return; + } + + Block bottom = rnd.nextInt(5) == 0 ? Block.DARK_PRISMARINE : Block.PRISMARINE; + unit.modifier().setBlock(point.withY(start.blockY() - depth), bottom); + for(int y = start.blockY() - depth + 1; y <= start.blockY(); y++) { + unit.modifier().setBlock(point.withY(y), Block.WATER); + } + + if(depth >= 2 && rnd.nextInt(4) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() - depth + 1), Block.SEAGRASS); + } + if(rnd.nextInt(20) == 0) { + unit.modifier().setBlock(point.withY(start.blockY() + 1), Block.LILY_PAD); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spaceSnake/SpaceSnake.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spaceSnake/SpaceSnake.java index 86f49ec..40d7208 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spaceSnake/SpaceSnake.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/spaceSnake/SpaceSnake.java @@ -125,7 +125,7 @@ public class SpaceSnake extends StatelessGame { } PlayState state = this.playerStates.get(playerBlockPlaceEvent.getPlayer()); - state.blocks.add(playerBlockPlaceEvent.getBlockPosition().asVec().asPosition()); + state.blocks.add(new Pos(playerBlockPlaceEvent.getBlockPosition())); state.cutToLength(pos -> this.setBlock(pos, Block.AIR)); MinecraftServer.getSchedulerManager().scheduleNextTick(() -> this.updateInv(playerBlockPlaceEvent.getPlayer())); diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/sumo/Sumo.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/sumo/Sumo.java index 607f109..26a3f7d 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/sumo/Sumo.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/sumo/Sumo.java @@ -32,7 +32,7 @@ public class Sumo extends StatelessGame { super(Dimension.OVERWORLD.key, "Sumo", new LastWinsScore()); this.getScore().setIgnoreLastPlayers(1); this.setTime(6000); - this.setTimeRate(0); + this.defaultClock().pause(); this.radius = radius; this.health = health; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/towerdefense/TowerdefenseRoom.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/towerdefense/TowerdefenseRoom.java index fc723a2..67f2c9f 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/towerdefense/TowerdefenseRoom.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/towerdefense/TowerdefenseRoom.java @@ -22,7 +22,12 @@ public class TowerdefenseRoom extends InstanceContainer { private final Towerdefense game; public TowerdefenseRoom(Player player, Towerdefense game) { - super(UUID.randomUUID(), Dimension.OVERWORLD.key); + this(UUID.randomUUID(), player, game); + } + + // eindeutiger Dimension-Name pro Instanz, siehe MineNetInstance + private TowerdefenseRoom(UUID uuid, Player player, Towerdefense game) { + super(uuid, Dimension.OVERWORLD.key, net.kyori.adventure.key.Key.key("minenet", "instance-" + uuid)); MinecraftServer.getInstanceManager().registerInstance(this); this.player = player; this.game = game; 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 3cfffe7..b189a4d 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,6 +1,7 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace; -import de.articdive.jnoise.JNoise; +import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; import eu.mhsl.minenet.minigames.score.FirstWinsScore; @@ -49,9 +50,8 @@ class TrafficLightRace extends StatelessGame { @Override protected void onLoad(@NotNull CompletableFuture callback) { final JNoise slowBatches = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.1) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.1) .build(); AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); @@ -62,7 +62,7 @@ class TrafficLightRace extends StatelessGame { } for(int z = this.preRun; z <= this.length + this.preRun; z++) { - batch.setBlock(x, 50, z, slowBatches.getNoise(x, z) > 0.6 ? Block.SOUL_SAND : BlockPallet.STREET.rnd()); + batch.setBlock(x, 50, z, slowBatches.evaluateNoise(x, z) > 0.6 ? Block.SOUL_SAND : BlockPallet.STREET.rnd()); } for(int z = this.preRun + this.length; z <= this.preRun + this.length + this.afterRun; z++) { diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java index 08bc107..899f8bc 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java @@ -15,8 +15,7 @@ import net.minestom.server.entity.EntityType; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.entity.metadata.other.FallingBlockMeta; -import net.minestom.server.event.player.PlayerStartSneakingEvent; -import net.minestom.server.event.player.PlayerStopSneakingEvent; +import net.minestom.server.event.player.PlayerInputEvent; import net.minestom.server.event.player.PlayerTickEvent; import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; @@ -45,8 +44,7 @@ class TurtleGame extends StatelessGame { this.eventNode() .addListener(PlayerTickEvent.class, this::onPlayerTick) - .addListener(PlayerStartSneakingEvent.class, this::onPlayerStartSneak) - .addListener(PlayerStopSneakingEvent.class, this::onPlayerStopSneak); + .addListener(PlayerInputEvent.class, this::onPlayerInput); } @Override @@ -66,14 +64,10 @@ class TurtleGame extends StatelessGame { } } - private void onPlayerStartSneak(@NotNull PlayerStartSneakingEvent event) { + private void onPlayerInput(@NotNull PlayerInputEvent event) { Player p = event.getPlayer(); - this.turtlePlayerMap.get(p).boostSpeed(); - } - - private void onPlayerStopSneak(@NotNull PlayerStopSneakingEvent event) { - Player p = event.getPlayer(); - this.turtlePlayerMap.get(p).cancelBoost(); + if(event.hasPressedShiftKey()) this.turtlePlayerMap.get(p).boostSpeed(); + if(event.hasReleasedShiftKey()) this.turtlePlayerMap.get(p).cancelBoost(); } protected void onPlayerTick(@NotNull PlayerTickEvent event) { diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/gameObjects/Turtle.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/gameObjects/Turtle.java index 5ba3916..7e83ff2 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/gameObjects/Turtle.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/gameObjects/Turtle.java @@ -1,6 +1,7 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.gameObjects; import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.entity.EntityCreature; @@ -52,7 +53,7 @@ public class Turtle extends EntityCreature { if(this.getInstance() == null) return; this.teleport(this.getPosition().withView(this.player.getPosition().withPitch(this.getPosition().pitch()))); Vec lookingVector = this.player.getPosition().direction().withY(0).mul(100); - this.lookAt(this.getPosition().add(lookingVector.asPosition())); + this.lookAt(this.getPosition().add(new Pos(lookingVector))); } public void move() { diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/hub/Hub.java b/src/main/java/eu/mhsl/minenet/minigames/instance/hub/Hub.java index ae79a8b..1ba0635 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/hub/Hub.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/hub/Hub.java @@ -36,7 +36,7 @@ public class Hub extends MineNetInstance implements Spawnable { this.setChunkLoader(new AnvilLoader(Path.of("maps/hub"))); this.setTime(18000); - this.setTimeRate(0); + this.defaultClock().pause(); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java index 0fd70dc..b2cbf83 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java @@ -9,10 +9,10 @@ import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.event.player.PlayerPacketEvent; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.inventory.click.ClickType; -import net.minestom.server.inventory.condition.InventoryConditionResult; +import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.network.packet.client.play.ClientNameItemPacket; @@ -45,9 +45,9 @@ public class JoinInventory extends InteractableInventory { } @Override - protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) { + protected void onClick(Player player, int slot, Click click, InventoryPreClickEvent event) { if(slot != 2) return; - inventoryConditionResult.setCancel(true); + event.setCancelled(true); player.closeInventory(); this.typedText = this.formatInput(this.typedText); diff --git a/src/main/java/eu/mhsl/minenet/minigames/message/type/TitleMessage.java b/src/main/java/eu/mhsl/minenet/minigames/message/type/TitleMessage.java index 11ddef5..1df6093 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/message/type/TitleMessage.java +++ b/src/main/java/eu/mhsl/minenet/minigames/message/type/TitleMessage.java @@ -2,13 +2,8 @@ package eu.mhsl.minenet.minigames.message.type; import eu.mhsl.minenet.minigames.message.TranslatableMessage; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.text.Component; import net.kyori.adventure.title.Title; -import net.kyori.adventure.title.TitlePart; import net.minestom.server.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnknownNullability; import java.time.Duration; import java.util.function.Consumer; @@ -41,26 +36,6 @@ public class TitleMessage extends TranslatableMessage { @Override public void send(Player p) { - Audience.audience(p).showTitle(new Title() { - @Override - public @NotNull Component title() { - return TitleMessage.this.build(p); - } - - @Override - public @NotNull Component subtitle() { - return TitleMessage.this.subtitle.build(p); - } - - @Override - public @Nullable Times times() { - return TitleMessage.this.times; - } - - @Override - public @UnknownNullability T part(@NotNull TitlePart part) { - return null; - } - }); + Audience.audience(p).showTitle(Title.title(this.build(p), this.subtitle.build(p), this.times)); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java index d76913e..35acaa7 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java +++ b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java @@ -44,11 +44,11 @@ public class Tournament { } return new Rewards( - this.memorialConfiguration.memorialMaterial().namespace().value(), + this.memorialConfiguration.memorialMaterial().key().value(), this.memorialConfiguration.memorialTitle(), this.memorialConfiguration.memorialLore(), this.getGameScores().keySet().stream().map(Player::getUuid).toList(), - this.rewardConfiguration.item().namespace().value(), + this.rewardConfiguration.item().key().value(), itemCount ); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/InteractableInventory.java b/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/InteractableInventory.java index 13a1eab..920fde7 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/InteractableInventory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/InteractableInventory.java @@ -2,24 +2,40 @@ package eu.mhsl.minenet.minigames.shared.inventory; import net.kyori.adventure.text.Component; import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.Inventory; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.inventory.click.ClickType; -import net.minestom.server.inventory.condition.InventoryConditionResult; +import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import org.jetbrains.annotations.NotNull; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; public class InteractableInventory extends Inventory { + private final Map clickActions = new ConcurrentHashMap<>(); + + private record ClickAction(ItemStack item, Consumer callback, boolean closeAfter) { + } + /** * Defines an Inventory with direct callbacks for ItemSlots */ protected InteractableInventory(@NotNull InventoryType inventoryType, @NotNull Component title) { super(inventoryType, title); - this.addInventoryCondition(this::onClick); + this.eventNode().addListener(InventoryPreClickEvent.class, event -> { + event.setCancelled(true); + this.onClick(event.getPlayer(), event.getSlot(), event.getClick(), event); + + ClickAction action = this.clickActions.get(event.getSlot()); + if(action == null) return; + + if(action.closeAfter()) event.getPlayer().closeInventory(); + action.callback().accept(new ItemClick(event.getPlayer(), this, event.getSlot(), action.item(), event.getClick())); + }); } /** @@ -27,13 +43,7 @@ public class InteractableInventory extends Inventory { */ protected void setClickableItem(ItemStack item, int slot, Consumer callback, boolean closeAfter) { this.setItemStack(slot, item); - this.addInventoryCondition((player, clickedSlot, clickType, inventoryConditionResult) -> { - if(clickedSlot == slot) { - if(closeAfter) player.closeInventory(); - callback.accept(new ItemClick(player, this, clickedSlot, item, clickType)); - } - inventoryConditionResult.setCancel(true); - }); + this.clickActions.put(slot, new ClickAction(item, callback, closeAfter)); } protected void setClickableItem(ItemStack item, int slot, Consumer callback) { @@ -62,7 +72,7 @@ public class InteractableInventory extends Inventory { /** * You may want to Override this method to get more generic click events */ - protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) { + protected void onClick(Player player, int slot, Click click, InventoryPreClickEvent event) { } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/ItemClick.java b/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/ItemClick.java index f28ab8f..d7a1051 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/ItemClick.java +++ b/src/main/java/eu/mhsl/minenet/minigames/shared/inventory/ItemClick.java @@ -2,7 +2,7 @@ package eu.mhsl.minenet.minigames.shared.inventory; import net.minestom.server.entity.Player; import net.minestom.server.inventory.Inventory; -import net.minestom.server.inventory.click.ClickType; +import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; public class ItemClick { @@ -10,17 +10,17 @@ public class ItemClick { private final InteractableInventory inventory; private final int clickedSlot; private final ItemStack item; - private final ClickType clickType; + private final Click click; /** * Describes a click on an Item from an IntractableInventory */ - public ItemClick(Player player, InteractableInventory inventory, int clickedSlot, ItemStack item, ClickType clickType) { + public ItemClick(Player player, InteractableInventory inventory, int clickedSlot, ItemStack item, Click click) { this.player = player; this.inventory = inventory; this.clickedSlot = clickedSlot; this.item = item; - this.clickType = clickType; + this.click = click; } public Player getPlayer() { @@ -39,7 +39,7 @@ public class ItemClick { return this.item; } - public ClickType getClickType() { - return this.clickType; + public Click getClick() { + return this.click; } } 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 6e9a312..22249cd 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/util/BatchUtil.java +++ b/src/main/java/eu/mhsl/minenet/minigames/util/BatchUtil.java @@ -2,6 +2,7 @@ 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; @@ -24,27 +25,19 @@ public class BatchUtil { } } - public static void loadAndApplyBatch(Batch batch, InstanceContainer instance, Runnable onFinish) { + public static void loadAndApplyBatch(AbsoluteBlockBatch batch, InstanceContainer instance, Runnable onFinish) { batch.awaitReady(); long[] affectedChunks = BatchUtil.getAffectedChunks(batch); - ChunkUtils.optionalLoadAll(instance, affectedChunks, null).thenRun(() -> batch.apply(instance, onFinish)); + ChunkUtils.optionalLoadAll(instance, affectedChunks, null).thenRun(() -> batch.apply(instance, b -> onFinish.run())); } - public static void loadAndApplyBatchBlocking(Batch batch, InstanceContainer instance) { + public static void loadAndApplyBatchBlocking(AbsoluteBlockBatch 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); - }); + loadChunksTask.thenRun(() -> batch.apply(instance, b -> future.complete(null))); try { future.get(); 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 index f7b9ce1..eb7f6fe 100644 --- 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 @@ -1,6 +1,7 @@ package eu.mhsl.minenet.minigames.world.generator.featureEnriched; -import de.articdive.jnoise.JNoise; +import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; import eu.mhsl.minenet.minigames.util.NumberUtil; import eu.mhsl.minenet.minigames.world.generator.terrain.HeightTerrainGenerator; import net.minestom.server.coordinate.Point; @@ -9,15 +10,13 @@ import java.util.function.Function; public class ValeGenerator extends HeightTerrainGenerator { private final JNoise curves = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.01) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.01) .build(); private final JNoise largeCurves = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.001) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.001) .build(); private Function xShiftMultiplier = multiplier -> 1d; @@ -33,7 +32,7 @@ public class ValeGenerator extends HeightTerrainGenerator { } public int getXShiftAtZ(int z) { - return (int) ((this.curves.getNoise(z) * 32 + this.largeCurves.getNoise(z) * 64) * this.xShiftMultiplier.apply(z) + this.xShiftOffset.apply(z)); + return (int) ((this.curves.evaluateNoise(z) * 32 + this.largeCurves.evaluateNoise(z) * 64) * this.xShiftMultiplier.apply(z) + this.xShiftOffset.apply(z)); } public void setXShiftMultiplier(Function xShiftMultiplier) { 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 877fe46..b5c2d76 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,6 +1,7 @@ package eu.mhsl.minenet.minigames.world.generator.terrain; -import de.articdive.jnoise.JNoise; +import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; import eu.mhsl.minenet.minigames.util.NumberUtil; import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.PlateTerrainGenerator; @@ -17,19 +18,16 @@ public class CircularPlateTerrainGenerator extends PlateTerrainGenerator { protected final Random rnd = new Random(); private final int size; private final JNoise base = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.01) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.01) .build(); private final JNoise batches = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.05) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.05) .build(); private final JNoise peaks = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.1) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.1) .build(); public CircularPlateTerrainGenerator(int size) { @@ -61,11 +59,11 @@ public class CircularPlateTerrainGenerator extends PlateTerrainGenerator { unit.modifier().setBlock(bottom, Block.GRASS_BLOCK); synchronized(this.base) { - double baseNoise = this.base.getNoise(bottom.x(), bottom.z()); + double baseNoise = this.base.evaluateNoise(bottom.x(), bottom.z()); double currentHeight = minTwo(NumberUtil.map(distance, 0, 400, -((double) this.size / 5), 200)) + baseNoise * 8; synchronized(this.batches) { - double elementNoise = this.batches.getNoise(bottom.x(), bottom.z()); + double elementNoise = this.batches.evaluateNoise(bottom.x(), bottom.z()); unit.modifier().fill( bottom, @@ -76,7 +74,7 @@ public class CircularPlateTerrainGenerator extends PlateTerrainGenerator { } synchronized(this.peaks) { - double peakNoise = this.peaks.getNoise(bottom.x(), bottom.z()); + double peakNoise = this.peaks.evaluateNoise(bottom.x(), bottom.z()); if(peakNoise > 0.97 && bottom.distance(new Pos(0, 0, 0)) > (this.size + 20)) { 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 index ae65546..0d456b3 100644 --- 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 @@ -1,6 +1,7 @@ package eu.mhsl.minenet.minigames.world.generator.terrain; -import de.articdive.jnoise.JNoise; +import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; import eu.mhsl.minenet.minigames.util.GeneratorUtils; import eu.mhsl.minenet.minigames.util.NumberUtil; import eu.mhsl.minenet.minigames.world.BlockPallet; @@ -17,19 +18,16 @@ import java.util.function.Function; public class HeightTerrainGenerator extends BaseGenerator { protected final Random rnd = new Random(); private final JNoise base = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.01) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.01) .build(); private final JNoise batches = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.05) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.05) .build(); private final JNoise peaks = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.1) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.1) .build(); private final BlockPallet blockPallet = BlockPallet.STONE; protected Function heightNoiseMultiplier = (Point) -> 16; @@ -43,13 +41,13 @@ public class HeightTerrainGenerator extends BaseGenerator { unit.modifier().setBlock(bottomPoint, this.blockPallet.rnd()); synchronized(this.base) { - double heightNoise = this.base.getNoise(bottomPoint.x(), bottomPoint.z()); + double heightNoise = this.base.evaluateNoise(bottomPoint.x(), bottomPoint.z()); double noiseModifier = heightNoise * this.heightNoiseMultiplier.apply(bottomPoint); double heightModifier = NumberUtil.clamp(this.calculateHeight.apply(bottomPoint) + noiseModifier, 1d, unit.size().y()); if(heightModifier < 1) System.out.println("HEIGHT MODIFIER ILLEGAL"); synchronized(this.batches) { - double batchNoise = this.batches.getNoise(bottomPoint.x(), bottomPoint.z()); + double batchNoise = this.batches.evaluateNoise(bottomPoint.x(), bottomPoint.z()); Block block = batchNoise < 0.9 ? batchNoise > -0.2 ? Block.GRASS_BLOCK : Block.SOUL_SAND : Block.STONE; unit.modifier().fill(bottomPoint, bottomPoint.add(1, heightModifier, 1), block); @@ -77,7 +75,7 @@ public class HeightTerrainGenerator extends BaseGenerator { } synchronized(this.peaks) { - double peakNoise = this.peaks.getNoise(bottomPoint.x(), bottomPoint.z()); + double peakNoise = this.peaks.evaluateNoise(bottomPoint.x(), bottomPoint.z()); if(peakNoise > 0.97 && bottomPoint.distance(new Pos(0, 0, 0)) > (50 + 20)) { 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 765fd95..33cb63e 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,6 +1,7 @@ package eu.mhsl.minenet.minigames.world.generator.terrain; -import de.articdive.jnoise.JNoise; +import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator; +import de.articdive.jnoise.pipeline.JNoise; import eu.mhsl.minenet.minigames.util.NumberUtil; import eu.mhsl.minenet.minigames.world.BlockPallet; import eu.mhsl.minenet.minigames.world.generator.PlateTerrainGenerator; @@ -21,19 +22,16 @@ public class SquarePlateTerrainGenerator extends PlateTerrainGenerator { private final int width; private final int length; private final JNoise base = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.01) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.01) .build(); private final JNoise batches = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.05) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.05) .build(); private final JNoise peaks = JNoise.newBuilder() - .fastSimplex() - .setSeed(this.rnd.nextLong()) - .setFrequency(0.1) + .fastSimplex(FastSimplexNoiseGenerator.newBuilder().setSeed(this.rnd.nextLong()).build()) + .scale(0.1) .build(); public SquarePlateTerrainGenerator(int width, int length) { @@ -82,7 +80,7 @@ public class SquarePlateTerrainGenerator extends PlateTerrainGenerator { unit.modifier().setBlock(bottom, Block.GRASS_BLOCK); synchronized(this.base) { - double baseNoise = this.base.getNoise(bottom.x(), bottom.z()); + double baseNoise = this.base.evaluateNoise(bottom.x(), bottom.z()); double[] possibleHeights = { 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(this.width, 0, 0)), 0, 400, -((double) this.width / 5), 200)) + baseNoise * 8, @@ -93,7 +91,7 @@ public class SquarePlateTerrainGenerator extends PlateTerrainGenerator { double currentHeight = Arrays.stream(possibleHeights).min().getAsDouble(); synchronized(this.batches) { - double elementNoise = this.batches.getNoise(bottom.x(), bottom.z()); + double elementNoise = this.batches.evaluateNoise(bottom.x(), bottom.z()); unit.modifier().fill( bottom, @@ -104,7 +102,7 @@ public class SquarePlateTerrainGenerator extends PlateTerrainGenerator { } synchronized(this.peaks) { - double peakNoise = this.peaks.getNoise(bottom.x(), bottom.z()); + double peakNoise = this.peaks.evaluateNoise(bottom.x(), bottom.z()); if(peakNoise > 0.97 && bottom.distance(new Pos(0, 0, 0)) > (this.width + 20)) { diff --git a/src/main/resources/lang/locales.map.csv b/src/main/resources/lang/locales.map.csv index 6790b7d..a28ce57 100644 --- a/src/main/resources/lang/locales.map.csv +++ b/src/main/resources/lang/locales.map.csv @@ -186,4 +186,8 @@ itemCount;Block Count;Block Anzahl ;; ns:game_ColorJump#;; name;Color Jump;Farbsprung -description;Jump on the right color!;Springe auf die richtige Farbe! \ No newline at end of file +description;Jump on the right color!;Springe auf die richtige Farbe! +;; +ns:game_PlayerRace#;; +name;Player Race;Wettrennen +description;Get to the other side as quickly as possible!;Komme so schnell wie möglich auf die andere Seite! \ No newline at end of file