rewrite chunk system checkpoint

This commit is contained in:
Spottedleaf 2023-06-07 22:21:04 -07:00
parent 0c4a1c4496
commit 819facd7c4
666 changed files with 23181 additions and 869 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 16 Feb 2023 16:50:05 -0800
Subject: [PATCH] Make ChunkStatus.EMPTY not rely on the main thread for
completion
In order to do this, we need to push the POI consistency checks
to a later status. Since FULL is the only other status that
uses the main thread, it can go there.
The consistency checks are only really for when a desync occurs,
and so that delaying the check only matters when the chunk data
has desync'd. As long as the desync is sorted before the
chunk is full loaded (i.e before setBlock can occur on
a chunk), it should not matter.
This change is primarily due to behavioural changes
in the chunk task queue brought by region threading -
which is to split the queue into separate regions. As such,
it is required that in order for the sync load to complete
that the region owning the chunk drain and execute the task
while ticking. However, that is not always possible in
region threading. Thus, removing the main thread reliance allows
the chunk to progress without requiring a tick thread.
Specifically, this allows far sync loads (outside of a specific
regions bounds) to occur without issue - namely with structure
searching.
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java
index fb42d776f15f735fb59e972e00e2b512c23a8387..300700477ee34bc22b31315825c0e40f61070cd5 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java
@@ -2,6 +2,8 @@ package io.papermc.paper.chunk.system.scheduling;
import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
+import com.mojang.logging.LogUtils;
+import io.papermc.paper.chunk.system.poi.PoiChunk;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -9,10 +11,13 @@ import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ImposterProtoChunk;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
+import org.slf4j.Logger;
import java.lang.invoke.VarHandle;
public final class ChunkFullTask extends ChunkProgressionTask implements Runnable {
+ private static final Logger LOGGER = LogUtils.getClassLogger();
+
protected final NewChunkHolder chunkHolder;
protected final ChunkAccess fromChunk;
protected final PrioritisedExecutor.PrioritisedTask convertToFullTask;
@@ -35,6 +40,15 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl
// See Vanilla protoChunkToFullChunk for what this function should be doing
final LevelChunk chunk;
try {
+ // moved from the load from nbt stage into here
+ final PoiChunk poiChunk = this.chunkHolder.getPoiChunk();
+ if (poiChunk == null) {
+ LOGGER.error("Expected poi chunk to be loaded with chunk for task " + this.toString());
+ } else {
+ poiChunk.load();
+ this.world.getPoiManager().checkConsistency(this.fromChunk);
+ }
+
if (this.fromChunk instanceof ImposterProtoChunk wrappedFull) {
chunk = wrappedFull.getWrapped();
} else {
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java
index be6f3f6a57668a9bd50d0ea5f2dd2335355b69d6..1f7c146ff0b2a835c818f49da6c1f1411f26aa39 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java
@@ -25,6 +25,7 @@ import org.slf4j.Logger;
import java.lang.invoke.VarHandle;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
public final class ChunkLoadTask extends ChunkProgressionTask {
@@ -34,9 +35,11 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
private final NewChunkHolder chunkHolder;
private final ChunkDataLoadTask loadTask;
- private boolean cancelled;
+ private volatile boolean cancelled;
private NewChunkHolder.GenericDataLoadTaskCallback entityLoadTask;
private NewChunkHolder.GenericDataLoadTaskCallback poiLoadTask;
+ private GenericDataLoadTask.TaskResult<ChunkAccess, Throwable> loadResult;
+ private final AtomicInteger taskCountToComplete = new AtomicInteger(3); // one for poi, one for entity, and one for chunk data
protected ChunkLoadTask(final ChunkTaskScheduler scheduler, final ServerLevel world, final int chunkX, final int chunkZ,
final NewChunkHolder chunkHolder, final PrioritisedExecutor.Priority priority) {
@@ -44,10 +47,18 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
this.chunkHolder = chunkHolder;
this.loadTask = new ChunkDataLoadTask(scheduler, world, chunkX, chunkZ, priority);
this.loadTask.addCallback((final GenericDataLoadTask.TaskResult<ChunkAccess, Throwable> result) -> {
- ChunkLoadTask.this.complete(result == null ? null : result.left(), result == null ? null : result.right());
+ ChunkLoadTask.this.loadResult = result; // must be before getAndDecrement
+ ChunkLoadTask.this.tryCompleteLoad();
});
}
+ private void tryCompleteLoad() {
+ if (this.taskCountToComplete.decrementAndGet() == 0) {
+ final GenericDataLoadTask.TaskResult<ChunkAccess, Throwable> result = this.cancelled ? null : this.loadResult; // only after the getAndDecrement
+ ChunkLoadTask.this.complete(result == null ? null : result.left(), result == null ? null : result.right());
+ }
+ }
+
@Override
public ChunkStatus getTargetStatus() {
return ChunkStatus.EMPTY;
@@ -65,11 +76,8 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
final NewChunkHolder.GenericDataLoadTaskCallback entityLoadTask;
final NewChunkHolder.GenericDataLoadTaskCallback poiLoadTask;
- final AtomicInteger count = new AtomicInteger();
final Consumer<GenericDataLoadTask.TaskResult<?, ?>> scheduleLoadTask = (final GenericDataLoadTask.TaskResult<?, ?> result) -> {
- if (count.decrementAndGet() == 0) {
- ChunkLoadTask.this.loadTask.schedule(false);
- }
+ ChunkLoadTask.this.tryCompleteLoad();
};
// NOTE: it is IMPOSSIBLE for getOrLoadEntityData/getOrLoadPoiData to complete synchronously, because
@@ -85,16 +93,16 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
}
if (!this.chunkHolder.isEntityChunkNBTLoaded()) {
entityLoadTask = this.chunkHolder.getOrLoadEntityData((Consumer)scheduleLoadTask);
- count.setPlain(count.getPlain() + 1);
} else {
entityLoadTask = null;
+ this.taskCountToComplete.getAndDecrement(); // we know the chunk load is not done here, as it is not scheduled
}
if (!this.chunkHolder.isPoiChunkLoaded()) {
poiLoadTask = this.chunkHolder.getOrLoadPoiData((Consumer)scheduleLoadTask);
- count.setPlain(count.getPlain() + 1);
} else {
poiLoadTask = null;
+ this.taskCountToComplete.getAndDecrement(); // we know the chunk load is not done here, as it is not scheduled
}
this.entityLoadTask = entityLoadTask;
@@ -107,14 +115,11 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
entityLoadTask.schedule();
}
- if (poiLoadTask != null) {
+ if (poiLoadTask != null) {
poiLoadTask.schedule();
}
- if (entityLoadTask == null && poiLoadTask == null) {
- // no need to wait on those, we can schedule now
- this.loadTask.schedule(false);
- }
+ this.loadTask.schedule(false);
}
@Override
@@ -129,15 +134,20 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
/*
Note: The entityLoadTask/poiLoadTask do not complete when cancelled,
- but this is fine because if they are successfully cancelled then
- we will successfully cancel the load task, which will complete when cancelled
+ so we need to manually try to complete in those cases
+ It is also important to note that we set the cancelled field first, just in case
+ the chunk load task attempts to complete with a non-null value
*/
if (this.entityLoadTask != null) {
- this.entityLoadTask.cancel();
+ if (this.entityLoadTask.cancel()) {
+ this.tryCompleteLoad();
+ }
}
if (this.poiLoadTask != null) {
- this.poiLoadTask.cancel();
+ if (this.poiLoadTask.cancel()) {
+ this.tryCompleteLoad();
+ }
}
this.loadTask.cancel();
}
@@ -249,7 +259,7 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
}
}
- public final class ChunkDataLoadTask extends CallbackDataLoadTask<ChunkSerializer.InProgressChunkHolder, ChunkAccess> {
+ public static final class ChunkDataLoadTask extends CallbackDataLoadTask<ChunkAccess, ChunkAccess> {
protected ChunkDataLoadTask(final ChunkTaskScheduler scheduler, final ServerLevel world, final int chunkX,
final int chunkZ, final PrioritisedExecutor.Priority priority) {
super(scheduler, world, chunkX, chunkZ, RegionFileIOThread.RegionFileType.CHUNK_DATA, priority);
@@ -262,7 +272,7 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
@Override
protected boolean hasOnMain() {
- return true;
+ return false;
}
@Override
@@ -272,35 +282,30 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
@Override
protected PrioritisedExecutor.PrioritisedTask createOnMain(final Runnable run, final PrioritisedExecutor.Priority priority) {
- return this.scheduler.createChunkTask(this.chunkX, this.chunkZ, run, priority);
+ throw new UnsupportedOperationException();
}
@Override
- protected TaskResult<ChunkAccess, Throwable> completeOnMainOffMain(final ChunkSerializer.InProgressChunkHolder data, final Throwable throwable) {
- if (data != null) {
- return null;
- }
-
- final PoiChunk poiChunk = ChunkLoadTask.this.chunkHolder.getPoiChunk();
- if (poiChunk == null) {
- LOGGER.error("Expected poi chunk to be loaded with chunk for task " + this.toString());
- } else if (!poiChunk.isLoaded()) {
- // need to call poiChunk.load() on main
- return null;
- }
+ protected TaskResult<ChunkAccess, Throwable> completeOnMainOffMain(final ChunkAccess data, final Throwable throwable) {
+ throw new UnsupportedOperationException();
+ }
- return new TaskResult<>(this.getEmptyChunk(), null);
+ private ProtoChunk getEmptyChunk() {
+ return new ProtoChunk(
+ new ChunkPos(this.chunkX, this.chunkZ), UpgradeData.EMPTY, this.world,
+ this.world.registryAccess().registryOrThrow(Registries.BIOME), (BlendingData)null
+ );
}
@Override
- protected TaskResult<ChunkSerializer.InProgressChunkHolder, Throwable> runOffMain(final CompoundTag data, final Throwable throwable) {
+ protected TaskResult<ChunkAccess, Throwable> runOffMain(final CompoundTag data, final Throwable throwable) {
if (throwable != null) {
LOGGER.error("Failed to load chunk data for task: " + this.toString() + ", chunk data will be lost", throwable);
- return new TaskResult<>(null, null);
+ return new TaskResult<>(this.getEmptyChunk(), null);
}
if (data == null) {
- return new TaskResult<>(null, null);
+ return new TaskResult<>(this.getEmptyChunk(), null);
}
// need to convert data, and then deserialize it
@@ -319,53 +324,18 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
this.world, chunkMap.getPoiManager(), chunkPos, converted, true
);
- return new TaskResult<>(chunkHolder, null);
+ return new TaskResult<>(chunkHolder.protoChunk, null);
} catch (final ThreadDeath death) {
throw death;
} catch (final Throwable thr2) {
LOGGER.error("Failed to parse chunk data for task: " + this.toString() + ", chunk data will be lost", thr2);
- return new TaskResult<>(null, thr2);
+ return new TaskResult<>(this.getEmptyChunk(), null);
}
}
- private ProtoChunk getEmptyChunk() {
- return new ProtoChunk(
- new ChunkPos(this.chunkX, this.chunkZ), UpgradeData.EMPTY, this.world,
- this.world.registryAccess().registryOrThrow(Registries.BIOME), (BlendingData)null
- );
- }
-
@Override
- protected TaskResult<ChunkAccess, Throwable> runOnMain(final ChunkSerializer.InProgressChunkHolder data, final Throwable throwable) {
- final PoiChunk poiChunk = ChunkLoadTask.this.chunkHolder.getPoiChunk();
- if (poiChunk == null) {
- LOGGER.error("Expected poi chunk to be loaded with chunk for task " + this.toString());
- } else {
- poiChunk.load();
- }
-
- if (data == null || data.protoChunk == null) {
- // throwable could be non-null, but the off-main task will print its exceptions - so we don't need to care,
- // it's handled already
-
- return new TaskResult<>(this.getEmptyChunk(), null);
- }
-
- // have tasks to run (at this point, it's just the POI consistency checking)
- try {
- if (data.tasks != null) {
- for (int i = 0, len = data.tasks.size(); i < len; ++i) {
- data.tasks.poll().run();
- }
- }
-
- return new TaskResult<>(data.protoChunk, null);
- } catch (final ThreadDeath death) {
- throw death;
- } catch (final Throwable thr2) {
- LOGGER.error("Failed to parse main tasks for task " + this.toString() + ", chunk data will be lost", thr2);
- return new TaskResult<>(this.getEmptyChunk(), null);
- }
+ protected TaskResult<ChunkAccess, Throwable> runOnMain(final ChunkAccess data, final Throwable throwable) {
+ throw new UnsupportedOperationException();
}
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
index f10ba4211cbdcc4f4ce3585c7cb3f80185e13b73..6f2c7baea0d1ac7813c7b85e1f5558573745762c 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
@@ -310,6 +310,17 @@ public class PoiManager extends SectionStorage<PoiSection> {
}
}
}
+
+ public void checkConsistency(net.minecraft.world.level.chunk.ChunkAccess chunk) {
+ int chunkX = chunk.getPos().x;
+ int chunkZ = chunk.getPos().z;
+ int minY = io.papermc.paper.util.WorldUtil.getMinSection(chunk);
+ int maxY = io.papermc.paper.util.WorldUtil.getMaxSection(chunk);
+ LevelChunkSection[] sections = chunk.getSections();
+ for (int section = minY; section <= maxY; ++section) {
+ this.checkConsistencyWithBlocks(SectionPos.of(chunkX, section, chunkZ), sections[section - minY]);
+ }
+ }
// Paper end - rewrite chunk system
public void checkConsistencyWithBlocks(SectionPos sectionPos, LevelChunkSection chunkSection) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index 55da32077d1db81ba197da0be5896da694f4bfa9..a7ee469bb2880a78540b79ae691ea449dfe22ce4 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -98,13 +98,11 @@ public class ChunkSerializer {
public static final class InProgressChunkHolder {
public final ProtoChunk protoChunk;
- public final java.util.ArrayDeque<Runnable> tasks;
public CompoundTag poiData;
- public InProgressChunkHolder(final ProtoChunk protoChunk, final java.util.ArrayDeque<Runnable> tasks) {
+ public InProgressChunkHolder(final ProtoChunk protoChunk) {
this.protoChunk = protoChunk;
- this.tasks = tasks;
}
}
// Paper end
@@ -112,12 +110,10 @@ public class ChunkSerializer {
public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) {
// Paper start - add variant for async calls
InProgressChunkHolder holder = loadChunk(world, poiStorage, chunkPos, nbt, true);
- holder.tasks.forEach(Runnable::run);
return holder.protoChunk;
}
public static InProgressChunkHolder loadChunk(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt, boolean distinguish) {
- java.util.ArrayDeque<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>();
// Paper end
ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
@@ -184,9 +180,7 @@ public class ChunkSerializer {
achunksection[k] = chunksection;
SectionPos sectionposition = SectionPos.of(chunkPos, b0);
- tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main
- poiStorage.checkConsistencyWithBlocks(sectionposition, chunksection);
- }); // Paper - delay this task since we're executing off-main
+ // Paper - rewrite chunk system - moved to final load stage
}
boolean flag3 = nbttagcompound1.contains("BlockLight", 7);
@@ -332,7 +326,7 @@ public class ChunkSerializer {
}
if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) {
- return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object1, false), tasksToExecuteOnMain); // Paper - Async chunk loading
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object1, false)); // Paper - Async chunk loading
} else {
ProtoChunk protochunk1 = (ProtoChunk) object1;
@@ -360,7 +354,7 @@ public class ChunkSerializer {
protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound5.getLongArray(s1), ((ChunkAccess) object1).getMinBuildHeight()));
}
- return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
+ return new InProgressChunkHolder(protochunk1); // Paper - Async chunk loading
}
}

