How to use multiple dependencies containing similar classes

Discussions about Coding and Scripting
OwYeaW
Average
Posts: 74
Joined: Fri Jan 09, 2015 4:24 pm

How to use multiple dependencies containing similar classes

Post by OwYeaW » Sun Oct 29, 2017 1:09 am

yo, i would like to know if its possible to use multiple dependencies that contain similar classes

for example:
i made a mutator that has a dependency on 3 versions of a package:
BTPlusPlusTournament_C.u
BTPlusPlusv0994_C.u
BTPlusPlusv0991_BTNet003_C.u

the mutator will detect which version the server is using:

Code: Select all

class BT_SpecMutator expands Mutator;

function PreBeginPlay ()
{
	local string ServerPackages;

	Super.PreBeginPlay();

    ServerPackages = CAPS(ConsoleCommand("get ini:Engine.Engine.GameEngine ServerPackages"));

	if(InStr(ServerPackages, "BTPlusPlusTournament_C") != -1)
	{
		Level.Game.HUDType = Class'BT_SpecHUD_Tournament';	
	}
	else if(InStr(ServerPackages, "BTPlusPlusv0994_C") != -1)
	{
		Level.Game.HUDType = Class'BT_SpecHUD_0994';
	}
	else if(InStr(ServerPackages, "BTPlusPlusv0991_BTNet003_C") != -1)
	{
		Level.Game.HUDType = Class'BT_SpecHUD_BTNet003';
	}
}
there are 3 BT_SpecHUD classes that need to use their own dependency package
but since the 3 dependency packages have similar classes, the BT_SpecHUD classes dont know which dependency is theirs

so is there a way to let each BT_SpecHUD class know which dependency package they need to use?

nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: How to use multiple dependencies containing similar clas

Post by nogardilaref » Sun Oct 29, 2017 1:03 pm

Depends a lot on how the actual dependencies themselves are coded, but if they use things like "IsA" then the answer is immediately a resounding "no".
Even if they use things like "MyClass(Actor) != None", I don't really know what the behavior will be (it's probably undefined or first come first served at worst, scoped to their own packages at best).
Either way, you're doing it the wrong way for what you want to achieve.

First, if the idea is for your package to work with whichever other package is loaded in the server, then you cannot hold dependencies to 3 variations of them all at once in the first place, since that would defeat the whole purpose of what you're doing, as that would require server owners to have all 3 versions.
And then, as new versions come along, you will probably want to support them too, and suddenly the whole thing explodes when you require admins to have 4, 5, 6, ... versions installed simply because you support all of them.

So the moment you hold 3 dependencies like that, you're already doing it wrong. Having this in mind should already make you seek a different way of doing things.

With that out of the way, so how can you support the 3 of them, without holding 3 dependencies?
Instead of directly depending on them with a single package, you have to invert the dependencies flow, and you do so by splitting your single package into 4 different ones.

One of the packages will be the core implementation, and it's where you actually implement all the common functionality, and is the one which has your mutator and whatnot to load everything up, and this package doesn't depend on anything at all whatsoever.
The other 3 however, will only have 1 dependency each: a dependency towards their respective package that you want to target.

Which means:
1 - Out of the 4 packages you provide, admins just need to use 2 of them: the core one and the one targeted for the BT version they're running, and they do not need to install the other versions.
2 - Whenever a new version comes along, you don't have to update your core package, you just need to create a new one for that version specifically, meaning that the whole thing scales well with new versions and require minimal maintenance and updates.
3 - You can deprecate and remove support for any version by simply not updating its respective package.
4 - Specific code and fixes to a package will remain in a separate package, while the core will remain always clean and work the same way.

A more practical example through a sample of code would be something like this: consider your core package with no ties to any other package, and have a class like this:

Code: Select all

class BT_SpecMutator expands Mutator;

var globalconfig string BTSpecHudPackageClass;

function PreBeginPlay ()
{
   local class<HUD> BTHudClass;

   Super.PreBeginPlay();

   BTHudClass = class<HUD>(DynamicLoadObject(BTSpecHudPackageClass, class'Class'));
   if (BTHudClass != None) {
      Level.Game.HUDType = BTHudClass;
   } else {
      //throw some error here
   }
}
Which then in its .ini file, BTSpecHudPackageClass could be "MyBTPlusPlusTournament_C.BT_SpecHUD_Tournament" for example, or any other corresponding to any other package.
You could even improve it by simply have it as "BTSpecHudPackage" where in the ini you would just need to have the package name, while the class would remain the same (this enters a bit the concept of interfaces, which I am not delve into right now).

Having that said, this can be improved and done in your own way of course, this is simply the most basic example of what I am trying to show you concerning the management of dependencies for each version.
But doing this or something similar, you eliminate any dependency problems you have now and that you may have in the future. :)

JackGriffin
Godlike
Posts: 3765
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: How to use multiple dependencies containing similar clas

Post by JackGriffin » Sun Oct 29, 2017 1:25 pm

If you are going to go balls-deep into dependencies like this why not just combine everything into your own single mod? Is the source code available for these mods? If it is then I'd just take a weekend and get all this under one roof.
So long, and thanks for all the fish

OwYeaW
Average
Posts: 74
Joined: Fri Jan 09, 2015 4:24 pm

Re: How to use multiple dependencies containing similar clas

Post by OwYeaW » Mon Oct 30, 2017 5:32 am

JackGriffin wrote:If you are going to go balls-deep into dependencies like this why not just combine everything into your own single mod? Is the source code available for these mods? If it is then I'd just take a weekend and get all this under one roof.
i had already thought about this idea, but since the stuff that i need to use from these mods contain timer and tick functions, i didnt think it was a good idea to go this way

i think that what nogardilaref said is a good solution to my problem
i got it very quickly working by following his steps

eventually i did this:

Code: Select all

BTHudClass = class<HUD>(DynamicLoadObject(BTSpecVersion $ "." $ BTSpecVersion, class'Class'));
made the package name and class name the same (example: BTSpec_0994.BTSpec_0994)
and in the ini: BTSpecVersion=BTSpec_0994

everything is working correctly as i desire now, im satisfied with this solution
thanks a lot for your clear response nogardilaref :tu: