
# Event Bus

These functions are for signalling and listening for event triggers. Basically it's a way of your code being able to tell the whole game what just happened, such as if a player did some action, or some other event happened. Note that this is more for games than for general modding, but is a helpful API regardless.

This is a global set of functions that do what they say on the tin mostly. The exception is `CONDITIONAL` which is a bit more involved (see below). Signals and listeners not only allow you to sometimes save on constant checks by using one-off events instead, but you can also allow extending, avoid some dependencies, and generally make things more reactive and less constant polling. Instead of checking constantly whether the player has just died and then come back to life, we use `core.register_on_respawnplayer`. This is no different except it is generalised and you can signal whatever thing you want.

## Example Use
```lua
LISTEN("on_player_damage", function(player, damage, source)
    core.chat_send_all(
        "Player "..player:get_player_name()..
        " was hit for "..damage.." HP"
    )
end)

LISTEN("can_player_take_damage", function(player, damage, source)
    if player:get_meta():get_string("invulnerable") == "true" then
        return false
    else
        return true
    end
end)

if CONDITIONAL("can_player_take_damage", player, damage, source) then
    SIGNAL("on_player_damage", player, damage, source)
end
```

## SIGNAL
```lua
SIGNAL(tag, ...)
```

## LISTEN
If any function calls `SIGNAL(tag)`, it will call the function you have passed to `LISTEN(tag, callback)`
```lua
LISTEN(tag, function() end)
```

## CONDITIONAL
If any signal returns `==false`, it will return `false` immediately. Otherwise, if one or more callback returns `true` it returns true, and if nothing gets returned then it returns `nil`. 

```lua
local mybool = CONDITIONAL(tag, ...)
```

Example:
```lua
LISTEN("can_be_damaged", function(self)
    if self._invulnerable then
        return false
    else
        return true
    end
end)

[...]

local is_damaged = CONDITIONAL("can_be_damaged", self)
```
This is good for conditions that need to be able to be extended, such as when an object should enter a "sleep" state, or to test if it is allowed to take some action.

## Things you should be aware of
Signals are not good for *all* things; generally you should use them only for things that have an outward effect. That means when you `SIGNAL`, that block of code that contains the `SIGNAL` call doesn't care what happens next. Only the `LISTEN`-er cares. This means signals are one-way. You tell the entire world something happened, and whether someone picks that up and does something is entirely up to circumstance, ***whether or not you currently know there is a listener out there who will pick it up!*** This is not like normal procedural code, where you cause the effects *within* the very block of code you're writing. That said, you *could* create an entire game using nothing but signals. It would just be confusing.

For the sake of consistency it's often best to observe the following rules with signals; signals where you don't care about the effect and you are only broadcasting the event happening at all, should be named `on_`[something happen]`ed`. The thing has already happen**ed** and it's **on** that thing happen**ed**. For `CONDITIONAL`s, it would be `can_`[something happen], or `is_`[something true].

Examples of when it makes sense to use them are:
- `on_gamestate_changed` --> when you change from "waiting for players" to "playing the game", maybe other parts of the game want to know this
- `on_mapgen_finished` --> if you have a set area you're generating, often you want to know when it's done, and callbacks can be just thrown away and use signals instead
- `is_player_ready` --> could be that you are waiting for players to be ready, and you don't care how "ready" is determined
- `on_player_ready` --> same thing, but this time it's when it actually triggers actively; some code has determined the player to be ready and has told you so

In reality, what it will be useful for is up to your circumstances. If you know you need it, use it. Don't try to shove it into some mod or game that doesn't benefit from it.

Another thing to note is that, used in this way you are essentially polluting the global scope of signal names. If you feel the need to do something like `on_mymod_thing_happened` instead of `on_thing_happened` then you should seriously question whether you should be using signals for it. Signals are more or less the domain of the game they are within. If you make a mod that expects `on_player_damaged` to give you a player, damage number and an object, but then some other mod expects it to give an entity instead of an object, you're gonna have a bad time. That's why signals are intended to be very non-specific to the event, or be game-domain where it doesn't matter. Don't make mods that use signals in silly ways in other words. Now that you can extract single signals out and add them to your object piecemeal, you *can* make them specific to your code instead of global, but be aware that this almost invariably *increases* interdependence rather than reducing it. It basically removes all the benefits an event bus has.

## Removing Signals
You may de-list a callback by having it return `any, true`. Both `SIGNAL` and `CONDITIONAL` will check for this second return value and then remove the callback from the list so it is ignored from then on. However, you absolutely should never rely on this since it means you're probably registering many listeners that potentially might not get removed. For example, never have an entity use `LISTEN`. Instead, use `LISTEN` after defining the entity and have it run on all your entities. Same with players; if you have players hook into callbacks on join, it might lead to a runaway situation in which there are thousands of useless callbacks.

## Performance
This is fast enough that in non-abuse situations, you never really need to consider it. Particularly with LuaJIT. That said, it is not highly optimised either, so avoid using it for thousands of calls. If you need such a use case, you should roll your own custom solution, and you probably have an X Y problem anyway if you need to signal tens of thousands of times per server step.

## Getting a standalone copy of event bus
It is only recommended for internal use where you know a feature / mod will not need to be accessed externally, but it is possible to get your own event bus. This is not really necessary since Lua tables are super fast, but you can do it if you really super duper want to.

```lua
local signal_copy = SIGNALS.new()
signal_copy.SIGNAL("on_something_happen", 38.2, 4)
```

See the documentation in the code itself more more advanced information, there are plenty of comments explaining how things are used. Many features have extensive hints so just mentioning `SIGNAL` is enough to get example uses.