Server/project/src/loaders/BundleLoader.ts

84 lines
2.6 KiB
TypeScript
Raw Normal View History

import path from "node:path";
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
import { BundleHashCacheService } from "@spt/services/cache/BundleHashCacheService";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { VFS } from "@spt/utils/VFS";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { inject, injectable } from "tsyringe";
2023-03-03 15:23:46 +00:00
export class BundleInfo {
modpath: string;
filename: string;
crc: number;
dependencies: string[];
2023-03-03 15:23:46 +00:00
constructor(modpath: string, bundle: BundleManifestEntry, bundleHash: number) {
this.modpath = modpath;
this.filename = bundle.key;
this.crc = bundleHash;
this.dependencies = bundle.dependencyKeys || [];
2023-03-03 15:23:46 +00:00
}
}
@injectable()
export class BundleLoader {
2023-03-03 15:23:46 +00:00
protected bundles: Record<string, BundleInfo> = {};
constructor(
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper,
@inject("VFS") protected vfs: VFS,
2023-11-15 20:35:05 -05:00
@inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("BundleHashCacheService") protected bundleHashCacheService: BundleHashCacheService,
@inject("PrimaryCloner") protected cloner: ICloner,
) {}
2023-03-03 15:23:46 +00:00
2023-07-15 11:00:35 +01:00
/**
* Handle singleplayer/bundles
*/
public getBundles(): BundleInfo[] {
2023-03-03 15:23:46 +00:00
const result: BundleInfo[] = [];
for (const bundle in this.bundles) {
result.push(this.getBundle(bundle));
2023-03-03 15:23:46 +00:00
}
return result;
}
public getBundle(key: string): BundleInfo {
return this.cloner.clone(this.bundles[key]);
2023-03-03 15:23:46 +00:00
}
public addBundles(modpath: string): void {
const bundleManifestArr = this.jsonUtil.deserialize<BundleManifest>(
this.vfs.readFile(`${modpath}bundles.json`),
).manifest;
2023-03-03 15:23:46 +00:00
for (const bundleManifest of bundleManifestArr) {
Changed mod path for loading bundles from the server to be relative (!389) **Before merging: Please test on a real Windows installation if possible!** I tested this on Linux as well as inside a Windows VM hosted on Linux, but wasn't able to test it on a real Windows installation. This commit fixes an issue with loading bundles from a native Linux server: When compiling the server natively for Linux & installing some mods, everything works except for mods trying to load bundles from the server. Reason is a malformed path to the bundle: ```ts 2024-07-30 23:48:16.968 +02:00|0.14.9.1.30626|Error|Default| EXCEPTION: System.IO.DirectoryNotFoundException: Could not find a part of the path "C:\home\USER\Games\escape-from-tarkov\drive_c\SPTarkov\user\mods\Bloody-Bullet-Wounds\bundles\assets\systems\effects\particlesystems\effects.bundle". ``` `process.cwd()` returns the linux-agnostic path of course, but for some reason it also returns `C:`. Changing the line to `modpath.slice(0, -1).replace(/\\/g, "/");` seems to work and the bundles seem to get loaded without issues (did a quick test raid), even without passing the absolute path to the mod. I tried to check why that is, and I think node is able to [get the cwd and resolve the relative path](https://github.com/nodejs/node/blob/4d1d88118b39d26aa33caa87e413683595d14788/src/path.cc#L101) by itself.. Reviewed-on: https://dev.sp-tarkov.com/SPT/Server/pulls/389 Co-authored-by: MadByte <madbyte@noreply.dev.sp-tarkov.com> Co-committed-by: MadByte <madbyte@noreply.dev.sp-tarkov.com> (cherry picked from commit 6f010acfca8ec57105a3cd3bc959ed61be206e13)
2024-07-31 14:14:56 +00:00
const relativeModPath = modpath.slice(0, -1).replace(/\\/g, "/");
const bundleLocalPath = `${modpath}bundles/${bundleManifest.key}`.replace(/\\/g, "/");
if (!this.bundleHashCacheService.calculateAndMatchHash(bundleLocalPath)) {
this.bundleHashCacheService.calculateAndStoreHash(bundleLocalPath);
}
const bundleHash = this.bundleHashCacheService.getStoredValue(bundleLocalPath);
Changed mod path for loading bundles from the server to be relative (!389) **Before merging: Please test on a real Windows installation if possible!** I tested this on Linux as well as inside a Windows VM hosted on Linux, but wasn't able to test it on a real Windows installation. This commit fixes an issue with loading bundles from a native Linux server: When compiling the server natively for Linux & installing some mods, everything works except for mods trying to load bundles from the server. Reason is a malformed path to the bundle: ```ts 2024-07-30 23:48:16.968 +02:00|0.14.9.1.30626|Error|Default| EXCEPTION: System.IO.DirectoryNotFoundException: Could not find a part of the path "C:\home\USER\Games\escape-from-tarkov\drive_c\SPTarkov\user\mods\Bloody-Bullet-Wounds\bundles\assets\systems\effects\particlesystems\effects.bundle". ``` `process.cwd()` returns the linux-agnostic path of course, but for some reason it also returns `C:`. Changing the line to `modpath.slice(0, -1).replace(/\\/g, "/");` seems to work and the bundles seem to get loaded without issues (did a quick test raid), even without passing the absolute path to the mod. I tried to check why that is, and I think node is able to [get the cwd and resolve the relative path](https://github.com/nodejs/node/blob/4d1d88118b39d26aa33caa87e413683595d14788/src/path.cc#L101) by itself.. Reviewed-on: https://dev.sp-tarkov.com/SPT/Server/pulls/389 Co-authored-by: MadByte <madbyte@noreply.dev.sp-tarkov.com> Co-committed-by: MadByte <madbyte@noreply.dev.sp-tarkov.com> (cherry picked from commit 6f010acfca8ec57105a3cd3bc959ed61be206e13)
2024-07-31 14:14:56 +00:00
this.addBundle(bundleManifest.key, new BundleInfo(relativeModPath, bundleManifest, bundleHash));
2023-03-03 15:23:46 +00:00
}
}
public addBundle(key: string, b: BundleInfo): void {
this.bundles[key] = b;
}
2023-03-03 15:23:46 +00:00
}
export interface BundleManifest {
manifest: BundleManifestEntry[];
2023-03-03 15:23:46 +00:00
}
export interface BundleManifestEntry {
key: string;
dependencyKeys: string[];
2023-11-15 20:35:05 -05:00
}