|
13 | 13 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange; |
14 | 14 | import lombok.Getter; |
15 | 15 | import org.bukkit.Bukkit; |
| 16 | +import org.bukkit.Location; |
16 | 17 | import org.bukkit.block.data.BlockData; |
17 | 18 | import org.bukkit.entity.Player; |
18 | 19 | import org.bukkit.scheduler.BukkitTask; |
@@ -81,28 +82,49 @@ public void sendBlockChanges(Stage stage, Audience audience, ConcurrentHashMap<B |
81 | 82 | // Send multiple block changes to the players |
82 | 83 | for (UUID uuid : audience.getPlayers()) { |
83 | 84 | Player onlinePlayer = Bukkit.getPlayer(uuid); |
| 85 | + if (onlinePlayer == null) continue; |
| 86 | + Location playerLocation = onlinePlayer.getLocation(); |
| 87 | + |
84 | 88 | // The chunk index is used to keep track of the current chunk being sent |
85 | 89 | AtomicInteger chunkIndex = new AtomicInteger(0); |
86 | | - if (onlinePlayer != null) { |
87 | | - // Create an array of chunks to send from the block changes map |
88 | | - BlockifyChunk[] chunksToSend = blockChanges.keySet().toArray(new BlockifyChunk[0]); |
89 | | - // Create a task to send a chunk to the player every tick |
90 | | - blockChangeTasks.put(uuid, Bukkit.getScheduler().runTaskTimer(Blockify.getInstance(), () -> { |
91 | | - // If the chunk index is greater than the length of the chunks to send array, cancel the task |
92 | | - if (chunkIndex.get() >= chunksToSend.length) { |
| 90 | + // Create an array of chunks to send from the block changes map |
| 91 | + List<BlockifyChunk> chunksToSend = new ArrayList<>(List.of(blockChanges.keySet().toArray(new BlockifyChunk[0]))); |
| 92 | + chunksToSend.sort((chunk1, chunk2) -> { |
| 93 | + // Get distance from chunks to player |
| 94 | + int x = playerLocation.getBlockX() / 16; |
| 95 | + int z = playerLocation.getBlockZ() / 16; |
| 96 | + int chunkX1 = chunk1.x(); |
| 97 | + int chunkZ1 = chunk1.z(); |
| 98 | + int chunkX2 = chunk2.x(); |
| 99 | + int chunkZ2 = chunk2.z(); |
| 100 | + |
| 101 | + // Calculate squared distances (more efficient than using square root) |
| 102 | + int distanceSquared1 = (chunkX1 - x) * (chunkX1 - x) + (chunkZ1 - z) * (chunkZ1 - z); |
| 103 | + int distanceSquared2 = (chunkX2 - x) * (chunkX2 - x) + (chunkZ2 - z) * (chunkZ2 - z); |
| 104 | + |
| 105 | + // Compare distances and return accordingly |
| 106 | + return Integer.compare(distanceSquared1, distanceSquared2); |
| 107 | + }); |
| 108 | + |
| 109 | + // Create a task to send a chunk to the player every tick |
| 110 | + blockChangeTasks.put(uuid, Bukkit.getScheduler().runTaskTimer(Blockify.getInstance(), () -> { |
| 111 | + // Loop through the chunks per tick |
| 112 | + for (int i = 0; i < stage.getChunksPerTick(); i++) { |
| 113 | + // Check if the chunk index is greater than the chunks to send length |
| 114 | + if (chunkIndex.get() >= chunksToSend.size()) { |
93 | 115 | blockChangeTasks.get(uuid).cancel(); |
94 | 116 | blockChangeTasks.remove(uuid); |
95 | 117 | return; |
96 | 118 | } |
97 | 119 | // Get the chunk from the chunks to send array |
98 | | - BlockifyChunk chunk = chunksToSend[chunkIndex.get()]; |
| 120 | + BlockifyChunk chunk = chunksToSend.get(chunkIndex.get()); |
99 | 121 | chunkIndex.getAndIncrement(); |
100 | 122 | // Check if the chunk is loaded, if not, return |
101 | 123 | if (!stage.getWorld().isChunkLoaded(chunk.x(), chunk.z())) return; |
102 | 124 | // Send the chunk packet to the player |
103 | 125 | Bukkit.getScheduler().runTaskAsynchronously(Blockify.getInstance(), () -> sendChunkPacket(stage, onlinePlayer, chunk, blockChanges)); |
104 | | - }, 0L, 1L)); |
105 | | - } |
| 126 | + } |
| 127 | + }, 0L, 1L)); |
106 | 128 | } |
107 | 129 | } |
108 | 130 |
|
|
0 commit comments