From b43a181bf41f89abdb2cedb4859bc49b48db3d96 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sat, 26 Jun 2021 17:26:01 +0200 Subject: [PATCH 1/4] Fix JSON serialization in export mod Fix incorrect serialization of control characters to \xHH escapes since JSON only support \uHHHH escapes, and serialization of infinite and NaN numbers. --- packages/slave/lua/export/data-final-fixes.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/slave/lua/export/data-final-fixes.lua b/packages/slave/lua/export/data-final-fixes.lua index c4f0e7d3..335ac5c1 100644 --- a/packages/slave/lua/export/data-final-fixes.lua +++ b/packages/slave/lua/export/data-final-fixes.lua @@ -46,11 +46,14 @@ end -- no game.table_to_json here :( local function table_to_json(data) if type(data) == "number" then + if data == math.huge then return "1e500" end -- Inf is not representable in JSON, but 1e500 will overflow to it. + if data == -math.huge then return "-1e500" end + if data ~= data then return "0" end -- NaN is not representable in JSON, treat as 0 instead. return string.format("%.17g", data) elseif type(data) == "string" then data = data:gsub('([\x00-\x1f\\"])', function(match) - return "\\x" .. string.format("%02x", match:byte()) + return "\\u00" .. string.format("%02x", match:byte()) end) return '"' .. data .. '"' From 5daa492f6824f591a47394d609b5d1018760b921 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sat, 26 Jun 2021 17:27:36 +0200 Subject: [PATCH 2/4] Emitt more useful error on parse error Rethrow parse errors with the JSON content that failed to parse for JSON content sent to Clusterio from Factorio. --- packages/lib/factorio/server.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/lib/factorio/server.js b/packages/lib/factorio/server.js index d61b49c9..5b08447a 100644 --- a/packages/lib/factorio/server.js +++ b/packages/lib/factorio/server.js @@ -605,7 +605,11 @@ class FactorioServer extends events.EventEmitter { let type = line.slice(channelEnd + 1, channelEnd + 2).toString("utf-8"); let content; if (type === "j") { - content = JSON.parse(line.slice(channelEnd + 2).toString("utf-8")); + try { + content = JSON.parse(line.slice(channelEnd + 2).toString("utf-8")); + } catch (err) { + throw new Error(`Malformed JSON to ${channel}: ${line.slice(channelEnd + 2).toString("utf-8")}`); + } } else if (type === "f") { let fileName = line.slice(channelEnd + 2).toString("utf-8"); From 80eae94fe194bcf1f14c163dd021c5db392f9ad4 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sat, 26 Jun 2021 17:29:07 +0200 Subject: [PATCH 3/4] Handle leading zeros in mod filenames It's possible to put leading zeroes in the names of mod zip files which cause the existing algorithm to find the mod zip from the mod version to fail. Fix by listing the mods directory and fixing the version numbers for any of the mods with leading zeros in them. --- packages/lib/factorio/export.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/lib/factorio/export.js b/packages/lib/factorio/export.js index 093e9be3..34ee2130 100644 --- a/packages/lib/factorio/export.js +++ b/packages/lib/factorio/export.js @@ -357,6 +357,28 @@ async function exportData(server) { throw new Error("No items got exported"); } + // Some mod authors put leading zeros into the versions of their zip files. + let splitter = /^(.*)_(\d+)\.(\d+)\.(\d+)\.zip?$/; + for (let entry of await fs.readdir(server.writePath("mods"))) { + let match = splitter.exec(entry); + if (!match) { + continue; + } + + let modVersion = `${match[2]}.${match[3]}.${match[4]}`; + let normalizedVersion = + `${Number.parseInt(match[2], 10)}.${Number.parseInt(match[3], 10)}.${Number.parseInt(match[4], 10)}` + ; + + if (modVersion === normalizedVersion) { + continue; + } + + if (modVersions.get(match[1]) === normalizedVersion) { + modVersions.set(match[1], modVersion); + } + } + let { iconSheet, itemData } = await exportItems(server, modVersions, items); let locale = await exportLocale(server, modVersions, modOrder, "en"); From 90a400b782918034e12792e648c40ed2551b8409 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sat, 26 Jun 2021 17:31:00 +0200 Subject: [PATCH 4/4] Handle mod not found in data export Handle the case of the mod file not being found from the mod version. This could happen if the naming scheme is weird or the mod is unpacked. --- packages/lib/factorio/export.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/lib/factorio/export.js b/packages/lib/factorio/export.js index 34ee2130..2e71dd08 100644 --- a/packages/lib/factorio/export.js +++ b/packages/lib/factorio/export.js @@ -90,7 +90,16 @@ async function loadFile(server, modVersions, modPath) { } } - let zip = await loadZip(server, modVersions, mod); + let zip; + try { + zip = await loadZip(server, modVersions, mod); + } catch (err) { + if (err.code === "ENOENT") { + return null; + } + throw err; + } + let file = zip.file(filePath); if (!file) { return null; @@ -310,7 +319,15 @@ async function exportLocale(server, modVersions, modOrder, languageCode) { continue; } - let zip = await loadZip(server, modVersions, mod); + let zip; + try { + zip = await loadZip(server, modVersions, mod); + } catch (err) { + if (err.code === "ENOENT") { + continue; + } + throw err; + } for (let file of zip.file(new RegExp(`locale\\/${languageCode}\\/.*\\.cfg`))) { let content = await file.async("nodebuffer"); mergeLocale(ini.parse(content.toString("utf8")));