2121
2222import java .util .*;
2323import java .util .concurrent .ConcurrentHashMap ;
24- import java .util .concurrent .atomic .AtomicInteger ;
24+ import java .util .concurrent .ExecutorService ;
25+ import java .util .concurrent .Executors ;
2526
2627@ Getter
2728public class BlockChangeManager {
@@ -147,15 +148,13 @@ public void sendBlockChanges(Stage stage, Audience audience, ConcurrentHashMap<B
147148 }
148149
149150 // Send multiple block changes to the players
151+ ExecutorService executorService = Executors .newSingleThreadExecutor ();
150152 for (Player onlinePlayer : audience .getOnlinePlayers ()) {
151153 Location playerLocation = onlinePlayer .getLocation ();
152154 if (playerLocation .getWorld () != stage .getWorld ()) continue ;
153155
154- // The chunk index is used to keep track of the current chunk being sent
155- AtomicInteger chunkIndex = new AtomicInteger (0 );
156156 // Create an array of chunks to send from the block changes map
157- List <BlockifyChunk > chunksToSend = new ArrayList <>(List .of (blockChanges .keySet ().toArray (new BlockifyChunk [0 ])));
158- chunksToSend .sort ((chunk1 , chunk2 ) -> {
157+ Comparator <BlockifyChunk > comparator = (chunk1 , chunk2 ) -> {
159158 // Get distance from chunks to player
160159 int x = playerLocation .getBlockX () / 16 ;
161160 int z = playerLocation .getBlockZ () / 16 ;
@@ -170,14 +169,17 @@ public void sendBlockChanges(Stage stage, Audience audience, ConcurrentHashMap<B
170169
171170 // Compare distances and return accordingly
172171 return Integer .compare (distanceSquared1 , distanceSquared2 );
173- });
172+ };
173+ Queue <BlockifyChunk > chunksToSend = new PriorityQueue <>(comparator );
174+ chunksToSend .addAll (blockChanges .keySet ());
174175
175176 // Create a task to send a chunk to the player every tick
176177 blockChangeTasks .put (onlinePlayer , Bukkit .getScheduler ().runTaskTimer (Blockify .getInstance (), () -> {
177178 // Check if player is online, if not, cancel the task
178179 if (!onlinePlayer .isOnline ()) {
179180 blockChangeTasks .computeIfPresent (onlinePlayer , (key , task ) -> {
180181 task .cancel ();
182+ executorService .shutdown ();
181183 return null ;
182184 });
183185 return ;
@@ -186,24 +188,24 @@ public void sendBlockChanges(Stage stage, Audience audience, ConcurrentHashMap<B
186188 // Loop through chunks per tick
187189 for (int i = 0 ; i < stage .getChunksPerTick (); i ++) {
188190 // If the chunk index is greater than the chunks to send length
189- if (chunkIndex . get () >= chunksToSend .size ()) {
191+ if (chunksToSend .isEmpty ()) {
190192 // Safely cancel the task and remove it from the map
191193 blockChangeTasks .computeIfPresent (onlinePlayer , (key , task ) -> {
192194 task .cancel ();
195+ executorService .shutdown ();
193196 return null ; // Remove the task
194197 });
195198 return ;
196199 }
197200
198201 // Get the chunk from the chunks to send array
199- BlockifyChunk chunk = chunksToSend .get (chunkIndex .get ());
200- chunkIndex .getAndIncrement ();
202+ BlockifyChunk chunk = chunksToSend .poll ();
201203
202204 // Check if the chunk is loaded; if not, return
203205 if (!stage .getWorld ().isChunkLoaded (chunk .x (), chunk .z ())) return ;
204206
205207 // Send the chunk packet to the player
206- Bukkit . getScheduler (). runTaskAsynchronously ( Blockify . getInstance (), () -> sendChunkPacket (stage , onlinePlayer , chunk , blockChanges ));
208+ executorService . submit ( () -> sendChunkPacket (stage , onlinePlayer , chunk , blockChanges ));
207209 }
208210 }, 0L , 1L ));
209211 }
@@ -220,7 +222,7 @@ public void sendBlockChanges(Stage stage, Audience audience, ConcurrentHashMap<B
220222 */
221223 public void sendChunkPacket (Stage stage , Player player , BlockifyChunk chunk , ConcurrentHashMap <BlockifyChunk , ConcurrentHashMap <BlockifyPosition , BlockData >> blockChanges ) {
222224 // Get the user from PacketEvents API
223- User user = PacketEvents .getAPI ().getPlayerManager ().getUser (player );
225+ final User user = PacketEvents .getAPI ().getPlayerManager ().getUser (player );
224226
225227 // Loop through the chunks y positions
226228 for (int chunkY = stage .getMinPosition ().getY () >> 4 ; chunkY <= stage .getMaxPosition ().getY () >> 4 ; chunkY ++) {
@@ -250,7 +252,8 @@ public void sendChunkPacket(Stage stage, Player player, BlockifyChunk chunk, Con
250252 // Send the packet to the player
251253 WrapperPlayServerMultiBlockChange .EncodedBlock [] encodedBlocksArray = encodedBlocks .toArray (new WrapperPlayServerMultiBlockChange .EncodedBlock [0 ]);
252254 WrapperPlayServerMultiBlockChange wrapper = new WrapperPlayServerMultiBlockChange (new Vector3i (chunk .x (), chunkY , chunk .z ()), true , encodedBlocksArray );
253- Bukkit .getScheduler ().runTask (Blockify .getInstance (), () -> user .sendPacket (wrapper ));
255+ if (user == null || !player .isOnline ()) return ;
256+ user .sendPacket (wrapper );
254257 }
255258 }
256259
0 commit comments