OXP Development Best Practices

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: winston, another_commander

User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4830
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: OXP Development Best Practices

Post by phkb »

I think this is the best place to put this...

When using timers, the normal, widely-used standard for creating the callback function is like this:

Code: Select all

this.$myFunction = function() {...}
However, internally, Oolite is unable to determine the function name from this definition, so any errors that relate to the timer, for instance

Code: Select all

10:03:18.802 [script.javaScript.unrootedTimer]: ----- WARNING: Timer <OOJSTimer 0x39246230>{nextTime: 30.002, one-shot, running, function: anonymous} 
is being garbage-collected while still running. You must keep a reference to all running timers, or they will stop unpredictably!
are impossible to trace back to the source.

However, simply by defining your callback function like this:

Code: Select all

this.$myFunction = function $myFunction() {...}
the function name can be correctly identified and debugging issues is much easier.

This also goes for instances where the function has been defined in the timer initialisation step:

Code: Select all

var myTimer = new Timer(this, function $myCallback() {...}, 5, 0);
UK_Eliter
---- E L I T E ----
---- E L I T E ----
Posts: 1248
Joined: Sat Sep 12, 2009 11:58 pm
Location: Essex (mainly industrial and occasionally anarchic)

Re: OXP Development Best Practices

Post by UK_Eliter »

I have noticed that error messages about timers do not give the timer name. However, I am unsure I understand your rememdy.

My scripts constructions of this form:

Code: Select all

this.dieTimer = new Timer(this,this.$die, 1.7);
What should I replace them with? With constructions of the following form?

Code: Select all

this.dieTimer = new Timer(this,function this.$die, 1.7);
Also, if I make the change you are recommending, do I need to change how I stop timers, remove timers, etc.?

Thanks.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4830
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: OXP Development Best Practices

Post by phkb »

UK_Eliter wrote:
What should I replace them with?
If you have your timer initialised like this:
UK_Eliter wrote:

Code: Select all

this.dieTimer = new Timer(this,this.$die, 1.7);
...then the function you are calling should be declared like this:

Code: Select all

this.$die = function $die() {
	// code of the function follows...
}
Basically, all you're doing is repeating the name of the function between the "function" and the "()".

Nothing else about the timers needs to change. All this does is gives the JS engine a function name to work with when displaying information back to you in the log file.
UK_Eliter
---- E L I T E ----
---- E L I T E ----
Posts: 1248
Joined: Sat Sep 12, 2009 11:58 pm
Location: Essex (mainly industrial and occasionally anarchic)

Re: OXP Development Best Practices

Post by UK_Eliter »

Got it. I think. I'll report back if I have problems. Thank you.
cag
Deadly
Deadly
Posts: 202
Joined: Fri Mar 17, 2017 1:49 am

Re: OXP Development Best Practices

Post by cag »

If you plan on profiling your code, I recommend adding the repeat name on all your functions. Otherwise you get:

Code: Select all

                                                        NAME  T  COUNT    TOTAL     SELF  TOTAL%   SELF%  SELFMAX
                                     WorldScriptsGetProperty  N    779    43.52    39.73    42.9    39.1     0.25
                                        OOStringFromJSString  N   1536     7.63     7.63     7.5     7.5     0.19
                                             ShipGetProperty  N   3778    13.91     7.07    13.7     7.0     0.01
                              (telescope.js:628) <anonymous>  J    244    86.55     5.88    85.3     5.8     0.19
                                         ShipEquipmentStatus  N    755    12.67     5.25    12.5     5.2     0.03
                              (telescope.js:670) <anonymous>  J    142    48.02     5.00    47.3     4.9     0.25
                                           EntityGetProperty  N   3278     7.64     4.76     7.5     4.7     0.02
    -[NSString(OOJavaScriptExtensions) oo:jsValueInContext:]  N   1281     3.99     3.99     3.9     3.9     0.03
                              (telescope.js:767) <anonymous>  J    144     6.31     2.13     6.2     2.1     0.25
                                         JSShipGetShipEntity  N   4533     1.73     1.73     1.7     1.7     0.01
                                         OOJSEntityGetEntity  N   3284     1.62     1.62     1.6     1.6     0.01
                              (telescope.js:609) <anonymous>  J    142    12.58     1.49    12.4     1.5     0.04
                              (telescope.js:621) <anonymous>  J    143    11.32     1.47    11.2     1.4     0.04
                                      JSValueToEquipmentType  N    755     7.02     1.32     6.9     1.3     0.03
                                      
By adding the 2nd function name, all the above "<anonymous>" tags get replaced with the actual function names. Esp. important if you're modifying code in real-time (ie. w/o restarting oolite), as the line numbers quickly become useless.
"Better to be thought a fool, boy, than to open your trap and remove all doubt." - Grandma [over time, just "Shut your trap... fool"]
"The only stupid questions are the ones you fail to ask." - Dad
How do I...? Nevermind.
UK_Eliter
---- E L I T E ----
---- E L I T E ----
Posts: 1248
Joined: Sat Sep 12, 2009 11:58 pm
Location: Essex (mainly industrial and occasionally anarchic)

Re: OXP Development Best Practices

Post by UK_Eliter »

I've just discovered error-checking plugins for editors. Specifically, the jshint javascript plugin for Sublime Text (though jshint has plugins for other editors). Getting such 'linters' installed, in Linux and especially Windows, was a pain. Also, I can't seem to stop jshint complaining about "use strict";. Further, it complains about problems that might seem merely cosmetic, such as missing semi-colons at the end of functions. Still, the plugin did pick up some errors of a more substantial kind, though even in nearly all of those cases the errors would not have been such - I hope - to affect functionality.

Anyone else use such a thing? (I've stated using a Bash linter on Linux too.)
cag
Deadly
Deadly
Posts: 202
Joined: Fri Mar 17, 2017 1:49 am

Re: OXP Development Best Practices

Post by cag »

I'm on Windows and use NotePad++ with a JSLint/JSHint plug-in. I find JSHint more useful, though I think we're stuck w/ the
Use the function form of "use strict"
message. You can DL the plug-in here:

https://sourceforge.net/projects/jslintnpp/

unzip and copy the .dll file into C:\Program Files (x86)\Notepad++\plugins\

In the JSHint options, I've got this:

Code: Select all

addFrameCallback, checkScanner, clock, console, consoleMessage, defaultFont, displayNameForCommodity, EquipmentInfo, 
expandDescription, expandMissionText, formatCredits, formatInteger, galaxyNumber, global, guiScreen, isValidFrameCallback, 
log, manifest, mission, missionVariables, oolite, player, randomInhabitantsDescription,  randomName, removeFrameCallback, 
setScreenBackground, setScreenOverlay, Sound, SoundSource, System, system, takeSnapShot, timeAccelerationFactor, Timer, 
Vector3D,worldScriptNames, worldScripts
in the "Predefined" options box (there may be more oolite specific ones, I just add them as they come up) and this:

Code: Select all

elision:true, shadow:false, esnext: true, validthis: true, curly: false, maxerr: 1000, asi: true, laxbreak: true, undef: true, unused:true
in the "Additional Options" box. Don't ask me what these do (it was a hit or miss procedure). The only message I get once all the errors are fixed is the one about "use strict". I don't think our version of JS (whatever that is) has it and this message can be ignored.

Given how long it takes to rebuild the cache and launch, this can be a real time-saver in the dev cycle. And if you're loading newly edited functions into the debug console, this is a must, as the console cannot give you line numbers for any errors.
"Better to be thought a fool, boy, than to open your trap and remove all doubt." - Grandma [over time, just "Shut your trap... fool"]
"The only stupid questions are the ones you fail to ask." - Dad
How do I...? Nevermind.
UK_Eliter
---- E L I T E ----
---- E L I T E ----
Posts: 1248
Joined: Sat Sep 12, 2009 11:58 pm
Location: Essex (mainly industrial and occasionally anarchic)

Re: OXP Development Best Practices

Post by UK_Eliter »

Hi cag,

The web does mention ways of avoiding the 'use strict' nag in JSHint. One of them involves doing something to every function in one's script. That's not worth it. There is at least one other way, though, at least for Sublime Text; but this other method / these other methods looked a bit involved themselves.

I don't see the other errors you mention, except perhaps one to do with SoundSource; I think the correct form of this is indeed SoundSource(), even though Oolite doesn't complain about SoundSource. Also, at one point the 'linter' did report something about some WorldScripts formulation, but that message seemed to go away.

PS: I use NotePad++ (on Windows) but only for Autohotkey coding and only because I can't find a SublimeText plugin for that. There are things I dislike about Sublime, but I do prefer it to NotePad++.
User avatar
Svengali
Commander
Commander
Posts: 2370
Joined: Sat Oct 20, 2007 2:52 pm

Re: OXP Development Best Practices

Post by Svengali »

You don't need to do it for every function. Just wrap your code in a function. Please also note that the jshint and the global settings will vary from script to script - sometimes you don't need them at all.

Code: Select all

/* jshint <your options> */
/* global <your global vars> */
(function(){
"use strict";
<your code>

}).call(this);
User avatar
Day
---- E L I T E ----
---- E L I T E ----
Posts: 545
Joined: Tue Mar 03, 2015 11:35 am
Location: Paris

Re: OXP Development Best Practices

Post by Day »

UK_Eliter wrote: Thu Jul 20, 2017 1:50 am
Anyone else use such a thing?
I use Intellij Idea.
UK_Eliter
---- E L I T E ----
---- E L I T E ----
Posts: 1248
Joined: Sat Sep 12, 2009 11:58 pm
Location: Essex (mainly industrial and occasionally anarchic)

Re: OXP Development Best Practices

Post by UK_Eliter »

Svengali: thank you - I thought someone here would know! The procedure is a bit of a pain - if one has many scripts - but now that I've got it set up, it's good.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6683
Joined: Wed Feb 28, 2007 7:54 am

Re: OXP Development Best Practices

Post by another_commander »

Cholmondely's post here reminded me of something that has been quite a bit wrong for some time with regards to nebulae from OXPs. This is an issue found with Cinematic Skies 1.3, but it could affect also other expansions which touch the nebulae in the game.

If you have Cinematic Skies installed from the Expansion Manager and dive in any planet's atmosphere, you will most likely end up looking at something like this when you look up:
Image

This is a heavy immersion breaker. The problem is that Cinematic Skies uses colorful RGB images for its nebulae. This does enhance the vibrance of the nebula colors in the game, but unfortunately the engine does not expect this type of data for nebulae. It requires grayscale images instead, while the colors themselves are managed from within planetinfo.plist by means of nebula_color_1, nebula_color_2, sky_color_1/2 etc. Those interested can check the core game files for reference.

The fix is of course to convert all these images inside the Textures folder to grayscale. For Cinematic Skies I have already done this and you can get a fixed version from this link. With this installed, the exact same location now looks clean and tidy like this:
Image

Remember dear OXP creators, if you are juggling with nebulae, give the engine what the engine expects and you will be rewarded.
User avatar
Cody
Sharp Shooter Spam Assassin
Sharp Shooter Spam Assassin
Posts: 16081
Joined: Sat Jul 04, 2009 9:31 pm
Location: The Lizard's Claw
Contact:

Re: OXP Development Best Practices

Post by Cody »

That link's asking me to sign-in to download.
I would advise stilts for the quagmires, and camels for the snowy hills
And any survivors, their debts I will certainly pay. There's always a way!
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6683
Joined: Wed Feb 28, 2007 7:54 am

Re: OXP Development Best Practices

Post by another_commander »

Cody wrote: Tue Jun 21, 2022 2:23 pm
That link's asking me to sign-in to download.
Strange. The file details list its sharing permissions as Everyone with the link can view.
User avatar
cbr
---- E L I T E ----
---- E L I T E ----
Posts: 1422
Joined: Thu Aug 27, 2015 4:24 pm

Re: OXP Development Best Practices

Post by cbr »

Cody wrote: Tue Jun 21, 2022 2:23 pm
That link's asking me to sign-in to download.
confirmed behaviour.
Post Reply