geforkt von Mirrors/Paper
0ea3083817
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: 1e843b72 #510: Add NamespacedKey#fromString() to fetch from user input a4d18241 #581: Add methods to modify despawn delay for wandering villagers CraftBukkit Changes: 0cd8f19f #802: Add methods to modify despawn delay for wandering villagers d5c5d998 SPIGOT-6362: ConcurrentModificationException: null --> Server Crash 8c7d69fe SPIGOT-5228: Entities that are removed during chunk unloads are not properly removed from the chunk.
169 Zeilen
8.8 KiB
Diff
169 Zeilen
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 c80af89b4ad0223577ed9513dcab0a784cc964e4..f60800c3bc06a38493e17b00b815f18cb87cc8bf 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,77 @@ 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);
|
|
+ int cx = chunk.getPos().x << 4;
|
|
+ int cz = chunk.getPos().z << 4;
|
|
+ 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(cx + x, y, cz + 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, true), 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 825c3c522b0497499b72cb9f2ff3edb39d8fea08..f3d5ea4672f950bd5c52b718f2e1e0280175ccb9 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
@@ -325,6 +325,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 025a5b24e259df04ee88cb251477c908bc909266..c507e71cef1da50e3709e358def6548cc69546e9 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -97,6 +97,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;
|
|
private final AtomicInteger u;
|
|
@@ -288,11 +294,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.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false));
|
|
this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper
|
|
this.l = supplier;
|