Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions paper-api/src/main/java/org/bukkit/WorldCreator.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
*
Expand Down Expand Up @@ -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.
*
* <p>The provided file represents the <strong>parent folder</strong> used for
* storing all world data (region files, player data, level data, etc.).</p>
*
* @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
*
Expand All @@ -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}.
* <p>
* 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.
* <p>
* 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.
*
* <p>If this returns {@code null}, vanilla or custom generator behavior will be used
* to determine the spawn position.</p>
*
* @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.
*
* <p>If this returns {@code null}, the spawn yaw will be determined by vanilla behavior
* or the world generator.</p>
*
* <p>This value is only meaningful if a forced spawn position is present.</p>
*
* @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.
*
* <p>If this returns {@code null}, the spawn pitch will be determined by vanilla behavior
* or the world generator.</p>
*
* <p>This value is only meaningful if a forced spawn position is present.</p>
*
* @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.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -23165,7 +23165,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
public MinecraftServer(
// CraftBukkit start
joptsimple.OptionSet options,
@@ -827,7 +914,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -833,7 +920,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevel.setSpawnSettings(serverLevel.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && serverLevel.getGameRules().get(GameRules.SPAWN_MONSTERS)); // Paper - per level difficulty (from setDifficulty(ServerLevel, Difficulty, boolean))
this.updateEffectiveRespawnData();
this.forceTicks = false; // CraftBukkit
Expand All @@ -23174,7 +23174,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
new org.bukkit.event.world.WorldLoadEvent(serverLevel.getWorld()).callEvent(); // Paper - call WorldLoadEvent
}

@@ -850,6 +937,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -856,6 +943,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public abstract boolean shouldRconBroadcast();

public boolean saveAllChunks(boolean suppressLogs, boolean flush, boolean force) {
Expand All @@ -23186,7 +23186,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
this.scoreboard.storeToSaveDataIfDirty(this.overworld().getDataStorage().computeIfAbsent(ScoreboardSaveData.TYPE));
boolean flag = false;

@@ -858,7 +950,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -864,7 +956,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
LOGGER.info("Saving chunks for level '{}'/{}", serverLevel, serverLevel.dimension().identifier());
}

Expand All @@ -23195,7 +23195,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
flag = true;
}

@@ -948,7 +1040,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -954,7 +1046,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}

Expand All @@ -23204,7 +23204,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND;

for (ServerLevel serverLevelx : this.getAllLevels()) {
@@ -958,18 +1050,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -964,18 +1056,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

this.waitUntilNextTick();
}
Expand All @@ -23230,7 +23230,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430

