mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-20 23:58:33 +02:00
The engine behind 'add more 2D tilesets / iso packs / 3D skins as products'. A pack is a self-contained render environment for a projection (topdown/iso/3d); because scenes are kind-based, the SAME pack renders both town and dungeon (interchangeable), and each maps to a catalog id (monetizable, entitlement-gated). - packRegistry.js: registerPack / packsForProjection / unlockedPacks (canUsePack) / activePackId (saved-if-unlocked else first unlocked) / setActivePack / activePackAssets. Per-projection active-pack selection, persisted. In-memory store fallback so it's testable under Node. - assetPacks: registers the 3 built-ins (roguelike-interior topdown, iso-dungeon, kenney-3d-characters) + activeIsoAssets()/activeThreeAssets() resolvers; RK.theme() now defaults to the active topdown pack. - isoRenderer + avatarVisuals (iso/3d character lookup) read the ACTIVE pack. - packRegistry loaded before assetPacks in tavern + game. Backward-compatible: one pack per projection resolves to today's defaults — nothing changes visually. Adding a pack now = registerPack(...) + assets + a catalog row. Tests: +5 (register/list, unlock filter, active/saved/fallback, refuse locked). Suite 58 suites / 419 tests green.
51 lines
2.1 KiB
JavaScript
51 lines
2.1 KiB
JavaScript
/**
|
|
* Pack registry — the engine for multi-pack, interchangeable render environments (products).
|
|
*/
|
|
describe('pack registry', () => {
|
|
let RK;
|
|
beforeEach(() => { jest.resetModules(); RK = require('../html/js/render/packRegistry'); });
|
|
|
|
function seed() {
|
|
RK.registerPack({ id: 'topA', label: 'A', projection: 'topdown', assets: { a: 1 } });
|
|
RK.registerPack({ id: 'isoFree', label: 'IsoFree', projection: 'iso', assets: { i: 1 } });
|
|
RK.registerPack({ id: 'isoPrem', label: 'IsoPrem', projection: 'iso', assets: { i: 2 } });
|
|
}
|
|
|
|
test('registers packs and lists them by projection', () => {
|
|
seed();
|
|
expect(RK.packsForProjection('iso').map(p => p.id).sort()).toEqual(['isoFree', 'isoPrem']);
|
|
expect(RK.getPackDef('topA').assets).toEqual({ a: 1 });
|
|
expect(RK.registerPack({ id: 'x' })).toBeNull(); // no projection -> rejected
|
|
});
|
|
|
|
test('unlockedPacks filters by canUsePack', () => {
|
|
seed();
|
|
RK.canUsePack = (id) => id !== 'isoPrem';
|
|
expect(RK.unlockedPacks('iso').map(p => p.id)).toEqual(['isoFree']);
|
|
});
|
|
|
|
test('active pack = saved-if-unlocked, else first unlocked; assets resolve', () => {
|
|
seed();
|
|
RK.canUsePack = () => true;
|
|
expect(RK.activePackId('iso')).toBe('isoFree'); // default = first unlocked
|
|
expect(RK.setActivePack('isoPrem')).toBe(true);
|
|
expect(RK.activePackId('iso')).toBe('isoPrem'); // saved choice sticks
|
|
expect(RK.activePackAssets('iso')).toEqual({ i: 2 });
|
|
});
|
|
|
|
test('a saved pack that later locks falls back; setActivePack refuses a locked pack', () => {
|
|
seed();
|
|
RK.canUsePack = () => true;
|
|
RK.setActivePack('isoPrem');
|
|
RK.canUsePack = (id) => id !== 'isoPrem'; // access lost
|
|
expect(RK.activePackId('iso')).toBe('isoFree'); // graceful fallback
|
|
expect(RK.setActivePack('isoPrem')).toBe(false); // refused
|
|
});
|
|
|
|
test('a projection with no packs resolves to null', () => {
|
|
seed();
|
|
expect(RK.activePackId('3d')).toBeNull();
|
|
expect(RK.activePackAssets('3d')).toBeNull();
|
|
});
|
|
});
|