Jump to content

Are there any Frameworks that are extensible by it nature?


Recommended Posts

Hello I wanted to ask about all techniques used by extensible frameworks since I'm currently trying to implement some mod that would be easy to extend by mods that I would create in future, means it would not be a hard dependency, also add a possibility to inference with every aspect of my mod. What I mean by that just take a look for handlers that I created for mod

; Handlers
; Registering as cow handlers
String beforeRegisterAsCowHandler = "beforeRegisterAsCow"
String afterRegisterAsCowHandler = "afterRegisterAsCow"

; Changing morphs on breasts handlers
String beforeBreastResizeHandler = "beforeBreastResize"
String getMaxMorphValueHandler = "getMaxMorphValue"
String getMinMorphValueHandler = "getMinMorphValue"
String afterBreastResizehandler = "afterBreastResize"
String getMorphLevelFromMilkLevelHandler = "getMorphLevelFromMilkLevel"

; Calculate milk production handlers
String beforeCalculateIncreaseInMilkAmountHandler = "beforeCalculateIncreaseInMilkAmount"
String maxAmountOfMilkCalcHandler = "maxAmountOfMilkCalc"
String productionRateCalcHandler = "productionRateCalc"
String initialTempProductionRateCalcHandler = "initialTempProductionRateCalc"
String totalAmountOfbeingHungryOrThirstyHandler "totalAmountOfbeingHungryOrThirsty"
String tempProductionRateCalcHandler = "tempProductionRateCalc"
String increaseInTempProductionRateCalcHandler = "increaseInTempProductionRateCalcH"
String producedMilkCalcHandler = "producedMilkCalc"
String idealMilkAmountCalcHandler = "idealMilkAmountCalc"
String overLimitMilkCalcHandler = "overLimitMilkCalc"
String totalMilkAmountCalcHandler = "totalMilkAmountCalc"
String tempMilkProductionRateCalcHandler = "tempMilkProductionRateCalc"
String afterCalculateIncreaseInMilkAmountHandler = "afterCalculateIncreaseInMilkAmount"

 

as you see each mod can register in some required mod to manage extensible framework a handler for those "events" I mean in reality it would be a function named like handler with Func suffix, which got a prevValue (a returned value from previous handlers) and standard set of parameters which can be extended by custom parameters existing on client form (yeah I know here might be a problem but since for now at least it compile, but as checking if it's really working I will wait until I have a running instance of skyrim se). So my question is how other frameworks resolved need for being extensible other than creating custom dll?

Link to comment

Typically what you see in framework type mods is that they provide a script that has global functions in it. These global functions can be used without having a reference to an instance of that script i.e. you can call <scriptname>.<functionname>() instead of having to get a reference to the Quest (or other object) form and cast it to a script type. These global functions do the Quest casting if needed, allowing for easier use of a framework's features. Generally I would avoid overusing this. You wouldn't want to expose all your Quest script functions through a system like this, or any high-traffic functions for that matter. Every call will again retrieve the form reference (if its needed for what the function does). It would result in some rather bloated code.

 

Another thing is mod events. This is one of the only truly optional interfaces that I can think of that really makes a mod dependency optional. If a mod event is sent but there's no one to receive it, it is simply discarded. With global functions you still have a hard depdency. Another optional interface is those provided by StorageUtil, but there is no built in messaging system in that.

 

What I personally do is a combination of mod events and what I call a linker "library". The linker library is a script with global functions, but instead of working like a proxy for Quest functions, it has functions that return references to the Quest objects. This linker library does not create an optional dependency (as it will fail without the linker), but it does allow me to be both lazy and efficient at the same time:

MyModMain main = MyModLinker.GetMain()

If (main)
    main.DoThings()
    main.DoMoreThings()
    main.DoEvenMoreThings()
    main.DoAllTheThings()
EndIf

 

Reference material can be found in SexLabUtil.psc for instance.

Link to comment
1 hour ago, traison said:

Typically what you see in framework type mods is that they provide a script that has global functions in it. These global functions can be used without having a reference to an instance of that script i.e. you can call <scriptname>.<functionname>() instead of having to get a reference to the Quest (or other object) form and cast it to a script type. These global functions do the Quest casting if needed, allowing for easier use of a framework's features. Generally I would avoid overusing this. You wouldn't want to expose all your Quest script functions through a system like this, or any high-traffic functions for that matter. Every call will again retrieve the form reference (if its needed for what the function does). It would result in some rather bloated code.

 

Another thing is mod events. This is one of the only truly optional interfaces that I can think of that really makes a mod dependency optional. If a mod event is sent but there's no one to receive it, it is simply discarded. With global functions you still have a hard depdency. Another optional interface is those provided by StorageUtil, but there is no built in messaging system in that.

 

What I personally do is a combination of mod events and what I call a linker "library". The linker library is a script with global functions, but instead of working like a proxy for Quest functions, it has functions that return references to the Quest objects. This linker library does not create an optional dependency (as it will fail without the linker), but it does allow me to be both lazy and efficient at the same time:

MyModMain main = MyModLinker.GetMain()

If (main)
    main.DoThings()
    main.DoMoreThings()
    main.DoEvenMoreThings()
    main.DoAllTheThings()
EndIf

 

Reference material can be found in SexLabUtil.psc for instance.

 yeah I also thought about mod events even tried to work with them but from my understanding it's really hard for them to influence result of event (since basically event is send after calculation completed). 

 

As for current I just write some code and probably when all basic dependencies are online I would test how much slower is skyrim with it if we get only main lib and around 100 hundred listeners :P if it really slow then I just don't publish a mod until I find a way to be acceptable for perfomance side

Link to comment

I overlooked the fact that if you reverse my linker library idea, you can use it to make a true optional dependency. Not sure why I didn't think of this when I created the design document for my own mods. :confused:

 

Example of what I do:

 

Common Module:
-- CommonScript
-- CommonLinker
---- void* GetCommonScript

Feature Module1:
-- FeatureScript
---- CommonLinker.GetCommonScript()

 

Example of the reverse with true optional dependencies:

 

Common Module:
-- CommonScript

Feature Module1:
-- FeatureScript
---- FeatureLinker.GetCommonScript()
-- FeatureLinker
---- void* GetCommonScript

 

Edited by traison
Link to comment
On 1/19/2024 at 4:24 PM, traison said:

I overlooked the fact that if you reverse my linker library idea, you can use it to make a true optional dependency. Not sure why I didn't think of this when I created the design document for my own mods. :confused:

 

Example of what I do:

 

Common Module:
-- CommonScript
-- CommonLinker
---- void* GetCommonScript

Feature Module1:
-- FeatureScript
---- CommonLinker.GetCommonScript()

 

Example of the reverse with true optional dependencies:

 

Common Module:
-- CommonScript

Feature Module1:
-- FeatureScript
---- FeatureLinker.GetCommonScript()
-- FeatureLinker
---- void* GetCommonScript

 

 

The concept is working nearly fine I'm by myself get also this idea although later so you are inventor :P But there is one problem we should have a handler Interface with predefined handlers that both Common Module and Feature Module knows about it so it's has a small dependency between them, but as long we install this common interface we can practically cover all cases that need to be done by sending announcer/register message through ModEvent and call handlers from feature Modules on requested part of code.

 

As for currently my code is at start of sixth refactor :D every time I write a half of new feature I got a better Idea for this (now it was an idea for plugin manager following your shared idea although as I first it read I didn't imagine how to use it properly in papyrus)

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use