mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 15:04:52 +09:00
Maintain strict tagging of GameVersion
This commit is contained in:
8 files changed
+37
-45
No files matched your search
@@ -763,12 +763,10 @@ export default class Controller {
|
||||
const serialized = rawJson as Static<typeof lib.ModPack.jsonSchema>[];
|
||||
return serialized.map(json => {
|
||||
for (const mod of json.mods) {
|
||||
// Older mod packs recorded builtins with a major.minor version; pad
|
||||
// those to major.minor.patch. Raw versions the game reads leniently
|
||||
// (e.g. with leading zeros) are kept verbatim so they still match the
|
||||
// mod's file name.
|
||||
// migrate: 2.0.0-alpha.22 - old buildins used X.Y rather than X.Y.Z
|
||||
// All other versions are kept verbatim so they still match the mod's file name.
|
||||
if (lib.isPartialVersion(mod.version)) {
|
||||
mod.version = lib.normaliseFullVersion(mod.version);
|
||||
mod.version = lib.normaliseFullVersion(mod.version) as lib.GameVersion;
|
||||
}
|
||||
}
|
||||
return json;
|
||||
|
||||
@@ -20,7 +20,7 @@ modCommands.add(new lib.Command({
|
||||
yargs.positional("mod-version", { describe: "Version of the mod", type: "string" });
|
||||
}],
|
||||
handler: async function(args: { name: string, modVersion: string }, control: Control) {
|
||||
if (!lib.isFullVersion(args.modVersion)) {
|
||||
if (!lib.isGameVersion(args.modVersion)) {
|
||||
throw new lib.CommandError("mod-version must match format digit.digit.digit");
|
||||
}
|
||||
let modInfo = await control.send(new lib.ModGetRequest(args.name, args.modVersion));
|
||||
@@ -191,7 +191,7 @@ modCommands.add(new lib.Command({
|
||||
yargs.positional("mod-version", { describe: "Version of mod to download", type: "string" });
|
||||
}],
|
||||
handler: async function(args: { name: string, modVersion: string }, control: Control) {
|
||||
if (!lib.isFullVersion(args.modVersion)) {
|
||||
if (!lib.isGameVersion(args.modVersion)) {
|
||||
throw new lib.CommandError("mod-version must match format digit.digit.digit");
|
||||
}
|
||||
let streamId = await control.send(new lib.ModDownloadRequest(args.name, args.modVersion));
|
||||
@@ -211,7 +211,7 @@ modCommands.add(new lib.Command({
|
||||
yargs.positional("mod-version", { describe: "Version of mod to delete", type: "string" });
|
||||
}],
|
||||
handler: async function(args: { name: string, modVersion: string }, control: Control) {
|
||||
if (!lib.isFullVersion(args.modVersion)) {
|
||||
if (!lib.isGameVersion(args.modVersion)) {
|
||||
throw new lib.CommandError("mod-version must match format digit.digit.digit");
|
||||
}
|
||||
await control.send(new lib.ModDeleteRequest(args.name, args.modVersion));
|
||||
|
||||
@@ -132,7 +132,7 @@ function setModPackMods(modPack: lib.ModPack, mods: string[] | undefined) {
|
||||
if (!version) {
|
||||
throw new lib.CommandError("Added mod must be formatted as name:version or name:version:sha1");
|
||||
}
|
||||
if (!lib.isFullVersion(version)) {
|
||||
if (!lib.isGameVersion(version)) {
|
||||
throw new lib.CommandError("version must match the format digit.digit.digit");
|
||||
}
|
||||
if (sha1 && !/^[0-9a-f]{40}$/.test(sha1)) {
|
||||
|
||||
@@ -8,8 +8,8 @@ import { findRoot } from "../zip_ops";
|
||||
import { ModRecord } from "./ModPack";
|
||||
|
||||
import {
|
||||
MajorMinorVersion, normaliseMajorMinorVersion, integerMajorMinorVersion,
|
||||
GameVersion, GameVersionSchema, normaliseGameVersion, integerGameVersion,
|
||||
MajorMinorVersion, MajorMinorVersionSchema, normaliseMajorMinorVersion, integerMajorMinorVersion,
|
||||
GameVersion, GameVersionSchema, isGameVersion, normaliseGameVersion, integerGameVersion,
|
||||
ModVersionEquality,
|
||||
} from "./version";
|
||||
|
||||
@@ -143,6 +143,10 @@ export default class ModInfo {
|
||||
return integerGameVersion(this.version);
|
||||
}
|
||||
|
||||
get normalisedVersion() {
|
||||
return normaliseGameVersion(this.version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display name of the mod.
|
||||
* Sourced from info.json.
|
||||
@@ -283,9 +287,7 @@ export default class ModInfo {
|
||||
// info.json fields
|
||||
if (json.name) { modInfo.name = json.name; }
|
||||
if (json.version) {
|
||||
// Validate that the raw version can be read, but keep it verbatim so
|
||||
// it still matches the mod's file name on disk and the portal.
|
||||
if (normaliseGameVersion(json.version) === undefined) {
|
||||
if (!isGameVersion(json.version)) {
|
||||
throw new Error(`Invalid mod version "${json.version}"`);
|
||||
}
|
||||
modInfo.version = json.version;
|
||||
@@ -330,7 +332,7 @@ export default class ModInfo {
|
||||
if (this.contact) { json.contact = this.contact; }
|
||||
if (this.homepage) { json.homepage = this.homepage; }
|
||||
if (this.description) { json.description = this.description; }
|
||||
if (this.factorioVersion !== "0.12") { json.factorio_version = this.factorioVersion; }
|
||||
if (this.factorioVersion !== "0.12") { json.factorio_version = this.factorioVersion as GameVersion; }
|
||||
if (this.dependencies.length !== 1 || this.dependencies[0].name !== "base") {
|
||||
json.dependencies = this.dependencySpecifications;
|
||||
}
|
||||
|
||||
@@ -434,24 +434,24 @@ export default class ModPack {
|
||||
* @return Built in mods for the given version
|
||||
*/
|
||||
static getBuiltinMods(factorioVersion: PartialVersion) {
|
||||
factorioVersion = normaliseFullVersion(factorioVersion);
|
||||
const version = normaliseFullVersion(factorioVersion) as GameVersion;
|
||||
const integerVersion = integerPartialVersion(factorioVersion);
|
||||
let defaultMods: ModRecord[] = [
|
||||
// "core" not included because core cannot be disabled
|
||||
{ name: "base", enabled: true, version: factorioVersion },
|
||||
{ name: "base", enabled: true, version: version },
|
||||
];
|
||||
|
||||
const integerVersion = integerPartialVersion(factorioVersion);
|
||||
if (integerVersion >= integerPartialVersion("1.2")) {
|
||||
defaultMods = defaultMods.concat([
|
||||
{ name: "elevated-rails", enabled: false, version: factorioVersion },
|
||||
{ name: "quality", enabled: false, version: factorioVersion },
|
||||
{ name: "space-age", enabled: false, version: factorioVersion },
|
||||
{ name: "elevated-rails", enabled: false, version: version },
|
||||
{ name: "quality", enabled: false, version: version },
|
||||
{ name: "space-age", enabled: false, version: version },
|
||||
]);
|
||||
}
|
||||
|
||||
if (integerVersion >= integerPartialVersion("2.1")) {
|
||||
defaultMods = defaultMods.concat([
|
||||
{ name: "recycler", enabled: false, version: factorioVersion },
|
||||
{ name: "recycler", enabled: false, version: version },
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,16 +37,13 @@ export const ApiVersions = ["0.13", "0.14", "0.15", "0.16", "0.17", "0.18", "1.0
|
||||
* not anchored at the end.
|
||||
*/
|
||||
const gameVersionRegExp = /^\s*(\d+)\.\s*(\d+)(?:\.\s*(\d+))?/;
|
||||
|
||||
/**
|
||||
* A raw, un-normalised version string exactly as the game reads it, such as a
|
||||
* mod's version taken from info.json or a mod file name. It is deliberately a
|
||||
* plain string alias so that any of the stricter, normalised version types
|
||||
* ({@link FullVersion}, {@link MajorMinorVersion}, {@link PartialVersion}) widen
|
||||
* into it for free, while a GameVersion can not be used where a normalised
|
||||
* version is required without going through {@link normaliseGameVersion} or
|
||||
* {@link integerGameVersion} first.
|
||||
* mod's version taken from info.json or a mod file name.
|
||||
*/
|
||||
export type GameVersion = string;
|
||||
declare const gameVersionSymbol: unique symbol;
|
||||
export type GameVersion = string & { [gameVersionSymbol]: void };
|
||||
export const GameVersionSchema = Type.Unsafe<GameVersion>(
|
||||
Type.String({ pattern: gameVersionRegExp.source })
|
||||
);
|
||||
@@ -63,7 +60,10 @@ export function isGameVersion(input: string): input is GameVersion {
|
||||
* @returns The normalised full version, or undefined if no major and minor
|
||||
* could be read.
|
||||
*/
|
||||
export function normaliseGameVersion(input: string): FullVersion | undefined {
|
||||
export function normaliseGameVersion(input: GameVersion): FullVersion;
|
||||
export function normaliseGameVersion(input: string): FullVersion | undefined;
|
||||
|
||||
export function normaliseGameVersion(input: string | GameVersion): FullVersion | undefined {
|
||||
const match = gameVersionRegExp.exec(input);
|
||||
if (match === null) {
|
||||
return undefined;
|
||||
@@ -71,19 +71,8 @@ export function normaliseGameVersion(input: string): FullVersion | undefined {
|
||||
return `${Number(match[1])}.${Number(match[2])}.${Number(match[3] ?? "0")}` as FullVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Integer representation of a raw {@link GameVersion}, normalised the same
|
||||
* lenient way the game reads it. Suitable for comparing versions that may carry
|
||||
* leading zeros, whitespace or trailing content.
|
||||
*
|
||||
* @throws if the input can not be read as a version.
|
||||
*/
|
||||
export function integerGameVersion(version: GameVersion) {
|
||||
const normalised = normaliseGameVersion(version);
|
||||
if (normalised === undefined) {
|
||||
throw new Error(`Invalid version "${version}"`);
|
||||
}
|
||||
return integerFullVersion(normalised);
|
||||
return integerFullVersion(normaliseGameVersion(version));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +276,10 @@ export class ModVersionRange {
|
||||
return this.minVersion.testIntegerVersion(other) && this.maxVersion.testIntegerVersion(other);
|
||||
}
|
||||
|
||||
testVersion(version: GameVersion) {
|
||||
testVersion(version: PartialVersion | GameVersion) {
|
||||
if (isPartialVersion(version)) {
|
||||
return this.testIntegerVersion(integerPartialVersion(version));
|
||||
}
|
||||
return this.testIntegerVersion(integerGameVersion(version));
|
||||
}
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ function DownloadDependenciesButton(props: DownloadDependenciesProps) {
|
||||
missing.map(mod => ({
|
||||
name: mod.name,
|
||||
// mod.version is the raw version; the equality bound must be canonical.
|
||||
version: new lib.ModVersionEquality("=", lib.normaliseGameVersion(mod.version)!),
|
||||
version: new lib.ModVersionEquality("=", mod.normalisedVersion),
|
||||
})),
|
||||
factorioVersion,
|
||||
)
|
||||
|
||||
@@ -170,7 +170,7 @@ function SearchModsButton() {
|
||||
if (modVersion) {
|
||||
control.send(
|
||||
new lib.ModPortalDownloadRequest(
|
||||
[{ name: modName, version: new lib.ModVersionEquality("=", lib.normaliseGameVersion(modVersion)!)}],
|
||||
[{ name: modName, version: new lib.ModVersionEquality("=", lib.normaliseGameVersion(modVersion))}],
|
||||
portalFactorioVersion
|
||||
)
|
||||
).then(() => {
|
||||
|
||||
Reference in new issue
Block a user