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