MonkeyLoader.GamePacks.Resonite icon indicating copy to clipboard operation
MonkeyLoader.GamePacks.Resonite copied to clipboard

Create functional equivalent to SyncMethods for Mods

Open Banane9 opened this issue 1 year ago • 0 comments

Problem

When generating UI in a Session from a Mod, there's the problem of making it usable for others as well. For simple things, like buttons on components in the inspector for example, this can be dealt with by implementing the functionality through vanilla components, or tranfering the trigger back to the generating user by toggling a boolean. See the implementation for LocalActionButtons for an example of this approach. However, for more complex scenarios this is not enough. Especially when mixing mod-generated UI with vanilla UI using SyncMethods to generate it. This becomes evident in Component Selector Additions for example when someone else uses the mod-generated Back button. Because it's not in the vanilla position, it doesn't get removed and gets regenerated in the scrolling list. This is the case even when the other user also has the necessary mod.

Options

A. Instead of going through the vanilla SyncMethod, the trigger could be transferred to the spawning user as well. This may add delays because of the transfer times. Some things like inspector lists are already always generated by the host though, so there is precedence.

B. At least for other users of the mod, the effect could be executed locally as well, as long as the necessary data is available (e.g. references and settings). The trigger also needs to be detected and mapped to calling the right function.

Implementation Idea

The immediate option for the data storage would be a DynamicVariableSpace with all the necessary data as its associated variables. In this regard, another independently-useful feature to add would be the option to synchronize a DynamicVariableSpace's variables with an object in the code. For this, any included properties / fields would have to be recreated as dynamic variables and any changes synchronized.

However, the more immediate problem would be to capturing the context that such a construct is supposed to be monitored for "calls". As DynamicVariableSpaces override the OnStart method, this could be used to bind against an appropriately named on when it appears, regardless of it being newly spawned or loaded from a saved world or item. The UpdateName method called by it could also be suitable, though it's called whenever the name is changed. This could also open the possibility of those links / calls being created "by hand". Passing a "call" may proof more complicated, as there's no event on the variable space for changed variables. Variables themselves don't have such an event either, and patching generics with Harmony is brittle at best. It may be possible to use the storing fields' Changed events for this directly, however.

Conclusion

Let me know what you think about this proposal. Please voice any concerns or other ideas for a possible implementation. Also feel free to suggest any alternatives.

Banane9 avatar Jan 17 '25 15:01 Banane9