mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-16 06:30:46 +01:00
Add Lighting Queue
The lighting queue spreads out the processing of light updates across multiple ticks based on how much free time the server has left at the end of the tick.
This commit is contained in:
parent
fc2341a996
commit
dd60ba4869
7 changed files with 260 additions and 263 deletions
|
@ -18,16 +18,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
// Paper start - Asynchronous light updates
|
||||
public AtomicInteger pendingLightUpdates = new AtomicInteger();
|
||||
public long lightUpdateTime;
|
||||
protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot
|
||||
public int lightUpdates; // Paper - Number of queued light updates for this chunk
|
||||
|
||||
+ // Paper start
|
||||
+ // Track the number of minecarts and items
|
||||
+ // Keep this synced with entitySlices.add() and entitySlices.remove()
|
||||
+ private final int[] itemCounts = new int[16];
|
||||
+ private final int[] inventoryEntityCounts = new int[16];
|
||||
// Paper end
|
||||
|
||||
+ // Paper end
|
||||
+
|
||||
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
|
||||
private int neighbors = 0x1 << 12;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
entity.ac = k;
|
||||
entity.ad = this.locZ;
|
||||
|
|
|
@ -8,15 +8,18 @@ diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/m
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.HashMap;
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
// CraftBukkit end
|
||||
|
||||
+// Paper start
|
||||
+import java.util.Set;
|
||||
+import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
// Paper end
|
||||
+// Paper end
|
||||
+
|
||||
public abstract class World implements IBlockAccess {
|
||||
|
||||
private int a = 63;
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Wed, 2 Mar 2016 00:52:31 -0600
|
||||
Subject: [PATCH] Configurable async light updates
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
||||
|
||||
}
|
||||
|
||||
+ public boolean useAsyncLighting;
|
||||
+ private void useAsyncLighting() {
|
||||
+ useAsyncLighting = false; //getBoolean( "use-async-lighting", false );
|
||||
+ log("World async lighting: " + useAsyncLighting);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -0,0 +0,0 @@ import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
+import java.util.concurrent.atomic.AtomicInteger; // Paper
|
||||
+
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
private int w;
|
||||
private ConcurrentLinkedQueue<BlockPosition> x;
|
||||
protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot
|
||||
+ // Paper start - Asynchronous light updates
|
||||
+ public AtomicInteger pendingLightUpdates = new AtomicInteger();
|
||||
+ public long lightUpdateTime;
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
|
||||
private int neighbors = 0x1 << 12;
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
private void a(int i, int j, int k, int l) {
|
||||
if (l > k && this.world.areChunksLoaded(new BlockPosition(i, 0, j), 16)) {
|
||||
for (int i1 = k; i1 < l; ++i1) {
|
||||
- this.world.c(EnumSkyBlock.SKY, new BlockPosition(i, i1, j));
|
||||
+ this.world.updateLight(EnumSkyBlock.SKY, new BlockPosition(i, i1, j));
|
||||
}
|
||||
|
||||
this.r = true;
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
|
||||
public void b(boolean flag) {
|
||||
if (this.l && !this.world.worldProvider.m() && !flag) {
|
||||
- this.h(this.world.isClientSide);
|
||||
+ this.recheckGaps(this.world.isClientSide); // Paper - Asynchronous lighting updates
|
||||
}
|
||||
|
||||
this.q = true;
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Paper- Recheck gaps asynchronously
|
||||
+ */
|
||||
+ public void recheckGaps(final boolean isClientSide) {
|
||||
+ if (!world.paperConfig.useAsyncLighting) {
|
||||
+ this.h(this.world.isClientSide);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ world.lightingExecutor.submit(new Runnable() {
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ Chunk.this.h(isClientSide);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
public boolean isReady() {
|
||||
// Spigot Start
|
||||
/*
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
}
|
||||
|
||||
public void queueUnload(int i, int j) {
|
||||
+ // Paper start - Asynchronous lighting updates
|
||||
+ Chunk chunk = chunks.get(LongHash.toLong(i, j));
|
||||
+ if (chunk != null && chunk.world.paperConfig.useAsyncLighting && (chunk.pendingLightUpdates.get() > 0 || chunk.world.getTime() - chunk.lightUpdateTime < 20)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.world.worldProvider.c(i, j)) {
|
||||
// CraftBukkit start
|
||||
this.unloadQueue.add(i, j);
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
// CraftBukkit end
|
||||
|
||||
+// Paper start
|
||||
+import java.util.concurrent.ExecutorService;
|
||||
+import java.util.concurrent.Executors;
|
||||
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
+// Paper end
|
||||
+
|
||||
public abstract class World implements IBlockAccess {
|
||||
|
||||
private int a = 63;
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
private org.spigotmc.TickLimiter entityLimiter;
|
||||
private org.spigotmc.TickLimiter tileLimiter;
|
||||
private int tileTickPosition;
|
||||
+ public ExecutorService lightingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Paper - Lighting Thread").build()); // Paper - Asynchronous lighting updates
|
||||
|
||||
public CraftWorld getWorld() {
|
||||
return this.world;
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
|
||||
if (!this.worldProvider.m()) {
|
||||
for (i1 = k; i1 <= l; ++i1) {
|
||||
- this.c(EnumSkyBlock.SKY, new BlockPosition(i, i1, j));
|
||||
+ this.updateLight(EnumSkyBlock.SKY, new BlockPosition(i, i1, j)); // Paper - Asynchronous lighting updates
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
boolean flag = false;
|
||||
|
||||
if (!this.worldProvider.m()) {
|
||||
- flag |= this.c(EnumSkyBlock.SKY, blockposition);
|
||||
+ flag |= this.updateLight(EnumSkyBlock.SKY, blockposition); // Paper - Asynchronous lighting updates
|
||||
}
|
||||
|
||||
- flag |= this.c(EnumSkyBlock.BLOCK, blockposition);
|
||||
+ flag |= this.updateLight(EnumSkyBlock.BLOCK, blockposition); // Paper - Asynchronous lighting updates
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Asynchronous lighting updates
|
||||
public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition) {
|
||||
+ return this.c(enumskyblock, blockposition, null, null);
|
||||
+ }
|
||||
+
|
||||
+ public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition, Chunk chunk, List<Chunk> neighbors) { // Paper
|
||||
// CraftBukkit start - Use neighbor cache instead of looking up
|
||||
- Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
- if (chunk == null || !chunk.areNeighborsLoaded(1) /*!this.areChunksLoaded(blockposition, 17, false)*/) {
|
||||
+ //Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ if (chunk == null /*|| !chunk.areNeighborsLoaded(1)*/ /*!this.areChunksLoaded(blockposition, 17, false)*/) {
|
||||
// CraftBukkit end
|
||||
return false;
|
||||
} else {
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
+ // Paper start - Asynchronous light updates
|
||||
+ if (chunk.world.paperConfig.useAsyncLighting) {
|
||||
+ chunk.pendingLightUpdates.decrementAndGet();
|
||||
+ if (neighbors != null) {
|
||||
+ for (Chunk neighbor : neighbors) {
|
||||
+ neighbor.pendingLightUpdates.decrementAndGet();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
this.methodProfiler.b();
|
||||
this.methodProfiler.a("checkedPosition < toCheckCount");
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Paper - Asynchronous lighting updates
|
||||
+ */
|
||||
+ public boolean updateLight(final EnumSkyBlock enumskyblock, final BlockPosition position) {
|
||||
+ int x = position.getX();
|
||||
+ int z = position.getZ();
|
||||
+ final Chunk chunk = this.getChunkIfLoaded(x >> 4, z >> 4);
|
||||
+ if (chunk == null || !chunk.areNeighborsLoaded(1)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (!chunk.world.paperConfig.useAsyncLighting) {
|
||||
+ return this.c(enumskyblock, position, chunk, null);
|
||||
+ }
|
||||
+
|
||||
+ chunk.pendingLightUpdates.incrementAndGet();
|
||||
+ chunk.lightUpdateTime = chunk.world.getTime();
|
||||
+
|
||||
+ final List<Chunk> neighbors = new ArrayList<Chunk>();
|
||||
+
|
||||
+ for (int cx = (x >> 4) - 1; cx <= (x >> 4) + 1; ++cx) {
|
||||
+ for (int cz = (z >> 4) - 1; cz <= (z >> 4) + 1; ++cz) {
|
||||
+ if (cx != x >> 4 && cz != z >> 4) {
|
||||
+ Chunk neighbor = this.getChunkIfLoaded(cx, cz);
|
||||
+ if (neighbor != null) {
|
||||
+ neighbor.pendingLightUpdates.incrementAndGet();
|
||||
+ neighbor.lightUpdateTime = chunk.world.getTime();
|
||||
+ neighbors.add(neighbor);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!Bukkit.isPrimaryThread()) {
|
||||
+ return this.c(enumskyblock, position, chunk, neighbors);
|
||||
+ }
|
||||
+
|
||||
+ lightingExecutor.submit(new Runnable() {
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ World.this.c(enumskyblock, position, chunk, neighbors);
|
||||
+ }
|
||||
+ });
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
public boolean a(boolean flag) {
|
||||
return false;
|
||||
}
|
||||
--
|
|
@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
||||
useAsyncLighting = false; //getBoolean( "use-async-lighting", false );
|
||||
log("World async lighting: " + useAsyncLighting);
|
||||
queueLightUpdates = getBoolean("queue-light-updates", false);
|
||||
log("Lighting Queue enabled: " + queueLightUpdates);
|
||||
}
|
||||
+
|
||||
+ public boolean disableEndCredits;
|
||||
|
|
231
Spigot-Server-Patches/Lighting-Queue.patch
Normal file
231
Spigot-Server-Patches/Lighting-Queue.patch
Normal file
|
@ -0,0 +1,231 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Wed, 2 Mar 2016 00:52:31 -0600
|
||||
Subject: [PATCH] Lighting Queue
|
||||
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/SpigotTimings.java b/src/main/java/co/aikar/timings/SpigotTimings.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/co/aikar/timings/SpigotTimings.java
|
||||
+++ b/src/main/java/co/aikar/timings/SpigotTimings.java
|
||||
@@ -0,0 +0,0 @@ public final class SpigotTimings {
|
||||
public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update");
|
||||
public static final Timing serverCommandTimer = Timings.ofSafe("Server Command");
|
||||
public static final Timing worldSaveTimer = Timings.ofSafe("World Save");
|
||||
+ public static final Timing lightingQueueTimer = Timings.ofSafe("Lighting Queue");
|
||||
|
||||
public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity");
|
||||
public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity");
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
|
||||
|
||||
}
|
||||
|
||||
+ public boolean queueLightUpdates;
|
||||
+ private void queueLightUpdates() {
|
||||
+ queueLightUpdates = getBoolean("queue-light-updates", false);
|
||||
+ log("Lighting Queue enabled: " + queueLightUpdates);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
private int w;
|
||||
private ConcurrentLinkedQueue<BlockPosition> x;
|
||||
protected gnu.trove.map.hash.TObjectIntHashMap<Class> entityCount = new gnu.trove.map.hash.TObjectIntHashMap<Class>(); // Spigot
|
||||
+ public int lightUpdates; // Paper - Number of queued light updates for this chunk
|
||||
|
||||
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
|
||||
private int neighbors = 0x1 << 12;
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
private void h(boolean flag) {
|
||||
this.world.methodProfiler.a("recheckGaps");
|
||||
if (this.world.areChunksLoaded(new BlockPosition(this.locX * 16 + 8, 0, this.locZ * 16 + 8), 16)) {
|
||||
+ // Paper start - Queue light update
|
||||
+ if (!world.paperConfig.queueLightUpdates) {
|
||||
+ recheckGaps(flag);
|
||||
+ } else {
|
||||
+ ++lightUpdates;
|
||||
+ world.getServer().getServer().lightingQueue.add(() -> {
|
||||
+ recheckGaps(flag);
|
||||
+ --lightUpdates;
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void recheckGaps(boolean flag) {
|
||||
+ if (true) {
|
||||
+ // Paper end
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
if (this.h[i + j * 16]) {
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
} else {
|
||||
if (flag) {
|
||||
this.initLighting();
|
||||
- } else {
|
||||
+ } else if (!world.paperConfig.queueLightUpdates) { // Paper
|
||||
int j1 = iblockdata.c();
|
||||
int k1 = iblockdata1.c();
|
||||
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
if (j1 != k1 && (j1 < k1 || this.getBrightness(EnumSkyBlock.SKY, blockposition) > 0 || this.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 0)) {
|
||||
this.d(i, k);
|
||||
}
|
||||
+ // Paper start - Queue light update
|
||||
+ } else {
|
||||
+ int j1 = iblockdata.c();
|
||||
+ int k1 = iblockdata1.c();
|
||||
+
|
||||
+ ++lightUpdates;
|
||||
+ world.getServer().getServer().lightingQueue.add(() -> {
|
||||
+ if (j1 > 0) {
|
||||
+ if (j >= i1) {
|
||||
+ this.c(i, j + 1, k);
|
||||
+ }
|
||||
+ } else if (j == i1 - 1) {
|
||||
+ this.c(i, j, k);
|
||||
+ }
|
||||
+
|
||||
+ if (j1 != k1 && (j1 < k1 || this.getBrightness(EnumSkyBlock.SKY, blockposition) > 0 || this.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 0)) {
|
||||
+ this.d(i, k);
|
||||
+ }
|
||||
+
|
||||
+ --lightUpdates;
|
||||
+ });
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
TileEntity tileentity;
|
||||
@@ -0,0 +0,0 @@ public class Chunk {
|
||||
|
||||
private EnumTileEntityState() {}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ public boolean hasLightUpdates() {
|
||||
+ if (world.paperConfig.queueLightUpdates) {
|
||||
+ if (lightUpdates > 0) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ for (int x = locX - 2; x <= locX + 2; ++x) {
|
||||
+ for (int z = locZ - 2; z <= locZ + 2; ++z) {
|
||||
+ if ((x == 0 && z == 0) || (x == locX && z == locZ)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Chunk chunk = world.getChunkIfLoaded(x, z);
|
||||
+ if (chunk != null && chunk.lightUpdates > 0) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
long chunkcoordinates = this.unloadQueue.popFirst();
|
||||
Chunk chunk = this.chunks.get(chunkcoordinates);
|
||||
if (chunk == null) continue;
|
||||
+ if (chunk.hasLightUpdates()) continue; // Paper - Don't unload chunks with pending light updates.
|
||||
|
||||
ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk);
|
||||
server.getPluginManager().callEvent(event);
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer;
|
||||
// CraftBukkit end
|
||||
import co.aikar.timings.SpigotTimings; // Paper
|
||||
|
||||
+// Paper start
|
||||
+import java.util.LinkedList;
|
||||
+import java.util.Queue;
|
||||
+// Paper end
|
||||
+
|
||||
public abstract class MinecraftServer implements Runnable, ICommandListener, IAsyncTaskHandler, IMojangStatistics {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
||||
public final Thread primaryThread;
|
||||
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
||||
public int autosavePeriod;
|
||||
+ public final Queue<Runnable> lightingQueue = new LinkedList<Runnable>(); // Paper - Queued light updates
|
||||
// CraftBukkit end
|
||||
|
||||
public MinecraftServer(OptionSet options, Proxy proxy, DataConverterManager dataconvertermanager, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) {
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
|
||||
|
||||
this.methodProfiler.b();
|
||||
this.methodProfiler.b();
|
||||
+
|
||||
+ // Paper start - Flush light updates
|
||||
+ if (!lightingQueue.isEmpty()) {
|
||||
+ SpigotTimings.lightingQueueTimer.startTiming();
|
||||
+
|
||||
+ int updatesThisTick = 0;
|
||||
+ long cachedTime = System.currentTimeMillis();
|
||||
+ long startTime = cachedTime - (this.h[this.ticks % 100] / 1000000);
|
||||
+ int maxTickTimeCap = MathHelper.floor((TICK_TIME / 1000000) * 0.8);
|
||||
+ int maxTickTime = Math.max(0, (int) (maxTickTimeCap - (cachedTime - startTime)));
|
||||
+ Runnable lightUpdate;
|
||||
+
|
||||
+ while (maxTickTime > 0 && (lightUpdate = lightingQueue.poll()) != null) {
|
||||
+ lightUpdate.run();
|
||||
+ if (++updatesThisTick % 10 == 0) {
|
||||
+ long currentTime = System.currentTimeMillis();
|
||||
+ if (currentTime - cachedTime > maxTickTime) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ cachedTime = currentTime;
|
||||
+ maxTickTime = Math.max(0, (int) (maxTickTimeCap - (currentTime - startTime)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ SpigotTimings.lightingQueueTimer.stopTiming();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
org.spigotmc.WatchdogThread.tick(); // Spigot
|
||||
co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Paper
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
} else {
|
||||
if (iblockdata.c() != iblockdata1.c() || iblockdata.d() != iblockdata1.d()) {
|
||||
this.methodProfiler.a("checkLight");
|
||||
- this.w(blockposition);
|
||||
+ // Paper start - Queue light update
|
||||
+ if (!paperConfig.queueLightUpdates) {
|
||||
+ this.w(blockposition);
|
||||
+ } else {
|
||||
+ ++chunk.lightUpdates;
|
||||
+ getMinecraftServer().lightingQueue.add(() -> {
|
||||
+ this.w(blockposition);
|
||||
+ --chunk.lightUpdates;
|
||||
+ });
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.methodProfiler.b();
|
||||
}
|
||||
|
||||
--
|
|
@ -144,9 +144,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (chunk.hasLightUpdates()) continue; // Paper - Don't unload chunks with pending light updates.
|
||||
|
||||
ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk);
|
||||
server.getPluginManager().callEvent(event);
|
||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -139,19 +139,19 @@ diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/m
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
// Paper start
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
+import java.util.HashMap;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
// Paper end
|
||||
@@ -0,0 +0,0 @@ import java.util.concurrent.Callable;
|
||||
|
||||
// CraftBukkit start
|
||||
import com.google.common.collect.Maps;
|
||||
+import java.util.HashMap; // Paper
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.BlockState;
|
||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||
private org.spigotmc.TickLimiter entityLimiter;
|
||||
private org.spigotmc.TickLimiter tileLimiter;
|
||||
private int tileTickPosition;
|
||||
public ExecutorService lightingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Paper - Lighting Thread").build()); // Paper - Asynchronous lighting updates
|
||||
+ public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<Explosion.CacheKey, Float>(); // Paper - Optimize explosions
|
||||
+ public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
||||
|
||||
public CraftWorld getWorld() {
|
||||
return this.world;
|
||||
|
|
Loading…
Reference in a new issue