Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14f6a38212 | |||
| 3bdc4113c0 | |||
| b7e292fe0e | |||
| 57cd5acdfd | |||
| 0f72b8049d | |||
| 9992b07ed5 | |||
| f55148203e | |||
| 9bdb98cdc9 | |||
| 6f0ebe4d12 | |||
| 58983be156 | |||
| ee7d434d7e | |||
| 410f7b4027 | |||
| e1515200ab | |||
| 27005f4fc4 | |||
| 2808393c23 | |||
| d0825695b3 | |||
| e822a5c5e2 | |||
| bf95c8dcc2 | |||
| 2f70b25e87 | |||
| cbec1ea7f8 | |||
| c176cfaf2c | |||
| 56f56d48b6 | |||
| 991e51bc10 | |||
| ffba86ac41 | |||
| f95c670514 | |||
| 0b3c757ce0 | |||
| 76df6643db | |||
| 7186b4dbea | |||
| 24d79d7a11 | |||
| 70fd5bafdb | |||
| 11ddd01470 | |||
| 7d5fb025bd | |||
| 05240660f2 | |||
| d0031b4ea5 | |||
| 360266339d | |||
| 325fba2a53 | |||
| e760cdb2c6 | |||
| c111c027ff | |||
| 73ab137ae4 | |||
| 9a9e646288 | |||
| 728dc92fc8 | |||
| 2f8ff36e5e | |||
| 5cb71c5c32 | |||
| 5ab42fde4b | |||
| d5c2f06409 | |||
| 1ff8cca7e9 | |||
| 47c40c4941 | |||
| d4a7fcada7 | |||
| a0124f1bcb | |||
| c79fbf3136 | |||
| 660eb645e4 | |||
| 3c50aca1e8 | |||
| 865cdfa605 | |||
| fe88e3f921 | |||
| 5e94479949 | |||
| b15c9c97b0 | |||
| 334e130cf6 | |||
| 31385fbd7f | |||
| b1b1e24104 |
Generated
+1
-1
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Minigames" />
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="25" />
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+1
-1
@@ -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_25" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
Generated
+1
@@ -4,6 +4,7 @@
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Minigames.main.iml" filepath="$PROJECT_DIR$/.idea/modules/Minigames.main.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Minigames.test.iml" filepath="$PROJECT_DIR$/.idea/modules/Minigames.test.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/eu.mhsl.minenet.Minigames.main.iml" filepath="$PROJECT_DIR$/.idea/modules/eu.mhsl.minenet.Minigames.main.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+4
@@ -10,4 +10,8 @@
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+7
-7
@@ -3,7 +3,7 @@
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id "com.github.johnrengelman.shadow" version "8.1.1"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.0"
|
||||
}
|
||||
|
||||
group 'eu.mhsl.minenet'
|
||||
@@ -35,7 +35,7 @@ allprojects {
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(25)
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ dependencies {
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
|
||||
|
||||
//https://jitpack.io/#Minestom/Minestom
|
||||
implementation 'net.minestom:minestom:2025.10.11-1.21.10'
|
||||
implementation 'net.minestom:minestom-snapshots:fd51c8d17a'
|
||||
|
||||
//Tools
|
||||
implementation 'de.articdive:jnoise:3.0.2'
|
||||
@@ -57,12 +57,12 @@ dependencies {
|
||||
|
||||
|
||||
//PvP
|
||||
implementation 'io.github.TogAr2:MinestomPvP:56a831b41cb2ec6db8da681ad5d212ed7c71e3ee'
|
||||
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("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")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -3,13 +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 io.github.togar2.pvp.MinestomPvP;
|
||||
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;
|
||||
@@ -26,7 +25,7 @@ public class Main {
|
||||
public static ConfigurationNode globalConfig;
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
static void main() throws ConfigurateException {
|
||||
public 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
|
||||
@@ -41,35 +40,29 @@ public class Main {
|
||||
|
||||
logger.info("Initialize Minecraft server...");
|
||||
|
||||
MinecraftServer server = null;
|
||||
if(serverConfig.node("open-to-lan").getBoolean()) OpenToLAN.open();
|
||||
|
||||
if(globalConfig.node("bungeecord", "enabled").getBoolean()) {
|
||||
server = MinecraftServer.init(new Auth.Bungee());
|
||||
}
|
||||
|
||||
if(globalConfig.node("velocity", "enabled").getBoolean()) {
|
||||
server = MinecraftServer.init(new Auth.Velocity(Objects.requireNonNull(globalConfig.node("velocity", "secret").getString())));
|
||||
}
|
||||
|
||||
if(server == null) server = MinecraftServer.init();
|
||||
|
||||
MinestomPvP.init();
|
||||
MinecraftServer server = MinecraftServer.init();
|
||||
// MinestomPvP.init();
|
||||
|
||||
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()));
|
||||
System.setProperty("minestom.registry.unsafe-ops", "true");
|
||||
|
||||
Commands.values();
|
||||
Listeners.values();
|
||||
Dimension.values();
|
||||
new HttpServer();
|
||||
|
||||
MinecraftServer.getSchedulerManager().scheduleTask(new TablistUpdateTask(), TaskSchedule.tick(20), TaskSchedule.tick(20));
|
||||
|
||||
logger.info("Starting Minecraft server ... ");
|
||||
|
||||
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();
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ public class PublishRewardCommand extends PrivilegedCommand {
|
||||
|
||||
String rewardRequestJson = new Gson().toJson(room.getTournament().getRewards());
|
||||
HttpRequest giveRewardsRequest = HttpRequest.newBuilder()
|
||||
.uri(new URI("http://10.20.7.1:8080/api/event/reward"))
|
||||
.uri(new URI("http://10.20.9.3:8080/api/event/reward"))
|
||||
.POST(HttpRequest.BodyPublishers.ofString(rewardRequestJson))
|
||||
.build();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class SetMemorialCommand extends PrivilegedCommand {
|
||||
ArgumentString loreArgument = ArgumentType.String("lore");
|
||||
|
||||
materialArgument.setSuggestionCallback(
|
||||
(_, _, suggestion) -> Material
|
||||
(sender, context, suggestion) -> Material
|
||||
.values()
|
||||
.stream()
|
||||
.map(material -> new SuggestionEntry(material.name(), Component.text(material.name())))
|
||||
@@ -35,7 +35,7 @@ public class SetMemorialCommand extends PrivilegedCommand {
|
||||
.getTournament()
|
||||
.setMemorialConfiguration(
|
||||
new MemorialConfiguration(
|
||||
Material.fromKey(context.get(materialArgument)),
|
||||
Material.fromNamespaceId(context.get(materialArgument)),
|
||||
context.get(titleArgument),
|
||||
context.get(loreArgument)
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ public class SetRewardCommand extends PrivilegedCommand {
|
||||
ArgumentStringArray amountsArgument = ArgumentType.StringArray("amount");
|
||||
|
||||
materialArgument.setSuggestionCallback(
|
||||
(_, _, suggestion) -> Material
|
||||
(sender, context, suggestion) -> Material
|
||||
.values()
|
||||
.stream()
|
||||
.map(material -> new SuggestionEntry(material.name(), Component.text(material.name())))
|
||||
@@ -37,7 +37,7 @@ public class SetRewardCommand extends PrivilegedCommand {
|
||||
.getTournament()
|
||||
.setRewardConfiguration(
|
||||
new RewardConfiguration(
|
||||
Material.fromKey(context.get(materialArgument)),
|
||||
Material.fromNamespaceId(context.get(materialArgument)),
|
||||
Arrays.stream(context.get(amountsArgument)).map(Integer::valueOf).collect(Collectors.toList())
|
||||
)
|
||||
);
|
||||
|
||||
@@ -25,6 +25,7 @@ public class SetRoomOwnerCommand extends PrivilegedCommand {
|
||||
});
|
||||
|
||||
this.addSyntax((sender, context) -> {
|
||||
System.out.println("Test");
|
||||
if(sender instanceof Player p) {
|
||||
Player newOwner = MinecraftServer.getConnectionManager().getOnlinePlayerByUsername(context.getRaw("player"));
|
||||
Room.getRoom(p).orElseThrow().setOwner(Objects.requireNonNull(newOwner));
|
||||
|
||||
@@ -2,6 +2,8 @@ package eu.mhsl.minenet.minigames.handler.global;
|
||||
|
||||
import eu.mhsl.minenet.minigames.message.Icon;
|
||||
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.event.EventListener;
|
||||
import net.minestom.server.event.player.PlayerChatEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -14,7 +16,14 @@ public class ChatFormatHandler implements EventListener<PlayerChatEvent> {
|
||||
|
||||
@Override
|
||||
public @NotNull Result run(@NotNull PlayerChatEvent event) {
|
||||
event.setFormattedMessage(new ChatMessage(Icon.CHAT).appendStatic(event.getRawMessage()).build(event.getPlayer()));
|
||||
NamedTextColor color = event.getPlayer().getPermissionLevel() > 0 ? NamedTextColor.AQUA : NamedTextColor.GRAY;
|
||||
event.setFormattedMessage(
|
||||
new ChatMessage(Icon.CHAT)
|
||||
.appendStatic(Component.text(event.getPlayer().getUsername(), color))
|
||||
.appendStatic(Component.text(" > ", NamedTextColor.DARK_GRAY))
|
||||
.appendStatic(event.getRawMessage())
|
||||
.build(event.getPlayer())
|
||||
);
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,49 @@
|
||||
package eu.mhsl.minenet.minigames.instance;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.registry.RegistryKey;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Prebuilt dimensions
|
||||
*/
|
||||
public enum Dimension {
|
||||
OVERWORLD(
|
||||
Key.key("minenet:fullbright_overworld"),
|
||||
NamespaceID.from("minenet:fullbright_overworld"),
|
||||
DimensionType
|
||||
.builder()
|
||||
.ambientLight(1.0f)
|
||||
.ambientLight(2.0f)
|
||||
.build()
|
||||
),
|
||||
|
||||
NETHER(
|
||||
Key.key("minenet:fullbright_nether"),
|
||||
NamespaceID.from("minenet:fullbright_nether"),
|
||||
DimensionType
|
||||
.builder()
|
||||
.ambientLight(1.0f)
|
||||
.ambientLight(2.0f)
|
||||
.effects("minecraft:the_nether")
|
||||
.build()
|
||||
),
|
||||
|
||||
THE_END(
|
||||
Key.key("minenet:fullbright_end"),
|
||||
NamespaceID.from("minenet:fullbright_end"),
|
||||
DimensionType
|
||||
.builder()
|
||||
.ambientLight(1.0f)
|
||||
.ambientLight(2.0f)
|
||||
.effects("minecraft:the_end")
|
||||
.build()
|
||||
);
|
||||
|
||||
public final DimensionType DIMENSION;
|
||||
public final Key namespaceID;
|
||||
public final RegistryKey<@NotNull DimensionType> key;
|
||||
public final NamespaceID namespaceID;
|
||||
public final DynamicRegistry.Key<DimensionType> key;
|
||||
|
||||
Dimension(Key namespaceID, DimensionType dimType) {
|
||||
Dimension(NamespaceID namespaceID, DimensionType dimType) {
|
||||
this.DIMENSION = dimType;
|
||||
this.namespaceID = namespaceID;
|
||||
|
||||
this.key = MinecraftServer.getDimensionTypeRegistry().register(this.namespaceID, this.DIMENSION);
|
||||
this.key = MinecraftServer.getDimensionTypeRegistry().register(namespaceID, this.DIMENSION);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,15 +7,14 @@ 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.RegistryKey;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MineNetInstance extends InstanceContainer {
|
||||
public MineNetInstance(RegistryKey<@NotNull DimensionType> type) {
|
||||
public MineNetInstance(DynamicRegistry.Key<DimensionType> type) {
|
||||
super(UUID.randomUUID(), type);
|
||||
MinecraftServer.getInstanceManager().registerInstance(this);
|
||||
|
||||
|
||||
@@ -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.RegistryKey;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
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(RegistryKey<@NotNull DimensionType> dimensionType) {
|
||||
public Game(DynamicRegistry.Key<DimensionType> dimensionType) {
|
||||
super(dimensionType);
|
||||
|
||||
MinecraftServer.getInstanceManager().registerInstance(this);
|
||||
|
||||
@@ -5,14 +5,19 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.acidRain.AcidRain
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.anvilRun.AnvilRunFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.backrooms.BackroomsFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars.BedwarsFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBattle.BlockBattleFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace.BlockBreakRaceFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.boatRace.BoatRaceFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef.BowSpleefFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.colorJump.ColorJumpFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.deathcube.DeathcubeFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace.ElytraRaceFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.fastbridge.FastbridgeFactory;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.highGround.HighGroundFactory;
|
||||
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;
|
||||
@@ -44,7 +49,12 @@ public enum GameList {
|
||||
HIGHGROUND(new HighGroundFactory(), GameType.PVP),
|
||||
FASTBRIDGE(new FastbridgeFactory(), GameType.OTHER),
|
||||
BLOCKBREAKRACE(new BlockBreakRaceFactory(), GameType.OTHER),
|
||||
SPACESNAKE(new SpaceSnakeFactory(), GameType.PVP);
|
||||
SPACESNAKE(new SpaceSnakeFactory(), GameType.PVP),
|
||||
BOATRACE(new BoatRaceFactory(), GameType.OTHER),
|
||||
PILLARS(new PillarsFactory(), GameType.PROTOTYPE),
|
||||
BLOCKBATTLE(new BlockBattleFactory(), GameType.PVP),
|
||||
COLORJUMP(new ColorJumpFactory(), GameType.JUMPNRUN),
|
||||
PLAYERRACE(new PlayerRaceFactory(), GameType.PROTOTYPE);
|
||||
|
||||
private final GameFactory factory;
|
||||
private final GameType type;
|
||||
|
||||
@@ -9,12 +9,11 @@ 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.RegistryKey;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.timer.ExecutionType;
|
||||
import net.minestom.server.timer.Task;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -27,7 +26,7 @@ public class StatelessGame extends Game {
|
||||
private int timeLimit = 0;
|
||||
private int timePlayed = 0;
|
||||
|
||||
public StatelessGame(RegistryKey<@NotNull DimensionType> dimensionType, String gameName, Score score) {
|
||||
public StatelessGame(DynamicRegistry.Key<DimensionType> dimensionType, String gameName, Score score) {
|
||||
super(dimensionType);
|
||||
this.score = score;
|
||||
this.name = gameName;
|
||||
|
||||
+9
-7
@@ -15,7 +15,8 @@ import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
|
||||
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
|
||||
import net.minestom.server.inventory.InventoryType;
|
||||
import net.minestom.server.inventory.click.Click;
|
||||
import net.minestom.server.inventory.click.ClickType;
|
||||
import net.minestom.server.inventory.condition.InventoryConditionResult;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
@@ -38,8 +39,8 @@ public class GameConfigurationInventory extends InteractableInventory {
|
||||
this.factory = factory;
|
||||
|
||||
room.eventNode()
|
||||
.addListener(AddEntityToInstanceEvent.class, _ -> MinecraftServer.getSchedulerManager().scheduleNextTick(this::updatePlayButton))
|
||||
.addListener(RemoveEntityFromInstanceEvent.class, _ -> MinecraftServer.getSchedulerManager().scheduleNextTick(this::updatePlayButton));
|
||||
.addListener(AddEntityToInstanceEvent.class, addEntityToInstanceEvent -> MinecraftServer.getSchedulerManager().scheduleNextTick(this::updatePlayButton))
|
||||
.addListener(RemoveEntityFromInstanceEvent.class, removeEntityFromInstanceEvent -> MinecraftServer.getSchedulerManager().scheduleNextTick(this::updatePlayButton));
|
||||
|
||||
ConfigManager config = factory.configuration();
|
||||
|
||||
@@ -52,7 +53,7 @@ public class GameConfigurationInventory extends InteractableInventory {
|
||||
)
|
||||
.build(),
|
||||
0,
|
||||
itemClick -> itemClick.player().closeInventory(),
|
||||
itemClick -> itemClick.getPlayer().closeInventory(),
|
||||
true
|
||||
);
|
||||
|
||||
@@ -105,7 +106,8 @@ public class GameConfigurationInventory extends InteractableInventory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick(Player player, int slot, Click clickType) {
|
||||
protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) {
|
||||
inventoryConditionResult.setCancel(true);
|
||||
|
||||
if(!this.map.containsKey(slot)) return;
|
||||
|
||||
@@ -131,7 +133,7 @@ public class GameConfigurationInventory extends InteractableInventory {
|
||||
.lore(restrictionHandler.getWarnings(restrictionData).stream().map(translatedComponent -> translatedComponent.getAssembled(this.p)).collect(Collectors.toList()))
|
||||
.build(),
|
||||
8,
|
||||
itemClick -> Game.initialize(this.factory, this.map.values().stream().toList(), itemClick.player()),
|
||||
itemClick -> Game.initialize(this.factory, this.map.values().stream().toList(), itemClick.getPlayer()),
|
||||
true
|
||||
);
|
||||
|
||||
@@ -153,7 +155,7 @@ public class GameConfigurationInventory extends InteractableInventory {
|
||||
this.updatePlayButton();
|
||||
return;
|
||||
}
|
||||
itemClick.player().playSound(Sound.sound(SoundEvent.ENTITY_SILVERFISH_DEATH, Sound.Source.AMBIENT, 1f, 1f));
|
||||
itemClick.getPlayer().playSound(Sound.sound(SoundEvent.ENTITY_SILVERFISH_DEATH, Sound.Source.AMBIENT, 1f, 1f));
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBattle;
|
||||
|
||||
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 io.github.togar2.pvp.events.FinalAttackEvent;
|
||||
import io.github.togar2.pvp.feature.CombatFeatures;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.Player;
|
||||
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.instance.batch.AbsoluteBlockBatch;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockBattle extends StatelessGame {
|
||||
private final Team teamBlue = new Team(new Pos(0,101,20).add(0.5).withView(180, 0), Team.Color.BLUE);
|
||||
private final Team teamRed = new Team(new Pos(0, 101, -20).add(0.5), Team.Color.RED);
|
||||
private final int itemCount;
|
||||
|
||||
private final Map<Player, Team> teams = new WeakHashMap<>();
|
||||
|
||||
public BlockBattle(int itemCount) {
|
||||
super(Dimension.THE_END.key, "Block Battle", new FirstWinsScore());
|
||||
|
||||
this.itemCount = itemCount;
|
||||
|
||||
this.eventNode().addChild(
|
||||
CombatFeatures.empty()
|
||||
.add(CombatFeatures.VANILLA_ATTACK)
|
||||
.add(CombatFeatures.VANILLA_DAMAGE)
|
||||
.add(CombatFeatures.VANILLA_KNOCKBACK)
|
||||
.build().createNode()
|
||||
);
|
||||
|
||||
this.eventNode().addListener(FinalAttackEvent.class, finalAttackEvent -> {
|
||||
if(this.isBeforeBeginning) finalAttackEvent.setCancelled(true);
|
||||
finalAttackEvent.setBaseDamage(0);
|
||||
((Player) finalAttackEvent.getTarget()).setHealth(20);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
||||
this.generatePlatform(new Pos(0, 100, 0), Block.GOLD_BLOCK, Block.YELLOW_CONCRETE_POWDER);
|
||||
this.generatePlatform(new Pos(0, 101, 0), Block.AIR, Block.SANDSTONE_SLAB);
|
||||
this.generatePlatform(new Pos(0, 100, 20), Block.BLUE_CONCRETE, Block.BLUE_CONCRETE_POWDER);
|
||||
this.generatePlatform(new Pos(0, 100, -20), Block.RED_CONCRETE, Block.RED_CONCRETE_POWDER);
|
||||
this.generatePlatform(new Pos(-5, 101, -14), Block.RED_STAINED_GLASS, Block.AIR);
|
||||
this.generatePlatform(new Pos(5, 101, 14), Block.BLUE_STAINED_GLASS, Block.AIR);
|
||||
|
||||
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||
|
||||
Pos[] positionsRedGlass = {
|
||||
new Pos(2, 102, -9),
|
||||
new Pos(-1, 103, -9),
|
||||
new Pos(-2, 104, -6),
|
||||
new Pos(-5, 103, -7),
|
||||
new Pos(-7, 102, -10),
|
||||
new Pos(3, 102, -12),
|
||||
new Pos(5, 101, -15)
|
||||
};
|
||||
|
||||
Pos[] positionsBlueGlass = {
|
||||
new Pos(-5, 101, 15),
|
||||
new Pos(-3, 102, 12),
|
||||
new Pos(-2, 102, 9),
|
||||
new Pos(1, 103, 9),
|
||||
new Pos(2, 104, 6),
|
||||
new Pos(5, 103, 7),
|
||||
new Pos(7, 102, 10)
|
||||
};
|
||||
|
||||
for(Pos pos : positionsRedGlass)
|
||||
batch.setBlock(pos, Block.RED_STAINED_GLASS);
|
||||
|
||||
for(Pos pos : positionsBlueGlass)
|
||||
batch.setBlock(pos, Block.BLUE_STAINED_GLASS);
|
||||
|
||||
BatchUtil.loadAndApplyBatch(batch, this, () -> {});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent playerBlockPlaceEvent) {
|
||||
Pos posGoldBlock = new Pos(playerBlockPlaceEvent.getBlockPosition()).sub(0, 1, 0);
|
||||
Block goldBlock = playerBlockPlaceEvent.getInstance().getBlock(posGoldBlock);
|
||||
|
||||
playerBlockPlaceEvent.setCancelled(goldBlock != Block.GOLD_BLOCK);
|
||||
|
||||
playerBlockPlaceEvent.getInstance().scheduler().scheduleNextTick(() -> {
|
||||
Pos middle = new Pos(0, 101, 0);
|
||||
boolean validBlue = true;
|
||||
boolean validRed = true;
|
||||
|
||||
for(int x = middle.blockX()-1; x < middle.blockX()+2; x++) {
|
||||
for(int z = middle.blockZ()-1; z < middle.blockZ()+2; z++) {
|
||||
if(playerBlockPlaceEvent.getInstance().getBlock(x, 101, z) != Block.BLUE_WOOL) {
|
||||
validBlue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!validBlue)
|
||||
break;
|
||||
}
|
||||
|
||||
for(int x = middle.blockX()-1; x < middle.blockX()+2; x++) {
|
||||
for(int z = middle.blockZ()-1; z < middle.blockZ()+2; z++) {
|
||||
if(playerBlockPlaceEvent.getInstance().getBlock(x, 101, z) != Block.RED_WOOL) {
|
||||
validRed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!validRed)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!validBlue && !validRed) return;
|
||||
var winningTeam = validBlue ? Team.Color.BLUE : Team.Color.RED;
|
||||
var winningPlayers = this.teams.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().color().equals(winningTeam))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
this.getScore().insertMultiple(winningPlayers);
|
||||
super.stop();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent playerBlockBreakEvent) {
|
||||
boolean isAllowed = Arrays.stream(Team.Color.values())
|
||||
.map(Team.Color::getMaterial)
|
||||
.map(Material::block)
|
||||
.toList()
|
||||
.contains(playerBlockBreakEvent.getBlock());
|
||||
if(!isAllowed) playerBlockBreakEvent.setCancelled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
||||
if(playerMoveEvent.getNewPosition().y() < 95) {
|
||||
var player = playerMoveEvent.getPlayer();
|
||||
|
||||
player.teleport(
|
||||
this.isBeforeBeginning
|
||||
? this.getSpawn()
|
||||
: this.teams.get(player).spawnPosition()
|
||||
);
|
||||
|
||||
this.giveItems(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
this.setTeams();
|
||||
this.getPlayers().forEach(player -> player.teleport(this.teams.get(player).spawnPosition()).thenRun(() -> {
|
||||
this.giveItems(player);
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
}));
|
||||
}
|
||||
|
||||
private void generatePlatform(Pos center, Block inner, Block outer) {
|
||||
for(int x = center.blockX()-2; x < center.blockX()+3; x++) {
|
||||
for(int z = center.blockZ()-2; z < center.blockZ()+3; z++) {
|
||||
this.setBlock(x, center.blockY(), z, outer);
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = center.blockX()-1; x < center.blockX()+2; x++) {
|
||||
for(int z = center.blockZ()-1; z < center.blockZ()+2; z++) {
|
||||
this.setBlock(x, center.blockY(), z, inner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setTeams() {
|
||||
List<Player> players = new ArrayList<>(this.getPlayers());
|
||||
Collections.shuffle(players);
|
||||
int halfPlayers = players.size()/2;
|
||||
players.subList(0, halfPlayers).forEach(player -> this.teams.put(player, this.teamBlue));
|
||||
players.subList(halfPlayers, players.size()).forEach(player -> this.teams.put(player, this.teamRed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pos getSpawn() {
|
||||
return new Pos(0, 101, 0).add(0.5);
|
||||
}
|
||||
|
||||
private void giveItems(Player player) {
|
||||
player.getInventory().clear();
|
||||
ItemStack item = ItemStack.of(
|
||||
this.teams.get(player).color().getMaterial(),
|
||||
this.itemCount
|
||||
);
|
||||
player.getInventory().addItemStack(item);
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBattle;
|
||||
|
||||
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 BlockBattleFactory implements GameFactory {
|
||||
@Override
|
||||
public TranslatedComponent name() {
|
||||
return TranslatedComponent.byId("game_BlockBattle#name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatedComponent description() {
|
||||
return TranslatedComponent.byId("game_BlockBattle#description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigManager configuration() {
|
||||
return new ConfigManager()
|
||||
.addOption(new NumericOption("itemCount", Material.WHITE_WOOL, TranslatedComponent.byId("game_BlockBattle#itemCount"), 1, 2, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material symbol() {
|
||||
return Material.GREEN_CONCRETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||
return new BlockBattle(configuration.get("itemCount").getAsInt()).setParent(parent);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBattle;
|
||||
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.item.Material;
|
||||
|
||||
public record Team(Pos spawnPosition, Color color) {
|
||||
public enum Color {
|
||||
RED(Material.RED_WOOL),
|
||||
BLUE(Material.BLUE_WOOL);
|
||||
|
||||
private final Material block;
|
||||
|
||||
Color(Material block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return this.block;
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.boatRace;
|
||||
|
||||
import eu.mhsl.minenet.minigames.Resource;
|
||||
import eu.mhsl.minenet.minigames.handler.global.PlayerLoginHandler;
|
||||
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.CommonProperties;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
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.instance.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onPlayerJoin(Player p) {
|
||||
Entity boat = new Entity(EntityType.OAK_BOAT);
|
||||
boat.setInstance(this, this.getSpawn());
|
||||
boat.setSynchronizationTicks(100000);
|
||||
PlayerLoginHandler.globalTeam.addMember(boat.getUuid().toString());
|
||||
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> boat.addPassenger(p));
|
||||
return super.onPlayerJoin(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
||||
for(int z = 9; z <= 32; z++) {
|
||||
this.setBlock(31, 235, z, Block.CHERRY_FENCE.withProperties(CommonProperties.fenceNorthSouth));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
for(int z = 9; z <= 32; z++) {
|
||||
this.setBlock(31, 235, z, Block.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerMove(@NotNull PlayerMoveEvent event) {
|
||||
if (this.isBeforeBeginning) return;
|
||||
|
||||
if(event.getNewPosition().z() > 469) {
|
||||
Player player = event.getPlayer();
|
||||
this.getScore().insertResult(player);
|
||||
|
||||
Entity vehicle = player.getVehicle();
|
||||
if(vehicle != null) {
|
||||
vehicle.removePassenger(player);
|
||||
player.teleport(player.getPosition().withY(y -> y + 3));
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
vehicle.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pos getSpawn() {
|
||||
return new Pos(20, 236, 20, -90, 0);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.boatRace;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.game.Game;
|
||||
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.room.Room;
|
||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||
import net.minestom.server.item.Material;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BoatRaceFactory implements GameFactory {
|
||||
@Override
|
||||
public TranslatedComponent name() {
|
||||
return TranslatedComponent.byId("game_BoatRace#name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material symbol() {
|
||||
return Material.OAK_BOAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||
return new BoatRace().setParent(parent);
|
||||
}
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.colorJump;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.Dimension;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||
import eu.mhsl.minenet.minigames.score.LastWinsScore;
|
||||
import eu.mhsl.minenet.minigames.util.BatchUtil;
|
||||
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.event.inventory.InventoryPreClickEvent;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import net.minestom.server.event.player.PlayerSwapItemEvent;
|
||||
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.timer.Scheduler;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class ColorJump extends StatelessGame {
|
||||
private final List<Block> blocks = List.of(
|
||||
Block.RED_CONCRETE,
|
||||
Block.ORANGE_CONCRETE,
|
||||
Block.YELLOW_CONCRETE,
|
||||
Block.LIME_CONCRETE,
|
||||
Block.LIGHT_BLUE_CONCRETE,
|
||||
Block.BLUE_CONCRETE,
|
||||
Block.PURPLE_CONCRETE,
|
||||
Block.PINK_CONCRETE
|
||||
);
|
||||
private Block currentBlock;
|
||||
private Block blockLastRound;
|
||||
private double roundTime = 5;
|
||||
private final double multiplierNextRoundTime = 0.9;
|
||||
|
||||
public ColorJump() {
|
||||
super(Dimension.THE_END.key, "ColorJump", new LastWinsScore());
|
||||
this.getScore().setIgnoreLastPlayers(1);
|
||||
|
||||
this.setGenerator(new CircularPlateTerrainGenerator(100));
|
||||
|
||||
this.eventNode().addListener(
|
||||
InventoryPreClickEvent.class,
|
||||
inventoryPreClickEvent -> inventoryPreClickEvent.setCancelled(true)
|
||||
);
|
||||
|
||||
this.eventNode().addListener(
|
||||
PlayerSwapItemEvent.class,
|
||||
playerSwapItemEvent -> playerSwapItemEvent.setCancelled(true)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
||||
this.generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
this.nextRound();
|
||||
}
|
||||
|
||||
private void nextRound() {
|
||||
this.generate();
|
||||
do {
|
||||
this.currentBlock = this.blocks.get(ThreadLocalRandom.current().nextInt(this.blocks.size()));
|
||||
} while(this.currentBlock == this.blockLastRound);
|
||||
this.blockLastRound = this.currentBlock;
|
||||
|
||||
ItemStack item = ItemStack.of(Objects.requireNonNull(this.currentBlock.registry().material()));
|
||||
this.getPlayers().forEach(player -> {
|
||||
player.getInventory().clear();
|
||||
for(int i = 0; i < 9; i++) {
|
||||
player.getInventory().setItemStack(i, item);
|
||||
}
|
||||
});
|
||||
|
||||
var scheduler = MinecraftServer.getSchedulerManager();
|
||||
TaskSchedule stop = TaskSchedule.stop();
|
||||
|
||||
scheduler.scheduleTask(() -> {
|
||||
if(!this.isRunning) return stop;
|
||||
this.destroyAllExcept(this.currentBlock);
|
||||
|
||||
scheduler.scheduleTask(() -> {
|
||||
if(this.isRunning) this.nextRound();
|
||||
return stop;
|
||||
}, TaskSchedule.seconds(3));
|
||||
return stop;
|
||||
}, TaskSchedule.seconds((long) this.roundTime));
|
||||
this.roundTime = this.roundTime * this.multiplierNextRoundTime;
|
||||
if(this.roundTime <= 1) this.roundTime = 1;
|
||||
|
||||
long totalTicks = (long) (this.roundTime * 20);
|
||||
this.scheduleExpUpdate(scheduler, totalTicks, totalTicks);
|
||||
}
|
||||
|
||||
private void scheduleExpUpdate(Scheduler scheduler, long remainingTicks, long totalTicks) {
|
||||
if (!this.isRunning) return;
|
||||
|
||||
if (remainingTicks <= 0) {
|
||||
this.getPlayers().forEach(player -> {
|
||||
player.setExp(0f);
|
||||
player.setLevel(0);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
float progress = (float) remainingTicks / totalTicks;
|
||||
|
||||
this.getPlayers().forEach(player -> {
|
||||
player.setExp(progress);
|
||||
player.setLevel((int) Math.ceil(remainingTicks / 20.0));
|
||||
});
|
||||
scheduler.scheduleTask(() -> {
|
||||
this.scheduleExpUpdate(scheduler, remainingTicks -1, totalTicks);
|
||||
return TaskSchedule.stop();
|
||||
}, TaskSchedule.tick(1));
|
||||
}
|
||||
|
||||
private void generate() {
|
||||
int y = 30;
|
||||
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||
|
||||
for (int x = -20; x <= 21; x += 2) {
|
||||
for (int z = -11; z <= 10; z += 2) {
|
||||
Block randomBlock = this.blocks.get(ThreadLocalRandom.current().nextInt(this.blocks.size()));
|
||||
|
||||
for (int dx = 0; dx < 2; dx++) {
|
||||
for (int dz = 0; dz < 2; dz++) {
|
||||
batch.setBlock(x + dx, y, z + dz, randomBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BatchUtil.loadAndApplyBatch(batch, this, () -> {});
|
||||
}
|
||||
|
||||
private void destroyAllExcept(Block block) {
|
||||
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||
int y = 30;
|
||||
|
||||
for (int x = -20; x <= 21; x++) {
|
||||
for(int z = -11; z <= 10; z++) {
|
||||
Pos blockPos = new Pos(x, y, z);
|
||||
if(this.getBlock(blockPos) != block)
|
||||
batch.setBlock(blockPos, Block.AIR);
|
||||
}
|
||||
}
|
||||
BatchUtil.loadAndApplyBatch(batch, this, () -> {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pos getSpawn() {
|
||||
return new Pos(0, 31, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
||||
var player = playerMoveEvent.getPlayer();
|
||||
|
||||
if(playerMoveEvent.getNewPosition().y() >= 29)
|
||||
return;
|
||||
player.teleport(this.getSpawn());
|
||||
if(this.isRunning) {
|
||||
this.getScore().insertResult(player);
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.colorJump;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.game.Game;
|
||||
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.room.Room;
|
||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||
import net.minestom.server.item.Material;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ColorJumpFactory implements GameFactory {
|
||||
|
||||
@Override
|
||||
public TranslatedComponent name() {
|
||||
return TranslatedComponent.byId("game_ColorJump#name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material symbol() {
|
||||
return Material.PINK_CONCRETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatedComponent description() {
|
||||
return TranslatedComponent.byId("game_ColorJump#description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||
return new ColorJump().setParent(parent);
|
||||
}
|
||||
}
|
||||
+1
@@ -35,6 +35,7 @@ class Deathcube extends StatelessGame {
|
||||
.add(CombatFeatures.VANILLA_KNOCKBACK)
|
||||
.build().createNode()
|
||||
);
|
||||
System.out.println(radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-1
@@ -133,7 +133,7 @@ public class ElytraRace extends StatelessGame {
|
||||
return;
|
||||
}
|
||||
|
||||
this.playerCheckpoints.putIfAbsent(player, new CheckPointData(this.ringSpacing, this.ringSpacing * 2));
|
||||
this.playerCheckpoints.putIfAbsent(player, new CheckPointData(0, this.ringSpacing));
|
||||
|
||||
if(newPos.z() > this.generatedUntil - this.ringSpacing) {
|
||||
this.generateRing(this.generatedUntil + this.ringSpacing);
|
||||
@@ -224,7 +224,9 @@ public class ElytraRace extends StatelessGame {
|
||||
}
|
||||
|
||||
private void toCheckpoint(Player p) {
|
||||
CheckPointData data = this.playerCheckpoints.get(p);
|
||||
Point checkpointPos = this.getRingPositionAtZ(this.playerCheckpoints.get(p).currentCheckpoint);
|
||||
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));
|
||||
|
||||
+1
-2
@@ -8,7 +8,6 @@ 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;
|
||||
@@ -51,7 +50,7 @@ class HighGround extends StatelessGame {
|
||||
|
||||
this.eventNode().addListener(
|
||||
EntityKnockbackEvent.class,
|
||||
entityKnockbackEvent -> entityKnockbackEvent.setSettings(new KnockbackSettings(1.1, 1.1, 2, 0, 0))
|
||||
entityKnockbackEvent -> entityKnockbackEvent.setStrength(1.1f)
|
||||
);
|
||||
|
||||
this.eventNode().addListener(InstanceTickEvent.class, instanceTickEvent -> {
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.pillars;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.Dimension;
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||
import eu.mhsl.minenet.minigames.score.LastWinsScore;
|
||||
import eu.mhsl.minenet.minigames.util.Position;
|
||||
import io.github.togar2.pvp.feature.CombatFeatures;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.Player;
|
||||
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.instance.block.Block;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
class Pillars extends StatelessGame {
|
||||
private int spawnPosx = 0;
|
||||
private int spawnPosz = 0;
|
||||
private final int pillarSpacing = 10;
|
||||
private final int pillarRowCount = 5;
|
||||
|
||||
public Pillars() {
|
||||
super(Dimension.THE_END.key, "Pillars", new LastWinsScore());
|
||||
this.getScore().setIgnoreLastPlayers(1);
|
||||
|
||||
this.eventNode().addChild(
|
||||
CombatFeatures.empty()
|
||||
.add(CombatFeatures.VANILLA_ATTACK)
|
||||
.add(CombatFeatures.VANILLA_DAMAGE)
|
||||
.add(CombatFeatures.VANILLA_KNOCKBACK)
|
||||
.build().createNode()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onPlayerJoin(Player p) {
|
||||
Pos pos = new Pos(this.spawnPosx * this.pillarSpacing, 100, this.spawnPosz * this.pillarSpacing);
|
||||
this.setBlock(pos.sub(0, 1, 0), Block.BEDROCK);
|
||||
|
||||
if(this.spawnPosx >= this.pillarRowCount) {
|
||||
this.spawnPosx = 0;
|
||||
this.spawnPosz++;
|
||||
}
|
||||
this.spawnPosx++;
|
||||
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> p.teleport(pos.add(0.5, 0, 0.5)));
|
||||
|
||||
return super.onPlayerJoin(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent playerBlockPlaceEvent) {}
|
||||
|
||||
@Override
|
||||
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent playerBlockBreakEvent) {}
|
||||
|
||||
@Override
|
||||
protected void onItemDrop(@NotNull ItemDropEvent itemDropEvent) {}
|
||||
|
||||
@Override
|
||||
public Pos getSpawn() {
|
||||
return new Pos(0, 105, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
||||
var player = playerMoveEvent.getPlayer();
|
||||
|
||||
if(this.isBeforeBeginning && Position.hasPositionChanged(player.getPosition(), playerMoveEvent.getNewPosition()))
|
||||
playerMoveEvent.setCancelled(true);
|
||||
|
||||
if(playerMoveEvent.getNewPosition().y() < 80) {
|
||||
this.getScore().insertResult(player);
|
||||
player.teleport(this.getSpawn());
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
this.getPlayers().forEach(player -> player.setGameMode(GameMode.SURVIVAL));
|
||||
|
||||
MinecraftServer.getSchedulerManager().submitTask(() -> {
|
||||
List<Material> materials = Material.values().stream()
|
||||
.filter(material -> !material.equals(Material.AIR))
|
||||
.toList();
|
||||
this.getPlayers().forEach(player -> {
|
||||
ItemStack item = ItemStack.of(materials.get(ThreadLocalRandom.current().nextInt(Material.values().toArray().length)));
|
||||
player.getInventory().addItemStack(item);
|
||||
});
|
||||
|
||||
return TaskSchedule.seconds(5);
|
||||
});
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.pillars;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.game.Game;
|
||||
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.room.Room;
|
||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||
import net.minestom.server.item.Material;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class PillarsFactory implements GameFactory {
|
||||
@Override
|
||||
public TranslatedComponent name() {
|
||||
return TranslatedComponent.byId("game_Pillars#name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatedComponent description() {
|
||||
return TranslatedComponent.byId("game_Pillars#description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material symbol() {
|
||||
return Material.BEDROCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||
return new Pillars().setParent(parent);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
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 net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PlayerRace extends StatelessGame {
|
||||
private final int height = 64;
|
||||
|
||||
public PlayerRace(int obstacleCount) {
|
||||
super(Dimension.THE_END.key, "PlayerRace", new LastWinsScore());
|
||||
this.setGenerator(new PlayerRaceChunkgenerator(this.height, obstacleCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pos getSpawn() {
|
||||
return new Pos(8, this.height + 1.5, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
||||
var player = playerMoveEvent.getPlayer();
|
||||
if(playerMoveEvent.getNewPosition().y() < this.height - 5)
|
||||
player.teleport(this.getSpawn());
|
||||
}
|
||||
}
|
||||
+61
@@ -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 Block.AMETHYST_BLOCK;
|
||||
if(z >= finishStart) return Block.DIAMOND_BLOCK;
|
||||
|
||||
int relative = (z - START_LENGTH) % PERIOD;
|
||||
return relative >= Obstacle.LENGTH ? BlockPallet.GROUND.rnd() : null;
|
||||
}
|
||||
}
|
||||
+40
@@ -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<String, Option<?>> configuration) throws Exception {
|
||||
return new PlayerRace(configuration.get("length").getAsInt()).setParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material symbol() {
|
||||
return Material.GRASS_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatedComponent description() {
|
||||
return TranslatedComponent.byId("game_PlayerRace#description");
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void generate(GenerationUnit unit, Point start) {
|
||||
Random rnd = seededRandom(start);
|
||||
|
||||
forEachColumn(start, point -> {
|
||||
double noise = this.ground.getNoise(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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};
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void generate(GenerationUnit unit, Point start) {
|
||||
Random rnd = seededRandom(start);
|
||||
|
||||
forEachColumn(start, point -> {
|
||||
Block floor = this.soil.getNoise(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void generate(GenerationUnit unit, Point start) {
|
||||
Random rnd = seededRandom(start);
|
||||
|
||||
forEachColumn(start, point -> {
|
||||
boolean stickyFloor = this.sticky.getNoise(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void generate(GenerationUnit unit, Point start) {
|
||||
Random rnd = seededRandom(start);
|
||||
|
||||
forEachColumn(start, point -> {
|
||||
double noise = this.streaks.getNoise(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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.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.getNoise(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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.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.getNoise(point.blockX(), point.blockZ()) * modifier;
|
||||
unit.modifier().setBlock(point.withY(heightAtBlock), Block.SOUL_SAND);
|
||||
unit.modifier().setBlock(point.withY(heightAtBlock-1), Block.SOUL_SAND);
|
||||
});
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
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.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<Obstacle> 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 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()));
|
||||
}
|
||||
|
||||
protected static void forEachColumn(Point start, Consumer<Point> 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);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.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.getNoise(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"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.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.getNoise(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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.playerRace.obstacles;
|
||||
|
||||
import de.articdive.jnoise.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)
|
||||
.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.getNoise(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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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};
|
||||
|
||||
@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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -110,7 +110,7 @@ public class SpaceSnake extends StatelessGame {
|
||||
playerMoveEvent.getPlayer().teleport(this.getSpawn());
|
||||
playerMoveEvent.getPlayer().setGameMode(GameMode.SPECTATOR);
|
||||
long livingPlayers = this.getPlayers().stream()
|
||||
.filter(p -> this.getScore().hasResult(p))
|
||||
.filter(p -> !this.getScore().hasResult(p))
|
||||
.count();
|
||||
if(livingPlayers == 1) this.setTimeLimit(10);
|
||||
if(livingPlayers == 0) this.stop();
|
||||
|
||||
+3
-2
@@ -28,7 +28,8 @@ public class StickFightFactory implements GameFactory {
|
||||
@Override
|
||||
public ConfigManager configuration() {
|
||||
return new ConfigManager()
|
||||
.addOption(new NumericOption("length", Material.SANDSTONE, TranslatedComponent.byId("optionCommon#length"), 7, 10, 13, 16, 19));
|
||||
.addOption(new NumericOption("length", Material.SANDSTONE, TranslatedComponent.byId("optionCommon#length"), 7, 10, 13, 16, 19))
|
||||
.addOption(new NumericOption("seconds", Material.CLOCK, TranslatedComponent.byId("optionCommon#seconds"), 30, 60, 90, 120));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,7 +41,7 @@ public class StickFightFactory implements GameFactory {
|
||||
|
||||
@Override
|
||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) {
|
||||
return new Stickfight(configuration.get("length").getAsInt()).setParent(parent);
|
||||
return new Stickfight(configuration.get("length").getAsInt(), configuration.get("seconds").getAsInt()).setParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+14
-1
@@ -10,6 +10,8 @@ import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -22,10 +24,12 @@ public class Stickfight extends StatelessGame {
|
||||
private final WeakHashMap<Player, Pos> spawnPoints = new WeakHashMap<>();
|
||||
private final Map<Player, Integer> scoreMap = new WeakHashMap<>();
|
||||
private boolean countdownStarted = false;
|
||||
private final int seconds;
|
||||
|
||||
public Stickfight(int length) {
|
||||
public Stickfight(int length, int seconds) {
|
||||
super(Dimension.OVERWORLD.key, "Stickfight", new LowestPointsWinScore());
|
||||
this.radius = length;
|
||||
this.seconds = seconds;
|
||||
|
||||
this.eventNode().addChild(
|
||||
CombatFeatures.empty()
|
||||
@@ -79,10 +83,18 @@ public class Stickfight extends StatelessGame {
|
||||
this.generateBridge(spawnX, spawnY, spawnZ);
|
||||
}
|
||||
|
||||
ItemStack item = ItemStack.of(Material.STICK).withGlowing(true);
|
||||
players.forEach(player -> player.getInventory().addItemStack(item));
|
||||
|
||||
this.setBlock(0, 50, 0, Block.GOLD_BLOCK);
|
||||
super.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
this.setTimeLimit(this.seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
this.scoreMap.forEach((player, score) -> this.getScore().insertResult(player, score));
|
||||
@@ -117,6 +129,7 @@ public class Stickfight extends StatelessGame {
|
||||
player.teleport(this.spawnPoints.get(player));
|
||||
this.scoreMap.putIfAbsent(player, 0);
|
||||
this.scoreMap.put(player, this.scoreMap.get(player) + 1);
|
||||
player.setLevel(this.scoreMap.get(player));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-29
@@ -6,16 +6,20 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game.Tetri
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game.Tetromino;
|
||||
import eu.mhsl.minenet.minigames.score.PointsWinScore;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.entity.metadata.display.BlockDisplayMeta;
|
||||
import net.minestom.server.event.player.PlayerHandAnimationEvent;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import net.minestom.server.event.player.PlayerTickEvent;
|
||||
import net.minestom.server.event.player.PlayerUseItemEvent;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -71,21 +75,29 @@ class Tetris extends StatelessGame {
|
||||
@Override
|
||||
protected void onPlayerLeave(Player p) {
|
||||
this.tetrisGames.get(p).sidebar.removeViewer(p);
|
||||
p.clearEffects();
|
||||
this.letPlayerLoose(p);
|
||||
p.setGameMode(GameMode.SURVIVAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerMove(@NotNull PlayerMoveEvent event) {
|
||||
private void onPlayerInteract(@NotNull PlayerUseItemEvent event) {
|
||||
event.setItemUseTime(0);
|
||||
this.tetrisGames.get(event.getPlayer()).pressedButton(TetrisGame.Button.mouseRight);
|
||||
}
|
||||
|
||||
private void onPlayerAttack(@NotNull PlayerHandAnimationEvent event) {
|
||||
this.tetrisGames.get(event.getPlayer()).pressedButton(TetrisGame.Button.mouseLeft);
|
||||
}
|
||||
|
||||
private void onPlayerTick(PlayerTickEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Pos currentPosition = event.getNewPosition();
|
||||
|
||||
TetrisGame tetrisGame = this.tetrisGames.get(player);
|
||||
|
||||
if(tetrisGame == null) {
|
||||
event.setCancelled(true);
|
||||
if(tetrisGame == null) return;
|
||||
if(tetrisGame.lost) {
|
||||
this.letPlayerLoose(player);
|
||||
return;
|
||||
}
|
||||
if(tetrisGame.lost) return;
|
||||
|
||||
if(player.getGameMode() == GameMode.SPECTATOR) return;
|
||||
|
||||
if(player.inputs().forward()) tetrisGame.pressedButton(TetrisGame.Button.W);
|
||||
@@ -93,26 +105,6 @@ class Tetris extends StatelessGame {
|
||||
if(player.inputs().right()) tetrisGame.pressedButton(TetrisGame.Button.D);
|
||||
if(player.inputs().left()) tetrisGame.pressedButton(TetrisGame.Button.A);
|
||||
if(player.inputs().jump()) tetrisGame.pressedButton(TetrisGame.Button.space);
|
||||
|
||||
event.setNewPosition(tetrisGame.getPlayerSpawnPosition().withView(currentPosition));
|
||||
player.setSprinting(false);
|
||||
}
|
||||
|
||||
protected void onPlayerInteract(@NotNull PlayerUseItemEvent event) {
|
||||
this.tetrisGames.get(event.getPlayer()).pressedButton(TetrisGame.Button.mouseRight);
|
||||
}
|
||||
|
||||
protected void onPlayerAttack(@NotNull PlayerHandAnimationEvent event) {
|
||||
this.tetrisGames.get(event.getPlayer()).pressedButton(TetrisGame.Button.mouseLeft);
|
||||
}
|
||||
|
||||
protected void onPlayerTick(PlayerTickEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
TetrisGame tetrisGame = this.tetrisGames.get(player);
|
||||
if(tetrisGame == null) return;
|
||||
if(tetrisGame.lost && player.getGameMode() != GameMode.SPECTATOR) {
|
||||
this.letPlayerLoose(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void letPlayerLoose(Player player) {
|
||||
@@ -120,6 +112,7 @@ class Tetris extends StatelessGame {
|
||||
if(!this.getScore().hasResult(player)) {
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
player.setInvisible(true);
|
||||
if(player.getVehicle() != null) player.getVehicle().removePassenger(player);
|
||||
this.getScore().insertResult(player, tetrisGame.getScore());
|
||||
}
|
||||
|
||||
@@ -157,6 +150,16 @@ class Tetris extends StatelessGame {
|
||||
p.teleport(tetrisGame.getPlayerSpawnPosition());
|
||||
tetrisGame.sidebar.addViewer(p);
|
||||
|
||||
MinecraftServer.getSchedulerManager().scheduleTask(() -> {
|
||||
Entity ghostBlock = new Entity(EntityType.BLOCK_DISPLAY);
|
||||
((BlockDisplayMeta) ghostBlock.getEntityMeta()).setBlockState(Block.AIR);
|
||||
ghostBlock.setNoGravity(true);
|
||||
ghostBlock.setInstance(this, tetrisGame.getPlayerSpawnPosition());
|
||||
ghostBlock.addPassenger(p);
|
||||
return TaskSchedule.stop();
|
||||
}, TaskSchedule.nextTick());
|
||||
|
||||
|
||||
return super.onPlayerJoin(p);
|
||||
}
|
||||
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
||||
|
||||
public enum Orientation {
|
||||
NONE,
|
||||
RIGHT,
|
||||
LEFT,
|
||||
UPSIDE_DOWN;
|
||||
|
||||
public Orientation rotated(boolean clockwise) {
|
||||
return switch(this) {
|
||||
case NONE -> clockwise ? Orientation.RIGHT : Orientation.LEFT;
|
||||
case RIGHT -> clockwise ? Orientation.UPSIDE_DOWN : Orientation.NONE;
|
||||
case UPSIDE_DOWN -> clockwise ? Orientation.LEFT : Orientation.RIGHT;
|
||||
case LEFT -> clockwise ? Orientation.NONE : Orientation.UPSIDE_DOWN;
|
||||
};
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class RotationChecker {
|
||||
private static final Map<Orientation, int[][]> STANDARD_WALL_KICKS = Map.of(
|
||||
Orientation.NONE, new int[][] {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}},
|
||||
Orientation.RIGHT, new int[][] {{0,0}, {1,0}, {1,-1}, {0,2}, {1,2}},
|
||||
Orientation.UPSIDE_DOWN, new int[][] {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}},
|
||||
Orientation.LEFT, new int[][] {{0,0}, {-1,0}, {-1,-1}, {0,2}, {-1,2}}
|
||||
);
|
||||
|
||||
private static final Map<Orientation, int[][]> I_WALL_KICKS = Map.of(
|
||||
Orientation.NONE, new int[][] {{0,0}, {-1,0}, {2,0}, {-1,0}, {2,0}},
|
||||
Orientation.RIGHT, new int[][] {{-1,0}, {0,0}, {0,0}, {0,1}, {0,-2}},
|
||||
Orientation.UPSIDE_DOWN, new int[][] {{-1,1}, {1,1}, {-2,1}, {1,0}, {-2,0}},
|
||||
Orientation.LEFT, new int[][] {{0,1}, {0,1}, {0,1}, {0,-1}, {0,2}}
|
||||
);
|
||||
|
||||
private static final Map<Orientation, int[][]> O_WALL_KICKS = Map.of(
|
||||
Orientation.NONE, new int[][] {{0,0}},
|
||||
Orientation.RIGHT, new int[][] {{0,-1}},
|
||||
Orientation.UPSIDE_DOWN, new int[][] {{-1,-1}},
|
||||
Orientation.LEFT, new int[][] {{-1,0}}
|
||||
);
|
||||
|
||||
public static int[][] getKicksArray(Orientation from, Orientation to, Tetromino.Shape shape) {
|
||||
int[][] firstOffsets = getOffsetData(from, shape);
|
||||
int[][] secondOffsets = getOffsetData(to, shape);
|
||||
int[][] result = new int[firstOffsets.length][2];
|
||||
|
||||
for(int i = 0; i < firstOffsets.length; i++) {
|
||||
result[i] = subtractInt(firstOffsets[i], secondOffsets[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] subtractInt(int[] first, int[] second) {
|
||||
return IntStream.range(0, first.length)
|
||||
.map(i -> first[i] - second[i])
|
||||
.toArray();
|
||||
}
|
||||
|
||||
private static int[][] getOffsetData(Orientation orientation, Tetromino.Shape shape) {
|
||||
return switch(shape) {
|
||||
case J, L, S, T, Z -> STANDARD_WALL_KICKS.get(orientation);
|
||||
case I -> I_WALL_KICKS.get(orientation);
|
||||
case O -> O_WALL_KICKS.get(orientation);
|
||||
};
|
||||
}
|
||||
}
|
||||
+91
-35
@@ -2,10 +2,9 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.scoreboard.Sidebar;
|
||||
import net.minestom.server.timer.Scheduler;
|
||||
import net.minestom.server.timer.Task;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
|
||||
import java.util.*;
|
||||
@@ -23,6 +22,9 @@ public class TetrisGame {
|
||||
private final Map<Button, Long> lastPresses = new HashMap<>();
|
||||
private final List<TetrisGame> otherTetrisGames = new ArrayList<>();
|
||||
private final Random random;
|
||||
private Task tetrominoLockTask;
|
||||
private int lockDelayResets;
|
||||
private int currentTetrominoLowestY = Integer.MAX_VALUE;
|
||||
public boolean lost = false;
|
||||
public boolean paused = true;
|
||||
public Tetromino currentTetromino;
|
||||
@@ -54,24 +56,27 @@ public class TetrisGame {
|
||||
}
|
||||
|
||||
public void pressedButton(Button button) {
|
||||
final int standardButtonDelay = 100;
|
||||
final int buttonDebounce = 70;
|
||||
final int standardButtonDelay = 95;
|
||||
final int wsButtonDebounce = 70;
|
||||
|
||||
if(this.lastPresses.getOrDefault(button, 0L) >= System.currentTimeMillis() - standardButtonDelay) return;
|
||||
|
||||
this.lastPresses.put(button, System.currentTimeMillis());
|
||||
if(button == Button.W) this.lastPresses.put(button, System.currentTimeMillis() + buttonDebounce);
|
||||
if(button == Button.S) this.lastPresses.put(button, System.currentTimeMillis() - buttonDebounce);
|
||||
switch(button) {
|
||||
case W -> this.lastPresses.put(button, System.currentTimeMillis() + wsButtonDebounce);
|
||||
case S -> this.lastPresses.put(button, System.currentTimeMillis() - wsButtonDebounce);
|
||||
case mouseLeft, mouseRight -> this.lastPresses.put(button, 0L);
|
||||
default -> this.lastPresses.put(button, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
if(this.lost || this.paused) return;
|
||||
|
||||
switch(button) {
|
||||
case A -> this.currentTetromino.moveLeft();
|
||||
case A -> this.moveLeft();
|
||||
case S -> this.moveDown();
|
||||
case D -> this.currentTetromino.moveRight();
|
||||
case D -> this.moveRight();
|
||||
case W -> this.hardDrop();
|
||||
case mouseLeft -> this.currentTetromino.rotate(false);
|
||||
case mouseRight -> this.currentTetromino.rotate(true);
|
||||
case mouseLeft -> this.rotate(false);
|
||||
case mouseRight -> this.rotate(true);
|
||||
case space -> this.switchHold();
|
||||
}
|
||||
}
|
||||
@@ -82,8 +87,7 @@ public class TetrisGame {
|
||||
|
||||
public void start() {
|
||||
this.paused = false;
|
||||
Scheduler scheduler = MinecraftServer.getSchedulerManager();
|
||||
scheduler.submitTask(() -> {
|
||||
this.instance.scheduler().submitTask(() -> {
|
||||
if(this.lost) return TaskSchedule.stop();
|
||||
int standardTickDelay = 40;
|
||||
if(this.isFast) standardTickDelay = 20;
|
||||
@@ -111,9 +115,12 @@ public class TetrisGame {
|
||||
|
||||
public void tick() {
|
||||
if(this.lost || this.paused) return;
|
||||
if(!this.currentTetromino.moveDown()) {
|
||||
this.setActiveTetrominoDown();
|
||||
if(this.currentTetromino.moveDown()) {
|
||||
this.stopTetrominoLockTask(this.currentTetromino.getYPosition() < this.currentTetrominoLowestY, false);
|
||||
} else {
|
||||
this.scheduleTetrominoLock();
|
||||
}
|
||||
this.currentTetrominoLowestY = Math.min(this.currentTetrominoLowestY, this.currentTetromino.getYPosition());
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
@@ -139,33 +146,43 @@ public class TetrisGame {
|
||||
this.lost = true;
|
||||
}
|
||||
|
||||
private boolean moveDown() {
|
||||
private void moveDown() {
|
||||
if(!this.currentTetromino.moveDown()) {
|
||||
this.setActiveTetrominoDown();
|
||||
return false;
|
||||
this.scheduleTetrominoLock();
|
||||
return;
|
||||
}
|
||||
this.stopTetrominoLockTask(this.currentTetromino.getYPosition() < this.currentTetrominoLowestY, false);
|
||||
this.score += 1;
|
||||
this.updateInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hardDrop() {
|
||||
private void moveLeft() {
|
||||
if(this.currentTetromino.moveLeft()) this.onSuccessfulMoveOrRotate();
|
||||
}
|
||||
|
||||
private void moveRight() {
|
||||
if(this.currentTetromino.moveRight()) this.onSuccessfulMoveOrRotate();
|
||||
}
|
||||
|
||||
private void rotate(boolean clockwise) {
|
||||
if(this.currentTetromino.rotate(clockwise)) this.onSuccessfulMoveOrRotate();
|
||||
}
|
||||
|
||||
private void hardDrop() {
|
||||
if(!this.currentTetromino.moveDown()) {
|
||||
this.setActiveTetrominoDown();
|
||||
return false;
|
||||
this.lockActiveTetromino();
|
||||
return;
|
||||
}
|
||||
do {
|
||||
this.score += 2;
|
||||
} while(this.currentTetromino.moveDown());
|
||||
this.updateInfo();
|
||||
while(this.currentTetromino.moveDown()) {
|
||||
this.score += 2;
|
||||
this.updateInfo();
|
||||
}
|
||||
this.setActiveTetrominoDown();
|
||||
return true;
|
||||
this.lockActiveTetromino();
|
||||
}
|
||||
|
||||
private boolean switchHold() {
|
||||
if(!this.holdPossible) return false;
|
||||
private void switchHold() {
|
||||
if(!this.holdPossible) return;
|
||||
this.stopTetrominoLockTask(true);
|
||||
|
||||
Tetromino newCurrentTetromino;
|
||||
if(this.holdTetromino == null) {
|
||||
@@ -181,6 +198,7 @@ public class TetrisGame {
|
||||
this.holdTetromino = new Tetromino(this.instance, this.currentTetromino.getShape());
|
||||
this.currentTetromino = newCurrentTetromino;
|
||||
|
||||
this.currentTetrominoLowestY = Integer.MAX_VALUE;
|
||||
this.currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
||||
this.currentTetromino.draw();
|
||||
if(!this.currentTetromino.moveDown()) this.loose();
|
||||
@@ -189,7 +207,12 @@ public class TetrisGame {
|
||||
this.holdTetromino.setPosition(this.holdPosition.add(xChange, 0, 0));
|
||||
this.holdTetromino.drawAsEntities();
|
||||
this.holdPossible = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onSuccessfulMoveOrRotate() {
|
||||
if(!this.currentTetromino.isGrounded()) return;
|
||||
this.stopTetrominoLockTask(false);
|
||||
this.scheduleTetrominoLock();
|
||||
}
|
||||
|
||||
private void updateNextTetrominoes() {
|
||||
@@ -235,11 +258,39 @@ public class TetrisGame {
|
||||
this.sidebar.updateLineScore("2", this.level);
|
||||
}
|
||||
|
||||
private void setActiveTetrominoDown() {
|
||||
private void scheduleTetrominoLock() {
|
||||
if(this.tetrominoLockTask == null || !this.tetrominoLockTask.isAlive())
|
||||
this.tetrominoLockTask = this.instance.scheduler().scheduleTask(() -> {
|
||||
if(this.currentTetromino.isGrounded()) {
|
||||
this.lockActiveTetromino();
|
||||
} else {
|
||||
this.stopTetrominoLockTask(false, false);
|
||||
}
|
||||
return TaskSchedule.stop();
|
||||
}, TaskSchedule.millis(500));
|
||||
}
|
||||
|
||||
private void stopTetrominoLockTask(boolean resetHard) {
|
||||
this.stopTetrominoLockTask(resetHard, true);
|
||||
}
|
||||
|
||||
private void stopTetrominoLockTask(boolean resetHard, boolean addToResets) {
|
||||
if(resetHard) this.lockDelayResets = 0;
|
||||
|
||||
if(this.lockDelayResets >= 15 && addToResets) {
|
||||
this.lockActiveTetromino();
|
||||
return;
|
||||
}
|
||||
if(this.tetrominoLockTask != null) {
|
||||
this.tetrominoLockTask.cancel();
|
||||
this.tetrominoLockTask = null;
|
||||
if(!resetHard && addToResets) this.lockDelayResets++;
|
||||
}
|
||||
}
|
||||
|
||||
private void lockActiveTetromino() {
|
||||
this.stopTetrominoLockTask(true);
|
||||
this.currentTetromino.removeOwnEntities();
|
||||
this.currentTetromino = this.nextTetrominoes.removeFirst();
|
||||
this.currentTetromino.remove();
|
||||
this.updateNextTetrominoes();
|
||||
|
||||
int removedLines = this.playfield.removeFullLines();
|
||||
int combatLines = 0;
|
||||
@@ -297,6 +348,11 @@ public class TetrisGame {
|
||||
|
||||
this.updateInfo();
|
||||
|
||||
this.currentTetromino = this.nextTetrominoes.removeFirst();
|
||||
this.currentTetromino.remove();
|
||||
this.updateNextTetrominoes();
|
||||
this.currentTetrominoLowestY = Integer.MAX_VALUE;
|
||||
|
||||
this.currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
||||
this.currentTetromino.draw();
|
||||
if(!this.currentTetromino.moveDown()) {
|
||||
|
||||
+32
-17
@@ -8,14 +8,12 @@ import net.minestom.server.entity.metadata.other.FallingBlockMeta;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.tag.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
public class Tetromino {
|
||||
private final static EntityType ghostEntityType = EntityType.FALLING_BLOCK;
|
||||
private final static Tag<String> uuidTag = Tag.String("uuid");
|
||||
private Orientation orientation = Orientation.NONE;
|
||||
private final Shape shape;
|
||||
private final StatelessGame instance;
|
||||
private final UUID uuid;
|
||||
@@ -28,10 +26,10 @@ public class Tetromino {
|
||||
this.uuid = UUID.randomUUID();
|
||||
|
||||
switch(this.shape) {
|
||||
case I -> this.shapeArray = new int[][]{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}};
|
||||
case I -> this.shapeArray = new int[][]{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}};
|
||||
case J -> this.shapeArray = new int[][]{{1, 0, 0}, {1, 1, 1}, {0, 0, 0}};
|
||||
case L -> this.shapeArray = new int[][]{{0, 0, 1}, {1, 1, 1}, {0, 0, 0}};
|
||||
case O -> this.shapeArray = new int[][]{{1, 1}, {1, 1}};
|
||||
case O -> this.shapeArray = new int[][]{{0, 1, 1}, {0, 1, 1}, {0, 0, 0}};
|
||||
case S -> this.shapeArray = new int[][]{{0, 1, 1}, {1, 1, 0}, {0, 0, 0}};
|
||||
case T -> this.shapeArray = new int[][]{{0, 1, 0}, {1, 1, 1}, {0, 0, 0}};
|
||||
case Z -> this.shapeArray = new int[][]{{1, 1, 0}, {0, 1, 1}, {0, 0, 0}};
|
||||
@@ -43,12 +41,23 @@ public class Tetromino {
|
||||
}
|
||||
|
||||
public void setPosition(Pos newPosition) {
|
||||
this.position = newPosition;
|
||||
this.position = new Pos(newPosition.x(), newPosition.y(), newPosition.z());
|
||||
}
|
||||
|
||||
public boolean rotate(boolean clockwise) {
|
||||
int[][] newShapeArray = this.getTurnedShapeArray(clockwise);
|
||||
return this.checkCollisionAndMove(this.position, newShapeArray);
|
||||
Orientation newOrientation = this.orientation.rotated(clockwise);
|
||||
|
||||
int[][] kicksArray = RotationChecker.getKicksArray(this.orientation, newOrientation, this.shape);
|
||||
for(int[] k : kicksArray) {
|
||||
Pos candidate = new Pos(this.position.x() + k[0], this.position.y() + k[1], this.position.z());
|
||||
if(this.checkCollisionAndMove(candidate, newShapeArray)) {
|
||||
this.orientation = newOrientation;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean moveDown() {
|
||||
@@ -73,7 +82,7 @@ public class Tetromino {
|
||||
public void draw(boolean withGhost) {
|
||||
if(withGhost) {
|
||||
Pos ghostPos = this.position;
|
||||
while(!this.checkCollision(ghostPos.sub(0, 1, 0), this.shapeArray)) {
|
||||
while(!this.hasCollision(ghostPos.sub(0, 1, 0), this.shapeArray)) {
|
||||
ghostPos = ghostPos.sub(0, 1, 0);
|
||||
}
|
||||
Pos positionChange = this.position.sub(ghostPos);
|
||||
@@ -182,7 +191,7 @@ public class Tetromino {
|
||||
|
||||
private boolean isPartOfTetromino(Pos position) {
|
||||
return this.getBlockPositions().stream()
|
||||
.anyMatch(pos -> pos.equals(position));
|
||||
.anyMatch(pos -> pos.sameBlock(position));
|
||||
}
|
||||
|
||||
private List<Pos> getBlockPositions() {
|
||||
@@ -198,10 +207,10 @@ public class Tetromino {
|
||||
for(int x = 0; x < arrayLength; x++) {
|
||||
for(int y = 0; y < arrayLength; y++) {
|
||||
if(shapeArray[arrayLength - 1 - y][x] == 1) {
|
||||
switch(this.shape) {
|
||||
case I -> returnList.add(position.add(x - 1, y - 2, 0));
|
||||
case O -> returnList.add(position.add(x, y, 0));
|
||||
default -> returnList.add(position.add(x - 1, y - 1, 0));
|
||||
if(Objects.requireNonNull(this.shape) == Shape.I) {
|
||||
returnList.add(position.add(x - 2, y - 2, 0));
|
||||
} else {
|
||||
returnList.add(position.add(x - 1, y - 1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,7 +219,7 @@ public class Tetromino {
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private boolean checkCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
private boolean hasCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
List<Pos> newBlockPositions = this.getBlockPositions(newPosition, newShapeArray);
|
||||
|
||||
for(Pos pos : newBlockPositions) {
|
||||
@@ -222,15 +231,21 @@ public class Tetromino {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isGrounded() {
|
||||
return this.hasCollision(this.position.sub(0, 1, 0), this.shapeArray);
|
||||
}
|
||||
|
||||
private boolean checkCollisionAndMove(Pos newPosition, int[][] newShapeArray) {
|
||||
if(!this.checkCollision(newPosition, newShapeArray)) {
|
||||
if(this.hasCollision(newPosition, newShapeArray)) return false;
|
||||
this.remove();
|
||||
this.shapeArray = Arrays.stream(newShapeArray).map(int[]::clone).toArray(int[][]::new);
|
||||
this.setPosition(newPosition);
|
||||
this.draw();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
public int getYPosition() {
|
||||
return Math.toIntExact(Math.round(this.position.y()));
|
||||
}
|
||||
|
||||
public enum Shape {
|
||||
|
||||
@@ -19,7 +19,7 @@ public class HubInventory extends InteractableInventory {
|
||||
.lore(TranslatedComponent.assemble("hub#create_description", p))
|
||||
.build(),
|
||||
12,
|
||||
itemClick -> Room.createRoom(itemClick.player()),
|
||||
itemClick -> Room.createRoom(itemClick.getPlayer()),
|
||||
true
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ public class HubInventory extends InteractableInventory {
|
||||
.lore(TranslatedComponent.assemble("hub#join_description", p))
|
||||
.build(),
|
||||
14,
|
||||
itemClick -> itemClick.player().openInventory(new JoinInventory(itemClick.player()))
|
||||
itemClick -> itemClick.getPlayer().openInventory(new JoinInventory(itemClick.getPlayer()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerPacketEvent;
|
||||
import net.minestom.server.inventory.InventoryType;
|
||||
import net.minestom.server.inventory.click.Click;
|
||||
import net.minestom.server.inventory.click.ClickType;
|
||||
import net.minestom.server.inventory.condition.InventoryConditionResult;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.network.packet.client.play.ClientNameItemPacket;
|
||||
@@ -31,7 +32,7 @@ public class JoinInventory extends InteractableInventory {
|
||||
.customName(Component.text(this.prefix))
|
||||
.build(),
|
||||
0,
|
||||
_ -> {
|
||||
itemClick -> {
|
||||
}
|
||||
);
|
||||
|
||||
@@ -44,8 +45,9 @@ public class JoinInventory extends InteractableInventory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick(Player player, int slot, Click clickType) {
|
||||
protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) {
|
||||
if(slot != 2) return;
|
||||
inventoryConditionResult.setCancel(true);
|
||||
player.closeInventory();
|
||||
|
||||
this.typedText = this.formatInput(this.typedText);
|
||||
|
||||
+2
-3
@@ -33,7 +33,7 @@ public class MinigameSelectInventory extends InteractableInventory {
|
||||
.lore(type.getDescription().addWrap().getWrappedAssembled(p))
|
||||
.build(),
|
||||
itemAlignment.next().get(),
|
||||
_ -> this.drawGames(type)
|
||||
itemClick -> this.drawGames(type)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,8 +62,7 @@ public class MinigameSelectInventory extends InteractableInventory {
|
||||
.lore(gameFactory.description().addWrap().getWrappedAssembled(this.p))
|
||||
.build(),
|
||||
offset + itemAlignment.next().get(),
|
||||
itemClick -> itemClick.player().openInventory(new GameConfigurationInventory(this.room, itemClick.player(), gameFactory)),
|
||||
true
|
||||
itemClick -> itemClick.getPlayer().openInventory(new GameConfigurationInventory(this.room, itemClick.getPlayer(), gameFactory))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,11 @@ public abstract class Score {
|
||||
throw new NotImplementedException("This Score type is not able to process points");
|
||||
}
|
||||
|
||||
public void insertMultiple(Set<Player> p) {
|
||||
p.forEach(player -> this.insertResultProcessor(player, () -> {}));
|
||||
this.insertResultImplementation(p);
|
||||
}
|
||||
|
||||
public void insertResult(Player p) {
|
||||
this.insertResultProcessor(p, () -> this.insertResultImplementation(Set.of(p)));
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ public class Tournament {
|
||||
for(Player player : players) {
|
||||
int points = (game.getScores().size() - count) + this.boost(count, game.getScores().size());
|
||||
|
||||
data.computeIfPresent(player, (_, existingPoints) -> existingPoints + points);
|
||||
data.computeIfAbsent(player, _ -> points);
|
||||
data.computeIfPresent(player, (existingPlayer, existingPoints) -> existingPoints + points);
|
||||
data.computeIfAbsent(player, newPlayer -> points);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -44,28 +44,28 @@ public class Tournament {
|
||||
}
|
||||
|
||||
return new Rewards(
|
||||
this.memorialConfiguration.memorialMaterial().key().value(),
|
||||
this.memorialConfiguration.memorialMaterial().namespace().value(),
|
||||
this.memorialConfiguration.memorialTitle(),
|
||||
this.memorialConfiguration.memorialLore(),
|
||||
this.getGameScores().keySet().stream().map(Player::getUuid).toList(),
|
||||
this.rewardConfiguration.item().key().value(),
|
||||
this.rewardConfiguration.item().namespace().value(),
|
||||
itemCount
|
||||
);
|
||||
}
|
||||
|
||||
public List<Set<Player>> getPlaces() {
|
||||
List<Set<Player>> players = new ArrayList<>(
|
||||
this.getGameScores().entrySet().stream()
|
||||
Map<Integer, Set<Player>> players = this.getGameScores().entrySet().stream()
|
||||
.collect(
|
||||
Collectors.groupingBy(
|
||||
Map.Entry::getValue,
|
||||
Collectors.mapping(Map.Entry::getKey, Collectors.toSet())
|
||||
)
|
||||
).values()
|
||||
);
|
||||
|
||||
Collections.reverse(players);
|
||||
return players;
|
||||
return players.entrySet().stream()
|
||||
.sorted(Map.Entry.<Integer, Set<Player>>comparingByKey().reversed())
|
||||
.map(Map.Entry::getValue)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private int boost(int selfPlace, int placeCount) {
|
||||
|
||||
+13
-39
@@ -2,64 +2,38 @@ 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.Click;
|
||||
import net.minestom.server.inventory.click.ClickType;
|
||||
import net.minestom.server.inventory.condition.InventoryConditionResult;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class InteractableInventory extends Inventory {
|
||||
private final Map<Integer, ClickableItem> clickableItems = new HashMap<>();
|
||||
|
||||
public record ItemClick(Player player, InteractableInventory inventory, int clickedSlot, ItemStack item, Click clickType) { }
|
||||
public record ClickableItem(ItemStack item, int slot, Consumer<ItemClick> callback, boolean closeAfterClick) { }
|
||||
|
||||
/**
|
||||
* Defines an Inventory with direct callbacks for ItemSlots
|
||||
*/
|
||||
protected InteractableInventory(@NotNull InventoryType inventoryType, @NotNull Component title) {
|
||||
super(inventoryType, title);
|
||||
|
||||
this.eventNode().addListener(
|
||||
InventoryPreClickEvent.class,
|
||||
inventoryPreClickEvent -> this.onClick(
|
||||
inventoryPreClickEvent.getPlayer(),
|
||||
inventoryPreClickEvent.getSlot(),
|
||||
inventoryPreClickEvent.getClick()
|
||||
)
|
||||
);
|
||||
|
||||
this.eventNode().addListener(InventoryPreClickEvent.class, inventoryPreClickEvent -> {
|
||||
@Nullable ClickableItem selectedItem = this.clickableItems.values().stream()
|
||||
.filter(clickableItem -> clickableItem.slot() == inventoryPreClickEvent.getSlot())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if(selectedItem == null) {
|
||||
inventoryPreClickEvent.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if(selectedItem.closeAfterClick()) inventoryPreClickEvent.getPlayer().closeInventory();
|
||||
selectedItem.callback().accept(
|
||||
new ItemClick(inventoryPreClickEvent.getPlayer(), this, inventoryPreClickEvent.getSlot(), selectedItem.item(), inventoryPreClickEvent.getClick())
|
||||
);
|
||||
inventoryPreClickEvent.setCancelled(true);
|
||||
});
|
||||
this.addInventoryCondition(this::onClick);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Item with Callback
|
||||
*/
|
||||
protected void setClickableItem(ItemStack item, int slot, Consumer<ItemClick> callback, boolean closeAfter) {
|
||||
ClickableItem clickableItem = new ClickableItem(item, slot, callback, closeAfter);
|
||||
this.setItemStack(clickableItem.slot(), clickableItem.item());
|
||||
this.clickableItems.put(clickableItem.slot(), clickableItem);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
protected void setClickableItem(ItemStack item, int slot, Consumer<ItemClick> callback) {
|
||||
@@ -73,7 +47,7 @@ public class InteractableInventory extends Inventory {
|
||||
this.setClickableItem(
|
||||
item,
|
||||
slot,
|
||||
_ -> {
|
||||
itemClick -> {
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -88,7 +62,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, Click clickType) {
|
||||
protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
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.item.ItemStack;
|
||||
|
||||
public class ItemClick {
|
||||
private final Player player;
|
||||
private final InteractableInventory inventory;
|
||||
private final int clickedSlot;
|
||||
private final ItemStack item;
|
||||
private final ClickType clickType;
|
||||
|
||||
/**
|
||||
* Describes a click on an Item from an IntractableInventory
|
||||
*/
|
||||
public ItemClick(Player player, InteractableInventory inventory, int clickedSlot, ItemStack item, ClickType clickType) {
|
||||
this.player = player;
|
||||
this.inventory = inventory;
|
||||
this.clickedSlot = clickedSlot;
|
||||
this.item = item;
|
||||
this.clickType = clickType;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
public Inventory getInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
public int getClickedSlot() {
|
||||
return this.clickedSlot;
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
public ClickType getClickType() {
|
||||
return this.clickType;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
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.Batch;
|
||||
import net.minestom.server.instance.batch.ChunkBatch;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BatchUtil {
|
||||
@@ -16,13 +16,10 @@ public class BatchUtil {
|
||||
field.setAccessible(true);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Long, ChunkBatch> chunkBatchesMap = (Map<Long, ChunkBatch>) field.get(batch);
|
||||
Long2ObjectMap<ChunkBatch> chunkBatchesMap = (Long2ObjectMap<ChunkBatch>) field.get(batch);
|
||||
|
||||
long[] out = new long[chunkBatchesMap.size()];
|
||||
int i = 0;
|
||||
for (Long k : chunkBatchesMap.keySet()) out[i++] = k;
|
||||
return out;
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
return chunkBatchesMap.keySet().toLongArray();
|
||||
} catch(NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@@ -39,9 +36,15 @@ public class BatchUtil {
|
||||
long[] affectedChunks = BatchUtil.getAffectedChunks(batch);
|
||||
CompletableFuture<Void> loadChunksTask = ChunkUtils.optionalLoadAll(instance, affectedChunks, null);
|
||||
|
||||
Runnable completerTask = () -> future.complete(null);
|
||||
Runnable completerTask = () -> {
|
||||
System.out.println("COMPLETE");
|
||||
future.complete(null);
|
||||
};
|
||||
|
||||
loadChunksTask.thenRun(() -> batch.apply(instance, completerTask));
|
||||
loadChunksTask.thenRun(() -> {
|
||||
System.out.println("BEGIN");
|
||||
batch.apply(instance, completerTask);
|
||||
});
|
||||
|
||||
try {
|
||||
future.get();
|
||||
|
||||
@@ -10,4 +10,11 @@ public class CommonProperties {
|
||||
this.put("east", "true");
|
||||
}
|
||||
};
|
||||
|
||||
public static Map<String, String> fenceNorthSouth = new HashMap<>() {
|
||||
{
|
||||
this.put("north", "true");
|
||||
this.put("south", "true");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,9 +33,15 @@ public class Position {
|
||||
public static List<Block> blocksBelowPlayer(Instance instance, Player p) {
|
||||
Point playerPos = p.getPosition();
|
||||
List<Block> blocks = new ArrayList<>();
|
||||
GeneratorUtils.foreachXZ(playerPos.sub(0.5, 1, 0.5), playerPos.add(0.5, -1, 0.5), point -> {
|
||||
blocks.add(instance.getBlock(point));
|
||||
});
|
||||
GeneratorUtils.foreachXZ(
|
||||
playerPos.sub(0.5, 1, 0.5),
|
||||
playerPos.add(0.5, -1, 0.5),
|
||||
point -> blocks.add(instance.getBlock(point))
|
||||
);
|
||||
return blocks.stream().distinct().toList();
|
||||
}
|
||||
|
||||
public static boolean hasPositionChanged(Pos oldPos, Pos newPos) {
|
||||
return !oldPos.withView(0, 0).equals(newPos.withView(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public class WeatherUtils {
|
||||
MinecraftServer.getSchedulerManager().submitTask(() -> {
|
||||
this.intensity += 0.1f;
|
||||
players.forEach(p -> p.sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.RAIN_LEVEL_CHANGE, this.intensity)));
|
||||
System.out.println(this.intensity);
|
||||
if(this.intensity < 1) {
|
||||
return TaskSchedule.millis(500);
|
||||
} else {
|
||||
|
||||
+2
@@ -38,6 +38,8 @@ public class CircularPlateGenerator extends HeightTerrainGenerator {
|
||||
@Override
|
||||
public void generate(@NotNull GenerationUnit unit) {
|
||||
this.execution.singleRun(() -> unit.fork(setter -> {
|
||||
System.out.println(new Pos(-(this.radius + this.centerX), unit.absoluteStart().y(), -(this.radius + this.centerZ)));
|
||||
System.out.println(new Pos(this.radius + this.centerX, this.height, this.radius + this.centerZ));
|
||||
GeneratorUtils.foreachXZ(
|
||||
new Pos(-(this.radius + this.centerX), unit.absoluteStart().y(), -(this.radius + this.centerZ)),
|
||||
new Pos(this.radius + this.centerX, this.height, this.radius + this.centerZ),
|
||||
|
||||
+3
@@ -46,6 +46,7 @@ public class HeightTerrainGenerator extends BaseGenerator {
|
||||
double heightNoise = this.base.getNoise(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());
|
||||
@@ -68,6 +69,8 @@ public class HeightTerrainGenerator extends BaseGenerator {
|
||||
Point absoluteHeight = bottomPoint.add(0, heightModifier, 0);
|
||||
int seaLevel = this.calculateSeaLevel.apply(bottomPoint);
|
||||
if(absoluteHeight.y() < seaLevel) {
|
||||
// System.out.println("HM:" + absoluteHeight.y() + " SL:" + seaLevel);
|
||||
// System.out.println("Filling from " + bottomPoint.y() + " to " + absoluteHeight.withY(seaLevel).y());
|
||||
unit.modifier().fill(bottomPoint.withY(v -> v + heightModifier), absoluteHeight.add(1, 0, 1).withY(seaLevel), Block.WATER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ optionPvpEnabled;pvp enabled;PvP aktiviert
|
||||
;;
|
||||
ns:game_Stickfight#;;
|
||||
name;Stickfight;Stockschlacht
|
||||
description;Push your opponents off the Bridge;Stoße deine Gegener von der Brücke
|
||||
description;Push your opponents off the Bridge;Stoße deine Gegener von der Brücke, der Spieler mit den wenigsten Toden gewinnt!
|
||||
;;
|
||||
ns:game_TrafficlightRace#;;
|
||||
name;Red light green light;Rotes licht, Grünes licht
|
||||
@@ -170,3 +170,20 @@ ns:game_TurtleGame#;;
|
||||
name;Turtle Game;Turtle Game
|
||||
description;Eat snacks and dodge bombs to get the highest score!;Esse Snacks und weiche Bomben aus, um den höchsten Score zu erreichen!
|
||||
startSpeed;Start Speed;Startgeschwindigkeit
|
||||
;;
|
||||
ns:game_BoatRace#;;
|
||||
name;Boatrace;Bootrennen
|
||||
description;;
|
||||
;;
|
||||
ns:game_Pillars#;;
|
||||
name;Pillars;Pillars
|
||||
description;Build yourself up with your random blocks to reach your opponents and push them down!;Baue dich mit deinen zufälligen Blöcken zu deinen Gegnern und schupse sie runter!
|
||||
;;
|
||||
ns:game_BlockBattle#;;
|
||||
name;Block Battle;Block Kampf
|
||||
description;The team that fills the center with their color first wins!;Das Team, welches als erstes die Mitte mit seiner Farbe gefüllt hat, gewinnt!
|
||||
itemCount;Block Count;Block Anzahl
|
||||
;;
|
||||
ns:game_ColorJump#;;
|
||||
name;Color Jump;Farbsprung
|
||||
description;Jump on the right color!;Springe auf die richtige Farbe!
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user