Explanation
There are four parts to this event system:
- manager → manages the lifecycle of the original event
- listener → detects and copies events
- handler → resolves copied events and cleans them up
- event → is what’s being asynchronously sent out and handled in other datapacks
Events are defined by a EVENT$name scoreboard and is managed using these variables EVENT$name.timer, EVENT$name.handled, and EVENT$name.copy (for local copy).
There are three important loops:
- datapack manager’s main loop → runs the command and event managers every 1s
- event listener loop → detects and copies events for processing every 7t
- event handler loop → resolves copied events and cleans them up every 1s
An event’s lifecycle is as follows:
<aside>
🔂
Event Lifecycle
- The send function is called, setting the
EVENT$name to BOOL$true and EVENT$name.timer to 0, any additional data required can be collected in the send function. For example, the sending entity can be tagged with DM_event_name.
- The event listener loop detects it and initializes
EVENT$name.handled to BOOL$false once
- A copy is made of the
EVENT$name under MyDatapack, or EVENT$name.copy under DatapackManager, this copy is what the handler will resolve
- The event manager will increment
EVENT$name.timer by 1 and the original event is cleaned up when EVENT$name.timer is 2
- Execute the event, the event will then be handled and
EVENT$name.handled is set to BOOL$true
- The event is cleaned up and
EVENT$name.handled is reset
</aside>
A few things should be noted:
- Copying events allows for async handling, which also frees up the original event, letting it be cleaned up and sent again with minimal delay. Each datapack now holds their own version of the event (and its data) which will all be managed independently and individually processed by each datapack. Processing can take longer if needed without affecting any of the other events or datapacks.
- Events can never trigger again if it isn’t handled, an example is player 1 handling their event while player 2 doesn’t, when the event is triggered a second time, player 1 will receive the event again while player 2 will remain unhandled. This limitation prevents accidental repeated triggers (if two things happen at once that both invoke the same event, providing a natural cooldown period of up to 2s) and overriding mid-execution (if handling an event takes time and should not be interrupted by itself).
Pattern