The problem#
The Factorio documentation includes a machine-readable version of the prototype API documentation. I wanted to be able to access that information from within a mod, which required somehow giving Lua access to a JSON object.
The solution#
Install my branch of json2lua
and run it on your
JSON file:
$ npm install git+https://github.com/dperelman/json2lua.git\#feature/string-escaping
$ npx json2lua "FILE.json" "FILE.lua"
Note the output is a Lua table literal, so you'll have to add code to actually assign it to a variable to be able to use it.
The details#
JSON interpreter in Lua#
As Factorio uses JSON for
things like blueprint strings, it includes a built-in
function game.json_to_table(json)
for parsing JSON
to a Lua table. Which isn't actually useful to us because the game
object is part of the "Runtime Stage" (which "takes place
alongside normal gameplay") and the prototype API is most useful during
the Prototype Stage.
I could have copied in that or some other Lua-implemented JSON parser, but I still would have had to figure out how to get the mod access to the JSON file. If I were going to wrap it into a Lua string, I figured I might as well figure out how just convert it into a Lua table.
Converting JSON to Lua#
Since interpreting the JSON inside the mod wasn't looking
straightforward, I decided to take a different approach of converting it
to Lua before the mod starts. Unsurprisingly, I wasn't the first person
to want to do this and I found multiple JSON-to-Lua converters including
the npm package json2lua
. Surprisingly, none of the ones
I tried actually handled string escaping properly; they just assumed
wrapping the literal string value with "
s would be sufficient, which
fails on any string that contains "
or any special characters like new
lines.
So I made my own branch1 where I
modified json2lua
to handle escaping strings
correctly. Luckily, Lua's string escaping is
well-designed to make this easy since if you use [[...]]
style string
literals then any characters are allowed between the brackets and are
interpreted literally. If the string does contain ]]
, then you can
use [=[...]=]
instead, up to as many =
s as you want. So the code to
escape a string str
is simple:
var i = 0;
var end = ']]';
do {
end = ']' + '='.repeat(i) + ']';
} while (str.includes(end));
return '[' + '='.repeat(i) + '[' + str + end;
Getting the machine-readable prototype API into the mod#
Now that I had figured out how to convert prototype-api.json
into
a Lua table, I made a script to automate the process. In my mod,
convert-to-lua.sh
downloads prototype-api.json
from the Factorio website (unless it's already been downloaded),
downloads my version of json2lua
, runs it, and outputs a file
prototype-api.lua
which assigns that Lua table to a global,
ReflectionLibraryMod.prototype_api
. That way I don't have to include
the prototype information in the source repository of my mod and it's
easy to update whenever Factorio updates it.
-
I did submit a pull request, but the project has has no activity for 5 years, so I'm not expecting it to get accepted. ↩
Comments
Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.
There are no comments yet.