mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-24 17:30:59 -05:00
Added dependency definition for a NeoForge mod
This commit is contained in:
parent
13da08b518
commit
a49dd1f6e3
2 changed files with 187 additions and 0 deletions
125
src/loaders/neoforge/neoforge-dependency.ts
Normal file
125
src/loaders/neoforge/neoforge-dependency.ts
Normal file
|
@ -0,0 +1,125 @@
|
|||
import { ACTION_NAME } from "@/action";
|
||||
import { Dependency, createDependency } from "@/dependencies";
|
||||
import { PlatformType } from "@/platforms";
|
||||
import { $i } from "@/utils/collections";
|
||||
import { asString } from "@/utils/string-utils";
|
||||
import { PartialRecord } from "@/utils/types";
|
||||
import { NeoForgeDependencyType } from "./neoforge-dependency-type";
|
||||
import { NeoForgeEnvironmentType } from "./neoforge-environment-type";
|
||||
import { RawNeoForgeMetadata } from "./raw-neoforge-metadata";
|
||||
|
||||
/**
|
||||
* A dependency configuration for a NeoForge mod.
|
||||
*/
|
||||
export interface NeoForgeDependency {
|
||||
/**
|
||||
* The mod id of the dependency.
|
||||
*/
|
||||
modId: string;
|
||||
|
||||
/**
|
||||
* Whether to crash if this dependency is not met.
|
||||
*/
|
||||
mandatory?: boolean;
|
||||
|
||||
/**
|
||||
* The type of the dependency.
|
||||
*/
|
||||
type?: NeoForgeDependencyType;
|
||||
|
||||
/**
|
||||
* The acceptable version range of the dependency, expressed as a Maven version spec.
|
||||
*
|
||||
* An empty string is an unbounded version range, which matches any version.
|
||||
*/
|
||||
versionRange?: string;
|
||||
|
||||
/**
|
||||
* Defines if the mod must load before or after this dependency.
|
||||
*
|
||||
* The valid values are `BEFORE` (must load before), `AFTER` (must load after), and `NONE` (does not care about order).
|
||||
*
|
||||
* Defaults to `NONE`.
|
||||
*/
|
||||
ordering?: "BEFORE" | "AFTER" | "NONE";
|
||||
|
||||
/**
|
||||
* The physical side. The valid values are:
|
||||
*
|
||||
* - `CLIENT` (present on the client).
|
||||
* - `SERVER` (present on the dedicated server).
|
||||
* - `BOTH`, the default one, (present on both sides).
|
||||
*/
|
||||
side?: NeoForgeEnvironmentType;
|
||||
|
||||
/**
|
||||
* Custom action payload.
|
||||
*/
|
||||
[ACTION_NAME]?: NeoForgeDependencyCustomPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom payload attached to a NeoForge dependency.
|
||||
*/
|
||||
type NeoForgeDependencyCustomPayload = {
|
||||
/**
|
||||
* Indicates whether the dependency should be ignored globally,
|
||||
* or by the platforms specified in the given array.
|
||||
*/
|
||||
ignore?: boolean | PlatformType[];
|
||||
} & PartialRecord<PlatformType, string>;
|
||||
|
||||
/**
|
||||
* A list of special dependencies that should be ignored.
|
||||
*/
|
||||
const IGNORED_DEPENDENCIES: readonly string[] = [
|
||||
"minecraft",
|
||||
"java",
|
||||
"neoforge",
|
||||
];
|
||||
|
||||
/**
|
||||
* Retrieves NeoForge dependencies from the metadata.
|
||||
*
|
||||
* @param metadata - The raw NeoForge metadata.
|
||||
*
|
||||
* @returns An array of NeoForge dependencies.
|
||||
*/
|
||||
export function getNeoForgeDependencies(metadata: RawNeoForgeMetadata): NeoForgeDependency[] {
|
||||
const dependencyMap = $i(Object.values(metadata?.dependencies || {}))
|
||||
.filter(x => Array.isArray(x))
|
||||
.flatMap(x => x)
|
||||
.filter(x => x?.modId)
|
||||
.map(x => [x.modId, x] as const)
|
||||
.reverse()
|
||||
.toMap();
|
||||
|
||||
return [...dependencyMap.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@link FabricDependency} to a {@link Dependency} object.
|
||||
*
|
||||
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
|
||||
*/
|
||||
export function normalizeNeoForgeDependency(dependency: NeoForgeDependency): Dependency | undefined {
|
||||
const payload = dependency?.[ACTION_NAME] || {};
|
||||
|
||||
const id = dependency?.modId;
|
||||
const versions = dependency?.versionRange;
|
||||
const ignore = IGNORED_DEPENDENCIES.includes(dependency?.modId) || typeof payload.ignore === "boolean" && payload.ignore;
|
||||
const ignoredPlatforms = typeof payload.ignore === "boolean" ? undefined : payload.ignore;
|
||||
const aliases = $i(PlatformType.values()).map(type => [type, payload[type] ? asString(payload[type]) : undefined] as const).filter(([, id]) => id).toMap();
|
||||
const type = NeoForgeDependencyType.toDependencyType(
|
||||
dependency?.type || ((dependency?.mandatory ?? true) ? NeoForgeDependencyType.REQUIRED : NeoForgeDependencyType.OPTIONAL)
|
||||
);
|
||||
|
||||
return createDependency({
|
||||
id,
|
||||
versions,
|
||||
type,
|
||||
ignore,
|
||||
ignoredPlatforms,
|
||||
aliases,
|
||||
});
|
||||
}
|
62
tests/unit/loaders/neoforge/neoforge-dependency.spec.ts
Normal file
62
tests/unit/loaders/neoforge/neoforge-dependency.spec.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { DependencyType } from "@/dependencies/dependency-type";
|
||||
import { RawNeoForgeMetadata } from "@/loaders/neoforge/raw-neoforge-metadata";
|
||||
import { NeoForgeDependencyType } from "@/loaders/neoforge/neoforge-dependency-type";
|
||||
import { getNeoForgeDependencies, normalizeNeoForgeDependency } from "@/loaders/neoforge/neoforge-dependency";
|
||||
|
||||
describe("getNeoForgeDependencies", () => {
|
||||
test("returns an array of dependencies specified in the given metadata", () => {
|
||||
const metadata = {
|
||||
dependencies: {
|
||||
"example-mod": [
|
||||
{
|
||||
modId: "depends-id",
|
||||
versionRange: "[1.0.0,)",
|
||||
},
|
||||
{
|
||||
modId: "suggests-id",
|
||||
versionRange: "[2.0.0,)",
|
||||
mandatory: false,
|
||||
},
|
||||
],
|
||||
|
||||
"example-mod-2": [{
|
||||
modId: "breaks-id",
|
||||
versionRange: "[4.0.0,5.0.0]",
|
||||
type: NeoForgeDependencyType.INCOMPATIBLE,
|
||||
}],
|
||||
},
|
||||
} as unknown as RawNeoForgeMetadata;
|
||||
|
||||
const dependencies = getNeoForgeDependencies(metadata);
|
||||
|
||||
expect(dependencies).toEqual([
|
||||
{ modId: "breaks-id", versionRange: "[4.0.0,5.0.0]", type: NeoForgeDependencyType.INCOMPATIBLE },
|
||||
{ modId: "suggests-id", versionRange: "[2.0.0,)", mandatory: false },
|
||||
{ modId: "depends-id", versionRange: "[1.0.0,)" },
|
||||
]);
|
||||
});
|
||||
|
||||
test("returns an empty array if no dependencies were specified", () => {
|
||||
expect(getNeoForgeDependencies({} as RawNeoForgeMetadata)).toEqual([]);
|
||||
});
|
||||
|
||||
test("returns an empty array if metadata was null or undefined", () => {
|
||||
expect(getNeoForgeDependencies(null)).toEqual([]);
|
||||
expect(getNeoForgeDependencies(undefined)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("normalizeNeoForgeDependency", () => {
|
||||
test("converts NeoForge dependency to a more abstract Dependency object", () => {
|
||||
const neoforgeDependency = { modId: "suggests-id", type: NeoForgeDependencyType.OPTIONAL, versionRange: "[2.0.0,)" };
|
||||
|
||||
const dependency = normalizeNeoForgeDependency(neoforgeDependency);
|
||||
|
||||
expect(dependency).toMatchObject({ id: "suggests-id", versions: ["[2.0.0,)"], type: DependencyType.OPTIONAL });
|
||||
});
|
||||
|
||||
test("returns undefined if dependency was null or undefined", () => {
|
||||
expect(normalizeNeoForgeDependency(null)).toBeUndefined();
|
||||
expect(normalizeNeoForgeDependency(undefined)).toBeUndefined();
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue