Skip to content

Commit a8c05a3

Browse files
authored
Add an option to WorldCreator to avoid spawn location computation on world creation (#13407)
1 parent 945aea9 commit a8c05a3

3 files changed

Lines changed: 94 additions & 5 deletions

File tree

paper-api/src/main/java/org/bukkit/WorldCreator.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.common.base.Preconditions;
44
import java.util.Random;
5+
import io.papermc.paper.math.Position;
56
import org.bukkit.command.CommandSender;
67
import org.bukkit.generator.BiomeProvider;
78
import org.bukkit.generator.ChunkGenerator;
@@ -26,6 +27,10 @@ public class WorldCreator {
2627
private boolean hardcore = false;
2728
private boolean bonusChest = false;
2829

30+
private @Nullable Position spawnPositionOverride;
31+
private @Nullable Float spawnYawOverride;
32+
private @Nullable Float spawnPitchOverride;
33+
2934
/**
3035
* Creates an empty WorldCreationOptions for the given world name.
3136
*
@@ -261,6 +266,80 @@ public WorldCreator type(@NotNull WorldType type) {
261266
return this;
262267
}
263268

269+
/**
270+
* Sets the forced spawn position for the world created by this {@link WorldCreator}.
271+
* <p>
272+
* This overrides vanilla and custom generator behavior without loading any chunks.
273+
* When a forced spawn is specified, the bonus chest will not be generated.
274+
*
275+
* @param position the spawn position
276+
* @param yaw the yaw rotation at spawn
277+
* @param pitch the pitch rotation at spawn
278+
* @return this object, for chaining
279+
*/
280+
@NotNull
281+
public WorldCreator forcedSpawnPosition(@NotNull Position position, float yaw, float pitch) {
282+
this.spawnPositionOverride = position; // If you set this to null, it wont do anything!
283+
this.spawnYawOverride = yaw;
284+
this.spawnPitchOverride = pitch;
285+
return this;
286+
}
287+
288+
/**
289+
* Clears any previously forced spawn position.
290+
* <p>
291+
* After calling this, vanilla spawn selection behavior is used.
292+
*
293+
* @return this object, for chaining
294+
*/
295+
@NotNull
296+
public WorldCreator clearForcedSpawnPosition() {
297+
this.spawnPositionOverride = null;
298+
this.spawnYawOverride = null;
299+
this.spawnPitchOverride = null;
300+
return this;
301+
}
302+
303+
/**
304+
* Gets the forced spawn position that will be applied when this world is created.
305+
* <p>
306+
* If this returns {@code null}, vanilla or custom generator behavior will be used
307+
* to determine the spawn position.
308+
*
309+
* @return the forced spawn position, or {@code null} for the vanilla behavior
310+
*/
311+
public @Nullable Position forcedSpawnPosition() {
312+
return this.spawnPositionOverride;
313+
}
314+
315+
/**
316+
* Gets the forced spawn yaw that will be applied when this world is created.
317+
* <p>
318+
* If this returns {@code null}, the spawn yaw will be determined by vanilla behavior
319+
* or the world generator.
320+
* <p>
321+
* This value is only meaningful if a forced spawn position is present.
322+
*
323+
* @return the forced spawn yaw, or {@code null} for the vanilla behavior
324+
*/
325+
public @Nullable Float forcedSpawnYaw() {
326+
return this.spawnYawOverride;
327+
}
328+
329+
/**
330+
* Gets the forced spawn pitch that will be applied when this world is created.
331+
* <p>
332+
* If this returns {@code null}, the spawn pitch will be determined by vanilla behavior
333+
* or the world generator.
334+
* <p>
335+
* This value is only meaningful if a forced spawn position is present.
336+
*
337+
* @return the forced spawn pitch, or {@code null} for the vanilla behavior
338+
*/
339+
public @Nullable Float forcedSpawnPitch() {
340+
return this.spawnPitchOverride;
341+
}
342+
264343
/**
265344
* Gets the generator that will be used to create or load the world.
266345
* <p>

paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@
300300
if (profiledDuration != null) {
301301
profiledDuration.finish(true);
302302
}
303-
@@ -422,33 +_,140 @@
303+
@@ -422,33 +_,150 @@
304304
}
305305
}
306306

@@ -430,9 +430,9 @@
430430
+ );
431431
+ }
432432
+ this.addLevel(serverLevel);
433-
+ this.initWorld(serverLevel);
433+
+ this.initWorld(serverLevel, null);
434434
+ }
435-
+ public void initWorld(ServerLevel overworld) {
435+
+ public void initWorld(ServerLevel overworld, org.bukkit.@Nullable WorldCreator worldCreator) {
436436
+ final net.minecraft.world.level.storage.ServerLevelData levelData = overworld.serverLevelData;
437437
+ final WorldOptions worldOptions = overworld.worldGenSettings.options();
438438
+ final boolean isDebug = this.worldData.isDebugWorld();
@@ -447,7 +447,17 @@
447447
if (!levelData.isInitialized()) {
448448
try {
449449
- setInitialSpawn(overworld, levelData, worldOptions.generateBonusChest(), isDebug, this.levelLoadListener);
450-
+ setInitialSpawn(overworld, levelData, worldOptions.generateBonusChest(), isDebug, overworld.levelLoadListener); // Paper - per world level load listener
450+
+ // Paper start - Allow direct setting spawn location
451+
+ if (worldCreator != null && worldCreator.forcedSpawnPosition() != null) {
452+
+ levelData.setSpawn(LevelData.RespawnData.of(overworld.dimension(),
453+
+ io.papermc.paper.util.MCUtil.toBlockPos(worldCreator.forcedSpawnPosition()),
454+
+ Objects.requireNonNullElse(worldCreator.forcedSpawnYaw(), LevelData.RespawnData.DEFAULT.yaw()),
455+
+ Objects.requireNonNullElse(worldCreator.forcedSpawnPitch(), LevelData.RespawnData.DEFAULT.pitch())
456+
+ ));
457+
+ } else {
458+
+ setInitialSpawn(overworld, levelData, worldOptions.generateBonusChest(), isDebug, overworld.levelLoadListener); // Paper - per world level load listener
459+
+ }
460+
+ // Paper end - Allow direct setting spawn location
451461
levelData.setInitialized(true);
452462
if (isDebug) {
453463
- this.setupDebugLevel(this.worldData);

paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1303,7 +1303,7 @@ public World createWorld(WorldCreator creator) {
13031303
}
13041304

13051305
this.console.addLevel(serverLevel);
1306-
this.console.initWorld(serverLevel);
1306+
this.console.initWorld(serverLevel, creator);
13071307

13081308
serverLevel.setSpawnSettings(true);
13091309

0 commit comments

Comments
 (0)