View File

@ -0,0 +1,999 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 26 Feb 2023 23:42:29 -0800
Subject: [PATCH] Increase parallelism for neighbour writing chunk statuses
Namely, everything after FEATURES. By creating a dependency
chain indicating what chunks are in use, we can safely
schedule completely independent tasks in parallel. This
will allow the chunk system to scale beyond 10 threads
per world.
diff --git a/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java
index cf7610b3396d03bf79a899d5d9cfc6debb5b90be..48bfee5b9db501fcdba4ddb1e4bff2718956a680 100644
--- a/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java
+++ b/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java
@@ -286,7 +286,92 @@ public class RegionizedPlayerChunkLoader {
}
}
- return chunks.toLongArray();
+ // to increase generation parallelism, we want to space the chunks out so that they are not nearby when generating
+ // this also means we are minimising locality
+ // but, we need to maintain sorted order by manhatten distance
+
+ // first, build a map of manhatten distance -> chunks
+ final java.util.List<LongArrayList> byDistance = new java.util.ArrayList<>();
+ for (final it.unimi.dsi.fastutil.longs.LongIterator iterator = chunks.iterator(); iterator.hasNext();) {
+ final long chunkKey = iterator.nextLong();
+
+ final int chunkX = CoordinateUtils.getChunkX(chunkKey);
+ final int chunkZ = CoordinateUtils.getChunkZ(chunkKey);
+
+ final int dist = Math.abs(chunkX) + Math.abs(chunkZ);
+ if (dist == byDistance.size()) {
+ final LongArrayList list = new LongArrayList();
+ list.add(chunkKey);
+ byDistance.add(list);
+ continue;
+ }
+
+ byDistance.get(dist).add(chunkKey);
+ }
+
+ // per distance we transform the chunk list so that each element is maximally spaced out from each other
+ for (int i = 0, len = byDistance.size(); i < len; ++i) {
+ final LongArrayList notAdded = byDistance.get(i).clone();
+ final LongArrayList added = new LongArrayList();
+
+ while (!notAdded.isEmpty()) {
+ if (added.isEmpty()) {
+ added.add(notAdded.removeLong(notAdded.size() - 1));
+ continue;
+ }
+
+ long maxChunk = -1L;
+ int maxDist = 0;
+
+ // select the chunk from the not yet added set that has the largest minimum distance from
+ // the current set of added chunks
+
+ for (final it.unimi.dsi.fastutil.longs.LongIterator iterator = notAdded.iterator(); iterator.hasNext();) {
+ final long chunkKey = iterator.nextLong();
+ final int chunkX = CoordinateUtils.getChunkX(chunkKey);
+ final int chunkZ = CoordinateUtils.getChunkZ(chunkKey);
+
+ int minDist = Integer.MAX_VALUE;
+
+ for (final it.unimi.dsi.fastutil.longs.LongIterator iterator2 = added.iterator(); iterator2.hasNext();) {
+ final long addedKey = iterator2.nextLong();
+ final int addedX = CoordinateUtils.getChunkX(addedKey);
+ final int addedZ = CoordinateUtils.getChunkZ(addedKey);
+
+ // here we use square distance because chunk generation uses neighbours in a square radius
+ final int dist = Math.max(Math.abs(addedX - chunkX), Math.abs(addedZ - chunkZ));
+
+ if (dist < minDist) {
+ minDist = dist;
+ }
+ }
+
+ if (minDist > maxDist) {
+ maxDist = minDist;
+ maxChunk = chunkKey;
+ }
+ }
+
+ // move the selected chunk from the not added set to the added set
+
+ if (!notAdded.rem(maxChunk)) {
+ throw new IllegalStateException();
+ }
+
+ added.add(maxChunk);
+ }
+
+ byDistance.set(i, added);
+ }
+
+ // now, rebuild the list so that it still maintains manhatten distance order
+ final LongArrayList ret = new LongArrayList(chunks.size());
+
+ for (final LongArrayList dist : byDistance) {
+ ret.addAll(dist);
+ }
+
+ return ret.toLongArray();
}
public static final class PlayerChunkLoaderData {
diff --git a/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java b/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java
index 0b7a2b0ead4f3bc07bfd9a38c2b7cf024bd140c6..36e93fefdfbebddce4c153974c7cd81af3cb92e9 100644
--- a/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java
+++ b/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java
@@ -4,7 +4,6 @@ import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
import ca.spottedleaf.starlight.common.light.BlockStarLightEngine;
import ca.spottedleaf.starlight.common.light.SkyStarLightEngine;
import ca.spottedleaf.starlight.common.light.StarLightInterface;
-import io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler;
import io.papermc.paper.util.CoordinateUtils;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.shorts.ShortCollection;
@@ -13,6 +12,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.chunk.ChunkStatus;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -201,7 +201,10 @@ public final class LightQueue {
this.chunkCoordinate = chunkCoordinate;
this.lightEngine = lightEngine;
this.queue = queue;
- this.task = queue.world.chunkTaskScheduler.lightExecutor.createTask(this, priority);
+ this.task = queue.world.chunkTaskScheduler.radiusAwareScheduler.createTask(
+ CoordinateUtils.getChunkX(chunkCoordinate), CoordinateUtils.getChunkZ(chunkCoordinate),
+ ChunkStatus.LIGHT.writeRadius, this, priority
+ );
}
public void schedule() {
@@ -230,23 +233,23 @@ public final class LightQueue {
@Override
public void run() {
- final SkyStarLightEngine skyEngine = this.lightEngine.getSkyLightEngine();
- final BlockStarLightEngine blockEngine = this.lightEngine.getBlockLightEngine();
- try {
- synchronized (this.queue) {
- this.queue.chunkTasks.remove(this.chunkCoordinate);
- }
+ synchronized (this.queue) {
+ this.queue.chunkTasks.remove(this.chunkCoordinate);
+ }
- boolean litChunk = false;
- if (this.lightTasks != null) {
- for (final BooleanSupplier run : this.lightTasks) {
- if (run.getAsBoolean()) {
- litChunk = true;
- break;
- }
+ boolean litChunk = false;
+ if (this.lightTasks != null) {
+ for (final BooleanSupplier run : this.lightTasks) {
+ if (run.getAsBoolean()) {
+ litChunk = true;
+ break;
}
}
+ }
+ final SkyStarLightEngine skyEngine = this.lightEngine.getSkyLightEngine();
+ final BlockStarLightEngine blockEngine = this.lightEngine.getBlockLightEngine();
+ try {
final long coordinate = this.chunkCoordinate;
final int chunkX = CoordinateUtils.getChunkX(coordinate);
final int chunkZ = CoordinateUtils.getChunkZ(coordinate);
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
index ce26fdfa1afc74ba93d19157042f6c55778011e1..718c1dd7b52fb9a501d552fdbcb3f9ff79d127d8 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
@@ -1022,17 +1022,23 @@ public final class ChunkHolderManager {
}
public Boolean tryDrainTicketUpdates() {
- final boolean acquired = this.ticketLock.tryLock();
- try {
- if (!acquired) {
- return null;
- }
+ boolean ret = false;
+ for (;;) {
+ final boolean acquired = this.ticketLock.tryLock();
+ try {
+ if (!acquired) {
+ return ret ? Boolean.TRUE : null;
+ }
- return Boolean.valueOf(this.drainTicketUpdates());
- } finally {
- if (acquired) {
- this.ticketLock.unlock();
+ ret |= this.drainTicketUpdates();
+ } finally {
+ if (acquired) {
+ this.ticketLock.unlock();
+ }
}
+ if (this.delayedTicketUpdates.isEmpty()) {
+ return Boolean.valueOf(ret);
+ } // else: try to re-acquire
}
}
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java
index 84d6af5c28cd0e81d50701bebe122f462720fbf8..d2bb266a5ed344507058778a94a8a4dcac61ba17 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java
@@ -2,9 +2,9 @@ package io.papermc.paper.chunk.system.scheduling;
import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadPool;
-import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadedTaskQueue;
import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
import com.mojang.logging.LogUtils;
+import io.papermc.paper.chunk.system.scheduling.queue.RadiusAwarePrioritisedExecutor;
import io.papermc.paper.configuration.GlobalConfiguration;
import io.papermc.paper.util.CoordinateUtils;
import io.papermc.paper.util.TickThread;
@@ -21,7 +21,6 @@ import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
-import org.bukkit.Bukkit;
import org.slf4j.Logger;
import java.io.File;
import java.util.ArrayDeque;
@@ -34,7 +33,6 @@ import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
public final class ChunkTaskScheduler {
@@ -108,9 +106,9 @@ public final class ChunkTaskScheduler {
public final ServerLevel world;
public final PrioritisedThreadPool workers;
- public final PrioritisedThreadPool.PrioritisedPoolExecutor lightExecutor;
- public final PrioritisedThreadPool.PrioritisedPoolExecutor genExecutor;
+ public final RadiusAwarePrioritisedExecutor radiusAwareScheduler;
public final PrioritisedThreadPool.PrioritisedPoolExecutor parallelGenExecutor;
+ private final PrioritisedThreadPool.PrioritisedPoolExecutor radiusAwareGenExecutor;
public final PrioritisedThreadPool.PrioritisedPoolExecutor loadExecutor;
private final PrioritisedThreadedTaskQueue mainThreadExecutor = new PrioritisedThreadedTaskQueue();
@@ -191,12 +189,11 @@ public final class ChunkTaskScheduler {
this.workers = workers;
final String worldName = world.getWorld().getName();
- this.genExecutor = workers.createExecutor("Chunk single-threaded generation executor for world '" + worldName + "'", 1);
- // same as genExecutor, as there are race conditions between updating blocks in FEATURE status while lighting chunks
- this.lightExecutor = this.genExecutor;
- this.parallelGenExecutor = newChunkSystemGenParallelism <= 1 ? this.genExecutor
- : workers.createExecutor("Chunk parallel generation executor for world '" + worldName + "'", newChunkSystemGenParallelism);
+ this.parallelGenExecutor = workers.createExecutor("Chunk parallel generation executor for world '" + worldName + "'", Math.max(1, newChunkSystemGenParallelism));
+ this.radiusAwareGenExecutor =
+ newChunkSystemGenParallelism <= 1 ? this.parallelGenExecutor : workers.createExecutor("Chunk radius aware generator for world '" + worldName + "'", newChunkSystemGenParallelism);
this.loadExecutor = workers.createExecutor("Chunk load executor for world '" + worldName + "'", newChunkSystemLoadParallelism);
+ this.radiusAwareScheduler = new RadiusAwarePrioritisedExecutor(this.radiusAwareGenExecutor, Math.max(1, newChunkSystemGenParallelism));
this.chunkHolderManager = new ChunkHolderManager(world, this);
}
@@ -688,16 +685,14 @@ public final class ChunkTaskScheduler {
}
public boolean halt(final boolean sync, final long maxWaitNS) {
- this.lightExecutor.halt();
- this.genExecutor.halt();
+ this.radiusAwareGenExecutor.halt();
this.parallelGenExecutor.halt();
this.loadExecutor.halt();
final long time = System.nanoTime();
if (sync) {
for (long failures = 9L;; failures = ConcurrentUtil.linearLongBackoff(failures, 500_000L, 50_000_000L)) {
if (
- !this.lightExecutor.isActive() &&
- !this.genExecutor.isActive() &&
+ !this.radiusAwareGenExecutor.isActive() &&
!this.parallelGenExecutor.isActive() &&
!this.loadExecutor.isActive()
) {
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkUpgradeGenericStatusTask.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkUpgradeGenericStatusTask.java
index 73ce0909bd89244835a0d0f2030a25871461f1e0..ecc366a4176b2efadc46aa91aa21621f0fc6abe9 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkUpgradeGenericStatusTask.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkUpgradeGenericStatusTask.java
@@ -39,8 +39,11 @@ public final class ChunkUpgradeGenericStatusTask extends ChunkProgressionTask im
this.fromStatus = chunk.getStatus();
this.toStatus = toStatus;
this.neighbours = neighbours;
- this.generateTask = (this.toStatus.isParallelCapable ? this.scheduler.parallelGenExecutor : this.scheduler.genExecutor)
- .createTask(this, priority);
+ if (this.toStatus.isParallelCapable) {
+ this.generateTask = this.scheduler.parallelGenExecutor.createTask(this, priority);
+ } else {
+ this.generateTask = this.scheduler.radiusAwareScheduler.createTask(chunkX, chunkZ, this.toStatus.writeRadius, this, priority);
+ }
}
@Override
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/queue/RadiusAwarePrioritisedExecutor.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/queue/RadiusAwarePrioritisedExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..3272f73013ea7d4efdd0ae2903925cc543be7075
--- /dev/null
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/queue/RadiusAwarePrioritisedExecutor.java
@@ -0,0 +1,668 @@
+package io.papermc.paper.chunk.system.scheduling.queue;
+
+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
+import io.papermc.paper.util.CoordinateUtils;
+import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+
+public class RadiusAwarePrioritisedExecutor {
+
+ private static final Comparator<DependencyNode> DEPENDENCY_NODE_COMPARATOR = (final DependencyNode t1, final DependencyNode t2) -> {
+ return Long.compare(t1.id, t2.id);
+ };
+
+ private final DependencyTree[] queues = new DependencyTree[PrioritisedExecutor.Priority.TOTAL_SCHEDULABLE_PRIORITIES];
+ private static final int NO_TASKS_QUEUED = -1;
+ private int selectedQueue = NO_TASKS_QUEUED;
+ private boolean canQueueTasks = true;
+
+ public RadiusAwarePrioritisedExecutor(final PrioritisedExecutor executor, final int maxToSchedule) {
+ for (int i = 0; i < this.queues.length; ++i) {
+ this.queues[i] = new DependencyTree(this, executor, maxToSchedule, i);
+ }
+ }
+
+ private boolean canQueueTasks() {
+ return this.canQueueTasks;
+ }
+
+ private List<PrioritisedExecutor.PrioritisedTask> treeFinished() {
+ this.canQueueTasks = true;
+ for (int priority = 0; priority < this.queues.length; ++priority) {
+ final DependencyTree queue = this.queues[priority];
+ if (queue.hasWaitingTasks()) {
+ final List<PrioritisedExecutor.PrioritisedTask> ret = queue.tryPushTasks();
+
+ if (ret == null || ret.isEmpty()) {
+ // this happens when the tasks in the wait queue were purged
+ // in this case, the queue was actually empty, we just had to purge it
+ // if we set the selected queue without scheduling any tasks, the queue will never be unselected
+ // as that requires a scheduled task completing...
+ continue;
+ }
+
+ this.selectedQueue = priority;
+ return ret;
+ }
+ }
+
+ this.selectedQueue = NO_TASKS_QUEUED;
+
+ return null;
+ }
+
+ private List<PrioritisedExecutor.PrioritisedTask> queue(final Task task, final PrioritisedExecutor.Priority priority) {
+ final int priorityId = priority.priority;
+ final DependencyTree queue = this.queues[priorityId];
+
+ final DependencyNode node = new DependencyNode(task, queue);
+
+ if (task.dependencyNode != null) {
+ throw new IllegalStateException();
+ }
+ task.dependencyNode = node;
+
+ queue.pushNode(node);
+
+ if (this.selectedQueue == NO_TASKS_QUEUED) {
+ this.canQueueTasks = true;
+ this.selectedQueue = priorityId;
+ return queue.tryPushTasks();
+ }
+
+ if (!this.canQueueTasks) {
+ return null;
+ }
+
+ if (PrioritisedExecutor.Priority.isHigherPriority(priorityId, this.selectedQueue)) {
+ // prevent the lower priority tree from queueing more tasks
+ this.canQueueTasks = false;
+ return null;
+ }
+
+ // priorityId != selectedQueue: lower priority, don't care - treeFinished will pick it up
+ return priorityId == this.selectedQueue ? queue.tryPushTasks() : null;
+ }
+
+ public PrioritisedExecutor.PrioritisedTask createTask(final int chunkX, final int chunkZ, final int radius,
+ final Runnable run, final PrioritisedExecutor.Priority priority) {
+ if (radius < 0) {
+ throw new IllegalArgumentException("Radius must be > 0: " + radius);
+ }
+ return new Task(this, chunkX, chunkZ, radius, run, priority);
+ }
+
+ public PrioritisedExecutor.PrioritisedTask createTask(final int chunkX, final int chunkZ, final int radius,
+ final Runnable run) {
+ return this.createTask(chunkX, chunkZ, radius, run, PrioritisedExecutor.Priority.NORMAL);
+ }
+
+ public PrioritisedExecutor.PrioritisedTask queueTask(final int chunkX, final int chunkZ, final int radius,
+ final Runnable run, final PrioritisedExecutor.Priority priority) {
+ final PrioritisedExecutor.PrioritisedTask ret = this.createTask(chunkX, chunkZ, radius, run, priority);
+
+ ret.queue();
+
+ return ret;
+ }
+
+ public PrioritisedExecutor.PrioritisedTask queueTask(final int chunkX, final int chunkZ, final int radius,
+ final Runnable run) {
+ final PrioritisedExecutor.PrioritisedTask ret = this.createTask(chunkX, chunkZ, radius, run);
+
+ ret.queue();
+
+ return ret;
+ }
+
+ public PrioritisedExecutor.PrioritisedTask createInfiniteRadiusTask(final Runnable run, final PrioritisedExecutor.Priority priority) {
+ return new Task(this, 0, 0, -1, run, priority);
+ }
+
+ public PrioritisedExecutor.PrioritisedTask createInfiniteRadiusTask(final Runnable run) {
+ return this.createInfiniteRadiusTask(run, PrioritisedExecutor.Priority.NORMAL);
+ }
+
+ public PrioritisedExecutor.PrioritisedTask queueInfiniteRadiusTask(final Runnable run, final PrioritisedExecutor.Priority priority) {
+ final PrioritisedExecutor.PrioritisedTask ret = this.createInfiniteRadiusTask(run, priority);
+
+ ret.queue();
+
+ return ret;
+ }
+
+ public PrioritisedExecutor.PrioritisedTask queueInfiniteRadiusTask(final Runnable run) {
+ final PrioritisedExecutor.PrioritisedTask ret = this.createInfiniteRadiusTask(run, PrioritisedExecutor.Priority.NORMAL);
+
+ ret.queue();
+
+ return ret;
+ }
+
+ // all accesses must be synchronised by the radius aware object
+ private static final class DependencyTree {
+
+ private final RadiusAwarePrioritisedExecutor scheduler;
+ private final PrioritisedExecutor executor;
+ private final int maxToSchedule;
+ private final int treeIndex;
+
+ private int currentlyExecuting;
+ private long idGenerator;
+
+ private final PriorityQueue<DependencyNode> awaiting = new PriorityQueue<>(DEPENDENCY_NODE_COMPARATOR);
+
+ private final PriorityQueue<DependencyNode> infiniteRadius = new PriorityQueue<>(DEPENDENCY_NODE_COMPARATOR);
+ private boolean isInfiniteRadiusScheduled;
+
+ private final Long2ReferenceOpenHashMap<DependencyNode> nodeByPosition = new Long2ReferenceOpenHashMap<>();
+
+ public DependencyTree(final RadiusAwarePrioritisedExecutor scheduler, final PrioritisedExecutor executor,
+ final int maxToSchedule, final int treeIndex) {
+ this.scheduler = scheduler;
+ this.executor = executor;
+ this.maxToSchedule = maxToSchedule;
+ this.treeIndex = treeIndex;
+ }
+
+ public boolean hasWaitingTasks() {
+ return !this.awaiting.isEmpty() || !this.infiniteRadius.isEmpty();
+ }
+
+ private long nextId() {
+ return this.idGenerator++;
+ }
+
+ private boolean isExecutingAnyTasks() {
+ return this.currentlyExecuting != 0;
+ }
+
+ private void pushNode(final DependencyNode node) {
+ if (!node.task.isFiniteRadius()) {
+ this.infiniteRadius.add(node);
+ return;
+ }
+
+ // set up dependency for node
+ final Task task = node.task;
+
+ final int centerX = task.chunkX;
+ final int centerZ = task.chunkZ;
+ final int radius = task.radius;
+
+ final int minX = centerX - radius;
+ final int maxX = centerX + radius;
+
+ final int minZ = centerZ - radius;
+ final int maxZ = centerZ + radius;
+
+ ReferenceOpenHashSet<DependencyNode> parents = null;
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ final DependencyNode dependency = this.nodeByPosition.put(CoordinateUtils.getChunkKey(currX, currZ), node);
+ if (dependency != null) {
+ if (parents == null) {
+ parents = new ReferenceOpenHashSet<>();
+ }
+ if (parents.add(dependency)) {
+ // added a dependency, so we need to add as a child to the dependency
+ if (dependency.children == null) {
+ dependency.children = new ArrayList<>();
+ }
+ dependency.children.add(node);
+ }
+ }
+ }
+ }
+
+ if (parents == null) {
+ // no dependencies, add straight to awaiting
+ this.awaiting.add(node);
+ } else {
+ node.parents = parents;
+ // we will be added to awaiting once we have no parents
+ }
+ }
+
+ // called only when a node is returned after being executed
+ private List<PrioritisedExecutor.PrioritisedTask> returnNode(final DependencyNode node) {
+ final Task task = node.task;
+
+ // now that the task is completed, we can push its children to the awaiting queue
+ this.pushChildren(node);
+
+ if (task.isFiniteRadius()) {
+ // remove from dependency map
+ this.removeNodeFromMap(node);
+ } else {
+ // mark as no longer executing infinite radius
+ if (!this.isInfiniteRadiusScheduled) {
+ throw new IllegalStateException();
+ }
+ this.isInfiniteRadiusScheduled = false;
+ }
+
+ // decrement executing count, we are done executing this task
+ --this.currentlyExecuting;
+
+ if (this.currentlyExecuting == 0) {
+ return this.scheduler.treeFinished();
+ }
+
+ return this.scheduler.canQueueTasks() ? this.tryPushTasks() : null;
+ }
+
+ private List<PrioritisedExecutor.PrioritisedTask> tryPushTasks() {
+ // tasks are not queued, but only created here - we do hold the lock for the map
+ List<PrioritisedExecutor.PrioritisedTask> ret = null;
+ PrioritisedExecutor.PrioritisedTask pushedTask;
+ while ((pushedTask = this.tryPushTask()) != null) {
+ if (ret == null) {
+ ret = new ArrayList<>();
+ }
+ ret.add(pushedTask);
+ }
+
+ return ret;
+ }
+
+ private void removeNodeFromMap(final DependencyNode node) {
+ final Task task = node.task;
+
+ final int centerX = task.chunkX;
+ final int centerZ = task.chunkZ;
+ final int radius = task.radius;
+
+ final int minX = centerX - radius;
+ final int maxX = centerX + radius;
+
+ final int minZ = centerZ - radius;
+ final int maxZ = centerZ + radius;
+
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ this.nodeByPosition.remove(CoordinateUtils.getChunkKey(currX, currZ), node);
+ }
+ }
+ }
+
+ private void pushChildren(final DependencyNode node) {
+ // add all the children that we can into awaiting
+ final List<DependencyNode> children = node.children;
+ if (children != null) {
+ for (int i = 0, len = children.size(); i < len; ++i) {
+ final DependencyNode child = children.get(i);
+ if (!child.parents.remove(node)) {
+ throw new IllegalStateException();
+ }
+ if (child.parents.isEmpty()) {
+ // no more dependents, we can push to awaiting
+ child.parents = null;
+ // even if the child is purged, we need to push it so that its children will be pushed
+ this.awaiting.add(child);
+ }
+ }
+ }
+ }
+
+ private DependencyNode pollAwaiting() {
+ final DependencyNode ret = this.awaiting.poll();
+ if (ret == null) {
+ return ret;
+ }
+
+ if (ret.parents != null) {
+ throw new IllegalStateException();
+ }
+
+ if (ret.purged) {
+ // need to manually remove from state here
+ this.pushChildren(ret);
+ this.removeNodeFromMap(ret);
+ } // else: delay children push until the task has finished
+
+ return ret;
+ }
+
+ private DependencyNode pollInfinite() {
+ return this.infiniteRadius.poll();
+ }
+
+ public PrioritisedExecutor.PrioritisedTask tryPushTask() {
+ if (this.currentlyExecuting >= this.maxToSchedule || this.isInfiniteRadiusScheduled) {
+ return null;
+ }
+
+ DependencyNode firstInfinite;
+ while ((firstInfinite = this.infiniteRadius.peek()) != null && firstInfinite.purged) {
+ this.pollInfinite();
+ }
+
+ DependencyNode firstAwaiting;
+ while ((firstAwaiting = this.awaiting.peek()) != null && firstAwaiting.purged) {
+ this.pollAwaiting();
+ }
+
+ if (firstInfinite == null && firstAwaiting == null) {
+ return null;
+ }
+
+ // firstAwaiting compared to firstInfinite
+ final int compare;
+
+ if (firstAwaiting == null) {
+ // we choose first infinite, or infinite < awaiting
+ compare = 1;
+ } else if (firstInfinite == null) {
+ // we choose first awaiting, or awaiting < infinite
+ compare = -1;
+ } else {
+ compare = DEPENDENCY_NODE_COMPARATOR.compare(firstAwaiting, firstInfinite);
+ }
+
+ if (compare >= 0) {
+ if (this.currentlyExecuting != 0) {
+ // don't queue infinite task while other tasks are executing in parallel
+ return null;
+ }
+ ++this.currentlyExecuting;
+ this.pollInfinite();
+ this.isInfiniteRadiusScheduled = true;
+ return firstInfinite.task.pushTask(this.executor);
+ } else {
+ ++this.currentlyExecuting;
+ this.pollAwaiting();
+ return firstAwaiting.task.pushTask(this.executor);
+ }
+ }
+ }
+
+ private static final class DependencyNode {
+
+ private final Task task;
+ private final DependencyTree tree;
+
+ // dependency tree fields
+ // (must hold lock on the scheduler to use)
+ // null is the same as empty, we just use it so that we don't allocate the set unless we need to
+ private List<DependencyNode> children;
+ // null is the same as empty, indicating that this task is considered "awaiting"
+ private ReferenceOpenHashSet<DependencyNode> parents;
+ // false -> scheduled and not cancelled
+ // true -> scheduled but cancelled
+ private boolean purged;
+ private final long id;
+
+ public DependencyNode(final Task task, final DependencyTree tree) {
+ this.task = task;
+ this.id = tree.nextId();
+ this.tree = tree;
+ }
+ }
+
+ private static final class Task implements PrioritisedExecutor.PrioritisedTask, Runnable {
+
+ // task specific fields
+ private final RadiusAwarePrioritisedExecutor scheduler;
+ private final int chunkX;
+ private final int chunkZ;
+ private final int radius;
+ private Runnable run;
+ private PrioritisedExecutor.Priority priority;
+
+ private DependencyNode dependencyNode;
+ private PrioritisedExecutor.PrioritisedTask queuedTask;
+
+ private Task(final RadiusAwarePrioritisedExecutor scheduler, final int chunkX, final int chunkZ, final int radius,
+ final Runnable run, final PrioritisedExecutor.Priority priority) {
+ this.scheduler = scheduler;
+ this.chunkX = chunkX;
+ this.chunkZ = chunkZ;
+ this.radius = radius;
+ this.run = run;
+ this.priority = priority;
+ }
+
+ private boolean isFiniteRadius() {
+ return this.radius >= 0;
+ }
+
+ private PrioritisedExecutor.PrioritisedTask pushTask(final PrioritisedExecutor executor) {
+ return this.queuedTask = executor.createTask(this, this.priority);
+ }
+
+ private void executeTask() {
+ final Runnable run = this.run;
+ this.run = null;
+ run.run();
+ }
+
+ private static void scheduleTasks(final List<PrioritisedExecutor.PrioritisedTask> toSchedule) {
+ if (toSchedule != null) {
+ for (int i = 0, len = toSchedule.size(); i < len; ++i) {
+ toSchedule.get(i).queue();
+ }
+ }
+ }
+
+ private void returnNode() {
+ final List<PrioritisedExecutor.PrioritisedTask> toSchedule;
+ synchronized (this.scheduler) {
+ final DependencyNode node = this.dependencyNode;
+ this.dependencyNode = null;
+ toSchedule = node.tree.returnNode(node);
+ }
+
+ scheduleTasks(toSchedule);
+ }
+
+ @Override
+ public void run() {
+ final Runnable run = this.run;
+ this.run = null;
+ try {
+ run.run();
+ } finally {
+ this.returnNode();
+ }
+ }
+
+ @Override
+ public boolean queue() {
+ final List<PrioritisedExecutor.PrioritisedTask> toSchedule;
+ synchronized (this.scheduler) {
+ if (this.queuedTask != null || this.dependencyNode != null || this.priority == PrioritisedExecutor.Priority.COMPLETING) {
+ return false;
+ }
+
+ toSchedule = this.scheduler.queue(this, this.priority);
+ }
+
+ scheduleTasks(toSchedule);
+ return true;
+ }
+
+ @Override
+ public boolean cancel() {
+ final PrioritisedExecutor.PrioritisedTask task;
+ synchronized (this.scheduler) {
+ if ((task = this.queuedTask) == null) {
+ if (this.priority == PrioritisedExecutor.Priority.COMPLETING) {
+ return false;
+ }
+
+ this.priority = PrioritisedExecutor.Priority.COMPLETING;
+ if (this.dependencyNode != null) {
+ this.dependencyNode.purged = true;
+ this.dependencyNode = null;
+ }
+
+ return true;
+ }
+ }
+
+ if (task.cancel()) {
+ // must manually return the node
+ this.run = null;
+ this.returnNode();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean execute() {
+ final PrioritisedExecutor.PrioritisedTask task;
+ synchronized (this.scheduler) {
+ if ((task = this.queuedTask) == null) {
+ if (this.priority == PrioritisedExecutor.Priority.COMPLETING) {
+ return false;
+ }
+
+ this.priority = PrioritisedExecutor.Priority.COMPLETING;
+ if (this.dependencyNode != null) {
+ this.dependencyNode.purged = true;
+ this.dependencyNode = null;
+ }
+ // fall through to execution logic
+ }
+ }
+
+ if (task != null) {
+ // will run the return node logic automatically
+ return task.execute();
+ } else {
+ // don't run node removal/insertion logic, we aren't actually removed from the dependency tree
+ this.executeTask();
+ return true;
+ }
+ }
+
+ @Override
+ public PrioritisedExecutor.Priority getPriority() {
+ final PrioritisedExecutor.PrioritisedTask task;
+ synchronized (this.scheduler) {
+ if ((task = this.queuedTask) == null) {
+ return this.priority;
+ }
+ }
+
+ return task.getPriority();
+ }
+
+ @Override
+ public boolean setPriority(final PrioritisedExecutor.Priority priority) {
+ if (!PrioritisedExecutor.Priority.isValidPriority(priority)) {
+ throw new IllegalArgumentException("Invalid priority " + priority);
+ }
+
+ final PrioritisedExecutor.PrioritisedTask task;
+ List<PrioritisedExecutor.PrioritisedTask> toSchedule = null;
+ synchronized (this.scheduler) {
+ if ((task = this.queuedTask) == null) {
+ if (this.priority == PrioritisedExecutor.Priority.COMPLETING) {
+ return false;
+ }
+
+ if (this.priority == priority) {
+ return true;
+ }
+
+ this.priority = priority;
+ if (this.dependencyNode != null) {
+ // need to re-insert node
+ this.dependencyNode.purged = true;
+ this.dependencyNode = null;
+ toSchedule = this.scheduler.queue(this, priority);
+ }
+ }
+ }
+
+ if (task != null) {
+ return task.setPriority(priority);
+ }
+
+ scheduleTasks(toSchedule);
+
+ return true;
+ }
+
+ @Override
+ public boolean raisePriority(final PrioritisedExecutor.Priority priority) {
+ if (!PrioritisedExecutor.Priority.isValidPriority(priority)) {
+ throw new IllegalArgumentException("Invalid priority " + priority);
+ }
+
+ final PrioritisedExecutor.PrioritisedTask task;
+ List<PrioritisedExecutor.PrioritisedTask> toSchedule = null;
+ synchronized (this.scheduler) {
+ if ((task = this.queuedTask) == null) {
+ if (this.priority == PrioritisedExecutor.Priority.COMPLETING) {
+ return false;
+ }
+
+ if (this.priority.isHigherOrEqualPriority(priority)) {
+ return true;
+ }
+
+ this.priority = priority;
+ if (this.dependencyNode != null) {
+ // need to re-insert node
+ this.dependencyNode.purged = true;
+ this.dependencyNode = null;
+ toSchedule = this.scheduler.queue(this, priority);
+ }
+ }
+ }
+
+ if (task != null) {
+ return task.raisePriority(priority);
+ }
+
+ scheduleTasks(toSchedule);
+
+ return true;
+ }
+
+ @Override
+ public boolean lowerPriority(final PrioritisedExecutor.Priority priority) {
+ if (!PrioritisedExecutor.Priority.isValidPriority(priority)) {
+ throw new IllegalArgumentException("Invalid priority " + priority);
+ }
+
+ final PrioritisedExecutor.PrioritisedTask task;
+ List<PrioritisedExecutor.PrioritisedTask> toSchedule = null;
+ synchronized (this.scheduler) {
+ if ((task = this.queuedTask) == null) {
+ if (this.priority == PrioritisedExecutor.Priority.COMPLETING) {
+ return false;
+ }
+
+ if (this.priority.isLowerOrEqualPriority(priority)) {
+ return true;
+ }
+
+ this.priority = priority;
+ if (this.dependencyNode != null) {
+ // need to re-insert node
+ this.dependencyNode.purged = true;
+ this.dependencyNode = null;
+ toSchedule = this.scheduler.queue(this, priority);
+ }
+ }
+ }
+
+ if (task != null) {
+ return task.lowerPriority(priority);
+ }
+
+ scheduleTasks(toSchedule);
+
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
index c709e27a00d8617f9a3346f85bd88ce47baa9c76..b4be02ec4bb77059f79d3e4d6a6f1ee4843a01f9 100644
--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
@@ -94,7 +94,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
++totalChunks;
}
- this.chunkMap.level.chunkTaskScheduler.lightExecutor.queueRunnable(() -> { // Paper - rewrite chunk system
+ this.chunkMap.level.chunkTaskScheduler.radiusAwareScheduler.queueInfiniteRadiusTask(() -> { // Paper - rewrite chunk system
this.theLightEngine.relightChunks(chunks, (ChunkPos chunkPos) -> {
chunkLightCallback.accept(chunkPos);
((java.util.concurrent.Executor)((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().mainThreadProcessor).execute(() -> {

View File

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 15 May 2023 12:24:17 -0700
Subject: [PATCH] Properly cancel chunk load tasks that were not scheduled
Since the chunk load task was not scheduled, the entity/poi load
task fields will not be set, but the task complete counter
will not be adjusted. Thus, the chunk load task will not complete.
To resolve this, detect when the entity/poi tasks were not scheduled
and decrement the task complete counter in such cases.
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java
index 1f7c146ff0b2a835c818f49da6c1f1411f26aa39..34dc2153e90a29bc9102d9497c3c53b5de15508e 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkLoadTask.java
@@ -25,7 +25,6 @@ import org.slf4j.Logger;
import java.lang.invoke.VarHandle;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
public final class ChunkLoadTask extends ChunkProgressionTask {
@@ -125,8 +124,12 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
@Override
public void cancel() {
// must be before load task access, so we can synchronise with the writes to the fields
+ final boolean scheduled;
this.scheduler.schedulingLock.lock();
try {
+ // fix cancellation of chunk load task - must read field here, as it may be written later conucrrently -
+ // we need to know if we scheduled _before_ cancellation
+ scheduled = this.scheduled;
this.cancelled = true;
} finally {
this.scheduler.schedulingLock.unlock();
@@ -139,15 +142,26 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
the chunk load task attempts to complete with a non-null value
*/
- if (this.entityLoadTask != null) {
- if (this.entityLoadTask.cancel()) {
- this.tryCompleteLoad();
+ if (scheduled) {
+ // since we scheduled, we need to cancel the tasks
+ if (this.entityLoadTask != null) {
+ if (this.entityLoadTask.cancel()) {
+ this.tryCompleteLoad();
+ }
}
- }
- if (this.poiLoadTask != null) {
- if (this.poiLoadTask.cancel()) {
- this.tryCompleteLoad();
+ if (this.poiLoadTask != null) {
+ if (this.poiLoadTask.cancel()) {
+ this.tryCompleteLoad();
+ }
}
+ } else {
+ // since nothing was scheduled, we need to decrement the task count here ourselves
+
+ // for entity load task
+ this.tryCompleteLoad();
+
+ // for poi load task
+ this.tryCompleteLoad();
}
this.loadTask.cancel();
}

View File

@ -0,0 +1,110 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 15 May 2023 11:34:28 -0700
Subject: [PATCH] Mark POI/Entity load tasks as completed before releasing
scheduling lock
It must be marked as completed during that lock hold since the
waiters field is set to null. Thus, any other thread attempting
a cancellation will fail to remove from waiters. Also, any
other thread attempting to cancel may set the completed field
to true which would cause accept() to fail as well.
Completion was always designed to happen while holding the
scheduling lock to prevent these race conditions. The code
was originally set up to complete while not holding the
scheduling lock to avoid invoking callbacks while holding the
lock, however the access to the completion field was not
considered.
Resolve this by marking the callback as completed during the
lock, but invoking the accept() function after releasing
the lock. This will prevent any cancellation attempts to be
blocked, and allow the current thread to complete the callback
without any issues.
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java
index 8013dd333e27aa5fd0beb431fa32491eec9f5246..efc9b7a304f10b6a23a36cffb0a4aaea6ab71129 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java
@@ -156,6 +156,12 @@ public final class NewChunkHolder {
LOGGER.error("Unhandled entity data load exception, data data will be lost: ", result.right());
}
+ // Folia start - mark these tasks as completed before releasing the scheduling lock
+ for (final GenericDataLoadTaskCallback callback : waiters) {
+ callback.markCompleted();
+ }
+ // Folia end - mark these tasks as completed before releasing the scheduling lock
+
completeWaiters = waiters;
} else {
// cancelled
@@ -187,7 +193,7 @@ public final class NewChunkHolder {
// avoid holding the scheduling lock while completing
if (completeWaiters != null) {
for (final GenericDataLoadTaskCallback callback : completeWaiters) {
- callback.accept(result);
+ callback.acceptCompleted(result); // Folia - mark these tasks as completed before releasing the scheduling lock
}
}
@@ -273,6 +279,12 @@ public final class NewChunkHolder {
LOGGER.error("Unhandled poi load exception, poi data will be lost: ", result.right());
}
+ // Folia start - mark these tasks as completed before releasing the scheduling lock
+ for (final GenericDataLoadTaskCallback callback : waiters) {
+ callback.markCompleted();
+ }
+ // Folia end - mark these tasks as completed before releasing the scheduling lock
+
completeWaiters = waiters;
} else {
// cancelled
@@ -304,7 +316,7 @@ public final class NewChunkHolder {
// avoid holding the scheduling lock while completing
if (completeWaiters != null) {
for (final GenericDataLoadTaskCallback callback : completeWaiters) {
- callback.accept(result);
+ callback.acceptCompleted(result); // Folia - mark these tasks as completed before releasing the scheduling lock
}
}
this.scheduler.schedulingLock.lock();
@@ -357,7 +369,7 @@ public final class NewChunkHolder {
}
}
- public static abstract class GenericDataLoadTaskCallback implements Cancellable, Consumer<GenericDataLoadTask.TaskResult<?, Throwable>> {
+ public static abstract class GenericDataLoadTaskCallback implements Cancellable { // Folia - mark callbacks as completed before unlocking scheduling lock
protected final Consumer<GenericDataLoadTask.TaskResult<?, Throwable>> consumer;
protected final NewChunkHolder chunkHolder;
@@ -393,13 +405,23 @@ public final class NewChunkHolder {
return this.completed = true;
}
- @Override
- public void accept(final GenericDataLoadTask.TaskResult<?, Throwable> result) {
+ // Folia start - mark callbacks as completed before unlocking scheduling lock
+ // must hold scheduling lock
+ void markCompleted() {
+ if (this.completed) {
+ throw new IllegalStateException("May not be completed here");
+ }
+ this.completed = true;
+ }
+ // Folia end - mark callbacks as completed before unlocking scheduling lock
+
+ // Folia - mark callbacks as completed before unlocking scheduling lock
+ void acceptCompleted(final GenericDataLoadTask.TaskResult<?, Throwable> result) {
if (result != null) {
- if (this.setCompleted()) {
+ if (this.completed) { // Folia - mark callbacks as completed before unlocking scheduling lock
this.consumer.accept(result);
} else {
- throw new IllegalStateException("Cannot be cancelled at this point");
+ throw new IllegalStateException("Cannot be uncompleted at this point"); // Folia - mark callbacks as completed before unlocking scheduling lock
}
} else {
throw new NullPointerException("Result cannot be null (cancelled)");

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Allow for toggling of spawn chunks
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index d87f02c748fe2e5b4ea251f6691e8907a152cb6d..f21ba175538436e59c45d5350ef7b2605ed96775 100644
index 5988c0847af4e8f0094328e91f736f25d567db60..fb78a91d1ab77f909823422c6d4e2ef7ed10c9c3 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -261,6 +261,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {

View File

@ -0,0 +1,119 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 2 Mar 2023 23:19:04 -0800
Subject: [PATCH] Cache whether region files do not exist
The repeated I/O of creating the directory for the regionfile
or for checking if the file exists can be heavy in
when pushing chunk generation extremely hard - as each chunk gen
request may effectively go through to the I/O thread.
diff --git a/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java b/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java
index a08cde4eefe879adcee7c4118bc38f98c5097ed0..8a11e10b01fa012b2f98b1c193c53251e848f909 100644
--- a/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java
+++ b/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java
@@ -819,8 +819,14 @@ public final class RegionFileIOThread extends PrioritisedQueueExecutorThread {
return file.hasChunk(chunkPos) ? Boolean.TRUE : Boolean.FALSE;
});
} else {
+ // first check if the region file for sure does not exist
+ if (taskController.doesRegionFileNotExist(chunkX, chunkZ)) {
+ return Boolean.FALSE;
+ } // else: it either exists or is not known, fall back to checking the loaded region file
+
return taskController.computeForRegionFileIfLoaded(chunkX, chunkZ, (final RegionFile file) -> {
if (file == null) { // null if not loaded
+ // not sure at this point, let the I/O thread figure it out
return Boolean.TRUE;
}
@@ -1116,6 +1122,10 @@ public final class RegionFileIOThread extends PrioritisedQueueExecutorThread {
return !this.tasks.isEmpty();
}
+ public boolean doesRegionFileNotExist(final int chunkX, final int chunkZ) {
+ return this.getCache().doesRegionFileNotExistNoIO(new ChunkPos(chunkX, chunkZ));
+ }
+
public <T> T computeForRegionFile(final int chunkX, final int chunkZ, final boolean existingOnly, final Function<RegionFile, T> function) {
final RegionFileStorage cache = this.getCache();
final RegionFile regionFile;
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 18ef7025f7f4dc2a4aff85ca65ff5a2d35a1ef06..fe8bb0037bb7f317fc32ac34461f4eb3a1f397f2 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -24,6 +24,35 @@ public class RegionFileStorage implements AutoCloseable {
private final Path folder;
private final boolean sync;
+ // Paper start - cache regionfile does not exist state
+ static final int MAX_NON_EXISTING_CACHE = 1024 * 64;
+ private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
+ private synchronized boolean doesRegionFilePossiblyExist(long position) {
+ if (this.nonExistingRegionFiles.contains(position)) {
+ this.nonExistingRegionFiles.addAndMoveToFirst(position);
+ return false;
+ }
+ return true;
+ }
+
+ private synchronized void createRegionFile(long position) {
+ this.nonExistingRegionFiles.remove(position);
+ }
+
+ private synchronized void markNonExisting(long position) {
+ if (this.nonExistingRegionFiles.addAndMoveToFirst(position)) {
+ while (this.nonExistingRegionFiles.size() >= MAX_NON_EXISTING_CACHE) {
+ this.nonExistingRegionFiles.removeLastLong();
+ }
+ }
+ }
+
+ public synchronized boolean doesRegionFileNotExistNoIO(ChunkPos pos) {
+ long key = ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ());
+ return !this.doesRegionFilePossiblyExist(key);
+ }
+ // Paper end - cache regionfile does not exist state
+
protected RegionFileStorage(Path directory, boolean dsync) { // Paper - protected constructor
this.folder = directory;
this.sync = dsync;
@@ -45,7 +74,7 @@ public class RegionFileStorage implements AutoCloseable {
}
public synchronized RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException {
// Paper end
- long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
+ long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); final long regionPos = i; // Paper - OBFHELPER
RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
if (regionfile != null) {
@@ -57,15 +86,27 @@ public class RegionFileStorage implements AutoCloseable {
// Paper end
return regionfile;
} else {
+ // Paper start - cache regionfile does not exist state
+ if (existingOnly && !this.doesRegionFilePossiblyExist(regionPos)) {
+ return null;
+ }
+ // Paper end - cache regionfile does not exist state
if (this.regionCache.size() >= 256) {
((RegionFile) this.regionCache.removeLast()).close();
}
- FileUtil.createDirectoriesSafe(this.folder);
+ // Paper - only create directory if not existing only - moved down
Path path = this.folder;
int j = chunkcoordintpair.getRegionX();
Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca");
- if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit
+ if (existingOnly && !java.nio.file.Files.exists(path1)) { // Paper start - cache regionfile does not exist state
+ this.markNonExisting(regionPos);
+ return null; // CraftBukkit
+ } else {
+ this.createRegionFile(regionPos);
+ }
+ // Paper end - cache regionfile does not exist state
+ FileUtil.createDirectoriesSafe(this.folder); // Paper - only create directory if not existing only - moved from above
RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync);
this.regionCache.putAndMoveToFirst(i, regionfile1);

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 96897d883671e018bae5f71545c5f7af205e309c..ff3073b6780c04f5f11b5384bb6b6289eafd0c4f 100644
index 164ce278f2696d4be6b57404648cb0e856464589..4d5a8c051ab7746ed40d5b79558e86238618827c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1466,7 +1466,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1460,7 +1460,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@DontObfuscate
public String getServerModName() {
@ -19,7 +19,7 @@ index 96897d883671e018bae5f71545c5f7af205e309c..ff3073b6780c04f5f11b5384bb6b6289
public SystemReport fillSystemReport(SystemReport details) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 7912cf0e4cab7d6c99106d43b2cdc4f4e80aebac..a79ae43bffcd23b5639cdc179f129b1879a5a779 100644
index 0a4b2529034b85609b2f8d3f3f633e8f6adbe34f..31085570f31a5de308cb1d767472ea130193e3cf 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -260,7 +260,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException;
@ -63,10 +63,10 @@ index 47c3c7484687b808341937f7e4ef1c0c410fa59f..a20eaa9b1d030ccd7e1fc49df47acee4
net.minecraft.server.Main.main(options);
} catch (Throwable t) {
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
index 335120afc88a8fc1543c2e6df516fd728e3ab032..d5863b0b06384b25eaa33572fa02649795463ed8 100644
index f1194eb6fdfba60959e00080d0562f2820d13b27..11d7ede26b46d0bf9cced65e8c3bcc41c8b66dbf 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread
@@ -19,7 +19,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
private WatchdogThread(long timeoutTime, boolean restart)
{
@ -75,7 +75,7 @@ index 335120afc88a8fc1543c2e6df516fd728e3ab032..d5863b0b06384b25eaa33572fa026497
this.timeoutTime = timeoutTime;
this.restart = restart;
}
@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread
@@ -65,14 +65,14 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
{
Logger log = Bukkit.getServer().getLogger();
log.log( Level.SEVERE, "------------------------------" );
@ -93,12 +93,12 @@ index 335120afc88a8fc1543c2e6df516fd728e3ab032..d5863b0b06384b25eaa33572fa026497
//
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
{
@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread
@@ -82,7 +82,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
}
//
log.log( Level.SEVERE, "------------------------------" );
- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" );
+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
log.log( Level.SEVERE, "------------------------------" );
//

View File

@ -201,7 +201,7 @@ index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de
+ }
+}
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 51eac8b7177db66c005e4eaca689cf96d10edeaa..6f64d98021e842905cdd6410ec355a6f136ec18f 100644
index 4f55f04812fe0306acfc4be45189f1f679e18e63..049f7dc31576980007eb8f0caab926bb58fead78 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -189,6 +189,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface

View File

@ -100,10 +100,10 @@ index 8d60b430357a1b761de325a21e1c52639a049403..213fed3a2b32226fc128d213ee3e9fa3
public void clientTick(Level world, BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index 127c4ebedb94631ceac92dbdcd465e904217d715..5e19b91e6fb7e5e354f55ea206b3d59e8767e714 100644
index be6e3e21ad62da01e5e2dd78e300cbc8efdbeb42..ea98625fe7c00743b8df74a24e6d4b75df4189a5 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -70,6 +70,11 @@ public interface EntityGetter {
@@ -82,6 +82,11 @@ public interface EntityGetter {
}
}
@ -115,7 +115,7 @@ index 127c4ebedb94631ceac92dbdcd465e904217d715..5e19b91e6fb7e5e354f55ea206b3d59e
@Nullable
default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate<Entity> targetPredicate) {
double d = -1.0D;
@@ -99,6 +104,20 @@ public interface EntityGetter {
@@ -111,6 +116,20 @@ public interface EntityGetter {
return this.getNearestPlayer(x, y, z, maxDistance, predicate);
}
@ -137,10 +137,10 @@ index 127c4ebedb94631ceac92dbdcd465e904217d715..5e19b91e6fb7e5e354f55ea206b3d59e
for(Player player : this.players()) {
if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 5afdada0d56c2f9af431ea6485faa277229befa9..1098c95f8f27e0ff3cf593a4f0dfde0dbe4d3152 100644
index 976eadd8200b2f4811d57b3c7fbd68cff1333924..dd65045f52da395bd3d106065b7390d3925bf96f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2169,8 +2169,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2211,8 +2211,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public String getLocale() {
return this.getHandle().locale;

View File

@ -12,7 +12,7 @@ Previous implementation did not calculate TPS correctly.
Switch to a realistic rolling average and factor in std deviation as an extra reporting variable
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ff3073b6780c04f5f11b5384bb6b6289eafd0c4f..2aeeffe6d011a1ecc848b80f0236c8a3f871a01c 100644
index 4d5a8c051ab7746ed40d5b79558e86238618827c..92eb6e80e3b6f74dd32a878e5436d338c89ea60e 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -285,7 +285,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@ -33,7 +33,7 @@ index ff3073b6780c04f5f11b5384bb6b6289eafd0c4f..2aeeffe6d011a1ecc848b80f0236c8a3
public final double[] recentTps = new double[ 3 ];
// Spigot end
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
@@ -973,6 +973,57 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -954,6 +954,57 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
{
return ( avg * exp ) + ( tps * ( 1 - exp ) );
}
@ -90,8 +90,8 @@ index ff3073b6780c04f5f11b5384bb6b6289eafd0c4f..2aeeffe6d011a1ecc848b80f0236c8a3
+ // Paper End
// Spigot End
protected void runServer() {
@@ -987,9 +1038,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public static volatile RuntimeException chunkSystemCrash; // Paper - rewrite chunk system
@@ -970,7 +1021,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Spigot start
Arrays.fill( recentTps, 20 );
@ -99,12 +99,18 @@ index ff3073b6780c04f5f11b5384bb6b6289eafd0c4f..2aeeffe6d011a1ecc848b80f0236c8a3
+ long start = System.nanoTime(), curTime, tickSection = start; // Paper - Further improve server tick loop
+ lastTick = start - TICK_TIME; // Paper
while (this.running) {
// Paper start - rewrite chunk system
// guarantee that nothing can stop the server from halting if it can at least still tick
@@ -978,7 +1030,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
throw this.chunkSystemCrash;
}
// Paper end - rewrite chunk system
- long i = (curTime = Util.getMillis()) - this.nextTickTime;
+ long i = ((curTime = System.nanoTime()) / (1000L * 1000L)) - this.nextTickTime; // Paper
if (i > 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit
long j = i / 50L;
@@ -1001,12 +1053,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -990,12 +1042,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
++MinecraftServer.currentTickLong; // Paper
@ -128,7 +134,7 @@ index ff3073b6780c04f5f11b5384bb6b6289eafd0c4f..2aeeffe6d011a1ecc848b80f0236c8a3
tickSection = curTime;
}
// Spigot end
@@ -1016,7 +1074,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1005,7 +1063,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
@ -139,7 +145,7 @@ index ff3073b6780c04f5f11b5384bb6b6289eafd0c4f..2aeeffe6d011a1ecc848b80f0236c8a3
this.startMetricsRecordingTick();
this.profiler.push("tick");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index a79ae43bffcd23b5639cdc179f129b1879a5a779..17056a7ea6c6a3a671872d2be603d7dd60ae04e9 100644
index 31085570f31a5de308cb1d767472ea130193e3cf..fb6ea46609489d802ed4b76b4074734dd3e3886f 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2437,6 +2437,17 @@ public final class CraftServer implements Server {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Only refresh abilities if needed
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 1098c95f8f27e0ff3cf593a4f0dfde0dbe4d3152..f4ec1141f13135286077875177de672905c8898a 100644
index dd65045f52da395bd3d106065b7390d3925bf96f..65d13b47b3af69e2256f7000b4634e8c688e22d8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1838,12 +1838,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -1880,12 +1880,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setFlying(boolean value) {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Entity Origin API
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 7cb5abfa89f842194325d26c6e95b49460c5968f..871234c2c381c6ff7a2a27a8542bbd498c1aec03 100644
index 62a95a0fac59683948f34b202e6e3859b6652d6d..d47e99ac96e622296d045cfcf93b53dddd314827 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2116,6 +2116,15 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -2282,6 +2282,15 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
entity.valid = true; // CraftBukkit
@ -25,7 +25,7 @@ index 7cb5abfa89f842194325d26c6e95b49460c5968f..871234c2c381c6ff7a2a27a8542bbd49
public void onTrackingEnd(Entity entity) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index f668a80c6bff67bf766207985c1af73f09e1bd1c..06d8211ef27a21da66d4622795cbcc8b37d2ce4e 100644
index 7f6a90fab14d6880f2784e1c62eb2f3c9da404b5..193b466e5dc52b9ecc878c4a680f88b8ce05e632 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -312,7 +312,27 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@ -56,7 +56,7 @@ index f668a80c6bff67bf766207985c1af73f09e1bd1c..06d8211ef27a21da66d4622795cbcc8b
public float getBukkitYaw() {
return this.yRot;
}
@@ -2010,6 +2030,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -2062,6 +2082,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.bukkitEntity.storeBukkitValues(nbt);
}
// CraftBukkit end
@ -72,7 +72,7 @@ index f668a80c6bff67bf766207985c1af73f09e1bd1c..06d8211ef27a21da66d4622795cbcc8b
return nbt;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
@@ -2137,6 +2166,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -2189,6 +2218,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
// CraftBukkit end

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Prevent tile entity and entity crashes
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index f21ba175538436e59c45d5350ef7b2605ed96775..627f80e726f306edc765be5e6ac59ca73aade10b 100644
index fb78a91d1ab77f909823422c6d4e2ef7ed10c9c3..a022d009b72e366ed69d05087457b712970c0b84 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -723,11 +723,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -728,11 +728,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
try {
tickConsumer.accept(entity);
} catch (Throwable throwable) {
@ -44,10 +44,10 @@ index b300d12e9e00519028b53aca9c3fb01f589eaa91..63acd109a79ed752a05df3d4f1b99309
}
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 09999a3f523ce6d652799215d3418284a69042c1..8e1ca484356a7eddcdb37ef7ec01dea9864eec70 100644
index 3da04db71d6f33b2f466c11e031e0a11c298379b..5d7290216d3a6ddb8e345a5b05da21ef28ed2307 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1057,11 +1057,11 @@ public class LevelChunk extends ChunkAccess {
@@ -1146,11 +1146,11 @@ public class LevelChunk extends ChunkAccess {
gameprofilerfiller.pop();
} catch (Throwable throwable) {

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Configurable top of nether void damage
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 06d8211ef27a21da66d4622795cbcc8b37d2ce4e..7358b918d03b0dee0541843a952d6b8bf939d877 100644
index 193b466e5dc52b9ecc878c4a680f88b8ce05e632..3088cdbb55b3054394fd3405797539f58a46f70c 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -663,7 +663,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -715,7 +715,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
public void checkBelowWorld() {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Always tick falling blocks
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 3e5d541d3d7fc3956b2fc68da9f22a0ab0367ce9..66dbfabdb104d272d48588a4773d198d3938f1ef 100644
index b47b740186c200c420dcb4d1537a93c743a887c1..a526816f261de2a75a04be82596a7d8d674ead4a 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -89,6 +89,7 @@ public class ActivationRange

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Configurable end credits
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 5872ead2fe3a64f02f8bc36603fbb856728fd255..eb42e0ce8e2698973307e2b6774cbbd79c1d6457 100644
index 32ef9f1ae0c35e927133572ebb6fbf50b0729a63..e42c07dfba3c18464f1f8e35fbd764812d8c4e50 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1024,6 +1024,7 @@ public class ServerPlayer extends Player {
@@ -1066,6 +1066,7 @@ public class ServerPlayer extends Player {
this.unRide();
this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
if (!this.wonGame) {

View File

@ -10,10 +10,10 @@ This patch adds a per-tick cache that is used for storing and retrieving
an entity's exposure during an explosion.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 2aeeffe6d011a1ecc848b80f0236c8a3f871a01c..d5ad3368a397e9fc02506187ccb1c386afd9ce2b 100644
index 92eb6e80e3b6f74dd32a878e5436d338c89ea60e..821725460b62ebadedb789f4408ef172416c2092 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1412,6 +1412,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1406,6 +1406,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.pop();
this.profiler.pop();
@ -120,7 +120,7 @@ index e360022498b91a8371b33d84bf6fff96c503999d..925d37ca684e7e6a3ad88e6e040f3599
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 627f80e726f306edc765be5e6ac59ca73aade10b..0a7a354c085655c243fdf94c7dc82cdc95b3987a 100644
index a022d009b72e366ed69d05087457b712970c0b84..da553430864689c426ad2c1dd74ad7d1134ffbae 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -167,6 +167,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Disable thunder
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 871234c2c381c6ff7a2a27a8542bbd498c1aec03..fdb2996562010fa6dd43b6a79b707cb86146bb48 100644
index d47e99ac96e622296d045cfcf93b53dddd314827..2df6cc14176465dcdc7cfc8d12382bf7edc49666 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -603,7 +603,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -752,7 +752,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
gameprofilerfiller.push("thunder");
BlockPos blockposition;

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Disable ice and snow
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index fdb2996562010fa6dd43b6a79b707cb86146bb48..ef48e76ca18576e631d5d2f1652d3449d558a582 100644
index 2df6cc14176465dcdc7cfc8d12382bf7edc49666..feee30aa0bccfa40765f1c4a179ba04907b11433 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -634,7 +634,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -783,7 +783,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
int l;
int i1;

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Implement PlayerLocaleChangeEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index eb42e0ce8e2698973307e2b6774cbbd79c1d6457..e448641f3e64114a6ff986990fc7bdaa28736129 100644
index e42c07dfba3c18464f1f8e35fbd764812d8c4e50..ee422a97a63749172f9f9643513ae9ab111c2400 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1811,7 +1811,7 @@ public class ServerPlayer extends Player {
@@ -1853,7 +1853,7 @@ public class ServerPlayer extends Player {
}
}
@ -17,7 +17,7 @@ index eb42e0ce8e2698973307e2b6774cbbd79c1d6457..e448641f3e64114a6ff986990fc7bdaa
public java.util.Locale adventure$locale = java.util.Locale.US; // Paper
public void updateOptions(ServerboundClientInformationPacket packet) {
// CraftBukkit start
@@ -1819,9 +1819,10 @@ public class ServerPlayer extends Player {
@@ -1861,9 +1861,10 @@ public class ServerPlayer extends Player {
PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT);
this.server.server.getPluginManager().callEvent(event);
}
@ -30,10 +30,10 @@ index eb42e0ce8e2698973307e2b6774cbbd79c1d6457..e448641f3e64114a6ff986990fc7bdaa
this.locale = packet.language;
// Paper start
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index f4ec1141f13135286077875177de672905c8898a..484fab5eeeb92407ded625b96678c9aa93199d70 100644
index 65d13b47b3af69e2256f7000b4634e8c688e22d8..4061b68edb8f501eea71ba009214ac3808506ec7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2169,8 +2169,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2211,8 +2211,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public String getLocale() {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Configurable container update tick rate
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index e448641f3e64114a6ff986990fc7bdaa28736129..95d9824ad7a00e8d75ce243403004193d0bee605 100644
index ee422a97a63749172f9f9643513ae9ab111c2400..321d14f241df1246061ba73b2488f5ab5326a734 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -241,6 +241,7 @@ public class ServerPlayer extends Player {
@ -16,7 +16,7 @@ index e448641f3e64114a6ff986990fc7bdaa28736129..95d9824ad7a00e8d75ce243403004193
// CraftBukkit start
public String displayName;
@@ -630,7 +631,12 @@ public class ServerPlayer extends Player {
@@ -672,7 +673,12 @@ public class ServerPlayer extends Player {
--this.invulnerableTime;
}

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Disable spigot tick limiters
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0a7a354c085655c243fdf94c7dc82cdc95b3987a..42e81640354c2679570823347b28ee1155e7a00e 100644
index da553430864689c426ad2c1dd74ad7d1134ffbae..78041052d7ab2e6b60405ce7e02468458650db22 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -689,9 +689,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -694,9 +694,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Spigot start
// Iterator iterator = this.blockEntityTickers.iterator();
int tilesThisCycle = 0;

View File

@ -12,7 +12,7 @@ improve setPosition to use raw
public net.minecraft.world.entity.Entity setRot(FF)V
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 90c73b9075489242556a7ba749618e20c0ed0c4d..2a905bc0c177fb7ad5464fb99682d475f42c0c85 100644
index 0338a6b245ee482d470f5a80da712679ab9890fa..f03058205342f06c1dfbf38313e7d2088327b104 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -240,7 +240,7 @@ public abstract class PlayerList {

View File

@ -21,10 +21,10 @@ character.
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 403f7c7f31e0072b0cad0706bc981ece24733a1d..42a44820a3c13e2b0e29e02ed384c1918c9a0b17 100644
index d72e8df4f99b6219ea305742f0cf8d1c1985ffd6..ddd437906801973e11386294e7e3f6846cc11cbc 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2034,7 +2034,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -2041,7 +2041,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
return true;
}
@ -33,7 +33,7 @@ index 403f7c7f31e0072b0cad0706bc981ece24733a1d..42a44820a3c13e2b0e29e02ed384c191
for (int i = 0; i < message.length(); ++i) {
if (!SharedConstants.isAllowedChatCharacter(message.charAt(i))) {
return true;
@@ -2051,7 +2051,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -2058,7 +2058,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
}
OutgoingChatMessage outgoing = OutgoingChatMessage.create(original);
@ -42,7 +42,7 @@ index 403f7c7f31e0072b0cad0706bc981ece24733a1d..42a44820a3c13e2b0e29e02ed384c191
this.handleCommand(s);
} else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) {
// Do nothing, this is coming from a plugin
@@ -2141,7 +2141,29 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -2148,7 +2148,29 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
}
}
@ -74,7 +74,7 @@ index 403f7c7f31e0072b0cad0706bc981ece24733a1d..42a44820a3c13e2b0e29e02ed384c191
if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot
this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 17056a7ea6c6a3a671872d2be603d7dd60ae04e9..6e488fe34231afa20d0f8f62299bb631359ee51c 100644
index fb6ea46609489d802ed4b76b4074734dd3e3886f..dd3935eeceba456b37a5fbcb874c1073bb76d473 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -875,6 +875,28 @@ public final class CraftServer implements Server {
@ -107,10 +107,10 @@ index 17056a7ea6c6a3a671872d2be603d7dd60ae04e9..6e488fe34231afa20d0f8f62299bb631
return true;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 484fab5eeeb92407ded625b96678c9aa93199d70..b8fc2196b8f77b826d229265e96b5cce1e5301cb 100644
index 4061b68edb8f501eea71ba009214ac3808506ec7..37ffadacbfd49743dac8739b74def818a351e563 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -437,7 +437,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -479,7 +479,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void chat(String msg) {
if (this.getHandle().connection == null) return;
@ -145,7 +145,7 @@ index 19c44daaa407b7c1c7a7ffe56fef8c8814c6d5b2..6a073a9dc44d93eba296a0e18a9c7be8
} finally {
try {
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
index 78669fa035b7537ff7e533cf32aaf2995625424f..7585a30e8f063ac2656b5de519b1e9edaceffbc7 100644
index 05e94702e42b8f5c35d2a112c486d57948a3acba..5409f230fdd53b70fc03c58177438534731ad4e6 100644
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
@@ -6,6 +6,7 @@ public class AsyncCatcher

View File

@ -18,10 +18,10 @@ index 23cb972ca3fde409be0d6517ef8f1c58dab47ff4..476a9b2db5deac803f1cb3c2cbe88b69
if (random.nextInt(10) == 0 && flag && pos.getY() < 40) {
return checkMobSpawnRules(type, world, spawnReason, pos, random);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index bf4b2f89d3a7133155c6272379c742318b2c1514..f07a6b1d782426581c84ffa19447c1375c4cbc07 100644
index 33677ec811ceab939c419bf7d31b99585e9a1ef1..8ae78690748b2cb5d5186d8859871c1630e10130 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -213,7 +213,7 @@ public class CraftChunk implements Chunk {
@@ -169,7 +169,7 @@ public class CraftChunk implements Chunk {
@Override
public boolean isSlimeChunk() {
// 987234911L is deterimined in EntitySlime when seeing if a slime can spawn in a chunk

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Expose server CommandMap
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 6e488fe34231afa20d0f8f62299bb631359ee51c..7681198cbc8f36b9e860182a1f3541a4b22fc82e 100644
index dd3935eeceba456b37a5fbcb874c1073bb76d473..9c80c55e8c15aa847aea134dd8121ee9d0c24d1c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2012,6 +2012,7 @@ public final class CraftServer implements Server {

View File

@ -63,7 +63,7 @@ index bd808eb312ade7122973a47f4b96505829511da5..bf0f9cab7c66c089f35b851e799ba4a4
// Paper end
buf.writeComponent(this.text);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index b8fc2196b8f77b826d229265e96b5cce1e5301cb..bd811f33bb2df565d876bc3433b1ce9ce58acba4 100644
index 37ffadacbfd49743dac8739b74def818a351e563..c6ceb5044e3dcf5f512dc1efc04e0785b1caadb0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1,5 +1,6 @@
@ -73,7 +73,7 @@ index b8fc2196b8f77b826d229265e96b5cce1e5301cb..bd811f33bb2df565d876bc3433b1ce9c
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.BaseEncoding;
@@ -283,6 +284,100 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -325,6 +326,100 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
}

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Add configurable portal search radius
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 7358b918d03b0dee0541843a952d6b8bf939d877..4d12403d8ae7c620e169e87b0a0ab48e28251811 100644
index 3088cdbb55b3054394fd3405797539f58a46f70c..756b8be27488c81172fe05fa0361ef3866f99bee 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3122,7 +3122,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -3174,7 +3174,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType());
BlockPos blockposition = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0);
// CraftBukkit start

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Add velocity warnings
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 7681198cbc8f36b9e860182a1f3541a4b22fc82e..6be92dea5f2c042a427de77b6ae5b9e45a662388 100644
index 9c80c55e8c15aa847aea134dd8121ee9d0c24d1c..1cca43506306994e740278a581b0d33924d08491 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -296,6 +296,7 @@ public final class CraftServer implements Server {
@ -62,10 +62,10 @@ index 0a6926f9b6be67d4d710d2fbc6bd2b1fcb0677a0..c9275f73be7332f79312037954f9685f
public double getHeight() {
return this.getHandle().getBbHeight();
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
index d5863b0b06384b25eaa33572fa02649795463ed8..2693cc933d746e40d8a47d96c6cb6799f0a2472f 100644
index 11d7ede26b46d0bf9cced65e8c3bcc41c8b66dbf..3ad14bf0697e682a2e777baa8faeb323d127fb13 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread
@@ -80,7 +80,19 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" );
log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem );
}
@ -85,4 +85,4 @@ index d5863b0b06384b25eaa33572fa02649795463ed8..2693cc933d746e40d8a47d96c6cb6799
+ // Paper end
log.log( Level.SEVERE, "------------------------------" );
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system

View File

@ -16,10 +16,10 @@ The wanted destination was on top of the emerald block however the player ended
This only is the case if the player is teleporting between worlds.
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index bd811f33bb2df565d876bc3433b1ce9ce58acba4..db7063bb4dddcf485f9e57505ae2bd31ade5376e 100644
index c6ceb5044e3dcf5f512dc1efc04e0785b1caadb0..8f5d6d4ea4a8a7de95c755594ba5ec3fd3902158 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1140,7 +1140,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -1182,7 +1182,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
entity.connection.teleport(to);
} else {
// The respawn reason should never be used if the passed location is non null.

View File

@ -88,7 +88,7 @@ index c6fb4c33d7ea52b88d8fc0d90748cbab7387c565..fed09b886f4fa0006d160e5f2abb00df
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 42e81640354c2679570823347b28ee1155e7a00e..a7fb12648c2e655e191d8c805753ae0c05421d17 100644
index 78041052d7ab2e6b60405ce7e02468458650db22..8149286827d9b609be47a4ded0413ca11f7858de 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1,5 +1,10 @@
@ -102,7 +102,7 @@ index 42e81640354c2679570823347b28ee1155e7a00e..a7fb12648c2e655e191d8c805753ae0c
import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import java.io.IOException;
@@ -725,6 +730,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -730,6 +735,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Paper start - Prevent tile entity and entity crashes
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
MinecraftServer.LOGGER.error(msg, throwable);
@ -131,7 +131,7 @@ index f1675e35be0ab7670c875c6b0d1e982a3ae09d1e..b2bb9bbd3af414c50ec3f8e3e171a679
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 8e1ca484356a7eddcdb37ef7ec01dea9864eec70..2006760ff24ec9ce5f71c107ddf942e550d03589 100644
index 5d7290216d3a6ddb8e345a5b05da21ef28ed2307..fe6b2ade9f167c36cbac594a25ad36ee14208fa0 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1,6 +1,7 @@
@ -163,7 +163,7 @@ index 8e1ca484356a7eddcdb37ef7ec01dea9864eec70..2006760ff24ec9ce5f71c107ddf942e5
// CraftBukkit end
}
}
@@ -1060,6 +1067,7 @@ public class LevelChunk extends ChunkAccess {
@@ -1149,6 +1156,7 @@ public class LevelChunk extends ChunkAccess {
// Paper start - Prevent tile entity and entity crashes
final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable);
@ -172,10 +172,10 @@ index 8e1ca484356a7eddcdb37ef7ec01dea9864eec70..2006760ff24ec9ce5f71c107ddf942e5
// Paper end
// Spigot start
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index d9daf07132c46548964a75588b69d7a74680e917..67a2f3c02aa4983b3ec2df073821190ddb36543c 100644
index e68205fe7169c7c5b7c6fdada2ee97d86107ca97..aa8972fd1a1fade05d60ab69efb8ff24f344508a 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -274,6 +274,7 @@ public class RegionFile implements AutoCloseable {
@@ -275,6 +275,7 @@ public class RegionFile implements AutoCloseable {
return true;
}
} catch (IOException ioexception) {
@ -183,7 +183,7 @@ index d9daf07132c46548964a75588b69d7a74680e917..67a2f3c02aa4983b3ec2df073821190d
return false;
}
}
@@ -355,6 +356,7 @@ public class RegionFile implements AutoCloseable {
@@ -356,6 +357,7 @@ public class RegionFile implements AutoCloseable {
((java.nio.Buffer) buf).position(5); // CraftBukkit - decompile error
filechannel.write(buf);
} catch (Throwable throwable) {

View File

@ -11,10 +11,10 @@ So avoid looking up scoreboards and short circuit to the "not on a team"
logic which is most likely to be true.
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 4d12403d8ae7c620e169e87b0a0ab48e28251811..bb8de860d826e4c92ffdbd7ef2675458d372bbdf 100644
index 756b8be27488c81172fe05fa0361ef3866f99bee..194c0f9e8b537d415d7cdedf9cd5d4870b60fb08 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2753,6 +2753,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -2805,6 +2805,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@Nullable
public Team getTeam() {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Complete resource pack API
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 42a44820a3c13e2b0e29e02ed384c1918c9a0b17..94636c92758568051f829aed59aab8728e7e7252 100644
index ddd437906801973e11386294e7e3f6846cc11cbc..a91cc53f9d601bbc51988b2b7855c6ebcc68d780 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1748,8 +1748,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -1755,8 +1755,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName());
this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"));
}
@ -23,7 +23,7 @@ index 42a44820a3c13e2b0e29e02ed384c1918c9a0b17..94636c92758568051f829aed59aab872
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index db7063bb4dddcf485f9e57505ae2bd31ade5376e..04e9a84b36f7f702e34216513348a0871ade22e5 100644
index 8f5d6d4ea4a8a7de95c755594ba5ec3fd3902158..f6006f696550126d1ba78fdc49821e20cd19b1f3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -178,6 +178,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@ -37,7 +37,7 @@ index db7063bb4dddcf485f9e57505ae2bd31ade5376e..04e9a84b36f7f702e34216513348a087
public CraftPlayer(CraftServer server, ServerPlayer entity) {
super(server, entity);
@@ -2292,6 +2296,45 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2334,6 +2338,45 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public boolean getAffectsSpawning() {
return this.getHandle().affectsSpawning;
}

View File

@ -16,7 +16,7 @@ modify that. Under the previous logic, plugins were unable (cleanly) override pe
A config option has been added for those who depend on the previous behavior, but I don't expect that.
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 6be92dea5f2c042a427de77b6ae5b9e45a662388..4edf6a317ba5ce46e098c4ce1836c147853eadb1 100644
index 1cca43506306994e740278a581b0d33924d08491..e509ab35bf8ffba3c1e04f1236f98c24c1e010f4 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -457,6 +457,7 @@ public final class CraftServer implements Server {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Allow Reloading of Custom Permissions
https://github.com/PaperMC/Paper/issues/49
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 4edf6a317ba5ce46e098c4ce1836c147853eadb1..2fa6753e7bd9c1a6c08b467fe6d2d7ca3943f0a7 100644
index e509ab35bf8ffba3c1e04f1236f98c24c1e010f4..dea53897919d46b90c99577fbb1985b2d0c65b5e 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2603,5 +2603,23 @@ public final class CraftServer implements Server {

View File

@ -7,7 +7,7 @@ Metadata is not meant to persist reload as things break badly with non primitive
This will remove metadata on reload so it does not crash everything if a plugin uses it.
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 2fa6753e7bd9c1a6c08b467fe6d2d7ca3943f0a7..0953f4555bc18176f35d91754ad308143899a8a7 100644
index dea53897919d46b90c99577fbb1985b2d0c65b5e..dbad9e72121562d22f8476bade4032661e280066 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -962,8 +962,16 @@ public final class CraftServer implements Server {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Add World Util Methods
Methods that can be used for other patches to help improve logic.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index ef48e76ca18576e631d5d2f1652d3449d558a582..71be3d403dc0c345b447685fa339cb1c455dd2a8 100644
index feee30aa0bccfa40765f1c4a179ba04907b11433..4598ca4cd9da931db33ca26576bfbcdf7df99094 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -221,7 +221,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@ -19,7 +19,7 @@ index ef48e76ca18576e631d5d2f1652d3449d558a582..71be3d403dc0c345b447685fa339cb1c
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index a7fb12648c2e655e191d8c805753ae0c05421d17..5e4b102e747a053280871879c3c18fc3d3d2d18a 100644
index 8149286827d9b609be47a4ded0413ca11f7858de..809f7db469583ea90fbb165cf180dc87055c6105 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -342,6 +342,22 @@ public abstract class Level implements LevelAccessor, AutoCloseable {

View File

@ -44,10 +44,10 @@ index 1238da8b035a0b0dd3d00557ca0de7a82f5fdf53..5e40ee2695b7ed50fddc0e8226f0b1b4
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 04e9a84b36f7f702e34216513348a0871ade22e5..877f82735c407c1d567628fafc7c7fd6adebb410 100644
index f6006f696550126d1ba78fdc49821e20cd19b1f3..af7f97b605b81a0b2dd812f491b6e324660fe260 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2096,6 +2096,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2138,6 +2138,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
public void setRealHealth(double health) {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Use a Shared Random for Entities
Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created.
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index bb8de860d826e4c92ffdbd7ef2675458d372bbdf..09cf1125221bdbebddabfc46095c3dbd153714c1 100644
index 194c0f9e8b537d415d7cdedf9cd5d4870b60fb08..3f8b0124e5c2a01f1cf3a344b8dd4075817cb001 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -162,6 +162,79 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@ -89,7 +89,7 @@ index bb8de860d826e4c92ffdbd7ef2675458d372bbdf..09cf1125221bdbebddabfc46095c3dbd
private CraftEntity bukkitEntity;
public CraftEntity getBukkitEntity() {
@@ -354,7 +427,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@@ -406,7 +479,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.bb = Entity.INITIAL_AABB;
this.stuckSpeedMultiplier = Vec3.ZERO;
this.nextStep = 1.0F;

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Configurable spawn chances for skeleton horses
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 71be3d403dc0c345b447685fa339cb1c455dd2a8..16e0887abe2643b13f7fefd986783e88d37fbdfb 100644
index 4598ca4cd9da931db33ca26576bfbcdf7df99094..f6be0fefb461c1b5fd0feb5553d36b5817b96e3a 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -607,7 +607,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -756,7 +756,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
if (this.isRainingAt(blockposition)) {
DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);

View File

@ -29,7 +29,7 @@ index 1b29c6872ebe54351f28c1f1f38b22561ba785ee..40950db0c242c65dfd4de247c8624935
this.x = x;
this.y = y;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 5e4b102e747a053280871879c3c18fc3d3d2d18a..dcf1894ed6939b47cd8323421d5734fd5af6dedb 100644
index 809f7db469583ea90fbb165cf180dc87055c6105..e5194f0650af2bce8aac24e34752b21015b92d4e 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -284,7 +284,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@ -88,7 +88,7 @@ index 60e760b42dd6471a229dfd45490dcf8c51979d35..4a3ac7dedf5cb1e76f16ec4f18e82afc
@Override
public FluidState getFluidState(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 2006760ff24ec9ce5f71c107ddf942e550d03589..b7e03ac0e07a48c5d3a401a918ab6cc2a7daafec 100644
index fe6b2ade9f167c36cbac594a25ad36ee14208fa0..4e93e9ce7a7f939f802e51072efd389a86b42fc4 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -295,12 +295,29 @@ public class LevelChunk extends ChunkAccess {

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener
Saves on some object allocation and processing when no plugin listens to this
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index d5ad3368a397e9fc02506187ccb1c386afd9ce2b..7fca70658ecdc89b79381ca2ab33b931ce6871ae 100644
index 821725460b62ebadedb789f4408ef172416c2092..81abb732e2bb3bca683028d505e7485052c0ec8d 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1373,6 +1373,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1367,6 +1367,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
@ -18,7 +18,7 @@ index d5ad3368a397e9fc02506187ccb1c386afd9ce2b..7fca70658ecdc89b79381ca2ab33b931
this.profiler.push(() -> {
return worldserver + " " + worldserver.dimension().location();
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 16e0887abe2643b13f7fefd986783e88d37fbdfb..5c2ca51139b0647a2c7ae1b268b6d151dc884eca 100644
index f6be0fefb461c1b5fd0feb5553d36b5817b96e3a..33c6a673d98323a3790b3e494841dffa9ce5f4f5 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -220,6 +220,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@ -30,10 +30,10 @@ index 16e0887abe2643b13f7fefd986783e88d37fbdfb..5c2ca51139b0647a2c7ae1b268b6d151
@Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI
return this.chunkSource.getChunk(x, z, false);
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index dcf1894ed6939b47cd8323421d5734fd5af6dedb..fc48c03fa4f3c7e2463ef2ce477ce1e71d1e3faf 100644
index e5194f0650af2bce8aac24e34752b21015b92d4e..127f4e98e11a57eb3dddbc8efdb0aa33fda37924 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -491,7 +491,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -496,7 +496,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// CraftBukkit start
iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam
CraftWorld world = ((ServerLevel) this).getWorld();

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Entity AddTo/RemoveFrom World Events
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 5c2ca51139b0647a2c7ae1b268b6d151dc884eca..79b572c8e3481ea4a6ac523c0a2f25204cf44e2d 100644
index 33c6a673d98323a3790b3e494841dffa9ce5f4f5..507cab9d689b774b320fac00f7760c4143957b67 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2126,6 +2126,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -2292,6 +2292,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.setOrigin(entity.getOriginVector().toLocation(getWorld()));
}
// Paper end
@ -16,7 +16,7 @@ index 5c2ca51139b0647a2c7ae1b268b6d151dc884eca..79b572c8e3481ea4a6ac523c0a2f2520
}
public void onTrackingEnd(Entity entity) {
@@ -2201,6 +2202,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -2367,6 +2368,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
}
// CraftBukkit end

View File

@ -11,7 +11,7 @@ For people who want all chunks to be treated equally, you can chose a fixed valu
This allows to fine-tune vanilla gameplay.
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index b7e03ac0e07a48c5d3a401a918ab6cc2a7daafec..419125e865cb086f0ef75f69749cc03a178d9a41 100644
index 4e93e9ce7a7f939f802e51072efd389a86b42fc4..becec8ded3f7ed53998b55523793e6e9cd05d492 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -280,6 +280,13 @@ public class LevelChunk extends ChunkAccess {

View File

@ -11,13 +11,13 @@ The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap).
The maximum size of the RegionFileCache is also made configurable.
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index b9b50c56e79297bb824a92355f437a5d4d7e6760..e4c706d553a3d7058a32409ec7af8771c92d9777 100644
index fe8bb0037bb7f317fc32ac34461f4eb3a1f397f2..8bff53217d087a9d53aa3738660dde563ee125f1 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -36,7 +36,7 @@ public class RegionFileStorage implements AutoCloseable {
if (regionfile != null) {
return regionfile;
} else {
@@ -91,7 +91,7 @@ public class RegionFileStorage implements AutoCloseable {
return null;
}
// Paper end - cache regionfile does not exist state
- if (this.regionCache.size() >= 256) {
+ if (this.regionCache.size() >= io.papermc.paper.configuration.GlobalConfiguration.get().misc.regionFileCacheSize) { // Paper - configurable
((RegionFile) this.regionCache.removeLast()).close();

View File

@ -22,10 +22,10 @@ index a5d57cc862036012d83b090bb1b3ccf4115a88b3..21068f766b75c414d5818073b7dca083
static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() {
@Override
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 94636c92758568051f829aed59aab8728e7e7252..c65282a85e2822b86f56c528ab838e628ea27411 100644
index a91cc53f9d601bbc51988b2b7855c6ebcc68d780..2b1311185bb08592038e256d860a722fbd4d9ffc 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2534,8 +2534,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -2541,8 +2541,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
});
}
}

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 79b572c8e3481ea4a6ac523c0a2f25204cf44e2d..6896ead71f87989c2fa90d0339eedfd08ac49dd1 100644
index 507cab9d689b774b320fac00f7760c4143957b67..508c1f2874db3add98aad29bd4eee6c9f5d58006 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1366,6 +1366,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -1517,6 +1517,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@Override
public void updateNeighborsAt(BlockPos pos, Block sourceBlock) {

View File

@ -18,7 +18,7 @@ index 1294b38262505b0d54089e428df9b363219de1f0..ee37ec0de1ca969144824427ae42b0c8
buf.writeComponent(this.playerPrefix);
buf.writeComponent(this.playerSuffix);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 7fca70658ecdc89b79381ca2ab33b931ce6871ae..feee1da3091fdbcef0336ab0ab85fd9f52ccac4b 100644
index 81abb732e2bb3bca683028d505e7485052c0ec8d..d2b07b5f0ff7466f22f2c25c7e0cb9a00b25f4f0 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -589,6 +589,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@ -43,7 +43,7 @@ index 7fca70658ecdc89b79381ca2ab33b931ce6871ae..feee1da3091fdbcef0336ab0ab85fd9f
this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP));
this.connection.acceptConnections();
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 2a905bc0c177fb7ad5464fb99682d475f42c0c85..ebbe5fb5d22cc6a7a2f131ab8fa209ff47c0c92a 100644
index f03058205342f06c1dfbf38313e7d2088327b104..05dd9e618336c5a8e44e20b97d9a7fd0fb5b3002 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -99,6 +99,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage;

View File

@ -6,7 +6,7 @@ Subject: [PATCH] remove null possibility for getServer singleton
to stop IDE complaining about potential NPE
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index feee1da3091fdbcef0336ab0ab85fd9f52ccac4b..ac0a6cfb6fb7d9fa696b1e35ebdfb37935b74048 100644
index d2b07b5f0ff7466f22f2c25c7e0cb9a00b25f4f0..8e3ff6870daff6dee7e38f72d1e37e9aa58dab35 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -193,6 +193,7 @@ import co.aikar.timings.MinecraftTimings; // Paper
@ -25,7 +25,7 @@ index feee1da3091fdbcef0336ab0ab85fd9f52ccac4b..ac0a6cfb6fb7d9fa696b1e35ebdfb379
this.metricsRecorder = InactiveMetricsRecorder.INSTANCE;
this.profiler = this.metricsRecorder.getProfiler();
this.onMetricsRecordingStopped = (methodprofilerresults) -> {
@@ -2332,9 +2334,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2326,9 +2328,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return false;
}

View File

@ -13,10 +13,10 @@ custom renderers are in use, defaulting to the much simpler Vanilla system.
Additionally, numerous issues to player position tracking on maps has been fixed.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 6896ead71f87989c2fa90d0339eedfd08ac49dd1..99a7fadf87b0b081a1f5ab15a8eeb1b0cb8572fe 100644
index 508c1f2874db3add98aad29bd4eee6c9f5d58006..90c19a08b51dee98701fc397ab95bf93cb1a2102 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2147,6 +2147,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -2313,6 +2313,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
{
if ( iter.next().player == entity )
{

View File

@ -490,7 +490,7 @@ index 0000000000000000000000000000000000000000..9cfa5d36a6991067a3866e0d437749fa
+ }
+}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 09cf1125221bdbebddabfc46095c3dbd153714c1..49f465d0009b084be2a8e809c53126af1ad72cd2 100644
index 3f8b0124e5c2a01f1cf3a344b8dd4075817cb001..f331c9ff4cc341c981515210d3f4bd92faa8fdc9 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -235,6 +235,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] System property for disabling watchdoge
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
index 2693cc933d746e40d8a47d96c6cb6799f0a2472f..6e1fa4f0616ccfd258acd1b4f5b08fc0ad4c9529 100644
index 3ad14bf0697e682a2e777baa8faeb323d127fb13..a9897c494b3dc56d900356d74030359832febbaa 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread
@@ -61,7 +61,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
while ( !this.stopping )
{
//

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Async GameProfileCache saving
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ac0a6cfb6fb7d9fa696b1e35ebdfb37935b74048..857cc4fcc586f7a8ea5baeeae69da62ebfdac77a 100644
index 8e3ff6870daff6dee7e38f72d1e37e9aa58dab35..14edacfd5cc77cc85dc84e3fdad94be8c8932dc6 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -954,7 +954,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -935,7 +935,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} catch (java.lang.InterruptedException ignored) {} // Paper
if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) {
MinecraftServer.LOGGER.info("Saving usercache.json");
@ -16,9 +16,9 @@ index ac0a6cfb6fb7d9fa696b1e35ebdfb37935b74048..857cc4fcc586f7a8ea5baeeae69da62e
+ this.getProfileCache().save(false); // Paper
}
// Spigot end
io.papermc.paper.chunk.system.io.RegionFileIOThread.close(true); // Paper // Paper - rewrite chunk system
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 6f64d98021e842905cdd6410ec355a6f136ec18f..a9cf8960d487ee71385341285a4b1618007d06dc 100644
index 049f7dc31576980007eb8f0caab926bb58fead78..81a0a897a1fd2a408bfe43f24ed5e5f4bbefe161 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -242,7 +242,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Faster redstone torch rapid clock removal
Only resize the the redstone torch list once, since resizing arrays / lists is costly
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index fc48c03fa4f3c7e2463ef2ce477ce1e71d1e3faf..15cb9a1dc2426dd87dc4bc4961812523ed9f639f 100644
index 127f4e98e11a57eb3dddbc8efdb0aa33fda37924..df194067094dd89423251207e62f477db6546264 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -173,6 +173,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {

View File

@ -43,7 +43,7 @@ index da98f074ccd5a40c635824112c97fd174c393cb1..6599f874d9f97e9ef4862039ecad7277
} else {
String[] astring1 = astring;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0953f4555bc18176f35d91754ad308143899a8a7..bbc9f231d658dfe8cb62a6c632e5373c97ac2a75 100644
index dbad9e72121562d22f8476bade4032661e280066..d83942d7f7260073e1c60e125eed6312ff89e434 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1735,7 +1735,7 @@ public final class CraftServer implements Server {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Configurable packet in spam threshold
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index c65282a85e2822b86f56c528ab838e628ea27411..96e38a914db34ed165bd5071585bc7e5ec7fb41d 100644
index 2b1311185bb08592038e256d860a722fbd4d9ffc..28ec3530a5c3df8e0c629228f80c0130cb65cc27 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1588,13 +1588,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -1595,13 +1595,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
// Spigot start - limit place/interactions
private int limitedPackets;
private long lastLimitedPacket = -1;

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Configurable flying kick messages
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 96e38a914db34ed165bd5071585bc7e5ec7fb41d..590880b71c3c1930eb84538af5f6c3b690bb690f 100644
index 28ec3530a5c3df8e0c629228f80c0130cb65cc27..6017d2d5378f1d6c2a258469cc24c51e7a4ab4b6 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -355,7 +355,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Allow Reloading of Command Aliases
Reload the aliases stored in commands.yml
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index bbc9f231d658dfe8cb62a6c632e5373c97ac2a75..3fff803c44c013dbcc2e639a08067d7ba3576a6d 100644
index d83942d7f7260073e1c60e125eed6312ff89e434..1889db501bb91671eac8b8672531427d7325f35e 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2629,5 +2629,24 @@ public final class CraftServer implements Server {

Some files were not shown because too many files have changed in this diff Show More