SignalSentry

An asset by kidManuel
The page banner background of a mountain and forest
SignalSentry hero image

Quick Information

0 ratings
SignalSentry icon image
kidManuel
SignalSentry

A micro util script for Godot Engine: Group a bunch of Signals get a notification when all of them are done!

Supported Engine Version
4.0
Version String
1.0
License Version
BSD-3-Clause
Support Level
community
Modified Date
6 months ago
Git URL
Issue URL

README Signal Sentry

Signal Sentry

A micro util script for Godot Engine: Group a bunch of Signals, get a notification when all of them are done!

This is of course inspired by Javascript's Promise.all(), and similar asynchronous grouping APIs.

Installation

Drop signal_sentry.gd anywhere on your project. That's it.

Usage

Basic example

func _ready() -> void:
    var timershort := get_tree().create_timer(2.0)
    var timerlong := get_tree().create_timer(5.0)

    SignalSentry.wait_for( \
        [timershort.timeout, timerlong.timeout] \
        func(_status: SignalSentry.Result) -> void: print('all timers done'), \
    )

SignalSentry.wait_for() is a static function that takes an Array of Signals to watch for, and a callback func to call when all Signals are done.

The callback is func is called with an enum Result for the group stautus : SUCCESS | CANCEL | TIMEOUT

Usage Pattern

Consider a turn based game, the way I would go about it would be something like:

func execute_enemies_turns() -> void:
    var enemy_turns: Array[Signal] = []

    for enemy in enemies:
        enemy.attack()
        enemy_turns.push_back(enemy.turn_finished)

    SignalSentry.wait_for(enemy_turns, new_player_turn)

func new_player_turn(enemy_turn_result: SignalSentry.Result) -> void:
    if enemy_turn_result == SignalSentry.Result.SUCCESS:
        player_options.display()

Timeouts and safety

It is important to use SignalSentry carefuly: If any of your dependency Signals fails to emit, the SignalSentry instance will NOT free automatically. This will cause an orphan instance and a memory leak (not a big one, but still). If you are going to be risky with your Signals, I recommend setting a safety timeout: float as the third argument of the watch_for() static function.

func risky_biz() -> void:
    var requests: Array[Signal] = []

    for client in http_client_list:
        client.make_request()
        requests.push_back(client.request_completed)

    SignalSentry.watch_for(requests, on_requests_finished, 10.0)

func on_requests_finished(result: SignalSentry.Result) -> void:
    match result:
        SignalSentry.Result.SUCCESS:
            start()
        SignalSentry.Result.TIMEOUT:
            retry()

Referencing

watch_for() returns a referene to the SignalSentry instance created. You can store this reference in a var and pass it around. You can then hook to the instance's done Signal from other Nodes.

    var my_sentry := SignalSentry.watch_for(bunch_o_signals, on_signals_done, 60.0)

    sibling_node_ref.pass_me_the_sentry(my_sentry)
    func pass_me_the_sentry(sentry: SignalSentry) -> void:
        sentry.done.connect(on_sentry_done)

    func on_sentry_done(result: SignalSentry.Result) -> void:
        [...]

Cancelling out

If for whatever reason you want to invalidate the Sentry instance, you can call the cancel() func on that instance. This will emit the done signal with the CANCELLED enum entry (index 1)

A micro util script for Godot Engine: Group a bunch of Signals get a notification when all of them are done!

Reviews

0 ratings

Your Rating

Headline must be at least 3 characters but not more than 50
Review must be at least 5 characters but not more than 500
Please sign in to add a review

Quick Information

0 ratings
SignalSentry icon image
kidManuel
SignalSentry

A micro util script for Godot Engine: Group a bunch of Signals get a notification when all of them are done!

Supported Engine Version
4.0
Version String
1.0
License Version
BSD-3-Clause
Support Level
community
Modified Date
6 months ago
Git URL
Issue URL

Open Source

Released under the AGPLv3 license

Plug and Play

Browse assets directly from Godot

Community Driven

Created by developers for developers