even even even even more work
This commit is contained in:
parent
03a53a63b6
commit
c300745c8b
79 changed files with 1260 additions and 1466 deletions
|
@ -1,320 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 9 Jun 2019 03:53:22 +0100
|
||||
Subject: [PATCH] incremental chunk saving
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 071e5e7f729d6c3ffb70506e7ef32eebee1e9118..48676152152faf7a7b9524ac37d8b4a8c32c4e2c 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -487,4 +487,19 @@ public class PaperWorldConfig {
|
||||
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
|
||||
log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
|
||||
}
|
||||
+
|
||||
+ public int autoSavePeriod = -1;
|
||||
+ private void autoSavePeriod() {
|
||||
+ autoSavePeriod = getInt("auto-save-interval", -1);
|
||||
+ if (autoSavePeriod > 0) {
|
||||
+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)");
|
||||
+ } else if (autoSavePeriod < 0) {
|
||||
+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public int maxAutoSaveChunksPerTick = 24;
|
||||
+ private void maxAutoSaveChunksPerTick() {
|
||||
+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index 962f425bbb7165740e77664dc543f976ef3d9c4a..dd3857bb6a002d8432ecbc6c6b52a39e5d55e6a6 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -42,7 +42,7 @@ public class Chunk implements IChunkAccess {
|
||||
private TickList<Block> o;
|
||||
private TickList<FluidType> p;
|
||||
private boolean q;
|
||||
- private long lastSaved;
|
||||
+ public long lastSaved; // Paper
|
||||
private volatile boolean s;
|
||||
private long inhabitedTime;
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 8a8fb6acaabc5fc179a23ce3e23ddb54e1ee23a4..7b855ec2914a8a31ce0ade0f7ad085dd04f71478 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -525,6 +525,15 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
} // Paper - Timings
|
||||
}
|
||||
|
||||
+ // Paper start - duplicate save, but call incremental
|
||||
+ public void saveIncrementally() {
|
||||
+ this.tickDistanceManager();
|
||||
+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings
|
||||
+ this.playerChunkMap.saveIncrementally();
|
||||
+ } // Paper - Timings
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 257adcf4d5387fc18d5c48e0fa221f68539ad8f9..7920d24ab089fb8360ef74946cf7dc35cb7625eb 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -168,6 +168,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
public static int currentTick = 0; // Paper - Further improve tick loop
|
||||
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
||||
public int autosavePeriod;
|
||||
+ public boolean serverAutoSave = false; // Paper
|
||||
public File bukkitDataPackFolder;
|
||||
public CommandDispatcher vanillaCommandDispatcher;
|
||||
private boolean forceTicks;
|
||||
@@ -1116,14 +1117,28 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
this.serverPing.b().a(agameprofile);
|
||||
}
|
||||
|
||||
- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
|
||||
- MinecraftServer.LOGGER.debug("Autosave started");
|
||||
+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down
|
||||
+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper
|
||||
+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper
|
||||
this.methodProfiler.enter("save");
|
||||
+ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper
|
||||
this.playerList.savePlayers();
|
||||
- this.saveChunks(true, false, false);
|
||||
+ }// Paper
|
||||
+ // Paper start
|
||||
+ for (WorldServer world : getWorlds()) {
|
||||
+ if (world.paperConfig.autoSavePeriod > 0) {
|
||||
+ try {
|
||||
+ world.saveIncrementally(serverAutoSave);
|
||||
+ } catch (ExceptionWorldConflict exceptionWorldConflict) {
|
||||
+ MinecraftServer.LOGGER.warn(exceptionWorldConflict.getMessage());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
this.methodProfiler.exit();
|
||||
- MinecraftServer.LOGGER.debug("Autosave finished");
|
||||
- }
|
||||
+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper
|
||||
+ //} // Paper
|
||||
|
||||
this.methodProfiler.enter("snooper");
|
||||
if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index 47e3e618c9e683e6975fb64e1094dc7078574dae..ed9ada49c7cc1131691bd6e005b2380274ef23e3 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -41,6 +41,9 @@ public class PlayerChunk {
|
||||
|
||||
private final PlayerChunkMap chunkMap; // Paper
|
||||
|
||||
+ long lastAutoSaveTime; // Paper - incremental autosave
|
||||
+ long inactiveTimeStart; // Paper - incremental autosave
|
||||
+
|
||||
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
|
||||
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
|
||||
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
||||
@@ -386,7 +389,19 @@ public class PlayerChunk {
|
||||
boolean flag2 = playerchunk_state.isAtLeast(PlayerChunk.State.BORDER);
|
||||
boolean flag3 = playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER);
|
||||
|
||||
+ boolean prevHasBeenLoaded = this.hasBeenLoaded; // Paper
|
||||
this.hasBeenLoaded |= flag3;
|
||||
+ // Paper start - incremental autosave
|
||||
+ if (this.hasBeenLoaded & !prevHasBeenLoaded) {
|
||||
+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime;
|
||||
+ if (timeSinceAutoSave < 0) {
|
||||
+ // safest bet is to assume autosave is needed here
|
||||
+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod;
|
||||
+ }
|
||||
+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave;
|
||||
+ this.chunkMap.autoSaveQueue.add(this);
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (!flag2 && flag3) {
|
||||
// Paper start - cache ticking ready status
|
||||
int expectCreateCount = ++this.fullChunkCreateCount;
|
||||
@@ -506,8 +521,32 @@ public class PlayerChunk {
|
||||
}
|
||||
|
||||
public void m() {
|
||||
+ boolean prev = this.hasBeenLoaded; // Paper
|
||||
+ this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER);
|
||||
+ // Paper start - incremental autosave
|
||||
+ if (prev != this.hasBeenLoaded) {
|
||||
+ if (this.hasBeenLoaded) {
|
||||
+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime;
|
||||
+ if (timeSinceAutoSave < 0) {
|
||||
+ // safest bet is to assume autosave is needed here
|
||||
+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod;
|
||||
+ }
|
||||
+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave;
|
||||
+ this.chunkMap.autoSaveQueue.add(this);
|
||||
+ } else {
|
||||
+ this.inactiveTimeStart = this.chunkMap.world.getTime();
|
||||
+ this.chunkMap.autoSaveQueue.remove(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - incremental autosave
|
||||
+ public boolean setHasBeenLoaded() {
|
||||
this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER);
|
||||
+ return this.hasBeenLoaded;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
public void a(ProtoChunkExtension protochunkextension) {
|
||||
for (int i = 0; i < this.statusFutures.length(); ++i) {
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index 34f470779fa5d1cf9638431253024481236c073b..4f5b516144829a7ae11f21a56789ac7a1f256250 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -332,6 +332,64 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - incremental autosave
|
||||
+ final it.unimi.dsi.fastutil.objects.ObjectRBTreeSet<PlayerChunk> autoSaveQueue = new it.unimi.dsi.fastutil.objects.ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> {
|
||||
+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime);
|
||||
+ if (timeCompare != 0) {
|
||||
+ return timeCompare;
|
||||
+ }
|
||||
+
|
||||
+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.location), MCUtil.getCoordinateKey(playerchunk2.location));
|
||||
+ });
|
||||
+
|
||||
+ protected void saveIncrementally() {
|
||||
+ int savedThisTick = 0;
|
||||
+ // optimized since we search far less chunks to hit ones that need to be saved
|
||||
+ List<PlayerChunk> reschedule = new ArrayList<>(this.world.paperConfig.maxAutoSaveChunksPerTick);
|
||||
+ long currentTick = this.world.getTime();
|
||||
+ long maxSaveTime = currentTick - this.world.paperConfig.autoSavePeriod;
|
||||
+
|
||||
+ for (Iterator<PlayerChunk> iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) {
|
||||
+ PlayerChunk playerchunk = iterator.next();
|
||||
+ if (playerchunk.lastAutoSaveTime > maxSaveTime) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ iterator.remove();
|
||||
+
|
||||
+ IChunkAccess ichunkaccess = playerchunk.getChunkSave().getNow(null);
|
||||
+ if (ichunkaccess instanceof Chunk) {
|
||||
+ boolean shouldSave = ((Chunk)ichunkaccess).lastSaved <= maxSaveTime;
|
||||
+
|
||||
+ if (shouldSave && this.saveChunk(ichunkaccess)) {
|
||||
+ ++savedThisTick;
|
||||
+
|
||||
+ if (!playerchunk.setHasBeenLoaded()) {
|
||||
+ // do not fall through to reschedule logic
|
||||
+ playerchunk.inactiveTimeStart = currentTick;
|
||||
+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) {
|
||||
+ break;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ reschedule.add(playerchunk);
|
||||
+
|
||||
+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0, len = reschedule.size(); i < len; ++i) {
|
||||
+ PlayerChunk playerchunk = reschedule.get(i);
|
||||
+ playerchunk.lastAutoSaveTime = this.world.getTime();
|
||||
+ this.autoSaveQueue.add(playerchunk);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
protected void save(boolean flag) {
|
||||
if (flag) {
|
||||
List<PlayerChunk> list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList());
|
||||
@@ -442,6 +500,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
this.world.unloadChunk(chunk);
|
||||
}
|
||||
+ this.autoSaveQueue.remove(playerchunk); // Paper
|
||||
|
||||
this.lightEngine.a(ichunkaccess.getPos());
|
||||
this.lightEngine.queueUpdate();
|
||||
@@ -623,6 +682,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
playerchunk.a(new ProtoChunkExtension(chunk));
|
||||
}
|
||||
|
||||
+ chunk.setLastSaved(this.world.getTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks
|
||||
+
|
||||
chunk.a(() -> {
|
||||
return PlayerChunk.getChunkState(playerchunk.getTicketLevel());
|
||||
});
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
index ca0a23be27ee8174204867d463eb89a10931ff84..a0484d8062ecfb817cfd5b996915dc8f9a4eb2bd 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -817,11 +817,44 @@ public class WorldServer extends World {
|
||||
return this.worldProvider.c();
|
||||
}
|
||||
|
||||
+ // Paper start - derived from below
|
||||
+ public void saveIncrementally(boolean doFull) throws ExceptionWorldConflict {
|
||||
+ ChunkProviderServer chunkproviderserver = this.getChunkProvider();
|
||||
+
|
||||
+ if (doFull) {
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld()));
|
||||
+ }
|
||||
+
|
||||
+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) {
|
||||
+ if (doFull) {
|
||||
+ this.saveData();
|
||||
+ }
|
||||
+
|
||||
+ timings.worldSaveChunks.startTiming(); // Paper
|
||||
+ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally();
|
||||
+ timings.worldSaveChunks.stopTiming(); // Paper
|
||||
+
|
||||
+
|
||||
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
|
||||
+ // PAIL - rename
|
||||
+ if (doFull) {
|
||||
+ WorldServer worldserver1 = this;
|
||||
+ WorldData worlddata = worldserver1.getWorldData();
|
||||
+
|
||||
+ worldserver1.getWorldBorder().save(worlddata);
|
||||
+ worlddata.setCustomBossEvents(this.server.getBossBattleCustomData().save());
|
||||
+ worldserver1.getDataManager().saveWorldData(worlddata, this.server.getPlayerList().save());
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) throws ExceptionWorldConflict {
|
||||
ChunkProviderServer chunkproviderserver = this.getChunkProvider();
|
||||
|
||||
if (!flag1) {
|
||||
- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
|
||||
+ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
|
||||
try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper
|
||||
if (iprogressupdate != null) {
|
||||
iprogressupdate.a(new ChatMessage("menu.savingLevel", new Object[0]));
|
||||
@@ -848,6 +881,7 @@ public class WorldServer extends World {
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ protected void saveData() throws ExceptionWorldConflict { this.m_(); } // Paper - OBFHELPER
|
||||
protected void m_() throws ExceptionWorldConflict {
|
||||
this.checkSession();
|
||||
this.worldProvider.i();
|
|
@ -0,0 +1,25 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 22 Jun 2019 04:20:47 -0700
|
||||
Subject: [PATCH] Use ChunkStatus cache when saving protochunks
|
||||
|
||||
The cache should contain the chunk status when saving. If not it
|
||||
will load it.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index 1d517fd1aea90edf470388fd857a41f2be149327..9171785ad54a26e95dea8b30509c1e49a5d9b22d 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -845,8 +845,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
NBTTagCompound nbttagcompound;
|
||||
|
||||
if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) {
|
||||
- nbttagcompound = this.readChunkData(chunkcoordintpair);
|
||||
- if (nbttagcompound != null && ChunkRegionLoader.a(nbttagcompound) == ChunkStatus.Type.LEVELCHUNK) {
|
||||
+ // Paper start - Optimize save by using status cache
|
||||
+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkcoordintpair);
|
||||
+ if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) {
|
||||
+ // Paper end
|
||||
return false;
|
||||
}
|
||||
|
21
removed/1.16/0412-Fix-spawn-radius-being-treated-as-0.patch
Normal file
21
removed/1.16/0412-Fix-spawn-radius-being-treated-as-0.patch
Normal file
|
@ -0,0 +1,21 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 15 Dec 2019 19:41:28 +0000
|
||||
Subject: [PATCH] Fix spawn radius being treated as 0
|
||||
|
||||
|
||||
Not needed anymore?
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
index 81f00141776a1767b907d14ef04f60b576110128..86bbbbaefca9ace5327d8bc2456939eb9ae8966a 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
@@ -129,7 +129,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
public final BlockPosition getSpawnPoint(WorldServer worldserver) {
|
||||
BlockPosition blockposition = worldserver.getSpawn();
|
||||
|
||||
- if (worldserver.worldProvider.g() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) {
|
||||
+ if (worldserver.worldProvider.f() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) { // Paper
|
||||
int i = Math.max(0, this.server.a(worldserver));
|
||||
int j = MathHelper.floor(worldserver.getWorldBorder().b((double) blockposition.getX(), (double) blockposition.getZ()));
|
||||
|
110
removed/1.16/0429-Seed-based-feature-search.patch
Normal file
110
removed/1.16/0429-Seed-based-feature-search.patch
Normal file
|
@ -0,0 +1,110 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Mon, 13 Jan 2020 15:40:32 +0100
|
||||
Subject: [PATCH] Seed based feature search
|
||||
|
||||
This fixes the issue where the server will load surrounding chunks up to
|
||||
a radius of 100 chunks in order to search for features e.g. when running
|
||||
the /locate command or for treasure maps (issue #2312).
|
||||
This is done by using the same seed checking functionality that is used
|
||||
by the server when generating these features before actually attempting
|
||||
to load the chunk to check if a feature is available in it.
|
||||
|
||||
The only downside of this is that it breaks once the seed or generator
|
||||
changes but this should usually not happen. A config option to disable
|
||||
this improvement is added though in case that should ever be necessary.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index cab503bd5c34d12b38a2f5deed6d3feb9287b370..2ab810f71beaa608af2194165696817a2cde4b92 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -357,6 +357,12 @@ public class PaperWorldConfig {
|
||||
}
|
||||
}
|
||||
|
||||
+ public boolean seedBasedFeatureSearch = true;
|
||||
+ private void seedBasedFeatureSearch() {
|
||||
+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch);
|
||||
+ log("Feature search is based on seed: " + seedBasedFeatureSearch);
|
||||
+ }
|
||||
+
|
||||
public int maxCollisionsPerEntity;
|
||||
private void maxEntityCollision() {
|
||||
maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) );
|
||||
diff --git a/src/main/java/net/minecraft/server/BiomeManager.java b/src/main/java/net/minecraft/server/BiomeManager.java
|
||||
index e96f544f126371f6f629a20ba3c99ba42d31e04a..68423645df3aa08d4c5126ff068d5e566927f744 100644
|
||||
--- a/src/main/java/net/minecraft/server/BiomeManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/BiomeManager.java
|
||||
@@ -12,10 +12,12 @@ public class BiomeManager {
|
||||
this.c = genlayerzoomer;
|
||||
}
|
||||
|
||||
+ public BiomeManager withProvider(WorldChunkManager worldchunkmanager) { return a(worldchunkmanager); } // Paper - OBFHELPER
|
||||
public BiomeManager a(WorldChunkManager worldchunkmanager) {
|
||||
return new BiomeManager(worldchunkmanager, this.b, this.c);
|
||||
}
|
||||
|
||||
+ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER
|
||||
public BiomeBase a(BlockPosition blockposition) {
|
||||
return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
index 5a975f6bc60922ac872ec9c00c9150ce7dcad046..f617636a22167b06ac8073aa25efd8c7099155f0 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
@@ -68,10 +68,12 @@ public class ChunkCoordIntPair {
|
||||
}
|
||||
}
|
||||
|
||||
+ public int getBlockX() { return d(); } // Paper - OBFHELPER
|
||||
public int d() {
|
||||
return this.x << 4;
|
||||
}
|
||||
|
||||
+ public int getBlockZ() { return e(); } // Paper - OBFHELPER
|
||||
public int e() {
|
||||
return this.z << 4;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
index e8ce2ecf23e58d82febf6b9441e0004e69cdc858..acfe732af5b9f63fc2f6b78499defabe2e73ee45 100644
|
||||
--- a/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
@@ -109,6 +109,15 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
|
||||
if (flag1 || flag2) {
|
||||
ChunkCoordIntPair chunkcoordintpair = this.a(chunkgenerator, seededrandom, j, k, i1, j1);
|
||||
if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
|
||||
+ // Paper start - seed based feature search
|
||||
+ if (world.paperConfig.seedBasedFeatureSearch) {
|
||||
+ BiomeManager biomeManager = world.getBiomeManager().withProvider(chunkgenerator.getWorldChunkManager());
|
||||
+ BiomeBase biomeBase = biomeManager.getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9));
|
||||
+ if (!shouldGenerate(biomeManager, chunkgenerator, seededrandom, chunkcoordintpair.x, chunkcoordintpair.z, biomeBase)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
StructureStart structurestart = world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS).a(this.b());
|
||||
|
||||
if (structurestart != null && structurestart.e()) {
|
||||
@@ -165,6 +174,7 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
|
||||
return new ChunkCoordIntPair(i + k, j + l);
|
||||
}
|
||||
|
||||
+ public boolean shouldGenerate(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int chunkX, int chunkZ, BiomeBase biomebase) { return a(biomemanager, chunkgenerator, random, chunkX, chunkZ, biomebase); } // Paper - OBFHELPER
|
||||
public abstract boolean a(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int i, int j, BiomeBase biomebase);
|
||||
|
||||
public abstract StructureGenerator.a a();
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 0fa2b335db297c6270090d3dd24ced92eab12825..d7ac4c86d170a8d7d816f86ac691c3b5129a20ba 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -1570,8 +1570,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
||||
return this.methodProfiler;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public BiomeManager d() {
|
||||
+ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER
|
||||
+ @Override public BiomeManager d() {
|
||||
return this.biomeManager;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue