diff --git a/paper-api/src/main/java/org/bukkit/WorldCreator.java b/paper-api/src/main/java/org/bukkit/WorldCreator.java index 6fb3c2fa739f..1e6a84b4cdd1 100644 --- a/paper-api/src/main/java/org/bukkit/WorldCreator.java +++ b/paper-api/src/main/java/org/bukkit/WorldCreator.java @@ -3,6 +3,7 @@ import com.google.common.base.Preconditions; import java.util.Random; import io.papermc.paper.math.Position; +import net.kyori.adventure.key.Key; import org.bukkit.command.CommandSender; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.ChunkGenerator; @@ -15,13 +16,14 @@ * Represents various types of options that may be used to create a world. */ public class WorldCreator { - private final NamespacedKey key; // Paper + private final NamespacedKey key; private final String name; private long seed; private World.Environment environment = World.Environment.NORMAL; private ChunkGenerator generator = null; private BiomeProvider biomeProvider = null; private WorldType type = WorldType.NORMAL; + private @Nullable Key customEnvironmentKey = null; private boolean generateStructures = true; private String generatorSettings = ""; private boolean hardcore = false; @@ -151,6 +153,9 @@ public WorldCreator copy(@NotNull World world) { seed = world.getSeed(); environment = world.getEnvironment(); + if (environment == World.Environment.CUSTOM) { + customEnvironmentKey = world.getEnvironmentKey(); + } generator = world.getGenerator(); biomeProvider = world.getBiomeProvider(); type = world.getWorldType(); @@ -173,6 +178,7 @@ public WorldCreator copy(@NotNull WorldCreator creator) { seed = creator.seed(); environment = creator.environment(); + customEnvironmentKey = creator.customEnvironmentKey(); generator = creator.generator(); biomeProvider = creator.biomeProvider(); type = creator.type(); @@ -231,15 +237,49 @@ public World.Environment environment() { } /** - * Sets the environment that will be used to create or load the world + * Sets the environment that will be used to create or load the world. + *

+ * Note: if the environment is {@link World.Environment#CUSTOM}, + * then you also need to set the key using {@link #customEnvironmentKey(Key)}. * * @param env World environment * @return This object, for chaining + * @see #customEnvironmentKey(Key) */ @NotNull public WorldCreator environment(@NotNull World.Environment env) { this.environment = env; + if (env != World.Environment.CUSTOM) { + this.customEnvironmentKey = null; + } + + return this; + } + + /** + * Gets the environment key that will be used to create or load the world + * if {@link #environment()} is {@link World.Environment#CUSTOM}. + * + * @return World environment key + */ + @ApiStatus.Experimental + public @Nullable Key customEnvironmentKey() { + return customEnvironmentKey; + } + + /** + * Sets the environment key that will be used to create or load the world and + * set the environment to {@link World.Environment#CUSTOM}. + * + * @param customEnvironmentKey World environment key + * @return This object, for chaining + */ + @ApiStatus.Experimental + public @NotNull WorldCreator customEnvironmentKey(@NotNull Key customEnvironmentKey) { + this.environment = World.Environment.CUSTOM; + this.customEnvironmentKey = customEnvironmentKey; + return this; } diff --git a/paper-api/src/main/java/org/bukkit/generator/WorldInfo.java b/paper-api/src/main/java/org/bukkit/generator/WorldInfo.java index 6c8d4f817f4f..d8ea2a824313 100644 --- a/paper-api/src/main/java/org/bukkit/generator/WorldInfo.java +++ b/paper-api/src/main/java/org/bukkit/generator/WorldInfo.java @@ -2,6 +2,7 @@ import java.util.UUID; import io.papermc.paper.world.flag.FeatureFlagSetHolder; +import net.kyori.adventure.key.Key; import org.bukkit.Keyed; import org.bukkit.World; import org.jetbrains.annotations.ApiStatus; @@ -40,6 +41,14 @@ public interface WorldInfo extends FeatureFlagSetHolder, Keyed { @NotNull World.Environment getEnvironment(); + /** + * Gets the environment key for this world. + * + * @return This world Environment key + */ + @ApiStatus.Experimental + @NotNull Key getEnvironmentKey(); + /** * Gets the Seed for this world. * diff --git a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index 595172fa7bfd..bc557943d767 100644 --- a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -274,7 +274,7 @@ if (profiledDuration != null) { profiledDuration.finish(true); } -@@ -415,33 +_,150 @@ +@@ -415,33 +_,151 @@ } } @@ -343,6 +343,7 @@ + worldDataAndGenSettings.genSettings().options().seed(), + worldDataAndGenSettings.data().enabledFeatures(), + loading.info().environment(), ++ io.papermc.paper.adventure.PaperAdventure.asAdventureKey(loading.info().stemKey()), + levelStem.type().value(), + levelStem.generator(), + this.registryAccess(), diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 83b8d44c7c8f..03e1c754d587 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -10,6 +10,7 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.JsonOps; +import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.configuration.GlobalConfiguration; import io.papermc.paper.configuration.PaperServerConfiguration; import io.papermc.paper.configuration.ServerConfiguration; @@ -1168,6 +1169,9 @@ public World createWorld(WorldCreator creator) { Preconditions.checkState(this.console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP"); //Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot create a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes. Preconditions.checkArgument(creator != null, "WorldCreator cannot be null"); + if ((creator.environment() == Environment.CUSTOM) == (creator.customEnvironmentKey() == null)) { + throw new IllegalArgumentException("Custom environment key cannot be null when environment is CUSTOM and vice versa"); + } String name = creator.name(); ChunkGenerator chunkGenerator = creator.generator(); @@ -1194,7 +1198,7 @@ public World createWorld(WorldCreator creator) { case NORMAL -> LevelStem.OVERWORLD; case NETHER -> LevelStem.NETHER; case THE_END -> LevelStem.END; - default -> throw new IllegalArgumentException("Illegal dimension (" + creator.environment() + ")"); + case CUSTOM -> PaperAdventure.asVanilla(Registries.LEVEL_STEM, creator.customEnvironmentKey()); }; RegistryAccess registryAccess = this.console.registryAccess(); @@ -1271,7 +1275,7 @@ public World createWorld(WorldCreator creator) { throw new IllegalStateException("Missing level stem for world " + name + " using key " + actualDimension); } - WorldInfo worldInfo = new CraftWorldInfo(loadedWorldData.bukkitName(), CraftNamespacedKey.fromMinecraft(dimensionKey.identifier()), genSettingsFinal.options().seed(), primaryLevelData.enabledFeatures(), creator.environment(), customStem.type().value(), customStem.generator(), registryAccess, loadedWorldData.uuid()); + WorldInfo worldInfo = new CraftWorldInfo(loadedWorldData.bukkitName(), CraftNamespacedKey.fromMinecraft(dimensionKey.identifier()), genSettingsFinal.options().seed(), primaryLevelData.enabledFeatures(), creator.environment(), io.papermc.paper.adventure.PaperAdventure.asAdventureKey(actualDimension), customStem.type().value(), customStem.generator(), this.getHandle().getServer().registryAccess(), loadedWorldData.uuid()); if (biomeProvider == null && chunkGenerator != null) { biomeProvider = chunkGenerator.getDefaultBiomeProvider(worldInfo); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index f3f068011abd..699bcfb2122c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -7,6 +7,7 @@ import com.google.common.collect.Lists; import com.mojang.datafixers.util.Pair; import io.papermc.paper.FeatureHooks; +import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.entity.poi.PaperPoiSearchResult; import io.papermc.paper.entity.poi.PaperPoiType; import io.papermc.paper.entity.poi.PoiSearchResult; @@ -34,6 +35,7 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; +import net.kyori.adventure.key.Key; import net.kyori.adventure.pointer.PointersSupplier; import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; @@ -874,6 +876,11 @@ public boolean createExplosion(Location loc, float power, boolean setFire, boole return this.environment; } + @Override + public @NotNull Key getEnvironmentKey() { + return PaperAdventure.asAdventureKey(this.getHandle().getTypeKey()); + } + @Override public @Nullable ChunkGenerator getGenerator() { return this.world.generator; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java b/paper-server/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java index f92a9daafb05..312d15727d5e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java @@ -1,6 +1,7 @@ package org.bukkit.craftbukkit.generator; import java.util.UUID; +import net.kyori.adventure.key.Key; import net.minecraft.core.RegistryAccess; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -17,6 +18,7 @@ public class CraftWorldInfo implements WorldInfo { private final NamespacedKey dimension; private final UUID uuid; private final World.Environment environment; + private final Key environmentKey; private final long seed; private final int minHeight; private final int maxHeight; @@ -30,6 +32,7 @@ public CraftWorldInfo( long seed, FeatureFlagSet enabledFeatures, World.Environment environment, + Key environmentKey, DimensionType dimensionType, ChunkGenerator vanillaChunkGenerator, RegistryAccess registryAccess, @@ -40,6 +43,7 @@ public CraftWorldInfo( this.seed = seed; this.enabledFeatures = enabledFeatures; this.environment = environment; + this.environmentKey = environmentKey; this.minHeight = dimensionType.minY(); this.maxHeight = dimensionType.minY() + dimensionType.height(); this.vanillaChunkGenerator = vanillaChunkGenerator; @@ -67,6 +71,11 @@ public long getSeed() { return this.seed; } + @Override + public Key getEnvironmentKey() { + return this.environmentKey; + } + @Override public int getMinHeight() { return this.minHeight;