Find a full install in host.factorio_directory instead of a setting

Per review, drop host.factorio_graphics_directory. findVersion takes a
headless option that filters installs by build, telling them apart by
data/base/graphics/icons. When the instance runs the headless build the
export looks for a full install of the same major.minor version in the
host's factorio directory. Server startup is unchanged.

If none is found the export still runs, and the reason is included in
the missing icons warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bbassieandClaude Opus 5.5 committed 2026-11-01 20:53:05 +00:00
1 parent 46c6153201
commit 37d74ca2a6
10 files changed
+132 -65

No files matched your search

File renamed without changes.

Before

Width:  |  Height:  |  Size: 206 B

After

Width:  |  Height:  |  Size: 206 B

@@ -0,0 +1,3 @@
---------------------------------------------------------------------------------------------------
Version: 0.1.2
About: Dummy changelog.txt for FactorioServer tests
@@ -0,0 +1,3 @@
---------------------------------------------------------------------------------------------------
Version: 0.1.2
About: Dummy changelog.txt for FactorioServer tests
+31 -15
View File
@@ -74,7 +74,7 @@ describe("host/src/export", function() {
});
// Stands in for the data dir of a full install
const graphicsDataDir = path.join("test", "file", "factorio-graphics");
const graphicsDataDir = path.join("test", "file", "factorio-mixed", "full", "data");
describe("loadSimpleIcon()", function() {
it("defaults icon_size to 64", async function() {
const icon = await _loadSimpleIcon(
@@ -124,21 +124,29 @@ describe("host/src/export", function() {
});
describe("findGraphicsDataDir()", function() {
const installs = path.join("test", "file", "factorio");
it("returns the data dir of the install matching the server version", async function() {
const dataDir = await _findGraphicsDataDir(testServer, installs);
assert.equal(dataDir, path.join(installs, "0.1.2", "data"));
assert.deepEqual(warnings, []);
const withInstalls = (factorioDir, version = testServer.version) => Object.create(testServer, {
_factorioDir: { value: factorioDir }, version: { value: version },
});
it("warns and returns undefined when no install matches the server version", async function() {
const server = Object.create(testServer, { version: { value: "0.2.5" } });
assert.equal(await _findGraphicsDataDir(server, installs), undefined);
assert.equal(warnings.length, 1);
assert.match(warnings[0], /^Unable to use host\.factorio_graphics_directory for Factorio 0\.2, /);
it("finds a full install matching the major and minor version of the server", async function() {
const files = { zipCache: new Map() };
await _findGraphicsDataDir(withInstalls(path.join("test", "file", "factorio"), "0.1.1"), files);
assert.deepEqual(files, { zipCache: new Map(), graphicsDataDir: path.join(installs, "0.1.2", "data") });
});
it("warns and returns undefined when the directory does not exist", async function() {
assert.equal(await _findGraphicsDataDir(testServer, path.join("test", "file", "missing")), undefined);
assert.equal(warnings.length, 1);
assert.match(warnings[0], /^Unable to use host\.factorio_graphics_directory for Factorio 0\.1, .*ENOENT/);
it("skips headless installs of the same version", async function() {
const files = { zipCache: new Map() };
await _findGraphicsDataDir(withInstalls(path.join("test", "file", "factorio-mixed")), files);
assert.equal(files.graphicsDataDir, graphicsDataDir);
});
it("records why when there is no full install", async function() {
const files = { zipCache: new Map() };
await _findGraphicsDataDir(withInstalls(installs, "0.2.5"), files);
assert.equal(files.graphicsDataDir, undefined);
assert.equal(files.graphicsError, "Unable to find full Factorio version 0.2");
});
it("records why when the directory does not exist", async function() {
const files = { zipCache: new Map() };
await _findGraphicsDataDir(withInstalls(path.join("test", "file", "missing")), files);
assert.match(files.graphicsError, /ENOENT/);
});
});
describe("warnMissingBuiltinIcons()", function() {
@@ -151,7 +159,15 @@ describe("host/src/export", function() {
]));
assert.equal(warnings.length, 1);
assert.match(warnings[0], /^2 icon files of the base game were not found/);
assert.match(warnings[0], /headless/);
assert.doesNotMatch(warnings[0], /headless/);
});
it("explains the headless build when no full install was found", function() {
_warnMissingBuiltinIcons(testServer, { zipCache: new Map(), graphicsError: "Not found" }, new Map([
["__base__/graphics/icons/a.png", null],
]));
assert.equal(warnings.length, 1);
assert.match(warnings[0], /has no graphics and no full install was found \(Not found\)/);
assert.match(warnings[0], /Add a full install of Factorio 0\.1 to host\.factorio_directory/);
});
it("does not warn when no builtin files are missing", function() {
_warnMissingBuiltinIcons(testServer, { zipCache: new Map() }, new Map([
+27
View File
@@ -105,6 +105,33 @@ describe("host/server", function() {
);
});
});
describe("headless option", function() {
const mixedDir = path.join("test", "file", "factorio-mixed");
it("should find only full installs when false", async function() {
const [dir] = await hostServer.findVersion(mixedDir, "0.1.2", { headless: false });
assert.equal(dir, path.join(mixedDir, "full", "data"));
});
it("should find only headless installs when true", async function() {
const [dir] = await hostServer.findVersion(mixedDir, "0.1.2", { headless: true });
assert.equal(dir, path.join(mixedDir, "headless", "data"));
});
it("should reject a direct install of the other build", async function() {
const installDir = path.join(mixedDir, "headless");
await assert.rejects(
hostServer.findVersion(installDir, "0.1.2", { headless: false }),
new Error(
`Unable to find a full install of Factorio 0.1.2: ${installDir} is a direct ` +
"(single-version) install of the headless build."
)
);
});
it("should reject if no install of that build has the version", async function() {
await assert.rejects(
hostServer.findVersion(path.join("test", "file", "factorio"), "0.1.2", { headless: true }),
new Error("Unable to find headless Factorio version 0.1.2")
);
});
});
});
describe("_listFactorioVersions()", function() {