Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v3 #1

Merged
merged 3 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/ci_workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Run tests

on: [push]

jobs:
build_and_run:
name: Build and run tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
lfs: true
- uses: actions/setup-java@v1
with:
java-version: '17'

- name: Build && Run
run: |
deployer_url="https://raw.githubusercontent.com/Insality/defold-deployer/4/deployer.sh"
curl -s ${deployer_url} | bash -s lbd --headless --settings ./test/test.ini

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: insality/defold-event
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@
Thumbs.db
manifest.private.der
manifest.public.der

deployer_version_settings.txt

.deployer_cache
bob.jar
deployer_build_stats.csv
dist
11 changes: 11 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"Lua.diagnostics.globals": [
"lua_script_instance",
"sys",
"init",
"describe",
"before",
"after",
"it"
]
}
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
![](media/logo.png)

[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality)

[![GitHub release (latest by date)](https://img.shields.io/github/v/tag/insality/defold-event?style=for-the-badge&label=Release)](https://github.com/Insality/defold-event/tags)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/insality/defold-event/ci-workflow.yml?branch=master&style=for-the-badge)](https://github.com/Insality/defold-event/actions)
[![codecov](https://img.shields.io/codecov/c/github/Insality/defold-event?style=for-the-badge)](https://codecov.io/gh/Insality/defold-event)

[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality)


# Event
Expand All @@ -26,7 +28,7 @@

Open your `game.project` file and add the following line to the dependencies field under the project section:

**[Event v2](https://github.com/Insality/defold-event/archive/refs/tags/2.zip)**
**[Event v3](https://github.com/Insality/defold-event/archive/refs/tags/2.zip)**

```
https://github.com/Insality/defold-event/archive/refs/tags/2.zip
Expand Down Expand Up @@ -70,6 +72,7 @@ Memory allocation tracking is turned off in release builds, regardless of the `g
### Quick API Reference

```lua
-- Event Module
event.set_logger(logger)
event.create(callback, [callback_context])
event:subscribe(callback, [callback_context])
Expand All @@ -78,10 +81,13 @@ event:is_subscribed(callback, [callback_context])
event:trigger(...)
event:is_empty()
event:clear()

-- Global Events Module
events.subscribe(name, callback, [callback_context])
events.unsubscribe(name, callback, [callback_context])
events.is_subscribed(name, callback, [callback_context])
events.trigger(name, ...)
events.is_empty(name)
events.clear(name)
events.clear_all()
```
Expand Down Expand Up @@ -228,6 +234,8 @@ Trigger the event, causing all subscribed callbacks to be executed.

- **Parameters:** Any number of parameters to be passed to the subscribed callbacks.

- **Return Value:** The return value of the last callback executed.

- **Usage Example:**

```lua
Expand Down Expand Up @@ -351,6 +359,24 @@ Throw a global event with the specified name. All subscribed callbacks will be e
events.trigger("on_game_over", "arg1", "arg2")
```

**events.is_empty**
---
```lua
events.is_empty(name)
```
Check if the specified global event has no subscribed callbacks.

- **Parameters:**
- `name`: The name of the global event to check.

- **Return Value:** `true` if the global event has no subscribed callbacks, `false` otherwise.

- **Usage Example:**

```lua
local is_empty = events.is_empty("on_game_over")
```

**events.clear**
---
```lua
Expand Down Expand Up @@ -425,6 +451,15 @@ If you have any issues, questions or suggestions please [create an issue](https:
- The `event:subscribe` and `event:unsubscribe` now return boolean value of success
</details>

### **V3**
<details>
<summary><b>Changelog</b></summary>

- Event Trigger now returns value of last executed callback
- Add `events.is_empty(name)` function
- Add tests for Event and Global Events modules
</details>


## ❤️ Support project ❤️

Expand Down
26 changes: 26 additions & 0 deletions USE_CASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function final(self)
end
```


### 2. Component-specific Events

Design components with built-in events, enabling customizable behavior for instances of the component. This is particularly useful for UI elements like buttons where you want to bind specific actions to events like clicks.
Expand Down Expand Up @@ -85,3 +86,28 @@ function init(self)
end

```


### 3. Lua annotations

You can use annotations to document your events and make them easier to understand.

```lua
---This event is triggered when the sound button is clicked.
---@class event.on_sound_click: event
---@field trigger fun(_, is_sound_on: boolean): boolean|nil
---@field subscribe fun(_, callback: fun(is_sound_on: boolean): boolean, _): boolean

local event = require("event.event")

---@type event.on_sound_click
local on_sound_click = event.create()

-- This callback params will be checked by Lua linter
on_sound_click:subscribe(function(is_sound_on)
print("Sound is on: ", is_sound_on)
end)

-- Trigger params will be checked by Lua linter
on_sound_click:trigger(true)
```
24 changes: 24 additions & 0 deletions event/annotations.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---@class event
---@field create fun(callback: function|nil, callback_context: any|nil): event
---@field subscribe fun(self: event, callback: function, callback_context: any|nil): boolean
---@field unsubscribe fun(self: event, callback: function, callback_context: any|nil): boolean
---@field is_subscribed fun(self: event, callback: function, callback_context: any|nil): boolean
---@field trigger fun(self: event, a: any, b: any, c: any, d: any, e: any, f: any, g: any, h: any, i: any, j: any): nil
---@field clear fun(self: event): nil
---@field is_empty fun(self: event): boolean

---@class events
---@field subscribe fun(event_name: string, callback: function, callback_context: any|nil): boolean
---@field unsubscribe fun(event_name: string, callback: function, callback_context: any|nil): boolean
---@field is_subscribed fun(event_name: string, callback: function, callback_context: any|nil): boolean
---@field trigger fun(event_name: string, ...: any): any @Result of the last callback
---@field clear fun(name: string): nil
---@field clear_all fun(): nil
---@field is_empty fun(name: string): boolean

---@class event.logger
---@field trace fun(logger: event.logger, message: string, data: any|nil)
---@field debug fun(logger: event.logger, message: string, data: any|nil)
---@field info fun(logger: event.logger, message: string, data: any|nil)
---@field warn fun(logger: event.logger, message: string, data: any|nil)
---@field error fun(logger: event.logger, message: string, data: any|nil)
42 changes: 22 additions & 20 deletions event/event.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ if not IS_DEBUG then
MEMORY_THRESHOLD_WARNING = 0
end


---@class event @Event Module
---@field callbacks table<number, table>
local M = {}

--- Use empty function to save a bit of memory
local EMPTY_FUNCTION = function(_, message, context) end

---@type event.logger
M.logger = {
trace = EMPTY_FUNCTION,
debug = EMPTY_FUNCTION,
Expand All @@ -21,7 +22,7 @@ M.logger = {
}


---@param logger_instance logger
---@param logger_instance event.logger
function M.set_logger(logger_instance)
M.logger = logger_instance
end
Expand All @@ -31,12 +32,13 @@ end
---Create new event instance. If callback is passed, it will be subscribed to the event.
---@param callback function|nil
---@param callback_context any|nil
---@return event
function M.create(callback, callback_context)
local instance = setmetatable({
_mapping = nil, -- Used for memory threshold warning, only in debug mode
callbacks = nil,
}, {
__index = M
__index = M,
})

if callback then
Expand Down Expand Up @@ -123,25 +125,20 @@ function M:is_subscribed(callback, callback_context)
end


---Trigger the event. All subscribed callbacks will be called in the order they were subscribed.
---@param a any
---@param b any
---@param c any
---@param d any
---@param e any
---@param f any
---@param g any
---@param h any
---@param i any
---@param j any
local last_used_memory = 0
function M:trigger(a, b, c, d, e, f, g, h, i, j)

---Trigger the event. All subscribed callbacks will be called in the order they were subscribed.
---@vararg any
---@return any @Result of the last triggered callback
function M:trigger(...)
if not self.callbacks then
return
end

local current_script_context = lua_script_instance.Get()

local result = nil

for index = 1, #self.callbacks do
local callback = self.callbacks[index]

Expand All @@ -153,11 +150,11 @@ function M:trigger(a, b, c, d, e, f, g, h, i, j)
last_used_memory = collectgarbage("count")
end

local ok, errors
local ok, result_or_error
if callback.callback_context then
ok, errors = pcall(callback.callback, callback.callback_context, a, b, c, d, e, f, g, h, i, j)
ok, result_or_error = pcall(callback.callback, callback.callback_context, ...)
else
ok, errors = pcall(callback.callback, a, b, c, d, e, f, g, h, i, j)
ok, result_or_error = pcall(callback.callback, ...)
end

if current_script_context ~= callback.script_context then
Expand All @@ -166,9 +163,12 @@ function M:trigger(a, b, c, d, e, f, g, h, i, j)

if not ok then
local traceback = debug.traceback()
M.logger:error("An error occurred during event processing", { errors = errors, traceback = traceback })
M.logger:error("An error occurred during event processing", { errors = result_or_error, traceback = traceback })
-- Print again cause it's just better to see it in the console
print(traceback)
pprint(result_or_error)
pprint(traceback)
else
result = result_or_error
end

if MEMORY_THRESHOLD_WARNING > 0 then
Expand All @@ -182,6 +182,8 @@ function M:trigger(a, b, c, d, e, f, g, h, i, j)
end
end
end

return result
end


Expand Down
15 changes: 14 additions & 1 deletion event/events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ M.events = {}
---Throws the event
---@param event_name string Event name
---@vararg any @Event params
---@return any @Result of the last triggered callback
function M.trigger(event_name, ...)
local event = M.events[event_name]

Expand All @@ -18,7 +19,7 @@ function M.trigger(event_name, ...)
})

if event then
event:trigger(...)
return event:trigger(...)
end
end

Expand Down Expand Up @@ -87,4 +88,16 @@ function M.is_subscribed(event_name, callback, callback_context)
end


---Check if the event is empty
---@param event_name string Event name
---@return boolean @True if event is empty. If event is not exist, return true
function M.is_empty(event_name)
if not M.events[event_name] then
return true
end

return M.events[event_name]:is_empty()
end


return M
5 changes: 3 additions & 2 deletions game.project
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bootstrap]
main_collection = /example/example.collectionc
main_collection = /test/test.collectionc

[script]
shared_state = 1
Expand All @@ -13,10 +13,11 @@ input_method = HiddenInputField

[project]
title = Defold Event
version = 1
version = 3
publisher = Insality
developer = Maksim Tuprikov, Insality
dependencies#0 = https://github.com/Insality/defold-log/archive/refs/tags/2.zip
dependencies#1 = https://github.com/britzl/deftest/archive/refs/tags/2.8.0.zip

[library]
include_dirs = event
Expand Down
14 changes: 14 additions & 0 deletions settings_deployer
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Path to bob folder. It will find and save new bob.jar files inside
bob_folder=./

# You can point bob version for project in format "filename:sha"
bob_sha="181:fd1ad4c17bfdcd890ea7176f2672c35102384419"

# Select Defold channel. Values: stable, beta, alpha
bob_channel="stable"

# If true, it will check and download latest bob version. It will ignore bob_sha param
use_latest_bob=false

# Select Defold build server
build_server="https://build.defold.com"
Loading
Loading