PDA

View Full Version : Shared Function in Ext



ApesAmongUs
September 30th, 2020, 15:15
I have 2 extensions that both require that the same function be altered. It's the same alteration in both, so I just replaced the function in both to allow me to run each independently of the other. This works, but is there a cleaner way of doing this? Like, for instance, could I make a third function that the other 2 depend on, so if I need to update it in the future, I can just update it in one place? If so, how do a set a dependence like that where one ext requires another? Or, is there a better way?

SilentRuin
September 30th, 2020, 16:04
I have 2 extensions that both require that the same function be altered. It's the same alteration in both, so I just replaced the function in both to allow me to run each independently of the other. This works, but is there a cleaner way of doing this? Like, for instance, could I make a third function that the other 2 depend on, so if I need to update it in the future, I can just update it in one place? If so, how do a set a dependence like that where one ext requires another? Or, is there a better way?

[Note: this is what I do and seems to work - but for all I know I've fooled myself on it - so just FYI. Appears to work for me, but I'm not a .lua expert.]

Well there are a lot of things to consider so I suppose I can just describe what I do.

First, I consider <loadorder> in extension.xml in my constellation of extensions. Most times I don't care but when I do - the load order determines what functions got loaded last (and win the function game).

Second, I always ALWAYS try to minimize my impact to others when I'm forced to override a function. This means if its a named script (has a name in your extension.xml or base xml that it incorporates) I always save the original function and use it if I can (not always possible). For example, I will save the original script in OnInit and replace it back in OnClose then try and use the original code for anything outside of my special need that made me override it. The example shows me calling the original code first but it could be called last or you could have logic surrounding it. This type of thing I document in my description of my extension as an overridden function (meaning I still touch the original code in case someone has changed it for their own uses).



local savegetItemSourceType = nil;

function onInit()
savegetItemSourceType = ItemManager.getItemSourceType;
ItemManager.getItemSourceType = getItemSourceType;
end

function onClose()
ItemManager.getItemSourceType = savegetItemSourceType;
end

function getItemSourceType(vNode)
-- Call original code
local sReturn = savegetItemSourceType(vNode);
if sReturn and sReturn ~= "" then
return sReturn;
end

-- Do my stuff if it did not resolve it

end



If I have to outright replace the code (not called original at all - because you can't always avoid that) I document it in my extension description as a COPY of the function (meaning I stomped it completely).

If it is not a named script then you have to replace the entire .lua file that is being triggered (or the .xml script) . You copy the entire file and replace the inards of each function with a super call to the original version of it with your overlaying file changes mixed in where needed. Magic of .lua fantasy grounds don't ask me to explain. Below is an example of me being forced to replace npc_main.lua (not a named script) ...



function onInit()
if super and super.onInit then
super.onInit();
end
end

function onSummaryChanged()
if super and super.onSummaryChanged then
super.onSummaryChanged();
end
end

function updateControl(sControl, bReadOnly, bForceHide)
if super and super.updateControl then
super.updateControl(sControl, bReadOnly, bForceHide);
end
end

... (etc.)


Where I insure all the original functions exist with a super call except the places I'm actually overriding or adding in. Even then I try to call the super version and only do my special stuff when some trigger indicates I need to.

In any case, that's what I do. I find it minimizes the impact you have on other extensions and that they have on you.

Having said that, FGU and other extensions can and will always be able to break you. It's the nature of extensions - there is no "safe word" to protect you from it. You can only minimize the chances it will happen.

bmos
August 8th, 2021, 13:25
A small improvement to this example (that SoxMax taught me):

function updateControl(sControl, bReadOnly, bForceHide, ...)
if super and super.updateControl then
super.updateControl(sControl, bReadOnly, bForceHide, ...);
end
end
This will pass along any additional arguments that other extensions have added.

ApesAmongUs
August 8th, 2021, 13:33
A small improvement to this example (that SoxMax taught me):

function updateControl(sControl, bReadOnly, bForceHide, ...)
if super and super.updateControl then
super.updateControl(sControl, bReadOnly, bForceHide, ...);
end
end
This will pass along any additional arguments that other extensions have added.

In have the feeling that this may be the solution to a bug I just got since the last update.

UrsaTeddy
August 14th, 2021, 03:06
Another option which works perfectly in all situations for myself is the creation of a base extension that is required for all of your extensions to work.

My base extension contains various utility functionality that is used by my other extensions and it guarantees that I only have one place to modify the code and it is carried through every extension.

This does require your common functionality to ensure a "black box" style usage (this goes in, that comes out) so that any extension using your code does not need to be changed to cater for updates to the function you may have put into this base extension.