Paper/patches/server/0455-Add-Plugin-Tickets-to-API-Chunk-Methods.patch
Nassim Jahnke 17f71ac87b
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#5904)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
70d24eb8 SPIGOT-6587: Update documentation/error of drop chance API

CraftBukkit Changes:
470050ad SPIGOT-6587: Update documentation/error of drop chance API
1c39efa3 Fix Inventory#getViewers on the player inventory not returning the player first time their inventory is opened
d161627d Fix PrepareItemCraftEvent#isRepair
aa1fae73 SPIGOT-6586: EntityChangeBlockEvent for falling block does not cancel properly
8a04072e SPIGOT-6583: Throwing eggs doesn't make sounds

Spigot Changes:
f773da84 Remove redundant patch
cd367234 Rebuild patches
2021-06-20 21:25:59 +02:00

122 lines
6.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 9 Jun 2020 03:33:03 -0400
Subject: [PATCH] Add Plugin Tickets to API Chunk Methods
Like previous versions, plugins loading chunks kept them loaded until
they garbage collected to avoid constant spamming of chunk loads
This adds tickets to a few more places so that they can be unloaded.
Additionally, this drops their ticket level to BORDER so they wont be ticking
so they will just sit inactive instead.
Using .loadChunk to keep a chunk ticking was a horrible idea for upstream
when we have TWO methods that are able to do that already in the API.
Also reduce their collection count down to a maximum of 1 second. Barely
anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and
since this wasn't spigot behavior, this is safe to mostly ignore (unless someone
wants it to collect even faster, they can restore that setting back to 1 instead of 20+)
Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons.
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 35339d49458aded3f80ff162b9725ceb84ae47c6..434a46dca55453815772eeb50ef412b02af2c0a1 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -346,7 +346,7 @@ public final class CraftServer implements Server {
this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient");
console.autosavePeriod = this.configuration.getInt("ticks-per.autosave");
this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose"));
- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks");
+ TicketType.PLUGIN.timeout = Math.min(20, this.configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second
this.minimumAPI = this.configuration.getString("settings.minimum-api");
this.loadIcon();
}
@@ -830,7 +830,7 @@ public final class CraftServer implements Server {
this.waterAmbientSpawn = this.configuration.getInt("spawn-limits.water-ambient");
this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient");
this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose"));
- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks");
+ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second
this.minimumAPI = this.configuration.getString("settings.minimum-api");
this.printSaveWarning = false;
console.autosavePeriod = this.configuration.getInt("ticks-per.autosave");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 72c9ad9f75c20d6c1a6d54e2913e2f9918c11ffd..f72471ac82907a0d5112598b3289689495285944 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -405,8 +405,21 @@ public class CraftWorld implements World {
@Override
public Chunk getChunkAt(int x, int z) {
- return this.world.getChunkSource().getChunk(x, z, true).bukkitChunk;
+ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it
+ net.minecraft.world.level.chunk.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z);
+ if (chunk == null) {
+ addTicket(x, z);
+ chunk = this.world.getChunkSource().getChunk(x, z, true);
+ }
+ return chunk.bukkitChunk;
+ // Paper end
+ }
+
+ // Paper start
+ private void addTicket(int x, int z) {
+ net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper
}
+ // Paper end
@Override
public Chunk getChunkAt(Block block) {
@@ -481,7 +494,7 @@ public class CraftWorld implements World {
public boolean unloadChunkRequest(int x, int z) {
org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
if (this.isChunkLoaded(x, z)) {
- this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE);
+ this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper
}
return true;
@@ -558,9 +571,12 @@ public class CraftWorld implements World {
org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
// Paper start - Optimize this method
ChunkPos chunkPos = new ChunkPos(x, z);
+ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper
+ if (immediate != null) return true; // Paper
if (!generate) {
- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z);
+
+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper
if (immediate == null) {
immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z);
}
@@ -568,7 +584,7 @@ public class CraftWorld implements World {
if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) {
return false; // not full status
}
- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE);
+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper
world.getChunk(x, z); // make sure we're at ticket level 32 or lower
return true;
}
@@ -594,7 +610,7 @@ public class CraftWorld implements World {
// we do this so we do not re-read the chunk data on disk
}
- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE);
+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper
world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true);
return true;
// Paper end
@@ -2544,6 +2560,7 @@ public class CraftWorld implements World {
return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> {
net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null);
+ if (chunk != null) addTicket(x, z); // Paper
return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk());
}, net.minecraft.server.MinecraftServer.getServer());
}