Note: Since AsyncBlockEvents is a highly technical library, there is only one page of documentation and it is expected you'll read all of it before implementing this library.
AsyncBlockEvents requires ProtocolLib to function.
AsyncBlockEvents is a library that allows you to use certain block events asynchronously. The following table shows what's supported:
| Bukkit event | AsyncBlockEvents event | Notes |
|---|---|---|
| AsyncBlockEvent | Base class for all but AsyncStructureGrowEvent | |
| BlockPlaceEvent | AsyncBlockPlaceEvent | New state data includes what is normally "post place" ie stair orientation |
| BlockBreakEvent | AsyncBlockBreakEvent | |
| PlayerInteractEvent | AsyncBlockInteractEvent | Only some right clicked blocks, see interact support table |
| PlayerBucketEmptyEvent | AsyncBucketEmptyEvent | |
| PlayerBucketFillEvent | AsyncBucketEmptyEvent | |
| StructureGrowEvent | AsyncStructureGrowEvent | Fired only as a result of player bonemeal usage |
| Block type | Implementation details |
|---|---|
| Lever | Change in byte data |
| Button | Change in byte data, 20/30 tick callback |
| Note block | Change in BlockState |
| Wooden door | Dual change in byte data, retransmission of both blocks |
| Trap door | Change in byte data |
| Fence gate | Change in byte data |
| Repeater | Change in byte data |
| Cauldron | Change in byte data, consumes item, returns item |
| Cake | Change in ID, byte data, fill hunger |
| Jukebox | Change in BlockState |
| Crafting table | Open inventory |
| Enchantment table | Open inventory |
| Ender chest | Open inventory |
| Chest | Open inventory |
| Dispenser | Open inventory |
| Furnace | Open inventory |
| Brewing stand | Open inventory |
| Notably NOT supported | |
| Bed | |
| Anvil | |
| End portal frame |
AsyncBlockEvents works by listening to events in Bukkit, like a normal plugin. However, it has its own event system that reprocesses events. The step by step process:
-Note: AsyncBlockEvents also uses ProtocolLibrary to prevent 'blinking' blocks and oddities with having blocks change multiple times in an instant. Events are simulated to normal success. Any change to an event's future state will mean there will be a perceptible time span where the block is the wrong type.
-Note: A synchronous prefire event (to prevent the block 'blip') is in development.
Basically, the event, despite balled in the event system twice, is cancelled for at least one of those passes. The vast majority of plugins ignore cancelled events, so it appears as if the event only happens once for the majority of plugins. of note, AsyncBlockEvents still (re)calls cancelled events, so that behavior is preserved and it is possible to uncancel an event asynchronously.
The is one issue however, if a plugin listening on priority HIGHEST uncancels some events, it can be after AsyncBlockEvents in the event process order. Any other HIGHEST plugin after, and all MONITOR plugins with then receive the uncancelled event twice. In my experience, uncancelling is really quite rare, and is generally unsuitable for HIGHEST priority, so the vast majority of plugins should still work. However, is must be stressed that AsyncBlockEvents is a massive hack, correct behavior is not guaranteed nor can be.
Flexibility. By decoupling events form the synchronous system, you can freely perform expensive tasks relating to block events with blocking the main thread. Say you wanted a plugin that set the color of wool placed as determined by pulling the "color of the minute" from a website. Synchronously blocking while you GET the color would lead to a pause in the main thread and create lag. What if the website was overloaded and had 5 second return times? Leave just one block in limbo, not the whole server.
-Obviously, you could schedule something to fetch the color and then change the block when it gets a response, but then you would be doing essentially what this plugin does (although AsyncBlockEvents has a much more generic handler). AsyncBlockEvents allows you to asynchronously handle events without even considering the implications of scheduling.
Additionally, by emulating these events, AsyncBlockEvents exposes fields that are normally not available. The base AsyncBlockEvent supports future state, experience, and item drops.
-What to drop xp if a user places a block? Easy. No need to schedule a synchronous task to ensure a plugin didn't cancel the even on you then have to spawn xp orbs yourself, just set the exp to drop to 10. If the event's cancelled later on, the xp won't drop. Simple.
-Want to change what happens if a user breaks a block? Maybe mining is too easy; maybe you want stone to 'break' into cobblestone before it can be mined out. Trying to implement this yourself would be almost impossible. (Worth nothing, so was AsyncBlockEvents) The cobble would still drop, you'd still have to set the block manually yourself, and that would be ignoring the implications of the event being cancelled later on! With AysncBlockEvents, simply set the future state to be a cobblestone block, set the drop to an empty list, and poof, miserable players all around.