2022-07-30 01:16:26 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
|
|
|
Date: Fri, 29 Jul 2022 12:35:19 -0400
|
|
|
|
Subject: [PATCH] Warn on plugins accessing faraway chunks
|
|
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
2024-10-27 18:11:15 +01:00
|
|
|
index 9afc0eaaca5ab7b6445d90ce53e31a6ae76f8848..f0c2187a92de633a1d4cc7e71ff62cbe30ce8774 100644
|
2022-07-30 01:16:26 +02:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
2024-10-27 18:11:15 +01:00
|
|
|
@@ -337,7 +337,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
2022-07-30 01:16:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isInWorldBoundsHorizontal(BlockPos pos) {
|
|
|
|
- return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000;
|
2024-01-18 15:56:25 +01:00
|
|
|
+ return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000; // Diff on change warnUnsafeChunk()
|
2022-07-30 01:16:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isOutsideSpawnableHeight(int y) {
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
2024-12-03 15:47:48 +01:00
|
|
|
index 33735897ec3800754ba690ca215d3d11d746f728..b0e57ca463a3c7cb1be8920a899c9afc7c871f4b 100644
|
2022-07-30 01:16:26 +02:00
|
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -302,9 +302,24 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2022-07-30 01:16:26 +02:00
|
|
|
public boolean setSpawnLocation(int x, int y, int z) {
|
|
|
|
return this.setSpawnLocation(x, y, z, 0.0F);
|
|
|
|
}
|
|
|
|
+ // Paper start
|
|
|
|
+ private static void warnUnsafeChunk(String reason, int x, int z) {
|
|
|
|
+ // if any chunk coord is outside of 30 million blocks
|
|
|
|
+ if (x > 1875000 || z > 1875000 || x < -1875000 || z < -1875000) {
|
|
|
|
+ Plugin plugin = io.papermc.paper.util.StackWalkerUtil.getFirstPluginCaller();
|
|
|
|
+ if (plugin != null) {
|
|
|
|
+ plugin.getLogger().warning("Plugin is %s at (%s, %s), this might cause issues.".formatted(reason, x, z));
|
|
|
|
+ }
|
|
|
|
+ if (net.minecraft.server.MinecraftServer.getServer().isDebugging()) {
|
|
|
|
+ io.papermc.paper.util.TraceUtil.dumpTraceForThread("Dangerous chunk retrieval");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Chunk getChunkAt(int x, int z) {
|
|
|
|
+ warnUnsafeChunk("getting a faraway chunk", x, z); // Paper
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) this.world.getChunk(x, z, ChunkStatus.FULL, true);
|
|
|
|
return new CraftChunk(chunk);
|
|
|
|
}
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -400,6 +415,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2024-06-14 14:11:52 +02:00
|
|
|
if (!unloadChunk0(x, z, false)) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-30 01:16:26 +02:00
|
|
|
+ warnUnsafeChunk("regenerating a faraway chunk", x, z); // Paper
|
2024-06-14 14:11:52 +02:00
|
|
|
|
|
|
|
final long chunkKey = ChunkCoordIntPair.pair(x, z);
|
|
|
|
world.getChunkProvider().unloadQueue.remove(chunkKey);
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -473,6 +489,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2022-07-30 01:16:26 +02:00
|
|
|
@Override
|
|
|
|
public boolean loadChunk(int x, int z, boolean generate) {
|
|
|
|
org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
|
|
|
|
+ warnUnsafeChunk("loading a faraway chunk", x, z); // Paper
|
2024-01-23 15:43:48 +01:00
|
|
|
ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper
|
|
|
|
|
|
|
|
// If generate = false, but the chunk already exists, we will get this back.
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -505,6 +522,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2022-07-30 01:16:26 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean addPluginChunkTicket(int x, int z, Plugin plugin) {
|
|
|
|
+ warnUnsafeChunk("adding a faraway chunk ticket", x, z); // Paper
|
|
|
|
Preconditions.checkArgument(plugin != null, "null plugin");
|
|
|
|
Preconditions.checkArgument(plugin.isEnabled(), "plugin is not enabled");
|
|
|
|
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -605,6 +623,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2022-07-30 01:16:26 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setChunkForceLoaded(int x, int z, boolean forced) {
|
|
|
|
+ warnUnsafeChunk("forceloading a faraway chunk", x, z); // Paper
|
|
|
|
this.getHandle().setChunkForced(x, z, forced);
|
|
|
|
}
|
|
|
|
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -939,6 +958,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2022-07-30 01:16:26 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) {
|
|
|
|
+ warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper
|
|
|
|
// Transient load for this tick
|
|
|
|
return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z);
|
|
|
|
}
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -2344,6 +2364,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2022-07-30 01:16:26 +02:00
|
|
|
// Paper start
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
@Override
|
|
|
|
public void getChunkAtAsync(int x, int z, boolean gen, boolean urgent, @NotNull Consumer<? super Chunk> cb) {
|
2022-07-30 01:16:26 +02:00
|
|
|
+ warnUnsafeChunk("getting a faraway chunk async", x, z); // Paper
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
ca.spottedleaf.moonrise.common.util.ChunkSystem.scheduleChunkLoad(
|
|
|
|
this.getHandle(), x, z, gen, ChunkStatus.FULL, true,
|
|
|
|
urgent ? ca.spottedleaf.concurrentutil.util.Priority.HIGHER : ca.spottedleaf.concurrentutil.util.Priority.NORMAL,
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -2356,6 +2377,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void getChunksAtAsync(int minX, int minZ, int maxX, int maxZ, boolean urgent, Runnable cb) {
|
|
|
|
+ warnUnsafeChunk("getting a faraway chunk async", minX, minZ); // Paper
|
|
|
|
+ warnUnsafeChunk("getting a faraway chunk async", maxX, maxZ); // Paper
|
|
|
|
this.getHandle().loadChunks(
|
|
|
|
minX, minZ, maxX, maxZ,
|
|
|
|
urgent ? ca.spottedleaf.concurrentutil.util.Priority.HIGHER : ca.spottedleaf.concurrentutil.util.Priority.NORMAL,
|