Jump to content

Immutability and encapsulation in mod design


Recommended Posts

So you want others to use two mod folders ? Cause one is not enough for you. You are just bad coder... how many others would you like. Let's throw a few in.... let's take a BG2Fixpack, and just cause it can, during install lets add in a BGT, Tutu and BG1 folder right in the game directory for the case where if the BG2Fixpack was infact installed in one of those, their workshops would have a place to occupie themselves in.
Then let's take an another multiplatform mod and have it do the same thing... throw in a few DECOPILES and well never hear the end of it cause the calculations will never end, on the single core weidu operation.

How to encapsulate

Are you sure this was it, and not:

BEGIN ~Component~

OUTER_SET key = 0
OUTER_SET key2 = 0
...
COPY ...
OUTER_SET key = %value%

Where the key's are the variable names and the %value% is numeric value.

Link to comment

So you want others to use two mod folders ? Cause one is not enough for you.

I want to use a folder outside the mod structure to compile. I'm happy to share that folder with everyone else. I notice that I've been doing this for at least five years and no-one has complained.

 

You are just bad coder...

Thank you for your constructive feedback. Since rather a lot of my code is out there already (SCS, SSL, the underlying converter code for IWD:EE) I'm happy that people have enough data to make their own assessments here.

 

let's take a BG2Fixpack, and just cause it can, during install lets add in a BGT, Tutu and BG1 folder right in the game directory for the case where if the BG2Fixpack was infact installed in one of those, their workshops would have a place to occupie themselves in.

Then let's take an another multiplatform mod and have it do the same thing...

There is quite a lot of space between "another folder should be used for the following pretty-extensively-laid-out reasons" and "every mod should just create folders for the hell of it". If you want to object to the specific arguments I've given, reasons would be nice.

 

 

How to encapsulate

Are you sure this was it, and not:

BEGIN ~Component~

OUTER_SET key = 0
OUTER_SET key2 = 0
...
COPY ...
OUTER_SET key = %value%
Where the key's are the variable names and the %value% is numeric value.

 

I haven't a clue what you mean here.
Link to comment

I haven't a clue what you mean here.

Before you start anything in a component, you rezero your variables you intent to utilize.

So the other components can't have set them to a value that you have no control over within the component.

 

Aka if a component sets "key" variable to 1, next sets it to 2... and then a component 1000 uses that same key as a variable on something, it can(actually will) cause a mess at some point, if the previous components are installed. Which is why you would re-set it to a zero(if it was not intended to be a value to keep account on).

Link to comment

Yes, you can assiduously make sure every variable you use is reset, ever array forgotten, every hash wiped, before each component, and hope like hell that you never ever miss one...

 

... or you can code in a way which makes it automatic. Which is what functions are for, and why encapsulation, modularity and side effect elimination has been a major theme of computer science in the last few decades.

Link to comment

..you can code in a way which makes it automatic. Which is what functions are for...

Erhm, I might have missed a LOTs, but does the weidu's ...

INCLUDE "%scsroot%/lib/awesome_component.tpa"
LAF awesome_component END

...do that if it's not coded inside it ? Cause I don't see how it would. Aka, is it coded in the LAF commands structure itself ?

Link to comment

@Wisp: cool - is that in the current WEIDU or queued for the next one?

Next one (you could pull and INCLUDE the function definitions today, but you'd do well to remember to take them back out when they'd no longer be necessary).

Edited by Wisp
Link to comment

I've added an option for controlling where the output ends up:

  • out_path, defaults to %tra_path%
  • If %out_path% is different from %tra_path%, no TRA files in %tra_path% are changed and no marker files or other new files are created
  • If converted TRA files are arranged in a directory structure in %tra_path%, a mirrored structure is created in %out_path%
  • Created files in %out_path% are uninstalled, but any new directory structures that may be created during install remain (because uninstalls do not reverse-create directories)
If you use %out_path%, HANDLE_CHARSETS is obviously no longer transparent, so any references to TRA files you may have in your TP2 need to take this into account, say by LOAD_TRAing ~%tra_folder%/%LANGUAGE%/%etc%~, where %tra_folder% effectively is %tra_path% on non-EE games and %out_path% on EE games. Similarly for USING, etc.

 

The conventional way of using HANDLE_CHARSETS seems to be to do a mass conversion in the ALWAYS block. In legacy mode, the function uses marker files to make sure conversions happen exactly once, but with %out_path%, there is no non-tenuous analogue (the presence of files in %out_path% does not, to my mind, imply the redundancy of conversion), so suggestion is that the mod author will have to handle it verself, or the ALWAYS HANDLE_CHARSETS will be run for every component (which is probably undesirable).

 

This is very cool, thank you!

 

 

There is now a template version on GitHub at https://github.com/Gibberlings3/immutable .

Thank you very much!

Link to comment

For Encapsulation: Why not put CLEAR_EVERYTHING as the first line in ALWAYS? Any disdavantages?

You might want to do it after each component, not before a random mod component is installed. As far as I can tell. As in, the code in ALWAYS is ran when the setup-.exe is ran, not between the components.
Link to comment

You might want to do it after each component, not before a random mod component is installed. As far as I can tell. As in, the code in ALWAYS is ran when the setup-.exe is ran, not between the components.

But in the WeiDU documentation about ALWAYS:

This flag specified a TP2 Action that is executed at the beginning of each Component, before the component-specific TP2 Action.

Link to comment

For Encapsulation: Why not put CLEAR_EVERYTHING as the first line in ALWAYS? Any disdavantages?

Yes. It means you can't read in data in your ALWAYS that's to be used in any component.

 

Example: SCS's ALWAYS block goes through every spell in the game and sets a variable with name equal to its ids reference, value equal to its spell file. It also goes through and finds a scroll for each wizad spell, and records that as the value of a variable. It takes 2-5 seconds and I'd rather not have those 2-5 seconds every component.

 

At a more conceptual level, I'd like my encapsulation to be built in to the way the code is structured, not forced explicitly. One of the main points of FUNCTIONs is to deliver this; why not use it? Put another way: why not avoid defining variables with global scope in the first place unless you want them to have global scope, rather than just clearing out the global scope on a regular basis?

Link to comment

There is now a template version on GitHub at https://github.com/Gibberlings3/immutable .

 

@Wisp: cool - is that in the current WEIDU or queued for the next one?

I tried to use the template in my mod and got an error "You have tried to run 'items.tph', but 'test/lib/items.tph.tpa' doesn't exist".

Seems the extension is automatically set to .tpa in the defination of run function, but WeiDU doesn't force it.

It should, IMHO, be removed, although that's just a template.

Edited by c4_angel
Link to comment

This is intentional. From the tp2 comments:

    /// This program looks for "%file%.tpa" in location "%mod_root%/%file_loc%".
    /// If it's not found, the install fails. If it's found, it's INCLUDEd and
    /// the program attempts to run "%file_loc%" as an ACTION_FUNCTION
    /// with tra file "%tra%.tra".
 

Rationale: "file" is both the name of the file in which the component function lives, and the name of the function itself. So a suffix has to be assumed. (Of course, I could allow for arbitrary suffices and strip them off when identifying the function name, but why bother?)

 

Of course, it's a template. If you don't like it, edit the run function.

Edited by DavidW
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...