Earewien / godot-traits

Traits made easy in Godot 4
MIT License
84 stars 5 forks source link

Automatically create trait dependencies (trait dependency injection) #5

Closed Earewien closed 9 months ago

Earewien commented 9 months ago

This PR brings automatic trait dependencies injection with cyclic dependency detection

Using this Healthable trait : it depends on a Killable and a Loggable. When assigning this trait to an object, if it is already killable or loggable, those traits are automatically injected to the Healthable instance. Else, they are automatically instantiated (recursively!) and saved into the receiver for futur usage.

This simplify trait usage, and guarantee that an object owns one and only one instance of each trait.

# @trait
class_name Healthable
extends RefCounted

var max_health:int = 100
var health:int = max_health:
    set(value):
        var old_health:int = health
        health = clamp(value, 0, max_health)
        if old_health != health:
            _loggable.log("HP : %s/%s" % [health, max_health])
            if value <= 0:
                _killable.kill()

# Reference to the Loggable, needed for this trait to print messages
var _loggable:Loggable
# Reference to the Killable, needed for this trait to handle death !
var _killable:Killable

# Automatically requires that the trait receiver is also a Killable and a Loggable object
# If the receiver does not have those traits yet, they will be automatically instantiated and
# registered into the receiver for future usages.
func _init(killable:Killable, loggable:Loggable) -> void:
    _killable = killable
    _loggable = loggable

Cyclic dependency error/detection:

image