rework for events and other stored functions. Fixes #984

This commit is contained in:
gnembon committed 2021-07-22 22:22:38 -03:00
1 parent 7ebc990ef6
commit 0e9df3701f
9 files changed
+139 -187

No files matched your search

+38 -17
View File
@@ -6,11 +6,14 @@ events occur, but app designers can create their own events and trigger them acr
When loading the app, each function that starts
with `__on_<event>` and has the required arguments, will be bound automatically to a corresponding built-in event. '`undef`'ying
of such function would result in unbinding the app from this event.
of such function would result in unbinding the app from this event. Defining event hanlder via `__on_<event>(... args) -> expr` is
equivalent of defining it via `handle_event('<event>', _(... args) -> expr)`
In case of `player` scoped apps,
all player action events will be directed to the appropriate player hosts. Global events, like `'tick'`, that don't have a specific
player target will be executed multiple times, once for each player, and once in `'global'` scoped apps.
player target will be executed multiple times, once for each player app instance. While each player app instance is independent,
statically defined event handlers will be copied to each players app, but if you want to apply them in more controlled way,
defining event handlers for each player in `__on_start()` function is preferred.
Most built-in events strive to report right before they take an effect in the game. The purpose of that is that this give a choice
for the programmer to handle them right away (as it happens, potentially affect the course of action by changing the
@@ -21,24 +24,43 @@ more control over these events.
Programmers can also define their own events and signal other events, including built-in events, and across all loaded apps.
## Event list
## App scopes and event distribution
Here is a list of events that are handled by default in scarpet. This list includes prefixes for function names, allowing apps
to autoload them, but you can always add any function to any event (using `/script event` command)
if it accepts required number of parameters.
Events triggered in an app can result in zero, one, or multiple executions, depending on the type of the event, and the app scope.
* player targeted events (like `player_breaks_block`) target each app once:
* for global scoped apps - targets a single app instance and provides `player` as the first argument.
* for player scoped apps - targets only a given player instance, providing player argument for API consistency,
since active player in player scoped apps can always be retrived using `player()`.
* global events could be handled by multiple players multiple times (like `explosion`, or `tick`):
* for global scoped apps - triggered once for the single app instance.
* for player scoped apps - triggered N times for each player separately, so they can do something with that information
* custom player targeted events (using `signal_event(<event>, <player>, data)`):
* for global scoped apps - doesn't trigger at all, since there is no way to pass the required player.
To target global apps with player information, use `null` for player target, and add player information to the `data`
* for player scoped apps - triggers once for the specified player and its app instance
* custom general events (using `signal_event(<event>, null, data)`) behave same like built-in global events:
* for global scoped apps - triggers once for the only global instance
* for player scoped apps - triggers N times, once for each player app instance
## Built-in events
Here is the list of events that are handled by default in scarpet. This list includes prefixes for function names, allowing apps
to register them when the app starts, but you can always add any handler function to any event using `/script event` command,
if it accepts the required number of parameters for the event.
## Meta-events
These events are not controlled / triggered by the game per se, but are important for the flow of the apps, however for all
intent and purpose can be treated as regular events. Unlike regular events, they cannot be hooked up to with 'handle_event',
but the apps themselves need to have them defined as distinct function definitions, same they cannot be signalled.
intent and purpose can be treated as regular events. Unlike regular events, they cannot be hooked up to with `handle_event()`,
and the apps themselves need to have them defined as distinct function definitions. They also cannot be triggered via `signal_event()`.
### `__on_start()`
Called once per app in its logical execution run. For `'global'` scope apps its executed right after the app is loaded. For
`'player'` scope apps, it is triggered once per player before the app can be used by that player. Since each player app acts
independently from other player apps, this is probably the best location to include some player specific initializations. Static
code (i.e. code typed directly in the app code that executes immediately, outside of function definitions), will only execute once
per app, regardless of scope, `'__on_start()'` allows to reliably call player specific initializations.
per app, regardless of scope, `'__on_start()'` allows to reliably call player specific initializations. However, most event handlers
defined in the static body of the app will be copied over to each player scoped instance when they join.
### `__on_close()`
@@ -50,8 +72,7 @@ the system is closing down exceptionally.
## Built-in global events
Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance
is responsible independently from handling their events, so a global event may be executed multiple times for each player.
will be triggerd once for each player, so a global event may be executed multiple times for such apps.
### `__on_server_starts()`
Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`.
@@ -73,13 +94,13 @@ Duplicate of `tick`, just automatically located in the end. Use `__on_tick() ->
### `__on_chunk_generated(x, z)`
Called right after a chunk at a given coordinate is full generated. `x` and `z` correspond
to the lowest x and z coords in the chunk. Handling of this event is scheduled as an off-tick task happening after the
chunk is confirmed to be generated and loaded to the game, so
handling of this event is not technically guaranteed, if the game crashes while players are moving for example, and can
be missed on the next start, if the game successfully saves it and fails to execute all remaining tasks. In normal operation
this should not happen, but be warned.
chunk is confirmed to be generated and loaded to the game, due to the off-thread chunk loading in the game. So
handling of this event is not technically guaranteed if the game crashes while players are moving for example, and the game
decides to shut down after chunk is fully loaded and before its handler is processed in between ticks. In normal operation
this should not happen, but let you be warned.
### `__on_chunk_loaded(x, z)`
Called right after a chunk at a given coordinate is loaded. All newly generated chunks are loaded as well.
Called right after a chunk at a given coordinate is loaded. All newly generated chunks are considered loaded as well.
`x` and `z` correspond to the lowest x and z coordinates in the chunk.
### `__on_lightning(block, mode)`
@@ -103,7 +124,7 @@ The parameter `entities` contains the list of entities that have been affected b
Triggered when a carpet mod rule is changed. It includes extension rules, not using default `/carpet` command,
which will then be namespaced as `namespace:rule`.
### entity load event -> check `entity_load_handler()`
### Entity load event -> check in details on `entity_load_handler()`
These will trigger every time an entity of a given type is loaded into the game: spawned, added with a chunks,
spawned from commands, anything really. Check `entity_load_handler()` in the entity section for details.