The hardest part of my own project is creating the massive file parser needed to allow modded content of all types. The absolute last thing I would have thought to use is fucking JavaScript.
I started experimenting with something similar in .NET (though in fairness my experiment is more of an alternative to Twine/SugarCube than anything else) and just ended up rolling my own parser.
Inno
kinda rolls their own parser, though that's more to handle the #IF/#ELSEIF/etc stuff.
You must be registered to see the links
.
I did consider using HTML/CSS for the main text output, just to make formatting super easy and modifiable with CSS. Just convert the presentable scene to HTML and toss it on screen, super easy. I'm going to bet that she thought the same and then just expanded from there.
I'm probably going to wind up taking that approach with my experiment as well, mostly due to the annoying lack of stable cross-platform .NET UI toolkits (being someone who primarily uses Linux/macOS and loves C#/.NET is rough at times, heh).
And yeah, LT essentially uses the JavaFX WebEngine for most of its display magic, and naturally that does involve a fair bit of frontend JavaScript to propagate JS events back to Java. The part that's really funny is that the conditionals handling is actually done using a separate JS interpreter! JavaFX uses JavaScriptCore, but LT's conditional parser uses Oracle's Nashorn JS engine.
And I'm not at all surprised she didn't implement any sanity checking into the system. A lot of this stuff seems to be her grabbing the simplest solution for the current problem and then running with it way further than she should. Adding sanity checking isn't simple.
There is some, but that mostly involves disabling the really spicy stuff. I haven't gone over it too thoroughly yet, but the main reason I couldn't easily write a random file into /var/tmp (or pretty much anywhere the user has access to in *nix, or somewhere on the same drive in Windows) is simply because the save game function (which is in one of the classes exposed to JS) is a static method, and there doesn't seem to be a way to access static methods with how the JS engine is configured.
If It Were Me™ and I had to implement it in this way, I would have created a barebones, purpose-built JavaScript API rather than directly exposing game classes. If this API were only intended for conditionals and checking game state (I'm not sure as of yet, to be honest), I would have ensured that it had access to exactly zero setters.
I'd ask you where in the project files all of this is, but I trashed my copy of the games source code a few days ago and I don't care enough to redownload it lol
Oh, don't worry. I'm not kind enough to keep that sort of information to myself.
Here's a couple of noteworthy methods that show off some of this behavior:
You must be registered to see the links
- Initializes Nashorn, removes a few globals, and stuffs the global namespace full of hot, juicy class instances.
You must be registered to see the links
- Evaluates the expressions in #IF/#ELSEIF statements.
That's fucking precious considering that she's admitted that she's just plain goofing off at least once. Hey Inno, maybe instead of making it so that I have to put my .jar in a specific directory, you can make it so that I don't have to use an outdated version of JDK to build this?
It's pretty easy to do that. Here's a fork of 0.3.19 on my GitHub that targets JDK 11 (since it's the latest LTS and all) and successfully builds with JDK 15:
You must be registered to see the links
. As an added bonus, my fork also uses Maven's dependencies system to fetch JavaFX, so it should be easier to build as well.
As I mentioned in one of my previous ramblings, one of the issues with this is the deprecation (and, as of JDK 15, the removal) of the Nashorn JS engine. LT uses this heavily when parsing XML conditionals, to the tune of thousands of eval() calls during long loiter/sleep periods. Nashorn seems to handle this use case far better than GraalJS does, so the JDK 11+ fork runs significantly slower than the JDK 8 builds.