this.isSaving = false;
this.resources.close();
@@ -989,6 +1077,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -995,6 +1083,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.services().nameToIdCache().save(false); // Paper - Perf: Async GameProfileCache saving
}
// Spigot end
Expand All @@ -23245,7 +23245,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
// Paper start - Improved watchdog support - move final shutdown items here
Util.shutdownExecutors();
try {
@@ -1083,16 +1179,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1089,16 +1185,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// execute small amounts of other tasks just in case the number of tasks we are
// draining is large - chunk system and packet processing may be latency sensitive

Expand Down Expand Up @@ -23280,15 +23280,15 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
profiler.pop(); // moonrise:run_all_chunk
profiler.pop(); // moonrise:run_all_tasks

@@ -1393,6 +1504,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1399,6 +1510,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

private boolean pollTaskInternal() {
if (super.pollTask()) {
+ this.moonrise$executeMidTickTasks(); // Paper - rewrite chunk system
return true;
} else {
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
@@ -1534,6 +1646,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1540,6 +1652,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper - improve tick loop - moved into runAllTasksAtTickStart
this.runAllTasksAtTickStart(); // Paper - improve tick loop
this.tickServer(sprinting ? () -> false : this::haveTime);
Expand All @@ -23302,7 +23302,7 @@ index cab1ab613dd081e9472de515a19e1b4738e4fba3..96f7f37c42cecea1d714f7b16276f430
this.tickFrame.end();
this.recordEndOfTick(); // Paper - improve tick loop
profilerFiller.pop();
@@ -2559,6 +2678,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2565,6 +2684,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}

Expand Down Expand Up @@ -31715,7 +31715,7 @@ index 9dc13a5b6cc1afc118a261802c71da25ae577fe5..a49a06662de4062a77112e358f536d45

public static ProblemReporter.PathElement problemPath(ChunkPos pos) {
diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java
index 2acee7d7211c4e7b9ac02e9a48d6c3ea239e6949..78600f4c583056403c93e72ec0996b00ec6d1284 100644
index faf8f53bdcaa69fbbd816739dd4f1e812ced2165..7b98964eb77a619bdaaf5a9d331e3cfe080b52a4 100644
--- a/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -116,7 +116,7 @@ public abstract class ChunkGenerator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33353,7 +33353,7 @@ index c9bbf15b75ac4516c7d7fdfaf2390351702ca415..372030b78d25b4ff0b18575d151b0a63
return structureTemplate.save(new CompoundTag());
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index bdaca3647425711ee8b10eb0593a9c3cb4037ede..bd910d8263ba8c2bdbeadf33ef5244464a32f8eb 100644
index c2ffe3c695911c706a257cfbf5c41166545f721d..e77ef704ebd2830b0d7e5afcbe873cd19293453f 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -383,6 +383,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving


diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index bd910d8263ba8c2bdbeadf33ef5244464a32f8eb..47f34dfddfb1cce87e08c9eb93ad5b2b23c1075b 100644
index e77ef704ebd2830b0d7e5afcbe873cd19293453f..9555d4cff8bdcfa64293b5a001b82a9bce808fd4 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -974,7 +974,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -980,7 +980,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
boolean var4;
try {
this.isSaving = true;
Expand All @@ -17,7 +17,7 @@ index bd910d8263ba8c2bdbeadf33ef5244464a32f8eb..47f34dfddfb1cce87e08c9eb93ad5b2b
var4 = this.saveAllChunks(suppressLogs, flush, force);
} finally {
this.isSaving = false;
@@ -1617,9 +1617,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1623,9 +1623,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}

this.ticksUntilAutosave--;
Expand Down Expand Up @@ -93,7 +93,7 @@ index 55d27aa4cff91ea61ff2ab9256acd2cd8694304a..d4466c7d30f47614a70d9ef24002a2d3
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 12ab84ddce4868ddb9e480a2bb8f322bc3346cce..a17d021269c65d98a2ba847c0059a421ea051863 100644
index 38c30d98a200dd2a5c888cc080e9c77795f0e0c4..dec9dd8e42f90ccf7e5e3ad945e459d07159250d 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -412,6 +412,7 @@ public abstract class PlayerList {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ index 2bc436cdf5180a7943c45fabb9fbbedae6f7db56..f312a7f5b1b2a777ab36b94ce7cbf387

@Override
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 47f34dfddfb1cce87e08c9eb93ad5b2b23c1075b..9934055a994c10d646d97a2d042d0e8b1e7e76c9 100644
index 9555d4cff8bdcfa64293b5a001b82a9bce808fd4..ee198a6aafbeebbaca6dac5b88ba7df14b569579 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1750,33 +1750,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1756,33 +1756,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}

Expand Down
4 changes: 2 additions & 2 deletions paper-server/patches/features/0028-Optimize-Hoppers.patch
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
+ }
+}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 9934055a994c10d646d97a2d042d0e8b1e7e76c9..e7d9306dfde918c1abb9e5320d7315810a66a4d7 100644
index ee198a6aafbeebbaca6dac5b88ba7df14b569579..8746d9df3817837c910a68c99a5378f1a2a9919d 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1805,6 +1805,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1811,6 +1811,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
serverLevel.updateLagCompensationTick(); // Paper - lag compensation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@
if (profiledDuration != null) {
profiledDuration.finish(true);
}
@@ -391,31 +_,127 @@
@@ -391,31 +_,137 @@
}
}

Expand Down Expand Up @@ -366,9 +366,9 @@
+ );
+ }
+ this.addLevel(serverLevel);
+ this.initWorld(serverLevel, serverLevelData, worldOptions);
+ this.initWorld(serverLevel, serverLevelData, worldOptions, null);
+ }
+ public void initWorld(ServerLevel serverLevel, net.minecraft.world.level.storage.PrimaryLevelData serverLevelData, WorldOptions worldOptions) {
+ public void initWorld(ServerLevel serverLevel, net.minecraft.world.level.storage.PrimaryLevelData serverLevelData, WorldOptions worldOptions, org.bukkit.@Nullable WorldCreator worldCreator) {
+ final boolean isDebugWorld = this.worldData.isDebugWorld();
+ if (serverLevel.generator != null) {
+ serverLevel.getWorld().getPopulators().addAll(serverLevel.generator.getDefaultPopulators(serverLevel.getWorld()));
Expand All @@ -379,7 +379,17 @@
if (!serverLevelData.isInitialized()) {
try {
- setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld, this.levelLoadListener);
+ setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld, serverLevel.levelLoadListener); // Paper - per world level load listener
+ // Paper start - Allow zeroing spawn location
+ if (worldCreator == null || worldCreator.forcedSpawnPosition() == null) {
+ setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld, serverLevel.levelLoadListener); // Paper - per world level load listener & rework world loading process
+ } else {
+ serverLevelData.setSpawn(LevelData.RespawnData.of(serverLevel.dimension(),
+ io.papermc.paper.util.MCUtil.toBlockPos(worldCreator.forcedSpawnPosition()),
+ java.util.Objects.requireNonNullElse(worldCreator.forcedSpawnYaw(), 0.0F),
+ java.util.Objects.requireNonNullElse(worldCreator.forcedSpawnPitch(), 0.0F)
+ ));
+ }
+ // Paper end - Allow zeroing spawn location
serverLevelData.setInitialized(true);
if (isDebugWorld) {
this.setupDebugLevel(this.worldData);
Expand Down
Loading
Loading