diff --git a/paper-api/src/main/java/org/bukkit/WorldCreator.java b/paper-api/src/main/java/org/bukkit/WorldCreator.java index 4b312399eced..5519513a480f 100644 --- a/paper-api/src/main/java/org/bukkit/WorldCreator.java +++ b/paper-api/src/main/java/org/bukkit/WorldCreator.java @@ -1,7 +1,9 @@ package org.bukkit; import com.google.common.base.Preconditions; +import java.nio.file.Path; import java.util.Random; +import io.papermc.paper.math.Position; import org.bukkit.command.CommandSender; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.ChunkGenerator; @@ -25,6 +27,15 @@ public class WorldCreator { private boolean hardcore = false; private boolean bonusChest = false; + @Nullable + private Position spawnPositionOverride; + @Nullable + private Float spawnYawOverride; + @Nullable + private Float spawnPitchOverride; + + private Path parentDirectory = Bukkit.getWorldContainer().toPath(); + /** * Creates an empty WorldCreationOptions for the given world name * @@ -206,6 +217,31 @@ public WorldCreator environment(@NotNull World.Environment env) { return this; } + /** + * Sets the directory that this world's data will be stored in. + * + *
The provided file represents the parent folder used for + * storing all world data (region files, player data, level data, etc.).
+ * + * @param override the parent directory to store this world's data in + * @return this object, for chaining + */ + @NotNull + public WorldCreator parentDirectory(@NotNull Path override) { + this.parentDirectory = override; + return this; + } + + /** + * Gets the directory used for storing this world's data. + * + * @return the parent directory used for world storage + */ + @NotNull + public Path parentDirectory() { + return this.parentDirectory; + } + /** * Gets the type of the world that will be created or loaded * @@ -229,6 +265,83 @@ public WorldCreator type(@NotNull WorldType type) { return this; } + /** + * Sets the forced spawn position for the world created by this {@link WorldCreator}. + *+ * This overrides vanilla and custom generator behavior without loading any chunks. + * When a forced spawn is specified, the bonus chest will not be generated. + * + * @param position the spawn position + * @param yaw the yaw rotation at spawn + * @param pitch the pitch rotation at spawn + * @return this creator for chaining + */ + @NotNull + public WorldCreator forcedSpawnPosition(@NotNull Position position, float yaw, float pitch) { + this.spawnPositionOverride = position; + this.spawnYawOverride = yaw; + this.spawnPitchOverride = pitch; + return this; + } + + /** + * Clears any previously forced spawn position. + *
+ * After calling this, vanilla spawn selection behavior is used. + * + * @return this creator for chaining + */ + @NotNull + public WorldCreator clearForcedSpawnPosition() { + this.spawnPositionOverride = null; + this.spawnYawOverride = null; + this.spawnPitchOverride = null; + return this; + } + + /** + * Gets the forced spawn position that will be applied when this world is created. + * + *
If this returns {@code null}, vanilla or custom generator behavior will be used + * to determine the spawn position.
+ * + * @return the forced spawn position, or {@code null} to use vanilla behavior + */ + @Nullable + public Position forcedSpawnPosition() { + return this.spawnPositionOverride; + } + + /** + * Gets the forced spawn yaw that will be applied when this world is created. + * + *If this returns {@code null}, the spawn yaw will be determined by vanilla behavior + * or the world generator.
+ * + *This value is only meaningful if a forced spawn position is present.
+ * + * @return the forced spawn yaw, or {@code null} to use vanilla behavior + */ + @Nullable + public Float forcedSpawnYaw() { + return this.spawnYawOverride; + } + + /** + * Gets the forced spawn pitch that will be applied when this world is created. + * + *If this returns {@code null}, the spawn pitch will be determined by vanilla behavior + * or the world generator.
+ * + *This value is only meaningful if a forced spawn position is present.
+ * + * @return the forced spawn pitch, or {@code null} to use vanilla behavior + */ + @Nullable + public Float forcedSpawnPitch() { + return this.spawnPitchOverride; + } + /** * Gets the generator that will be used to create or load the world. *
diff --git a/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch
index 9de3cccbff3e..3961874a2e5e 100644
--- a/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch
+++ b/paper-server/patches/features/0001-Moonrise-optimisation-patches.patch
@@ -23059,7 +23059,7 @@ index cda915fcb4822689f42b25280eb99aee082ddb74..094d2d528cb74b8f1d277cd780bba7f4
thread1 -> {
DedicatedServer dedicatedServer1 = new DedicatedServer(
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
-index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430fe35d6bc 100644
+index 35f2485b8d727695476531391f886c4a598e486e..c2ffe3c695911c706a257cfbf5c41166545f721d 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -185,7 +185,7 @@ import net.minecraft.world.scores.ScoreboardSaveData;
@@ -23165,7 +23165,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
public MinecraftServer(
// CraftBukkit start
joptsimple.OptionSet options,
-@@ -827,7 +914,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop