Changeset View
Standalone View
binaries/data/mods/public/globalscripts/Templates.js
/** | /** | ||||
* Loads history and gameplay data of all civs. | |||||
* Can be used from GUI and rmgen (because the simulation doesn't have these functions yet). | |||||
leper: Maybe explain why, also this should not be the case. | |||||
Not Done Inline ActionsAn explanation would be either lengthy or incomplete and as weird as the weirdness it describes. Agree the differences shouldn't be there to begin with, which is why I wrote that ticket. But unifying it with the simulation should be done in a separate diff as that will have separate controversies and we likely don't want to look at GUI and rmgen code when discussing the simulation changes. The most important difference is the directory restriction for the simulation that we don't have for GUI and rmgen. Secondly the different function names. (possibly more differences as I didn't completely investigate the ComponentManager. Also I was surprised from D754 that the ComponentManager was accessible from the GUI.) elexis: An explanation would be either lengthy or incomplete and as weird as the weirdness it describes. | |||||
Not Done Inline ActionsDifferent patch for merging the simulation sounds good. The directory restriction should be fixed by having a function to read simulation data files (or enumerat them), and expose that under the same name to all the different contexts. I'm quite certain that it isn't. The exported functions are named the same though. leper: Different patch for merging the simulation sounds good.
The directory restriction should be… | |||||
Not Done Inline ActionsReadSimulationJSONFile, possibly. Will have to look in depth. There is only one cpp file that contains "BroadcastMessage" and that is the ComponentManager. We must fix that, it's quite bad to expose so many simulation functions to the GUI revealed by that diplo patch. elexis: `ReadSimulationJSONFile`, possibly. Will have to look in depth.
There is only one cpp file… | |||||
Not Done Inline ActionscmpGuiInterface is a simulation component. It's the place where GuiInterfaceCalls end up, which is the way to get information about the simulation from the GUI (and to some extent help visualize some things (instant feedback for rallypoints), but for those some care needs to be taken to not change the simulation state). leper: `cmpGuiInterface` is a simulation component. It's the place where `GuiInterfaceCall`s end up… | |||||
Not Done Inline ActionsAh right, it goes through the GUIInterface, not directly from the GUI. Then I can sleep better. elexis: Ah right, it goes through the GUIInterface, not directly from the GUI. Then I can sleep better. | |||||
* | |||||
* @param selectableOnly {boolean} - Only load civs that can be selected | |||||
* in the gamesetup. Scenario maps might set non-selectable civs. | |||||
*/ | |||||
function loadCivFiles(selectableOnly) | |||||
{ | |||||
let civFiles = Engine.BuildDirEntList("simulation/data/civs/", "*.json", false); | |||||
let propertyNames = [ | |||||
Not Done Inline ActionsShouldn't that just always be Engine? I'd rather rename a few exposed functions than have this. Also scriptInterface is a bad name, since what you want here is some object, which in some cases is the global object and in some might not be. And if we need to pass something here I'd default to Engine and make the weird context do more work. leper: Shouldn't that just always be `Engine`? I'd rather rename a few exposed functions than have… | |||||
Not Done Inline ActionsIt always is Engine, just that Engine is called RMS in the rmgen context (and there are about 700 references to that). Optional arguments mean people don't find out what they should pass unless the default doesn't coincidentally work as intended. elexis: It always is `Engine`, just that `Engine` is called `RMS` in the `rmgen` context (and there are… | |||||
Not Done Inline ActionsAnd there is a single caller of that in the whole rmgen. So using Engine here seems like the cleaner choice. I don't expect people to have to care about the fact that RMS is used in one place, and Engine everywhere else. Having that as an optional parameter is exactly about hiding something nobody should have to care about (the one call in rmgen is in the library...). Normally it shouldn't even be a parameter, but since the random map code is somewhat strange we should at least make this work as expected for everyone else, not force the "normal" code to change how it does things. leper: And there is a single caller of that in the whole rmgen. So using Engine here seems like the… | |||||
Not Done Inline ActionsWe only have 2 calls to this function, one RMS and one GUI.
And they don't have to. Hiding values behind defaults when the caller has to care about the correctness of the value counteracts. I can rename from RMS to Engine for consistency when my rmgen branches have been transfered. However it's not inherently bad that variables can have arbitrary names, but a feature of object orientation that was specifically planned when C++ functions exposed to JS were moved from the global scope to objects in https://wildfiregames.com/forum/index.php?/topic/17289-discussion-spidermonkey-upgrade/ elexis: We only have 2 calls to this function, one RMS and one GUI.
> I don't expect people to have to… | |||||
Not Done Inline ActionsAnd the simulation will not end up using this function after that future patch? The correct value is Engine in all cases apart from the random map context. And that one is non-standard in quite a few other ways, so making that jump through a single hoop to make the code nicer for everyone else is something we should do. Once the random map scripts have been cleaned up the hoop can be removed since it isn't needed anymore and nothing else has to change a lot anymore. The first post in that topic also talks about "Standardizing scripting access" which IMO includes having Engine everywhere and assuming that to be the correct thing. Not requiring code that is doing everything correctly (regarding this issue) to do more than it needs to, push the ugly compatibilty code on the ugly user. leper: And the simulation will not end up using this function after that future patch?
The correct… | |||||
Not Done Inline ActionsThe simulation would add the third call to this function (SkirmishReplacer.js), but the argument is independent from the quantity of calls. Removing the argument would make the calls nicer to read, hiding the value in a fraction of calls makes it harder to read due to the additional effort to lookup the values of the call in multiple files. If RMS is renamed to Engine we can remove the scriptInterface argument from the 2 to 3 calls. If those were hundreds, I might agree that we could use the bad practice to ease the the future rename. (Just to have it stated, there is also the possibility that other scriptinterfaces are added later by us or mods and that more than one scriptinterface exists simultaneously. But I agree to assume that there is only one and that its called Engine until there is a documented use case). elexis: The simulation would add the third call to this function (SkirmishReplacer.js), but the… | |||||
Not Done Inline ActionsThose aren't scriptinterfaces, not really, those are objects that implement those functions. globalscripts is about being usable by most (read all) of the contexts. These functions should just need the minimal amount of parameters to do their thing. Requiring passing Engine (which is the default and the expected name) in cases where one should be able to assume that this is the expected thing (see Resources.js and l10n.js for other uses of Engine) is just wrong. If RMS is at one point renamed to Engine one can just remove the parameter and be done, no changes needed for any other callsites that do what is already expected. The random map scripts decided to be different, so they should have to pay the cost of being like that instead of doing the same thing as all the other code (that this is the case because of historic reasons is not really the point). The possibility that those aren't called Engine just means that someone decided to ignore any advice and do things differently because pointless work is fun. That said you could still just do var Engine = RMS; and be done. But I'll not accept this as long as we don't default to Engine and instead make code that follows what most of the code does jump through hoops just because RMS decided to be different for no reason. leper: Those aren't scriptinterfaces, not really, those are objects that implement those functions. | |||||
Not Done Inline Actions
Let's go for engine, shall we?
Making it optional doesn't increase the usability.
Not convinced, sorry.
Obfuscating the value makes every caller pay. The readers of the simulation are still confronted with the unwanted variability once they peel off the obfuscation.
Would buy that argument if it were an order of magnitude more calls than 3
So I have the choice to commit something which you consider a defect, something which I consider a defect, or something which multiple people consider a defect. I can offer to add the default and add "Some disagreements by me" to the commit message. Another possibility would be avoiding the argument altogether and setting let engine = Engine || RMS; // RMS is stupid to the globalscripts function.
is a good example where we could mitigate different code paths for each context by reducing the differences in C++
That can solely be used by the GUI of the public and modmod mod. elexis: > scriptinterfaces, not really
Let's go for `engine`, shall we?
> globalscripts is about being… | |||||
Not Done Inline Actions
Still not that nice.
For non-RMS code it does.
The caller shouldn't need to care, so requiring it to care (in the non-RMS case) is making it pay.
Until we fix that part, which unless I missed something was the point of a certain ticket.
So we are going to write shitty code because it is only used twice currently?
Well, or you could change the RMS code to do var Engine = RMS; and have nice code in globalscripts.
See above. I still consider the current workaround somewhat ugly. >> Resources.js
Yes, and that is why we should have a function to load simulation data exposed to everyone. Wasn't unifying that the point of that ticket? The template code also does something similar (or did) since it gets slightly different data based on a few things.
You might have missed the markForTranslation functions there. Yes some care with not calling some things from some places needs to be taken, but having it like this seems nicer than having to do the caching in every gui page and including tons of files. leper: > Let's go for engine, shall we?
Still not that nice.
> Making it optional doesn't increase… | |||||
Not Done Inline ActionsThe only usability that can be meant when comparing a mandatory argument with a default value from a mandatory argument without default value is perceived readability. No, renaming RMS to Engine was not the intention of the ticket. Deleting more than 50 shitty lines in exchange for, depending on the revision, one or two shitty lines that can be removed afterwards. I rather add one shitty line inside a function or rebase 20 patches than exposing a new proxy to more than 70 files that might, judging from the current usage, refer to it 10 times per file (opposed to loadCivData which is called once per context on init). Maybe. As long as we don't copy the entire function but call a function with the shared code with an argument. Possibly. elexis: The only usability that can be meant when comparing a mandatory argument with a default value… | |||||
Not Done Inline ActionsDefaults: One example where I have used default values is the upcoming starting base unification patch. ReadJSONFile: l10n.js: Thanks for your comments and replies, even if I don't agree with all of them. elexis: `Defaults`: One example where I have used default values is the upcoming [[ https://github. | |||||
Not Done Inline Actions(Besides, if it's preposterous to have more than one ScriptInterface simultaneously and a name different than Engine, then the nativeScopeArgument should be removed and fixed to Engine. elexis: (Besides, if it's preposterous to have more than one ScriptInterface simultaneously and a name… | |||||
Not Done Inline ActionsExcuse me for not liking to fight windmills again. Adding new bad code is worse than having somewhat broken code that's already there. Neither of those is nice, but adding to the pile will not end well. Why have a need for the simulation to specify that it wants to read something from the simulation? Up to quite recently hardcoding Engine wasn't possible because there were places that didn't use it. Strange, isn't it? Then someone changed that, but decided a quick replace and a snarky comment was all that was needed. Sometimes interesting things happen and questions are only asked afterwards instead of before when one could actually figure out these things. leper: Excuse me for not liking to fight windmills again.
Adding new bad code is worse than having… | |||||
"Code", "Culture", "Name", "Emblem", "History", "Music", "Factions", "CivBonuses", "TeamBonuses", | |||||
"SkirmishReplacements", "Structures", "StartEntities", "Formations", "AINames", "SelectableInGameSetup"] | |||||
let civData = {}; | |||||
for (let filename of civFiles) | |||||
{ | |||||
let data = Engine.ReadJSONFile(filename); | |||||
if (!data) | |||||
throw new Error("Could not load " + filename); | |||||
for (let prop of propertyNames) | |||||
if (data[prop] === undefined) | |||||
throw new Error(filename + " doesn't contain " + prop); | |||||
if (!selectableOnly || data.SelectableInGameSetup) | |||||
civData[data.Code] = data; | |||||
} | |||||
return civData; | |||||
} | |||||
/** | |||||
* Gets an array of all classes for this identity template | * Gets an array of all classes for this identity template | ||||
*/ | */ | ||||
function GetIdentityClasses(template) | function GetIdentityClasses(template) | ||||
{ | { | ||||
var classList = []; | var classList = []; | ||||
if (template.Classes && template.Classes._string) | if (template.Classes && template.Classes._string) | ||||
classList = classList.concat(template.Classes._string.split(/\s+/)); | classList = classList.concat(template.Classes._string.split(/\s+/)); | ||||
▲ Show 20 Lines • Show All 479 Lines • Show Last 20 Lines |
Maybe explain why, also this should not be the case.