rbxts-flamework / core

Flamework is an extensible game framework. It requires typescript and offers many useful features.
MIT License
101 stars 8 forks source link

Pass additional parameters to subcomponents #65

Closed Abbaok closed 1 year ago

Abbaok commented 1 year ago

Currently, the Scripting API can only instantiate components without passing parameters. Sometimes sub-components need additional information to execute correctly.

This leads to the workaround that a method within the sub-component is abused as a constructor and it sets the desired initial state just after instantiation. As long as this initial status is not yet set by this method, all lifecycle events of the component must terminate, since the component was not yet correctly initialized at that time. This workaround makes the onStart method of Flamework obsolete and replaces it with its own onStart method.

Example: Parent component: const components = Dependency<Components>(); const item = components.addComponent<Item>(itemClone); item.construct(this.attributes.Owner, spawnPosition);

In the item component

interface ItemAttributes {
    IsConstructed: boolean;
    Owner: number;
    SpawnPosition: Vector3;
}
interface ItemInstance extends Part {}

@Component({
    tag: "Item",
})
export class Item extends BaseComponent<ItemAttributes, ItemInstance> implements OnTick {
    constructor() {
        super();
    }

    construct(owner: number, spawnPosition: Vector3) {
        this.attributes.Owner = owner;
        this.attributes.SpawnPosition = spawnPosition;
        this.attributes.IsConstructed = true;

        this.onStart();
    }

    onStart() { // Is not a lifecycle method (implementation of the interface is missing!)
        // Add my cool Item behavior
        this.instance.Position = this.attributes.SpawnPosition;
        this.instance.Anchored = false;
    }

    onTick(dt: number) {
        if (!this.attributes.IsConstructed) {
            // Don't start tick-based Item behavior while it is not full constructed
            return;
        }
        // My cool Item behavior
    }
}

In some cases it would be sufficient to be able to access the attributes of the parent component with little effort. This would be the case for the Owner attribute. For the SpawnPosition attribute, however, this solution would not be sufficient.

Fireboltofdeath commented 1 year ago

I'd recommend passing the attributes from your parent component to the child component,. You can also add components from the parent component, if you don't want the components running prior to the attributes getting added or updated.

It isn't very feasible to allow users to pass values through to the constructor as Flamework needs to be able to create components automatically as well as inject dependencies.

I'm going to close this, feel free to reopen it if you have a reason why that solution is unoptimal.