13 Commits

Author SHA1 Message Date
MineTec 26eff149d4 removed deprecated use of old DimensionType constructor and updated map file paths accordingly 2026-08-09 12:35:05 +02:00
jannis 7734b225eb Merge pull request 'added playerrace and updated to version 26.2' (#14) from develop-jannis into develop
Reviewed-on: #14
Reviewed-by: Lars Neuhaus <larslukasneuhaus@gmx.de>
2026-07-31 20:04:15 +00:00
Pupsi 1a9b9f5fd2 added return to player race position check 2026-07-31 13:28:27 +02:00
jannis b0cf527977 removed unnecessary comments 2026-07-29 15:59:08 +02:00
jannis 01646546a3 fixen issues with playerrace and changed the item selection in pillars 2026-07-26 22:03:11 +02:00
jannis 13a0cdde3a changed gametype of playerrace to jumpnrun and changed symbol to dirt path in playerrace 2026-07-20 21:12:33 +02:00
jannis 7d60c74d85 fixed generation ofo elytrarace 2026-07-20 13:47:25 +02:00
MineTec 0d7f1fc646 updated dependencies and updated all usages accordingly, replaced deprecated methods, and updated project to JDK 25 2026-07-19 19:37:44 +02:00
jannis ee421245d1 added translations 2026-07-19 01:50:34 +02:00
jannis d75332927c fixed that something can generate twice in playerrace 2026-07-19 01:31:53 +02:00
jannis 2c579f4afe fixen generating problem and finished logic of playerrace 2026-07-19 01:11:56 +02:00
jannis 82984cf5cf added LadderWall2 and added checkpoints 2026-07-19 00:16:12 +02:00
jannis 41753f2805 Merge pull request 'Finalized ColorJump' (#13) from develop-jannis into develop
Reviewed-on: #13
Reviewed-by: Lars Neuhaus <larslukasneuhaus@gmx.de>
2026-07-15 16:15:14 +00:00
142 changed files with 519 additions and 399 deletions
+7
View File
@@ -3,4 +3,11 @@
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="Minigames" options="-Xlint:deprecation" />
<module name="Minigames.test" options="-Xlint:deprecation" />
<module name="eu.mhsl.minenet.Minigames.main" options="-Xlint:deprecation" />
</option>
</component>
</project>
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK" />
</project>
+17 -40
View File
@@ -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"
}
Binary file not shown.
+3 -1
View File
@@ -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
Vendored
+7 -11
View File
@@ -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.
Vendored
+12 -24
View File
@@ -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%
@@ -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();
@@ -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)
)
@@ -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())
)
);
@@ -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) {
@@ -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<PlayerTickEvent> {
private static final int TICKS_REQUIRED_TO_FREEZE = 140;
@Override
public @NotNull Class<PlayerTickEvent> 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;
}
}
@@ -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<DimensionType> key;
public final Key namespaceID;
public final RegistryKey<DimensionType> key;
Dimension(NamespaceID namespaceID, DimensionType dimType) {
Dimension(Key namespaceID, DimensionType dimType) {
this.DIMENSION = dimType;
this.namespaceID = namespaceID;
@@ -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<DimensionType> type) {
super(UUID.randomUUID(), type);
public MineNetInstance(RegistryKey<DimensionType> 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<DimensionType> type) {
super(uuid, type, Key.key("minenet", "instance-" + uuid));
MinecraftServer.getInstanceManager().registerInstance(this);
this.eventNode()
@@ -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> dimensionType) {
public Game(RegistryKey<DimensionType> dimensionType) {
super(dimensionType);
MinecraftServer.getInstanceManager().registerInstance(this);
@@ -54,7 +54,7 @@ public enum GameList {
PILLARS(new PillarsFactory(), GameType.PROTOTYPE),
BLOCKBATTLE(new BlockBattleFactory(), GameType.PVP),
COLORJUMP(new ColorJumpFactory(), GameType.JUMPNRUN),
PLAYERRACE(new PlayerRaceFactory(), GameType.PROTOTYPE);
PLAYERRACE(new PlayerRaceFactory(), GameType.JUMPNRUN);
private final GameFactory factory;
private final GameType type;
@@ -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> dimensionType, String gameName, Score score) {
public StatelessGame(RegistryKey<DimensionType> dimensionType, String gameName, Score score) {
super(dimensionType);
this.score = score;
this.name = gameName;
@@ -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;
@@ -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);
}
@@ -26,6 +26,7 @@ import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.timer.ExecutionType;
import net.minestom.server.timer.TaskSchedule;
import net.minestom.server.world.DimensionType;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -41,7 +42,7 @@ public class Bedwars extends StatelessGame {
public Bedwars() throws IOException {
super(Dimension.OVERWORLD.key, "Bedwars", new LastWinsScore());
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("bedwars/test")));
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("bedwars/test"), DimensionType.OVERWORLD.key()));
Configuration config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(Resource.GAME_MAP.getPath().resolve("bedwars/test/config.yml").toFile());
List<String> teamNames = config.getStringList("setup.teams");
@@ -15,6 +15,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.anvil.AnvilLoader;
import net.minestom.server.instance.block.Block;
import net.minestom.server.world.DimensionType;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
@@ -23,7 +24,7 @@ import java.util.concurrent.CompletableFuture;
public class BoatRace extends StatelessGame {
public BoatRace() {
super(Dimension.OVERWORLD.key, "boatRace", new FirstWinsScore());
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("boatRace/woodlandMansion")));
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("boatRace/woodlandMansion"), DimensionType.OVERWORLD.key()));
}
@Override
@@ -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);
@@ -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 -> {
@@ -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<String> 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<Material> 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<Material> 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<Material> 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);
});
}
}
@@ -2,17 +2,55 @@ 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.LastWinsScore;
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<Player, Double> zLine = new WeakHashMap<>();
private final Map<Player, Double> zSpawnPoint = new WeakHashMap<>();
private final int obstacleCount;
public PlayerRace(int obstacleCount) {
super(Dimension.THE_END.key, "PlayerRace", new LastWinsScore());
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<Void> 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
@@ -20,10 +58,29 @@ public class PlayerRace extends StatelessGame {
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)
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());
}
}
@@ -52,7 +52,7 @@ public class PlayerRaceChunkgenerator extends BaseGenerator {
private static Block groundBlockAt(int z, int finishStart, int finishEnd) {
if(z < 0 || z >= finishEnd) return null;
if(z < START_LENGTH) return Block.AMETHYST_BLOCK;
if(z < START_LENGTH) return BlockPallet.GROUND.rnd();
if(z >= finishStart) return Block.DIAMOND_BLOCK;
int relative = (z - START_LENGTH) % PERIOD;
@@ -30,7 +30,7 @@ public class PlayerRaceFactory implements GameFactory {
@Override
public Material symbol() {
return Material.GRASS_BLOCK;
return Material.DIRT_PATH;
}
@Override
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Dichter Bambushain: Die dünnen Halme haben kleine Hitboxen —
* wer sich geschickt durchschlängelt, verliert kaum Tempo.
*/
class BambooThicket extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -1,20 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Basaltdeltas-Säulenfeld: Hohe Basaltsäulen mit Seelenlaternen bilden
* einen düsteren Hindernisparcours zum Durchkurven.
*/
class BasaltPillars extends Obstacle {
private final JNoise ground = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.13)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.13)
.build();
@Override
@@ -22,7 +19,7 @@ class BasaltPillars extends Obstacle {
Random rnd = seededRandom(start);
forEachColumn(start, point -> {
double noise = this.ground.getNoise(point.blockX(), point.blockZ());
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);
});
@@ -6,11 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Süßbeerenfeld: Die Büsche bremsen stark. Ein geschwungener Trampelpfad
* führt hindurch, ist aber in der Mitte selbst zugewuchert —
* ganz ohne Gestrüpp kommt hier niemand durch.
*/
class BerryPatch extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Ausgetrocknetes Flussbett: Ein zwei Blöcke tiefer Graben quer zur Strecke,
* auf dessen Grund bemooste Findlinge liegen. Rein springen, durchkämpfen, rausklettern.
*/
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};
@@ -6,11 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* End-Ruine: Zwei Endstein-Ziegelmauern (nicht überspringbar) mit versetzten,
* schmalen Durchgängen, dazwischen ein dichtes Chorus-Dickicht und
* Purpur-Trümmer. Passt zur End-Dimension des Spiels.
*/
class ChorusGrove extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -1,20 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Verlassener Fichtenhain: Spinnweben zwischen alten Baumstümpfen
* bremsen jeden, der nicht sauber um sie herumläuft.
*/
class CobwebGrove extends Obstacle {
private final JNoise soil = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.12)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.12)
.build();
@Override
@@ -22,7 +19,7 @@ class CobwebGrove extends Obstacle {
Random rnd = seededRandom(start);
forEachColumn(start, point -> {
Block floor = this.soil.getNoise(point.blockX(), point.blockZ()) > 0 ? Block.PODZOL : Block.COARSE_DIRT;
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);
@@ -6,11 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Tropfsteinkamm: Drei Zackenreihen aus Dripstone-Sockeln mit Stalagmiten
* obendrauf sind unpassierbar — nur die versetzten Lücken führen hindurch.
* Dazwischen ragen weitere Stalagmiten aus dem Boden.
*/
class DripstoneSpikes extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Gläsernes Labyrinth auf Quarzboden: Fast unsichtbare Glasscheiben-Wände
* mit versetzten Lücken — wer rast, läuft dagegen.
*/
class GlassPaneWeave extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Bauernhof-Hürdenlauf: Vier Reihen Strohballen — die flachen müssen ohne
* Lücke übersprungen werden, die hohen zwingen durch eine schmale Gasse.
*/
class HayHurdles extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -1,20 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Honigwaben-Feld: klebrige Honigflecken im Boden bremsen, zwei Honigwände
* mit versetzten Durchlässen zwingen in eine Zickzack-Linie.
*/
class HoneyField extends Obstacle {
private final JNoise sticky = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.2)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.2)
.build();
@Override
@@ -22,7 +19,7 @@ class HoneyField extends Obstacle {
Random rnd = seededRandom(start);
forEachColumn(start, point -> {
boolean stickyFloor = this.sticky.getNoise(point.blockX(), point.blockZ()) > 0.35;
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);
});
@@ -1,20 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Spiegelglatte Eisfläche: Blue-Ice-Streifen beschleunigen unkontrolliert,
* zwei Eiswände mit versetzten Durchlässen müssen rutschend getroffen werden.
*/
class IceRink extends Obstacle {
private final JNoise streaks = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.15)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.15)
.build();
@Override
@@ -22,7 +19,7 @@ class IceRink extends Obstacle {
Random rnd = seededRandom(start);
forEachColumn(start, point -> {
double noise = this.streaks.getNoise(point.blockX(), point.blockZ());
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);
@@ -7,11 +7,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Alte Festungsmauer quer über die Strecke: Drei Blöcke hoch, zu hoch zum
* Springen — nur an manchen Säulen hängen Leitern, den Aufstieg muss man
* erst finden. Auf der Rückseite geht es überall hinunter.
*/
class LadderWall extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -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<Integer> 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"));
}
}
}
}
}
@@ -7,10 +7,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Heckengarten: Zwei Blöcke hohe Azaleen-Hecken mit versetzten Durchgängen,
* dazwischen blühen Blumen — hübsch, aber im Weg.
*/
class LeafHedges extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -1,21 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Mangroven-Schlammbecken: Die Becken liegen einen Block tief — man fällt in
* den zähen Schlamm und muss sich wieder herauskämpfen, während
* Mangrovenwurzeln die trockenen Umwege versperren.
*/
class MudPools extends Obstacle {
private final JNoise pools = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.11)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.11)
.build();
@Override
@@ -24,7 +20,7 @@ class MudPools extends Obstacle {
forEachColumn(start, point -> {
int z = relZ(point, start);
double noise = this.pools.getNoise(point.blockX(), point.blockZ());
double noise = this.pools.evaluateNoise(point.blockX(), point.blockZ());
boolean pool = z >= 1 && z <= 14 && noise > 0.05;
if(pool) {
@@ -1,14 +1,15 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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()
.fastSimplex()
.setFrequency(0.1)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.1)
.build();
@Override
@@ -16,7 +17,7 @@ class Mudpit extends Obstacle {
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.getNoise(point.blockX(), point.blockZ()) * modifier;
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);
});
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Riesenpilz-Wäldchen auf Myzel: Die breiten Kappen hängen so tief, dass man
* darunter nur kriechend durchkommt — oder außen eng um die Stiele kurvt.
*/
class MushroomRoofs extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -4,6 +4,7 @@ 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;
@@ -32,20 +33,22 @@ public abstract class Obstacle {
new MushroomRoofs(),
new SandDunes(),
new LadderWall(),
new LadderWall2(),
new GlassPaneWeave(),
new BoulderTrench(),
new BambooThicket()
);
/**
* Generiert das Hindernis ab {@code start} (16 breit, {@link #LENGTH} lang).
* {@code unit} kann ein Fork sein, der über Chunk-Grenzen reicht — daher nie
* über die Unit-Bounds iterieren, sondern über {@link #forEachColumn(Point, Consumer)}.
*/
public abstract void generate(GenerationUnit unit, Point start);
public static Obstacle getRandomObstacle() {
return obstacles.get(ThreadLocalRandom.current().nextInt(obstacles.size()));
private static final List<Obstacle> 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<Point> callback) {
@@ -1,23 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Verschneites Feld voller Pulverschnee-Verwehungen: Sie liegen auf dem Boden
* statt darunter — man watet stark gebremst hindurch, bleibt aber nie stecken
* (aus einer Grube käme man ohne Lederstiefel nicht mehr heraus).
* Die geschwungene Packeis-Spur ist schnell, aber rutschig — und selbst dort
* lauern vereinzelte Verwehungen.
*/
class PowderSnowField extends Obstacle {
private final JNoise drifts = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.14)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.14)
.build();
@Override
@@ -28,7 +22,7 @@ class PowderSnowField extends Obstacle {
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.getNoise(point.blockX(), point.blockZ());
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);
@@ -1,20 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Wüstendünen: Sanfte Sandhügel kosten beim Rauflaufen Sprungkraft und Tempo,
* vertrocknete Büsche krönen die Kämme. An den Chunk-Rändern flacht das Feld ab.
*/
class SandDunes extends Obstacle {
private final JNoise dunes = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.08)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.08)
.build();
@Override
@@ -23,7 +20,7 @@ class SandDunes extends Obstacle {
forEachColumn(start, point -> {
double taper = -1.25 * Math.cos(relZ(point, start) * Math.PI / 7.5) + 1.25;
double noise = (this.dunes.getNoise(point.blockX(), point.blockZ()) + 1) / 2;
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++) {
@@ -1,20 +1,17 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
import de.articdive.jnoise.JNoise;
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;
/**
* Schleimmorast: Der Großteil des Bodens ist Slime — bremst stark und lässt
* Springer unkontrolliert abprallen. Nur schmale Moos-Inseln bieten Halt.
*/
class SlimePatches extends Obstacle {
private final JNoise blobs = JNoise.newBuilder()
.fastSimplex()
.setFrequency(0.18)
.perlin(PerlinNoiseGenerator.newBuilder().build())
.scale(0.18)
.build();
@Override
@@ -23,7 +20,7 @@ class SlimePatches extends Obstacle {
forEachColumn(start, point -> {
int z = relZ(point, start);
boolean slime = z >= 1 && z <= 14 && this.blobs.getNoise(point.blockX(), point.blockZ()) > -0.2;
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) {
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Mauer-Slalom: Steinmauern sind zu hoch zum Überspringen, die Durchgänge
* liegen abwechselnd links und rechts — volle Breite Zickzack.
*/
class WallSlalom extends Obstacle {
@Override
public void generate(GenerationUnit unit, Point start) {
@@ -6,10 +6,6 @@ import net.minestom.server.instance.generator.GenerationUnit;
import java.util.Random;
/**
* Breiter Wassergraben mit schmalen Sandufern: Fast der ganze Chunk muss
* durchschwommen werden, nur vereinzelte Seerosenblätter helfen Mutigen.
*/
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};
@@ -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()));
@@ -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;
@@ -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;
@@ -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<Void> 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++) {
@@ -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) {
@@ -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() {
@@ -12,8 +12,7 @@ import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerBlockInteractEvent;
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
import net.minestom.server.instance.anvil.AnvilLoader;
import java.nio.file.Path;
import net.minestom.server.world.DimensionType;
public class Hub extends MineNetInstance implements Spawnable {
public static final Hub INSTANCE = new Hub();
@@ -21,7 +20,7 @@ public class Hub extends MineNetInstance implements Spawnable {
static {
MinecraftServer.getInstanceManager().registerInstance(INSTANCE);
INSTANCE.setChunkLoader(new AnvilLoader(Resource.HUB_MAP.getPath()));
INSTANCE.setChunkLoader(new AnvilLoader(Resource.HUB_MAP.getPath(), DimensionType.OVERWORLD.key()));
INSTANCE.eventNode()
.addListener(PlayerBlockBreakEvent.class, CommonEventHandles::cancel)
@@ -33,10 +32,9 @@ public class Hub extends MineNetInstance implements Spawnable {
private Hub() {
super(Dimension.THE_END.key);
this.setChunkLoader(new AnvilLoader(Path.of("maps/hub")));
this.setTime(18000);
this.setTimeRate(0);
this.defaultClock().pause();
}
@@ -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);
@@ -18,6 +18,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.instance.anvil.AnvilLoader;
import net.minestom.server.world.DimensionType;
import java.util.*;
import java.util.logging.Logger;
@@ -102,7 +103,7 @@ public class Room extends MineNetInstance implements Spawnable {
private void construct() {
MinecraftServer.getInstanceManager().registerInstance(this);
this.setChunkLoader(new AnvilLoader(Resource.LOBBY_MAP.getPath()));
this.setChunkLoader(new AnvilLoader(Resource.LOBBY_MAP.getPath(), DimensionType.OVERWORLD.key()));
this.gameSelector = new GameSelector();
this.gameSelector.setInstance(this, new Pos(0.5, 50, 19.5));
@@ -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 <T> @UnknownNullability T part(@NotNull TitlePart<T> part) {
return null;
}
});
Audience.audience(p).showTitle(Title.title(this.build(p), this.subtitle.build(p), this.times));
}
}
@@ -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
);
}
@@ -12,6 +12,7 @@ import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.anvil.AnvilLoader;
import net.minestom.server.world.DimensionType;
import java.util.Comparator;
import java.util.List;
@@ -29,7 +30,7 @@ public class TournamentDisplay extends MineNetInstance implements Spawnable {
public TournamentDisplay(Tournament tournament) {
super(Dimension.OVERWORLD.key);
this.setChunkLoader(new AnvilLoader(Resource.RESULT_DISPLAY.getPath()));
this.setChunkLoader(new AnvilLoader(Resource.RESULT_DISPLAY.getPath(), DimensionType.OVERWORLD.key()));
this.places = tournament.getPlaces();
this.tournament = tournament;
@@ -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<Integer, ClickAction> clickActions = new ConcurrentHashMap<>();
private record ClickAction(ItemStack item, Consumer<ItemClick> 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<ItemClick> 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<ItemClick> 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) {
}
}
@@ -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;
}
}
@@ -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<Void> future = new CompletableFuture<>();
batch.awaitReady();
long[] affectedChunks = BatchUtil.getAffectedChunks(batch);
CompletableFuture<Void> 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();
@@ -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<Integer, Double> 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<Integer, Double> xShiftMultiplier) {
@@ -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)) {
@@ -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<Point, Integer> 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)) {
@@ -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)) {
+5 -1
View File
@@ -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!
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!
1 map en_us de_de
186
187 ns:game_ColorJump#
188 name Color Jump Farbsprung
189 description Jump on the right color! Springe auf die richtige Farbe!
190
191 ns:game_PlayerRace#
192 name Player Race Wettrennen
193 description Get to the other side as quickly as possible! Komme so schnell wie möglich auf die andere Seite!

Some files were not shown because too many files have changed in this diff Show More