weatherfactory / cultistsimulator-visible

Read-only preview builds of Cultist Simulator for the convenience of modders and the curious.
https://weatherfactory.biz/cultist-simulator/
36 stars 6 forks source link

Modding Suggestion: Add `virtual` modifier to properties of base game entity types. #234

Closed Montessquio closed 1 year ago

Montessquio commented 1 year ago

Proposal

Adding the virtual keyword to the public properties of several classes would greatly increase the capabilities of DLL mods.

The classes I believe would benefit from virtual members are:

Although for completeness it may be best to apply this to all the classes defined in SecretHistories.Entities (save for singletons/core components, like FucineRoot?).

Rationale

Recently I've been attempting to create subclasses of game entity types for my library mod. A prototypical (if contrived) example would be a Card subclass (content omitted for brevity):

public class Card : Element
{
    public override bool IsAspect { get; } = false;
}

In this case, an instance of Card could be downcast to an Element and added to Element's entity store without hassle, but all Cards and their own subclasses would be guaranteed to be not-Aspects. This is currently not possible (as of 2022.10.k.6 KALMIA, which is the current version I have on steam).

Besides the type specialization example above, this would also allow DLL modders to easily leverage lots of other functionality when combined with runtime patching. Cards could have low-cost dynamic card text, images, aspect and decay targets. Recipes could procedurally generate their results when they finish, or have more complex branching logic than the current system allows.

All of this is technically already possible in the current DLL modding system, but it's tedious and prone to esoteric crashes since it must be done with runtime patches.

Virtual Methods?

In addition to properties it may be useful to add the virtual modifier to some methods in these classes, too. For example, if a modder were to create a custom Situation, they may want to also customize sphere/dominion/subscriber interactions.

Impact

I don't believe this would cause any problems in the vanilla engine or in existing mods. No existing code in vanilla or existing DLL mods would be overriding these elements, and enabling DLL mods means the user implicitly (soon to be explicitly, with Ghirbi) agrees that they know DLL mods could possibly cause strange and even harmful behavior in their game. Since the responsibility not to break things is already on DLL modders, adding this shouldn't change any expectations.

I went ahead and manually modified SecretHistories.Main.dll to implement this change for select classes as a test (Element, Verb, Situation, and Recipe and at least for those changes nothing seems to be broken and all functionality in an unmodded game is unchanged.

alexiskennedy commented 1 year ago

I'm afraid this is very unlikely to happen, for two reasons.

(1) I can't commit to providing a stable API for modders. I have to be able to change internals without worrying about an unspecified number of mods. The Fucine/JSON layer is guaranteed stable. It wouldn't break anything today, but when I change the implementation of these core classes, no-one will thank me. And it's me who'll get hit with the bug reports from users :-) (roughly half my help queue is mod related issues).

(2) There is a performance effect. I assumed this would be trivial, but I spent a few minutes looking into it and to my surprise it's really not, especially with getters/setters.

alexiskennedy commented 1 year ago

re (i) - Hejlsberg on why C# has virtual in the first place. Sorry if you've read this already or I'm teaching you to suck eggs! but it brought home to me the dangers of inheritance (I came up on Smalltalk and Java) more succinctly than anything else I've read. https://www.artima.com/articles/versioning-virtual-and-override

Montessquio commented 1 year ago

Thanks for taking the time to reply! I'll find another way to do what I was trying to do.