mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-02 21:17:00 +01:00
b31089a929
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: d264e972 #591: Add option for a consumer before spawning an item 1c537fce #590: Add spawn and transform reasons for piglin zombification. CraftBukkit Changes: ee5006d1 #810: Add option for a consumer before spawning an item f6a39d3c #809: Add spawn and transform reasons for piglin zombification. 0c24068a Organise imports Spigot Changes: bff52619 Organise imports
168 lines
8.8 KiB
Diff
168 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 2079bb001ea2678f6181f913262a9b7731fae778..7367781d360a8eb3a1b22de5c0b57dd98e6763d6 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 b508e8318d0608d9bae34d9551d1cb654e53d24e..d1ec4de8b64934bb5e9346398bc471dab8457b83 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -98,6 +98,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;
|
|
@@ -289,11 +295,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;
|