Created
July 4, 2026 21:02
-
-
Save ShiftSad/a75eeda3d0f55d47672d818700f4ce70 to your computer and use it in GitHub Desktop.
BlockPlacementQueue.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class BlockPlacementQueue { | |
| private static final long MAX_MS_PER_TICK = 10; | |
| private static BlockPlacementQueue instance; | |
| private final Plugin plugin; | |
| private final Queue<BlockPlacementTask> taskQueue = new ConcurrentLinkedQueue<>(); | |
| private BukkitTask processingTask; | |
| private BlockPlacementQueue(Plugin plugin) { | |
| this.plugin = plugin; | |
| } | |
| public static void initialize(Plugin plugin) { | |
| if (instance == null) { | |
| instance = new BlockPlacementQueue(plugin); | |
| } | |
| } | |
| public static BlockPlacementQueue getInstance() { | |
| if (instance == null) { | |
| throw new IllegalStateException("BlockPlacementQueue has not been initialized. Call initialize() first."); | |
| } | |
| return instance; | |
| } | |
| public CompletableFuture<Void> queueBlocks(BlockPlacement[] blocks) { | |
| if (blocks.length == 0) { | |
| return CompletableFuture.completedFuture(null); | |
| } | |
| CompletableFuture<Void> future = new CompletableFuture<>(); | |
| taskQueue.add(new BlockPlacementTask(blocks, 0, future)); | |
| ensureProcessingRunning(); | |
| return future; | |
| } | |
| private void ensureProcessingRunning() { | |
| if (processingTask == null || processingTask.isCancelled()) { | |
| processingTask = Bukkit.getScheduler().runTaskTimer(plugin, this::processTick, 1L, 1L); | |
| } | |
| } | |
| private void processTick() { | |
| if (taskQueue.isEmpty()) { | |
| if (processingTask != null) { | |
| processingTask.cancel(); | |
| processingTask = null; | |
| } | |
| return; | |
| } | |
| long startTime = System.currentTimeMillis(); | |
| while (!taskQueue.isEmpty() && (System.currentTimeMillis() - startTime) < MAX_MS_PER_TICK) { | |
| BlockPlacementTask task = taskQueue.peek(); | |
| if (task == null) break; | |
| while (task.currentIndex < task.blocks.length && (System.currentTimeMillis() - startTime) < MAX_MS_PER_TICK) { | |
| BlockPlacement block = task.blocks[task.currentIndex]; | |
| block.world().getBlockAt(block.x(), block.y(), block.z()).setType(block.material(), false); | |
| task.currentIndex++; | |
| } | |
| if (task.currentIndex >= task.blocks.length) { | |
| taskQueue.poll(); | |
| task.future.complete(null); | |
| } | |
| } | |
| } | |
| public record BlockPlacement(World world, int x, int y, int z, Material material) {} | |
| private static class BlockPlacementTask { | |
| final BlockPlacement[] blocks; | |
| int currentIndex; | |
| final CompletableFuture<Void> future; | |
| BlockPlacementTask(BlockPlacement[] blocks, int startIndex, CompletableFuture<Void> future) { | |
| this.blocks = blocks; | |
| this.currentIndex = startIndex; | |
| this.future = future; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment