Solution to "Only one DLL at a time?"

Irkalla

ENTP POWWWEEEEEER
Joined
Sep 25, 2012
Messages
1,009
Location
Way down around Vicksburg
I'm not familiar with how to do it, but I know that one could include all the DLL's from an entire directory in C++. What stops us from doing this with the gamesources and shipping them as being dependent upon this custom DLL? Everyone that wants to depend on the inclusion gamesource should put their DLL in the same modbuddy folder, then VFS their DLL.

Or, even better, have the base DLL look in the gamedatabase for DLL's to include. Include the ones specified that we find. But, is the gamedatabase initialized at this point?

But yeah, I couldn't think of any specific reason WHY we'd be limited to just one DLL. Depend on a gamesource that has nothing new except some sort of inclusion script, and we should be able to have an indefinite amount of DLL's running at the same time, given they don't conflict.

I think the main issue would be with needing to overwrite existing functions and such. Doesn't C++ have a file scope that a function defaults to residing in? In that case, wouldn't we need to...
Spoiler :
make everything global?


Link to video.

Then there's a third solution I've come up with, which involves exposing EVERY[safe]THING to Lua. This way we wouldn't NEED to do any C++ Modifications... unless we wanted to overwrite something... In which case we'd have to...
Spoiler :
translate EVERYTHING to Lua?


Link to video.


You know what, this is sounding like a dumber and dumber idea the more I think about it.

We got a proper coder that can comment on this?
 
I don't think I'm a "proper" coder that you need, but I wonder what are you going to achieve... if there are multiple DLLs that define the same functions, which one should be used?
 
I don't think I'm a "proper" coder that you need, but I wonder what are you going to achieve... if there are multiple DLLs that define the same functions, which one should be used?

Modders need to communicate and define responsibility, I guess. Base dll author marks his mod as conflicting with mods whose authors won't cooperate.
 
Then there's a third solution I've come up with, which involves exposing EVERY[safe]THING to Lua.

That's what a common DLL should focus on, BUT it will still have limitations.

For example, adding a game event is very simple, the difficulty as pointed out by whoward69 in another thread is to know where to place it.

Say you want to add a game event to check if an unit can enter a tile (for a railroads artillery for example), you may want to add something everyone could use and add a game event in the CanMove functions of CvUnits. But this is called so many times when the game is running (pathfinder...) that adding a game event here crash the game, even if it's not called on the Lua side. And if it was working, it would have a serious impact on performance.
 
I'm not familiar with how to do it, but I know that one could include all the DLL's from an entire directory in C++.
You could (and with the correct framework can) do this - BUT the classes in the DLL have to be unique. So while DLL A could contain only CvPlot and DLL B could contain only CvUnit, if DLL C contains either of those two classes you have a conflict and must decide which one to load - you cannot have both active at the same time.

Stop thinking in terms of "script files" that get executed in the order the lines in the file occur in, but in terms of "compiling and linking" - they are two very, very different beasts.

Classes must also be complete - ie every method defined in the header must be in the class at compile time - so you can't have DLL A with CvPlot::MethodX() and DLL B with CvPlot::MethodY() as neither A nor B would compile as they are missing methods.

Now you CAN achieve those kinds of effects - using MethodX from DLL A and MethodY from DLL B, it's known as dependency injection and is part of IoC/AOP frameworks, but it is something you design in from day 1 and requires a true OO design and implementation (which the Civ5 code does not adopt - C++ it may be, OO it is not).

What stops us from doing this with the gamesources and shipping them as being dependent upon this custom DLL? Everyone that wants to depend on the inclusion gamesource should put their DLL in the same modbuddy folder, then VFS their DLL.

Or, even better, have the base DLL look in the gamedatabase for DLL's to include. Include the ones specified that we find. But, is the gamedatabase initialized at this point?
Works for scripts, does not work for compiled langauges.

But yeah, I couldn't think of any specific reason WHY we'd be limited to just one DLL.
For all the reasons given above - compiled langauges do NOT operate the same way as script files.

Depend on a gamesource that has nothing new except some sort of inclusion script, and we should be able to have an indefinite amount of DLL's running at the same time, given they don't conflict.
Which they will.

I think the main issue would be with needing to overwrite existing functions and such. Doesn't C++ have a file scope that a function defaults to residing in? In that case, wouldn't we need to... make everything global?
But given that none of the existing code is written this way, you're talking about re-writing the ENTIRE GameCore code base

Then there's a third solution I've come up with, which involves exposing EVERY[safe]THING to Lua. This way we wouldn't NEED to do any C++ Modifications... unless we wanted to overwrite something... In which case we'd have to... translate EVERYTHING to Lua?
And if you think game turns are slow now ...
 
You could (and with the correct framework can) do this - BUT the classes in the DLL have to be unique. So while DLL A could contain only CvPlot and DLL B could contain only CvUnit, if DLL C contains either of those two classes you have a conflict and must decide which one to load - you cannot have both active at the same time.

Stop thinking in terms of "script files" that get executed in the order the lines in the file occur in, but in terms of "compiling and linking" - they are two very, very different beasts.

Classes must also be complete - ie every method defined in the header must be in the class at compile time - so you can't have DLL A with CvPlot::MethodX() and DLL B with CvPlot::MethodY() as neither A nor B would compile as they are missing methods.

Now you CAN achieve those kinds of effects - using MethodX from DLL A and MethodY from DLL B, it's known as dependency injection and is part of IoC/AOP frameworks, but it is something you design in from day 1 and requires a true OO design and implementation (which the Civ5 code does not adopt - C++ it may be, OO it is not).


Works for scripts, does not work for compiled langauges.


For all the reasons given above - compiled langauges do NOT operate the same way as script files.


Which they will.


But given that none of the existing code is written this way, you're talking about re-writing the ENTIRE GameCore code base


And if you think game turns are slow now ...


I think you can tell what sort of instruction-giving I come from :p Compiling linking and all that junk is just a bit over my head at the moment. I'm too much of a generalist to sit down and focus on coding...

Also, Lua's pretty lightweight and fast. But yeah that's a totally way of going about it, I agree.
 
Now you CAN achieve those kinds of effects - using MethodX from DLL A and MethodY from DLL B, it's known as dependency injection and is part of IoC/AOP frameworks, but it is something you design in from day 1 and requires a true OO design and implementation (which the Civ5 code does not adopt - C++ it may be, OO it is not).

I'm pretty sure you don't need to pull in one of those huge frameworks to achieve this effect. Just think of any program using dll plugins. You should be able to get a handle on any dll you have the name of with:
HINSTANCE dllHandle = LoadLibrary("dllName.dll");
and then get a pointer on a function with:
GetProcAddress(dllHandle, "funcName");

And there's nothing keeping you from simultaneously having:
HINSTANCE dllHandle2 = LoadLibrary("dllName2.dll");
GetProcAddress(dllHandle2, "funcName"); //notice it is the same "funcName" as before

And so on for any number of dlls.
To make something of this, there should be one "universal" dll which has been told to load all the dlls in some directory or from some xml file, and all those "plugin" dlls will have to have been compiled against a predefined "dll plugin interface", a set of methods through which the plugins execute their code. The universal dll has to define just where those methods are invoked.

But i think this idea makes less sense then git idea. Even though you won't have multiple dlls with git, it should make it easy to create a custom dll using the wanted parts from different branches, achieving somewhat the same result.
 
Except for a class method it's not "funcName" but the mangled form with the parameter signature added.

You're still going to have to rewrite very large chunks of the existing code to use GetProcAddress in EVERY method you want to be able to over-ride (and there are hundreds of them) and also add configuartion logic - both to tell the code which DLLs provide what overrides and also what to do to resolve conflicts when more than one DLL provides the same method - sounds like a framework to me.
 
But i think this idea makes less sense then git idea.

A shared code-base via git (or whatever) is going to be the way to go IMHO
 
A shared code-base via git (or whatever) is going to be the way to go IMHO

Yeah, this stuff's a hot mess...

And yeah, I know lower level languages are generally faster. But as far as scripting goes, Lua's the gold standard.

Really, they should have made Lua more powerful than it is. Not to imply it isn't... But still, there's just some things we should be able to do with Lua besides obscure stuff the developers needed to do for the vanilla game.

For example, I can't see a clear method to create a promotion or trait, and then give that trait or promotion a name I can use with database scripting.
 
And yeah, I know lower level languages are generally faster. But as far as scripting goes, Lua's the gold standard.
So is Bradley Wiggins, but even an overweight oaf in a modest family car will leave him standing.
 
For example, I can't see a clear method to create a promotion or trait, and then give that trait or promotion a name I can use with database scripting.

That's what SQL is for. It really helps if you use the right tool in the box for the job and not try to solve everything by hitting it with a hammer ... "gold-plated" or not.
 
Back
Top Bottom