Files
Nitro_Render_V3/packages/session/src/product/ProductDataLoader.ts
T
medievalshell ae9bc8bfce feat(utils): split-aware gamedata loader with tiered merge
Introduces loadGamedata(url, options?) and mergeGamedata(a, b) in
@nitrots/utils. The loader transparently accepts:

- a single-file URL (legacy) -> parsed as before
- a directory URL ending with '/' -> tier-merged from core/custom/seasonal,
  each tier driven by its own manifest.json5

Merge rules:

- arrays of objects sharing an id key (id, classname, name): merged by id,
  later layers overriding earlier ones
- arrays without an id key: concatenated
- plain objects: recursive merge per key
- anything else: later value wins

All gamedata consumers (FurnitureDataLoader, ProductDataLoader,
EffectAssetDownloadManager, AvatarRenderManager actions+figuredata,
LocalizationManager) are migrated to loadGamedata. Behaviour is unchanged
for single-file URLs, so existing deployments need no config changes;
opt-in to split mode by appending '/' to the URL once the layout is in
place.

README updated with the directory layout, merge table and programmatic
usage example. The companion CLI splitter that produces the core/ tier
from legacy files lives in the Nitro V3 client repo.
2026-05-18 21:19:54 +02:00

42 lines
1.3 KiB
TypeScript

import { IProductData } from '@nitrots/api';
import { GetConfiguration } from '@nitrots/configuration';
import { loadGamedata } from '@nitrots/utils';
import { ProductData } from './ProductData';
export class ProductDataLoader
{
private _products: Map<string, IProductData>;
constructor(products: Map<string, IProductData>)
{
this._products = products;
}
public async init(): Promise<void>
{
const url = GetConfiguration().getValue<string>('productdata.url');
if(!url || !url.length) throw new Error('Missing "productdata.url" in config — add the product data URL to your renderer-config.json');
let responseData: any;
try
{
responseData = await loadGamedata(url);
}
catch(err)
{
throw new Error(`Could not load product data from "${ url }" — check "productdata.url" in renderer-config.json (${ err?.message || err })`);
}
this.parseProducts(responseData.productdata);
}
private parseProducts(data: { [index: string]: any }): void
{
if(!data) return;
for(const product of data.product) (product && this._products.set(product.code, new ProductData(product.code, product.name, product.description)));
}
}