f0409edcd7
Upon further knowledge of the system, it is known that region files are closing properly, as well as this didn't help native memory use anyways. This patch also caused issues compiling on a newer JDK being able to release the jar to java 8 users.
166 lines
8.8 KiB
Diff
166 lines
8.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Thu, 7 May 2020 19:17:36 -0400
|
|
Subject: [PATCH] Fix Light Command
|
|
|
|
This lets you run /paper fixlight <chunkRadius> (max 5) to automatically
|
|
fix all light data in the chunks.
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
index 182b440ba4802d199b8e44f7779b3401ace495d5..10b72083322b7f8e3e14525b3e834f5374ec369d 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
@@ -20,6 +20,7 @@ import org.bukkit.command.Command;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.craftbukkit.CraftServer;
|
|
import org.bukkit.craftbukkit.CraftWorld;
|
|
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
|
import org.bukkit.entity.Player;
|
|
|
|
import java.io.File;
|
|
@@ -36,14 +37,14 @@ public class PaperCommand extends Command {
|
|
public PaperCommand(String name) {
|
|
super(name);
|
|
this.description = "Paper related commands";
|
|
- this.usageMessage = "/paper [heap | entity | reload | version | debug | dumpwaiting | chunkinfo | syncloadinfo]";
|
|
+ this.usageMessage = "/paper [heap | entity | reload | version | debug | dumpwaiting | chunkinfo | syncloadinfo | fixlight]";
|
|
this.setPermission("bukkit.command.paper");
|
|
}
|
|
|
|
@Override
|
|
public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
|
|
if (args.length <= 1)
|
|
- return getListMatchingLast(args, "heap", "entity", "reload", "version", "debug", "dumpwaiting", "chunkinfo", "syncloadinfo");
|
|
+ return getListMatchingLast(args, "heap", "entity", "reload", "version", "debug", "dumpwaiting", "chunkinfo", "syncloadinfo", "fixlight");
|
|
|
|
switch (args[0].toLowerCase(Locale.ENGLISH))
|
|
{
|
|
@@ -144,6 +145,9 @@ public class PaperCommand extends Command {
|
|
case "syncloadinfo":
|
|
this.doSyncLoadInfo(sender, args);
|
|
break;
|
|
+ case "fixlight":
|
|
+ this.doFixLight(sender, args);
|
|
+ break;
|
|
case "ver":
|
|
case "version":
|
|
Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version");
|
|
@@ -160,6 +164,75 @@ public class PaperCommand extends Command {
|
|
return true;
|
|
}
|
|
|
|
+ private void doFixLight(CommandSender sender, String[] args) {
|
|
+ if (!(sender instanceof Player)) {
|
|
+ sender.sendMessage("Only players can use this command");
|
|
+ return;
|
|
+ }
|
|
+ int radius = 2;
|
|
+ if (args.length > 1) {
|
|
+ try {
|
|
+ radius = Math.min(5, Integer.parseInt(args[1]));
|
|
+ } catch (Exception e) {
|
|
+ sender.sendMessage("Not a number");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ CraftPlayer player = (CraftPlayer) sender;
|
|
+ EntityPlayer handle = player.getHandle();
|
|
+ net.minecraft.server.WorldServer world = (WorldServer) handle.world;
|
|
+ LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine();
|
|
+
|
|
+ BlockPosition center = MCUtil.toBlockPosition(player.getLocation());
|
|
+ Deque<ChunkCoordIntPair> queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius));
|
|
+ updateLight(sender, world, lightengine, queue);
|
|
+ }
|
|
+
|
|
+ private void updateLight(CommandSender sender, WorldServer world, LightEngineThreaded lightengine, Deque<ChunkCoordIntPair> queue) {
|
|
+ ChunkCoordIntPair coord = queue.poll();
|
|
+ if (coord == null) {
|
|
+ sender.sendMessage("All Chunks Light updated");
|
|
+ return;
|
|
+ }
|
|
+ world.getChunkProvider().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> {
|
|
+ if (ex != null) {
|
|
+ sender.sendMessage("Error loading chunk " + coord);
|
|
+ updateLight(sender, world, lightengine, queue);
|
|
+ return;
|
|
+ }
|
|
+ Chunk chunk = (Chunk) either.left().orElse(null);
|
|
+ if (chunk == null) {
|
|
+ updateLight(sender, world, lightengine, queue);
|
|
+ return;
|
|
+ }
|
|
+ lightengine.a(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue
|
|
+ sender.sendMessage("Updating Light " + coord);
|
|
+ for (int y = 0; y < world.getHeight(); y++) {
|
|
+ for (int x = 0; x < 16; x++) {
|
|
+ for (int z = 0; z < 16; z++) {
|
|
+ BlockPosition pos = new BlockPosition(chunk.getPos().getBlockX() + x, y, chunk.getPos().getBlockZ() + z);
|
|
+ lightengine.a(pos);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ lightengine.queueUpdate();
|
|
+ PlayerChunk visibleChunk = world.getChunkProvider().playerChunkMap.getVisibleChunk(chunk.coordinateKey);
|
|
+ if (visibleChunk != null) {
|
|
+ world.getChunkProvider().playerChunkMap.addLightTask(visibleChunk, () -> {
|
|
+ MinecraftServer.getServer().processQueue.add(() -> {
|
|
+ visibleChunk.sendPacketToTrackedPlayers(new PacketPlayOutLightUpdate(chunk.getPos(), lightengine), false);
|
|
+ updateLight(sender, world, lightengine, queue);
|
|
+ });
|
|
+ });
|
|
+ } else {
|
|
+ updateLight(sender, world, lightengine, queue);
|
|
+ }
|
|
+ lightengine.a(world.paperConfig.lightQueueSize);
|
|
+ }, MinecraftServer.getServer());
|
|
+ }
|
|
+
|
|
private void doSyncLoadInfo(CommandSender sender, String[] args) {
|
|
if (!SyncLoadFinder.ENABLED) {
|
|
sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set.");
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
index 03fb688fe4bdc19b4bc36b1f1d5b40c61e7bef9b..aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
@@ -327,6 +327,7 @@ public class PlayerChunk {
|
|
|
|
}
|
|
|
|
+ public void sendPacketToTrackedPlayers(Packet<?> packet, boolean flag) { a(packet, flag); } // Paper - OBFHELPER
|
|
private void a(Packet<?> packet, boolean flag) {
|
|
// Paper start - per player view distance
|
|
// there can be potential desync with player's last mapped section and the view distance map, so use the
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
index f832e7cdfc6741a932787f02754f145202ff7887..f361939b9ae451bdccf7922e9cca09344c6152b5 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -95,6 +95,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
private final ChunkTaskQueueSorter p;
|
|
private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> mailboxWorldGen;
|
|
final Mailbox<ChunkTaskQueueSorter.a<Runnable>> mailboxMain; // Paper - private -> package private
|
|
+ // Paper start
|
|
+ final Mailbox<ChunkTaskQueueSorter.a<Runnable>> mailboxLight;
|
|
+ public void addLightTask(PlayerChunk playerchunk, Runnable run) {
|
|
+ this.mailboxLight.a(ChunkTaskQueueSorter.a(playerchunk, run));
|
|
+ }
|
|
+ // Paper end
|
|
public final WorldLoadListener worldLoadListener;
|
|
public final PlayerChunkMap.a chunkDistanceManager; public final PlayerChunkMap.a getChunkMapDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER
|
|
private final AtomicInteger u;
|
|
@@ -282,11 +288,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
Mailbox<Runnable> mailbox = Mailbox.a("main", iasynctaskhandler::a);
|
|
|
|
this.worldLoadListener = worldloadlistener;
|
|
- ThreadedMailbox<Runnable> threadedmailbox1 = ThreadedMailbox.a(executor, "light");
|
|
+ ThreadedMailbox<Runnable> lightthreaded; ThreadedMailbox<Runnable> threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper
|
|
|
|
this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE);
|
|
this.mailboxWorldGen = this.p.a(threadedmailbox, false);
|
|
this.mailboxMain = this.p.a(mailbox, false);
|
|
+ this.mailboxLight = this.p.a(lightthreaded, false);// Paper
|
|
this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getWorldProvider().f(), threadedmailbox1, this.p.a(threadedmailbox1, false));
|
|
this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper
|
|
this.l = supplier;
|