mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 15:04:52 +09:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d97b69b07 | ||
|
|
5b4621a7de |
No files matched your search
@@ -146,7 +146,7 @@ Your instances (save files etc) will be stored there.
|
||||
|
||||
Make sure to note down the admin authentication token it provides at the end as you will need it later.
|
||||
|
||||
3. If you chose to use local factorio directory for the Factorio installation, download the Windows 64-bit zip package from https://www.factorio.com/download and extract it to the `factorio` folder in your clusterio installation folder.
|
||||
3. If you chose to use the local `factorio` directory for the Factorio installation, you can let the installer download the latest headless release automatically, or manually download the Windows 64-bit zip package from https://www.factorio.com/download and extract it to the `factorio` folder in your clusterio installation folder.
|
||||
|
||||
|
||||
### MacOS Setup
|
||||
|
||||
+110
-16
@@ -43,6 +43,9 @@ const availablePlugins = [
|
||||
{ name: "Server Select", value: "@hornwitser/server_select" },
|
||||
];
|
||||
|
||||
const windowsHeadlessDownloadUrl = "https://factorio-repackager.fly.dev/get-download/latest/headless/win64";
|
||||
const headlessDownloadPlatforms = new Set(["linux", "win32"]);
|
||||
|
||||
const factorioLocations = {
|
||||
win32: [
|
||||
"C:\\Program Files\\Factorio",
|
||||
@@ -53,6 +56,10 @@ const factorioLocations = {
|
||||
],
|
||||
};
|
||||
|
||||
function supportsHeadlessDownload(platform = process.platform) {
|
||||
return headlessDownloadPlatforms.has(platform);
|
||||
}
|
||||
|
||||
|
||||
class LineSplitter extends stream.Transform {
|
||||
constructor(options) {
|
||||
@@ -647,14 +654,14 @@ async function inquirerMissingArgs(args) {
|
||||
foundLocations.push(location);
|
||||
}
|
||||
}
|
||||
if (process.platform === "linux") {
|
||||
if (supportsHeadlessDownload()) {
|
||||
if (args.hasOwnProperty("downloadHeadless")) { answers.downloadHeadless = args.downloadHeadless; }
|
||||
|
||||
answers = await inquirer.prompt([
|
||||
{
|
||||
type: "confirm",
|
||||
name: "downloadHeadless",
|
||||
message: "(Linux only) Automatically download latest factorio release?",
|
||||
message: "Automatically download latest headless Factorio release?",
|
||||
default: true,
|
||||
},
|
||||
], answers);
|
||||
@@ -671,7 +678,7 @@ async function inquirerMissingArgs(args) {
|
||||
message: "Path to Factorio installation",
|
||||
choices: [
|
||||
...foundLocations.map(location => ({ name: `${location} (auto detected)`, value: location })),
|
||||
{ name: "Use local factorio directory, you must copy an installation to it", value: "factorio" },
|
||||
{ name: "Use local factorio directory", value: "factorio" },
|
||||
{ name: "Provide path manually", value: null },
|
||||
],
|
||||
},
|
||||
@@ -801,6 +808,87 @@ async function downloadLinuxServer() {
|
||||
}
|
||||
}
|
||||
|
||||
async function getFactorioVersion(factorioDir) {
|
||||
const changelogPath = path.join(factorioDir, "data", "changelog.txt");
|
||||
const changelog = await fs.readFile(changelogPath, "utf8");
|
||||
for (const line of changelog.split(/\r?\n/)) {
|
||||
const index = line.indexOf(":");
|
||||
if (index === -1) {
|
||||
continue;
|
||||
}
|
||||
if (line.slice(0, index).trim().toLowerCase() === "version") {
|
||||
return line.slice(index + 1).trim();
|
||||
}
|
||||
}
|
||||
throw new Error(`Unable to detect Factorio version from ${changelogPath}`);
|
||||
}
|
||||
|
||||
async function findFactorioRoot(rootDir) {
|
||||
const entries = await fs.readdir(rootDir);
|
||||
const factorioRoot = entries.find(entry => entry === "factorio" || entry === "Factorio")
|
||||
?? (entries.length === 1 ? entries[0] : null);
|
||||
if (!factorioRoot) {
|
||||
throw new Error(`Unable to locate extracted Factorio directory in ${rootDir}`);
|
||||
}
|
||||
return path.join(rootDir, factorioRoot);
|
||||
}
|
||||
|
||||
async function downloadWindowsServer() {
|
||||
let res = await fetch(windowsHeadlessDownloadUrl);
|
||||
if (res.status === 202) {
|
||||
throw new Error("Latest Windows headless package is not ready yet, try again in a few minutes.");
|
||||
}
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch ${windowsHeadlessDownloadUrl}: HTTP ${res.status} ${res.statusText}`);
|
||||
}
|
||||
if (!res.body) {
|
||||
throw new Error("Windows headless download did not include an archive payload");
|
||||
}
|
||||
|
||||
const tmpDir = path.join("temp", "create-temp");
|
||||
const archivePath = path.join(tmpDir, "factorio-headless-win64.zip");
|
||||
const tmpArchivePath = `${archivePath}.tmp`;
|
||||
const tmpExtractDir = path.join(tmpDir, "win64-extract");
|
||||
|
||||
await fs.emptyDir(tmpDir);
|
||||
|
||||
logger.info("Downloading latest Windows headless release. This may take a while.");
|
||||
const writeStream = fs.createWriteStream(tmpArchivePath);
|
||||
stream.Readable.fromWeb(res.body).pipe(writeStream);
|
||||
await finished(writeStream);
|
||||
await fs.rename(tmpArchivePath, archivePath);
|
||||
|
||||
try {
|
||||
const expandArchiveCommand =
|
||||
`Expand-Archive -LiteralPath '${archivePath.replace(/'/g, "''")}' ` +
|
||||
`-DestinationPath '${tmpExtractDir.replace(/'/g, "''")}' -Force`;
|
||||
await execFile("powershell.exe", [
|
||||
"-NoProfile",
|
||||
"-NonInteractive",
|
||||
"-ExecutionPolicy",
|
||||
"Bypass",
|
||||
"-Command",
|
||||
expandArchiveCommand,
|
||||
]);
|
||||
} catch (err) {
|
||||
logger.error("error executing command - do you have PowerShell available?");
|
||||
throw err;
|
||||
}
|
||||
|
||||
const tmpFactorioDir = await findFactorioRoot(tmpExtractDir);
|
||||
const version = await getFactorioVersion(tmpFactorioDir);
|
||||
const factorioDir = path.join("factorio", version);
|
||||
|
||||
if (await fs.pathExists(factorioDir)) {
|
||||
logger.warn(`setting downloadDir to ${factorioDir}, but not downloading because already existing`);
|
||||
} else {
|
||||
await fs.ensureDir("factorio");
|
||||
await fs.rename(tmpFactorioDir, factorioDir);
|
||||
}
|
||||
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
async function main() {
|
||||
let args = yargs
|
||||
.option("log-level", {
|
||||
@@ -824,7 +912,7 @@ async function main() {
|
||||
nargs: 1, describe: "HTTP port to listen on [standalone/controller]", type: "number",
|
||||
})
|
||||
.option("download-headless", {
|
||||
describe: "Download the latest headless release [standalone/controller] [linux only]",
|
||||
describe: "Download the latest headless release [standalone/host]",
|
||||
type: "boolean", nargs: 0,
|
||||
})
|
||||
.option("host-name", {
|
||||
@@ -861,17 +949,17 @@ async function main() {
|
||||
;
|
||||
|
||||
if (process.platform === "linux") {
|
||||
args = args
|
||||
.option("allow-install-as-root", {
|
||||
nargs: 0, describe: "(Linux only) Allow installing as root (not recommended)", type: "boolean",
|
||||
})
|
||||
.option("download-headless", {
|
||||
nargs: 0,
|
||||
describe: "(Linux only) Automatically download and unpack the latest factorio release. " +
|
||||
"Can be set to false using --no-download-headless.",
|
||||
type: "boolean",
|
||||
})
|
||||
;
|
||||
args = args.option("allow-install-as-root", {
|
||||
nargs: 0, describe: "(Linux only) Allow installing as root (not recommended)", type: "boolean",
|
||||
});
|
||||
}
|
||||
if (supportsHeadlessDownload()) {
|
||||
args = args.option("download-headless", {
|
||||
nargs: 0,
|
||||
describe: "Automatically download and unpack the latest headless Factorio release. " +
|
||||
"Can be set to false using --no-download-headless.",
|
||||
type: "boolean",
|
||||
});
|
||||
}
|
||||
|
||||
args = args.argv;
|
||||
@@ -901,7 +989,13 @@ async function main() {
|
||||
if (answers.factorioDir !== "factorio") {
|
||||
throw new InstallError("--download-headless option requires --factorio-dir to be set to factorio");
|
||||
}
|
||||
await downloadLinuxServer();
|
||||
if (process.platform === "linux") {
|
||||
await downloadLinuxServer();
|
||||
} else if (process.platform === "win32") {
|
||||
await downloadWindowsServer();
|
||||
} else {
|
||||
throw new InstallError("--download-headless is only supported on Linux and Windows");
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
|
||||
+102
-36
@@ -19,7 +19,7 @@ const execFileAsync = util.promisify(child_process.execFile);
|
||||
* @param factorioDir - Path factorio dir containing data/changelog.txt.
|
||||
*/
|
||||
async function getFactorioVersion(factorioDir: string) {
|
||||
let changelog;
|
||||
let changelog: string;
|
||||
const changelogPath = path.join(factorioDir, "data", "changelog.txt");
|
||||
try {
|
||||
changelog = await fs.readFile(changelogPath, "utf-8");
|
||||
@@ -106,34 +106,40 @@ async function listFactorioVersions(factorioDir: string) {
|
||||
* @throws Network error if status of request is not ok
|
||||
*/
|
||||
async function downloadAndExtractZip(url: string, targetDir: string) {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
||||
}
|
||||
const res = await fetchDownload(url);
|
||||
|
||||
// Load the ZIP with JSZip
|
||||
// Load the ZIP with JSZip
|
||||
const buffer = Buffer.from(await res.arrayBuffer());
|
||||
const zip = await JSZip.loadAsync(buffer);
|
||||
const tmpTargetDir = `${targetDir}.tmp-extract`;
|
||||
const stripRootDir = hasSingleArchiveRoot(Object.values(zip.files));
|
||||
|
||||
// Extract each file/folder
|
||||
await fs.ensureDir(targetDir);
|
||||
await Promise.all(
|
||||
Object.values(zip.files).map(async (entry) => {
|
||||
const parts = entry.name.split("/").filter(Boolean);
|
||||
const strippedPath = parts.slice(1).join("/");
|
||||
if (!strippedPath) {
|
||||
return; // This copies the behaviour of tar --strip-components 1
|
||||
}
|
||||
await fs.remove(tmpTargetDir);
|
||||
await fs.ensureDir(tmpTargetDir);
|
||||
try {
|
||||
await Promise.all(
|
||||
Object.values(zip.files).map(async (entry) => {
|
||||
const parts = entry.name.split("/").filter(Boolean);
|
||||
const strippedParts = stripRootDir ? parts.slice(1) : parts;
|
||||
if (!strippedParts.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entryPath = path.join(targetDir, strippedPath);
|
||||
if (entry.dir) {
|
||||
await fs.ensureDir(entryPath);
|
||||
} else {
|
||||
await fs.ensureDir(path.dirname(entryPath));
|
||||
await fs.writeFile(entryPath, await entry.async("nodebuffer"));
|
||||
}
|
||||
})
|
||||
);
|
||||
const entryPath = validatedExtractPath(tmpTargetDir, strippedParts);
|
||||
if (entry.dir) {
|
||||
await fs.ensureDir(entryPath);
|
||||
} else {
|
||||
await fs.ensureDir(path.dirname(entryPath));
|
||||
await fs.writeFile(entryPath, await entry.async("nodebuffer"));
|
||||
}
|
||||
})
|
||||
);
|
||||
await fs.remove(targetDir);
|
||||
await fs.rename(tmpTargetDir, targetDir);
|
||||
} catch (err) {
|
||||
await fs.remove(tmpTargetDir);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,10 +150,7 @@ async function downloadAndExtractZip(url: string, targetDir: string) {
|
||||
* @throws Network error if status of request is not ok
|
||||
*/
|
||||
async function downloadAndExtractTar(url: string, targetDir: string) {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
||||
}
|
||||
const res = await fetchDownload(url);
|
||||
|
||||
// Write the buffer to a temp file
|
||||
const tmpFilePath = `${targetDir}.tmp`;
|
||||
@@ -157,7 +160,9 @@ async function downloadAndExtractTar(url: string, targetDir: string) {
|
||||
|
||||
// Execute tar CLI to extract
|
||||
try {
|
||||
await execFileAsync("tar", ["-xf", tmpFilePath, "-C", targetDir, "--strip-components", "1"]);
|
||||
await execFileAsync("tar", [
|
||||
"-xf", tarPath(tmpFilePath), "-C", tarPath(targetDir), "--strip-components", "1",
|
||||
]);
|
||||
} catch (err: any) {
|
||||
if (err.code === "ENOENT") {
|
||||
throw new Error("error executing tar command, do you have 'xz-utils' installed?");
|
||||
@@ -169,6 +174,57 @@ async function downloadAndExtractTar(url: string, targetDir: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchDownload(url: string) {
|
||||
const res = await fetch(url);
|
||||
if (res.status === 202) {
|
||||
let detail = "";
|
||||
try {
|
||||
detail = await res.text();
|
||||
} catch {
|
||||
}
|
||||
throw new Error(`Download is not ready yet for ${url}${detail ? `: ${detail}` : ""}`);
|
||||
}
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function tarPath(filePath: string) {
|
||||
if (process.platform === "win32") {
|
||||
return filePath.replace(/\\/g, "/");
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
function hasSingleArchiveRoot(entries: JSZip.JSZipObject[]) {
|
||||
const rootNames = new Set(
|
||||
entries
|
||||
.map(entry => entry.name.split("/").filter(Boolean)[0])
|
||||
.filter((value): value is string => Boolean(value))
|
||||
);
|
||||
return rootNames.size === 1;
|
||||
}
|
||||
|
||||
function validatedExtractPath(rootDir: string, parts: string[]) {
|
||||
const entryPath = path.resolve(rootDir, ...parts);
|
||||
const relative = path.relative(rootDir, entryPath);
|
||||
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
||||
throw new Error(`Refusing to extract unsafe ZIP entry ${parts.join("/")}`);
|
||||
}
|
||||
return entryPath;
|
||||
}
|
||||
|
||||
function getHeadlessDownload(version: lib.ExternalFactorioVersion) {
|
||||
if (process.platform === "linux") {
|
||||
return { url: version.headlessUrl, extract: downloadAndExtractTar };
|
||||
}
|
||||
if (process.platform === "win32" && version.windowsHeadlessUrl) {
|
||||
return { url: version.windowsHeadlessUrl, extract: downloadAndExtractZip };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find factorio data directory of the given version
|
||||
*
|
||||
@@ -749,7 +805,7 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
|
||||
;
|
||||
|
||||
let type = line.subarray(channelEnd + 1, channelEnd + 2).toString("utf-8");
|
||||
let content;
|
||||
let content: unknown;
|
||||
if (type === "j") {
|
||||
try {
|
||||
content = JSON.parse(line.subarray(channelEnd + 2).toString("utf-8"));
|
||||
@@ -905,7 +961,7 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
|
||||
return;
|
||||
}
|
||||
|
||||
let newWhitelistJson;
|
||||
let newWhitelistJson: unknown;
|
||||
try {
|
||||
newWhitelistJson = await fs.readJSON(filePath);
|
||||
} catch (err: any) {
|
||||
@@ -985,8 +1041,8 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
|
||||
const installedVersions = await listFactorioVersions(this._factorioDir);
|
||||
if (!installedVersions.versions.has(latestVersion.version)) {
|
||||
const v = latestVersion.version;
|
||||
// Can't download if not linux or this is a direct install
|
||||
if (installedVersions.direct || process.platform !== "linux") {
|
||||
const download = getHeadlessDownload(latestVersion);
|
||||
if (installedVersions.direct || !download) {
|
||||
this._logger.info(`A newer version of factorio is available (${v}) but must be manually downloaded`);
|
||||
return;
|
||||
}
|
||||
@@ -994,8 +1050,18 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
|
||||
// Download the newer version
|
||||
this._logger.info(`A newer version of factorio is available (${v}), starting download...`);
|
||||
const dst = path.join(this._factorioDir, latestVersion.version);
|
||||
await downloadAndExtractTar(latestVersion.headlessUrl, dst);
|
||||
this._logger.info(`Downloaded factorio version ${v}`);
|
||||
try {
|
||||
await download.extract(download.url, dst);
|
||||
this._logger.info(`Downloaded factorio version ${v}`);
|
||||
} catch (err: unknown) {
|
||||
if (installedVersions.versions.size > 0) {
|
||||
this._logger.warn(
|
||||
`Failed to download factorio version ${v}, continuing with installed versions: ${err}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1051,7 +1117,7 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
|
||||
}
|
||||
|
||||
} else if (this._unexpected.length === 0) {
|
||||
let msg;
|
||||
let msg: string;
|
||||
if (code !== null) {
|
||||
msg = `Factorio server unexpectedly shut down with code ${code}`;
|
||||
} else {
|
||||
|
||||
+9
-5
@@ -2,6 +2,7 @@ import { Static, Type } from "@sinclair/typebox";
|
||||
import { FullVersionSchema, integerFullVersion, isFullVersion } from "../data/version";
|
||||
|
||||
const ARCHIVE_URL = "https://factorio.com/download/archive/";
|
||||
const WINDOWS_HEADLESS_BASE_URL = "https://factorio-repackager.fly.dev/get-download";
|
||||
|
||||
/**
|
||||
* Represents the parsed result of a factorio version
|
||||
@@ -10,9 +11,10 @@ export const ExternalFactorioVersionSchema = Type.Object({
|
||||
stable: Type.Boolean(),
|
||||
version: FullVersionSchema,
|
||||
headlessUrl: Type.String(),
|
||||
windowsHeadlessUrl: Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
export type ExternalFactorioVersion = Static<typeof ExternalFactorioVersionSchema>
|
||||
export type ExternalFactorioVersion = Static<typeof ExternalFactorioVersionSchema>;
|
||||
|
||||
/**
|
||||
* Fetch all factorio versions that support headless
|
||||
@@ -21,7 +23,7 @@ export type ExternalFactorioVersion = Static<typeof ExternalFactorioVersionSchem
|
||||
* @throws Network errors and non-ok status responses
|
||||
*/
|
||||
export async function fetchFactorioVersions(): Promise<ExternalFactorioVersion[]> {
|
||||
let res;
|
||||
let res: Response;
|
||||
|
||||
try {
|
||||
res = await fetch(ARCHIVE_URL);
|
||||
@@ -48,11 +50,11 @@ function parseFactorioVersions(html: string): ExternalFactorioVersion[] {
|
||||
|
||||
// Match <a class=" slot-button-inline version-button-stable " href="/download/archive/2.0.72">2.0.72</a>
|
||||
// eslint-disable-next-line max-len
|
||||
const anchorRegex = /<a[^>]*class="[^"]*version-button-(?<kind>stable|experimental)[^"]*"[^>]*href="[^"]*\/download\/archive\/(?<version>\d+\.\d+.\d+)"[^>]*>/g;
|
||||
const anchorRegex = /<a[^>]*class="[^"]*version-button-(?<kind>stable|experimental)[^"]*"[^>]*href="[^"]*\/download\/archive\/(?<version>\d+\.\d+\.\d+)"[^>]*>/g;
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
let match = anchorRegex.exec(html);
|
||||
const minimumMultiplayerVersion = integerFullVersion("0.12.35");
|
||||
while ((match = anchorRegex.exec(html)) !== null) {
|
||||
while (match !== null) {
|
||||
const kind = match.groups?.kind;
|
||||
const version = match.groups?.version;
|
||||
|
||||
@@ -61,8 +63,10 @@ function parseFactorioVersions(html: string): ExternalFactorioVersion[] {
|
||||
version: version,
|
||||
stable: kind === "stable",
|
||||
headlessUrl: `https://www.factorio.com/get-download/${version}/headless/linux64`,
|
||||
windowsHeadlessUrl: `${WINDOWS_HEADLESS_BASE_URL}/${version}/headless/win64`,
|
||||
});
|
||||
}
|
||||
match = anchorRegex.exec(html);
|
||||
}
|
||||
|
||||
return [...versions.values()];
|
||||
|
||||
+36
-12
@@ -364,10 +364,12 @@ describe("host/server", function() {
|
||||
stable: true,
|
||||
version: "0.2.1",
|
||||
headlessUrl: "test1",
|
||||
windowsHeadlessUrl: "win-test1",
|
||||
}, {
|
||||
stable: false,
|
||||
version: "0.2.0",
|
||||
headlessUrl: "test2",
|
||||
windowsHeadlessUrl: "win-test2",
|
||||
}]);
|
||||
|
||||
assert.equal(fetchCalledWith, null);
|
||||
@@ -380,10 +382,12 @@ describe("host/server", function() {
|
||||
stable: true,
|
||||
version: "0.1.1",
|
||||
headlessUrl: "test1",
|
||||
windowsHeadlessUrl: "win-test1",
|
||||
}, {
|
||||
stable: false,
|
||||
version: "0.1.0",
|
||||
headlessUrl: "test2",
|
||||
windowsHeadlessUrl: "win-test2",
|
||||
}]);
|
||||
|
||||
assert.equal(fetchCalledWith, null);
|
||||
@@ -395,21 +399,28 @@ describe("host/server", function() {
|
||||
stable: true,
|
||||
version: "0.1.5",
|
||||
headlessUrl: "test1",
|
||||
windowsHeadlessUrl: "win-test1",
|
||||
}, {
|
||||
stable: true,
|
||||
version: "0.1.1",
|
||||
headlessUrl: "test1",
|
||||
windowsHeadlessUrl: "win-test1",
|
||||
}, {
|
||||
stable: false,
|
||||
version: "0.1.0",
|
||||
headlessUrl: "test2",
|
||||
windowsHeadlessUrl: "win-test2",
|
||||
}]);
|
||||
|
||||
assert.equal(fetchCalledWith, null);
|
||||
});
|
||||
it("should do nothing when on windows", async function() {
|
||||
let logLine = null;
|
||||
server._logger = { info: line => { logLine = line; } };
|
||||
it("should do attempt to download on windows", async function() {
|
||||
let infoLine = null;
|
||||
let warnLine = null;
|
||||
server._logger = {
|
||||
info: line => { infoLine = line; },
|
||||
warn: line => { warnLine = line; },
|
||||
};
|
||||
Object.defineProperty(process, "platform", { value: "win32" });
|
||||
|
||||
server._factorioDir = path.join("test", "file", "factorio");
|
||||
@@ -418,44 +429,56 @@ describe("host/server", function() {
|
||||
stable: true,
|
||||
version: "0.1.5",
|
||||
headlessUrl: "test1",
|
||||
windowsHeadlessUrl: "win-test1",
|
||||
}, {
|
||||
stable: true,
|
||||
version: "0.1.1",
|
||||
headlessUrl: "test2",
|
||||
windowsHeadlessUrl: "win-test2",
|
||||
}, {
|
||||
stable: false,
|
||||
version: "0.1.0",
|
||||
headlessUrl: "test3",
|
||||
windowsHeadlessUrl: "win-test3",
|
||||
}]);
|
||||
|
||||
assert.equal(fetchCalledWith, null);
|
||||
assert.ok(logLine !== null);
|
||||
assert.ok(logLine.endsWith("but must be manually downloaded"));
|
||||
assert.equal(fetchCalledWith, "win-test1");
|
||||
assert.ok(infoLine !== null);
|
||||
assert.ok(infoLine.endsWith("starting download..."));
|
||||
assert.ok(warnLine?.includes("continuing with installed versions"));
|
||||
});
|
||||
it("should do attempt to download on linux", async function() {
|
||||
let logLine = null;
|
||||
server._logger = { info: line => { logLine = line; } };
|
||||
let infoLine = null;
|
||||
let warnLine = null;
|
||||
server._logger = {
|
||||
info: line => { infoLine = line; },
|
||||
warn: line => { warnLine = line; },
|
||||
};
|
||||
Object.defineProperty(process, "platform", { value: "linux" });
|
||||
|
||||
server._factorioDir = path.join("test", "file", "factorio");
|
||||
server._targetVersion = target === "0.1.1" ? "0.1.5" : target;
|
||||
await assert.rejects(server.checkForUpdates([{
|
||||
await server.checkForUpdates([{
|
||||
stable: true,
|
||||
version: "0.1.5",
|
||||
headlessUrl: "test1",
|
||||
windowsHeadlessUrl: "win-test1",
|
||||
}, {
|
||||
stable: true,
|
||||
version: "0.1.1",
|
||||
headlessUrl: "test2",
|
||||
windowsHeadlessUrl: "win-test2",
|
||||
}, {
|
||||
stable: false,
|
||||
version: "0.1.0",
|
||||
headlessUrl: "test3",
|
||||
}]), new Error("Failed to fetch test1: -1 Fetch called"));
|
||||
windowsHeadlessUrl: "win-test3",
|
||||
}]);
|
||||
|
||||
assert.equal(fetchCalledWith, "test1");
|
||||
assert.ok(logLine !== null);
|
||||
assert.ok(logLine.endsWith("starting download..."));
|
||||
assert.ok(infoLine !== null);
|
||||
assert.ok(infoLine.endsWith("starting download..."));
|
||||
assert.ok(warnLine?.includes("continuing with installed versions"));
|
||||
});
|
||||
});
|
||||
/* eslint-enable no-loop-func */
|
||||
@@ -474,6 +497,7 @@ describe("host/server", function() {
|
||||
stable: true,
|
||||
version: "2.0.73",
|
||||
headlessUrl: "https://www.factorio.com/get-download/2.0.73/headless/linux64",
|
||||
windowsHeadlessUrl: "https://factorio-repackager.fly.dev/get-download/2.0.73/headless/win64",
|
||||
}]);
|
||||
});
|
||||
});
|
||||
|
||||
+3
@@ -55,11 +55,13 @@ describe("FactorioVersions", function() {
|
||||
stable: false,
|
||||
version: "2.0.73",
|
||||
headlessUrl: "https://www.factorio.com/get-download/2.0.73/headless/linux64",
|
||||
windowsHeadlessUrl: "https://factorio-repackager.fly.dev/get-download/2.0.73/headless/win64",
|
||||
},
|
||||
{
|
||||
stable: true,
|
||||
version: "2.0.72",
|
||||
headlessUrl: "https://www.factorio.com/get-download/2.0.72/headless/linux64",
|
||||
windowsHeadlessUrl: "https://factorio-repackager.fly.dev/get-download/2.0.72/headless/win64",
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -91,6 +93,7 @@ describe("FactorioVersions", function() {
|
||||
stable: true,
|
||||
version: "2.0.73",
|
||||
headlessUrl: "https://www.factorio.com/get-download/2.0.73/headless/linux64",
|
||||
windowsHeadlessUrl: "https://factorio-repackager.fly.dev/get-download/2.0.73/headless/win64",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user