Page 1 of 1

New Wiki Page on OXP Dependencies

Posted: Sun Nov 07, 2010 1:13 am
by PhantorGorth
Just to let people know I have just added a page to the wiki regarding how to handle OXP dependencies with Javascript.

It can be found at: http://wiki.alioth.net/index.php/Handli ... JavaScript

Regards,

Phantor Gorth

Posted: Sun Nov 07, 2010 9:32 am
by Thargoid
A simpler way to do it may be to use a small timer to delay the check for the dependency OXPs. That way you can be sure that everything that will be loaded has been (presuming you don't set the timer too short), and can take appropriate action.

It may also be clearer in your code to use either worldScripts.OXP_B.startUp() or worldScripts["OXP_B"].startUp() syntax. Both are equivalent but it may be clearer in your example scripting if you only use one of them (currently both are in there). Personally I would recommend the latter as it can deal with spaces whereas the former one can't.

Also a couple of other points. OXP_B etc is perhaps not the best term to use, as it's the scripts (and script names) that you're referring to within the OXP, not the OXP itself. Remember you may well have more than one script being loaded for a given OXP.

Secondly in your example, this.startUp() for OXP_B would run twice. Once when called by your example script, and a second time automatically when the game parses the OXP_B script in the normal fashion. This may cause problems for some scripts.

Posted: Sun Nov 07, 2010 11:09 am
by Eric Walch
Thargoid wrote:
A simpler way to do it may be to use a small timer to delay the check for the dependency OXPs. That way you can be sure that everything that will be loaded has been (presuming you don't set the timer too short), and can take appropriate action.
I agree that timers should be mentioned as an option to. It works more general because you don't check against a specific oxp but just make sure your startup code runs after all other startup codes that don't use timers itself.

And dependencies are not only present during startup. Using timers is also useful for witchspace jumps were your code must run last. e.g. the rock_hermit_locator adds buoys to pirate coves. In order to do so it must run after the pirate cove addition script. The method of deleting the shipExitedWitchspace handler won't work there.

Posted: Sun Nov 07, 2010 11:20 am
by PhantorGorth
Thargoid wrote:
A simpler way to do it may be to use a small timer to delay the check for the dependency OXPs. That way you can be sure that everything that will be loaded has been (presuming you don't set the timer too short), and can take appropriate action.
I made reference to this technique as not supporting dependencies chains (if not too clearly). It works for a single level of dependency and that's it.
It may also be clearer in your code to use either worldScripts.OXP_B.startUp() or worldScripts["OXP_B"].startUp() syntax. Both are equivalent but it may be clearer in your example scripting if you only use one of them (currently both are in there). Personally I would recommend the latter as it can deal with spaces whereas the former one can't.
Agreed. I will change it to one of the syntaxes for consistency.
Also a couple of other points. OXP_B etc is perhaps not the best term to use, as it's the scripts (and script names) that you're referring to within the OXP, not the OXP itself. Remember you may well have more than one script being loaded for a given OXP.
I know exactly what you mean. Maybe "OXP_A_Script" format?
Secondly in your example, this.startUp() for OXP_B would run twice. Once when called by your example script, and a second time automatically when the game parses the OXP_B script in the normal fashion. This may cause problems for some scripts.
Actually you are wrong and I have stated this in the example.
Wiki Page wrote:
"Finally Oolite will try to call OXP_B's startUp function which also has been deleted and will also therefore be skipped."
The whole point of the method is that the startUp functions after being called are deleted so they do not exist to be called again. I have also tested this method quite thoroughly.

Posted: Sun Nov 07, 2010 11:29 am
by PhantorGorth
Eric Walch wrote:
Thargoid wrote:
A simpler way to do it may be to use a small timer to delay the check for the dependency OXPs. That way you can be sure that everything that will be loaded has been (presuming you don't set the timer too short), and can take appropriate action.
I agree that timers should be mentioned as an option to. It works more general because you don't check against a specific oxp but just make sure your startup code runs after all other startup codes that don't use timers itself.

And dependencies are not only present during startup. Using timers is also useful for witchspace jumps were your code must run last. e.g. the rock_hermit_locator adds buoys to pirate coves. In order to do so it must run after the pirate cove addition script. The method of deleting the shipExitedWitchspace handler won't work there.
I was only interested in loading dependencies for this wiki page when I wrote it, but your point for shipExitedWitchspace is valid as other events won't get loaded again on game restart. I would not recommend a timer at all for loading dependencies though. A separate section on that page for other dependencies issues should cover that rather than combining them as that would be confusing.

Posted: Sun Nov 07, 2010 11:51 am
by Kaks
Nice addition to the wiki! However, I do have a couple of suggestions for -err- streamlining the template.

I personally wouldn't differentiate between 'old style' & 'new style' script & use a local function to provide a more generic approach:

Code: Select all

this.runOtherStartUp = function(s) {
    if (worldScripts[s].startUp) worldScripts[s].startUp(); // Call the other startUp.
    if (worldScripts[s].startUp) delete worldScripts[s].startUp; // Make sure the other startUp is run only once.
};
then call the new function on either of the scripts...

Code: Select all

this.runOtherStartUp('Oxp_B');
this.runOtherStartUp('Oxp_Old');
You might also want to show a 'shortcut' for this piece of code:

Code: Select all

      // Test for existence of an OXP that isn't required but effects the way this OXP works.
      if (worldScripts["Oxp_X"])
      {
         this.Oxp_X_Exists = true;
      }
      else
      {
         this.Oxp_X_Exists = false;
      }
i.e.

Code: Select all

      // Test for existence of an OXP that isn't required but effects the way this OXP works.
      this.Oxp_X_Exists = !!worldScripts['Oxp_X'];
Of course, the shortcut is not as 'easy' for beginners to read as the first one (one ! ensures we're dealing with a boolean value, the other 'flips' the boolean value the right way round), however it is easier to modify... :)

Just my 2p's worth! :D

Posted: Sun Nov 07, 2010 12:06 pm
by PhantorGorth
Kaks wrote:
Nice addition to the wiki!
Thanks.
However, I do have a couple of suggestions for -err- streamlining the template.

I personally wouldn't differentiate between 'old style' & 'new style' script & use a local function to provide a more generic approach:

Code: Select all

this.runOtherStartUp = function(s) {
    if (worldScripts[s].startUp) worldScripts[s].startUp(); // Call the other startUp.
    if (worldScripts[s].startUp) delete worldScripts[s].startUp; // Make sure the other startUp is run only once.
};
then call the new function on either of the scripts...

Code: Select all

this.runOtherStartUp('Oxp_B');
this.runOtherStartUp('Oxp_Old');
That would work nicely and does simply it. I will probably change that. I will still need to specify that you should do the delete at the beginning of your startUp as it is there to prevent dependency loops causing an infinite calling loop.
You might also want to show a 'shortcut' for this piece of code:

Code: Select all

      // Test for existence of an OXP that isn't required but effects the way this OXP works.
      if (worldScripts["Oxp_X"])
      {
         this.Oxp_X_Exists = true;
      }
      else
      {
         this.Oxp_X_Exists = false;
      }
i.e.

Code: Select all

      // Test for existence of an OXP that isn't required but effects the way this OXP works.
      this.Oxp_X_Exists = !!worldScripts['Oxp_X'];
Of course, the shortcut is not as 'easy' for beginners to read as the first one (one ! ensures we're dealing with a boolean value, the other 'flips' the boolean value the right way round), however it is easier to modify... :)
That's nice too but the syntax is not obvious at all even to me so I would like to see other's opinions first on whether to change that part.

Posted: Sun Nov 07, 2010 12:17 pm
by Micha
PhantorGorth wrote:
Kaks wrote:

Code: Select all

      // Test for existence of an OXP that isn't required but effects the way this OXP works.
      this.Oxp_X_Exists = !!worldScripts['Oxp_X'];
Of course, the shortcut is not as 'easy' for beginners to read as the first one (one ! ensures we're dealing with a boolean value, the other 'flips' the boolean value the right way round), however it is easier to modify... :)
That's nice too but the syntax is not obvious at all even to me so I would like to see other's opinions first on whether to change that part.
That's the point of comments - to explain code which is not easily readable.

Posted: Sun Nov 07, 2010 12:42 pm
by PhantorGorth
Micha wrote:
That's the point of comments - to explain code which is not easily readable.
Can't argue with that.

Posted: Sun Nov 07, 2010 4:52 pm
by PhantorGorth
I have updated the page.

http://wiki.alioth.net/index.php/Handli ... JavaScript

Regards,

Phantor Gorth

Re: New Wiki Page on OXP Dependencies

Posted: Sat Dec 05, 2015 12:08 pm
by ocz
Is this still state of the art? I've got my share of problems using the worldScripts[stringWithScriptName] method.

Also: I believe there is a ";" missing in line 22 of the main code example.

> if (worldScripts["OXPAdditionalCargoSpaceWorkaroundScripts"].startUp) log("Yes");
Exception: TypeError: worldScripts.OXPAdditionalCargoSpaceWorkaroundScripts is undefined
Active script: oolite-debug-console 1.82
oolite-debug-console.js, line 844:
}


OXPAdditionalCargoSpaceWorkaroundScripts.js does exist and is listed in world-scripts.plist. Is startUp() auto deleted after it run in the startup phase?

Re: New Wiki Page on OXP Dependencies

Posted: Sat Dec 05, 2015 2:23 pm
by Norby
ocz wrote:
OXPAdditionalCargoSpaceWorkaroundScripts.js does exist
Do not use the name of the file but the content of this.name within.

Re: New Wiki Page on OXP Dependencies

Posted: Sat Dec 05, 2015 2:32 pm
by ocz
Norby wrote:
Do not use the name of the file but the content of this.name within.
I'm sorry, I'm not catching your drift. Could you give a small syntax example?

var f = worldScripts["IAmAScriptFilesNameWithoutTheJs"].andIamAMethod();

this.f() is than a function defined in "IAmAScriptFilesNameWithoutTheJs.js", right?

Re: New Wiki Page on OXP Dependencies

Posted: Sat Dec 05, 2015 2:45 pm
by Norby
Scripts in Oolite should begin with a this.name definition, which is the key in the worldScripts array if the js file is added into any Config/world-scripts.plist . Your example is working only if the filename without .js and the content of this.name within the file is equal.

Re: New Wiki Page on OXP Dependencies

Posted: Sat Dec 05, 2015 3:05 pm
by ocz
OOOHHHHHHhhhh...........!!!!
You meant this.name from the file header.

"use strict";
this.name = "OXPAdditionalCargoSpaceWorkaround Script";
this.author = "ocz";
this.copyright = "2015 ocz";
this.licence = "CC BY-NC-SA 4.0";

It is actually used for something! Totally forgot about it. My bad.