2019-05-29 00:40:29 +08:00
|
|
|
import { NpcType, ObjectType } from '../../domain';
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
export function getAreaRenderData(
|
2019-05-29 00:40:29 +08:00
|
|
|
episode: number,
|
2019-05-29 07:37:00 +08:00
|
|
|
areaId: number,
|
|
|
|
areaVersion: number
|
2019-05-29 00:40:29 +08:00
|
|
|
): Promise<ArrayBuffer> {
|
2019-05-29 07:37:00 +08:00
|
|
|
return getAreaAsset(episode, areaId, areaVersion, 'render');
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
export function getAreaCollisionData(
|
2019-05-29 00:40:29 +08:00
|
|
|
episode: number,
|
2019-05-29 07:37:00 +08:00
|
|
|
areaId: number,
|
|
|
|
areaVersion: number
|
2019-05-29 00:40:29 +08:00
|
|
|
): Promise<ArrayBuffer> {
|
2019-05-29 07:37:00 +08:00
|
|
|
return getAreaAsset(episode, areaId, areaVersion, 'collision');
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
export async function getNpcData(npcType: NpcType): Promise<{ url: string, data: ArrayBuffer }> {
|
2019-06-01 05:20:13 +08:00
|
|
|
const url = npcTypeToUrl(npcType);
|
|
|
|
const data = await getAsset(url);
|
|
|
|
return ({ url, data });
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
export async function getObjectData(objectType: ObjectType): Promise<{ url: string, data: ArrayBuffer }> {
|
2019-06-01 05:20:13 +08:00
|
|
|
const url = objectTypeToUrl(objectType);
|
|
|
|
const data = await getAsset(url);
|
|
|
|
return ({ url, data });
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cache for the binary data.
|
|
|
|
*/
|
2019-05-29 07:37:00 +08:00
|
|
|
const bufferCache: Map<string, Promise<ArrayBuffer>> = new Map();
|
2019-05-29 00:40:29 +08:00
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
function getAsset(url: string): Promise<ArrayBuffer> {
|
|
|
|
const promise = bufferCache.get(url);
|
2019-05-29 00:40:29 +08:00
|
|
|
|
|
|
|
if (promise) {
|
|
|
|
return promise;
|
|
|
|
} else {
|
2019-05-29 07:37:00 +08:00
|
|
|
const baseUrl = process.env.PUBLIC_URL;
|
|
|
|
const promise = fetch(baseUrl + url).then(r => r.arrayBuffer());
|
|
|
|
bufferCache.set(url, promise);
|
2019-05-29 00:40:29 +08:00
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
const areaBaseNames = [
|
2019-05-29 00:40:29 +08:00
|
|
|
[
|
|
|
|
['city00_00', 1],
|
|
|
|
['forest01', 1],
|
|
|
|
['forest02', 1],
|
|
|
|
['cave01_', 6],
|
|
|
|
['cave02_', 5],
|
|
|
|
['cave03_', 6],
|
|
|
|
['machine01_', 6],
|
|
|
|
['machine02_', 6],
|
|
|
|
['ancient01_', 5],
|
|
|
|
['ancient02_', 5],
|
|
|
|
['ancient03_', 5],
|
|
|
|
['boss01', 1],
|
|
|
|
['boss02', 1],
|
|
|
|
['boss03', 1],
|
|
|
|
['darkfalz00', 1]
|
|
|
|
],
|
|
|
|
[
|
|
|
|
['labo00_00', 1],
|
|
|
|
['ruins01_', 3],
|
|
|
|
['ruins02_', 3],
|
|
|
|
['space01_', 3],
|
|
|
|
['space02_', 3],
|
|
|
|
['jungle01_00', 1],
|
|
|
|
['jungle02_00', 1],
|
|
|
|
['jungle03_00', 1],
|
|
|
|
['jungle04_', 3],
|
|
|
|
['jungle05_00', 1],
|
|
|
|
['seabed01_', 3],
|
|
|
|
['seabed02_', 3],
|
|
|
|
['boss05', 1],
|
|
|
|
['boss06', 1],
|
|
|
|
['boss07', 1],
|
|
|
|
['boss08', 1],
|
|
|
|
['jungle06_00', 1],
|
|
|
|
['jungle07_', 5]
|
|
|
|
],
|
|
|
|
[
|
2019-05-29 07:37:00 +08:00
|
|
|
// Don't remove this empty array, see usage of areaBaseNames in areaVersionToBaseUrl.
|
2019-05-29 00:40:29 +08:00
|
|
|
],
|
|
|
|
[
|
|
|
|
['city02_00', 1],
|
|
|
|
['wilds01_00', 1],
|
|
|
|
['wilds01_01', 1],
|
|
|
|
['wilds01_02', 1],
|
|
|
|
['wilds01_03', 1],
|
|
|
|
['crater01_00', 1],
|
|
|
|
['desert01_', 3],
|
|
|
|
['desert02_', 3],
|
|
|
|
['desert03_', 3],
|
|
|
|
['boss09_00', 1]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
function areaVersionToBaseUrl(
|
2019-05-29 00:40:29 +08:00
|
|
|
episode: number,
|
2019-05-29 07:37:00 +08:00
|
|
|
areaId: number,
|
|
|
|
areaVariant: number
|
2019-05-29 00:40:29 +08:00
|
|
|
): string {
|
2019-05-29 07:37:00 +08:00
|
|
|
const episodeBaseNames = areaBaseNames[episode - 1];
|
2019-05-29 00:40:29 +08:00
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
if (0 <= areaId && areaId < episodeBaseNames.length) {
|
|
|
|
const [baseName, variants] = episodeBaseNames[areaId];
|
2019-05-29 00:40:29 +08:00
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
if (0 <= areaVariant && areaVariant < variants) {
|
2019-05-29 00:40:29 +08:00
|
|
|
let variant: string;
|
|
|
|
|
|
|
|
if (variants === 1) {
|
|
|
|
variant = '';
|
|
|
|
} else {
|
2019-05-29 07:37:00 +08:00
|
|
|
variant = String(areaVariant);
|
2019-05-29 00:40:29 +08:00
|
|
|
while (variant.length < 2) variant = '0' + variant;
|
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
return `/maps/map_${baseName}${variant}`;
|
2019-05-29 00:40:29 +08:00
|
|
|
} else {
|
2019-05-29 07:37:00 +08:00
|
|
|
throw new Error(`Unknown variant ${areaVariant} of area ${areaId} in episode ${episode}.`);
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
} else {
|
2019-05-29 07:37:00 +08:00
|
|
|
throw new Error(`Unknown episode ${episode} area ${areaId}.`);
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type AreaAssetType = 'render' | 'collision';
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
function getAreaAsset(
|
2019-05-29 00:40:29 +08:00
|
|
|
episode: number,
|
2019-05-29 07:37:00 +08:00
|
|
|
areaId: number,
|
|
|
|
areaVariant: number,
|
2019-05-29 00:40:29 +08:00
|
|
|
type: AreaAssetType
|
|
|
|
): Promise<ArrayBuffer> {
|
|
|
|
try {
|
2019-05-29 07:37:00 +08:00
|
|
|
const baseUrl = areaVersionToBaseUrl(episode, areaId, areaVariant);
|
2019-05-29 00:40:29 +08:00
|
|
|
const suffix = type === 'render' ? 'n.rel' : 'c.rel';
|
2019-05-29 07:37:00 +08:00
|
|
|
return getAsset(baseUrl + suffix);
|
2019-05-29 00:40:29 +08:00
|
|
|
} catch (e) {
|
|
|
|
return Promise.reject(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
function npcTypeToUrl(npcType: NpcType): string {
|
|
|
|
switch (npcType) {
|
2019-05-29 00:40:29 +08:00
|
|
|
// The dubswitch model in in XJ format.
|
2019-05-29 07:37:00 +08:00
|
|
|
case NpcType.Dubswitch: return `/npcs/${npcType.code}.xj`;
|
2019-05-29 00:40:29 +08:00
|
|
|
|
|
|
|
// Episode II VR Temple
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
case NpcType.Hildebear2: return npcTypeToUrl(NpcType.Hildebear);
|
|
|
|
case NpcType.Hildeblue2: return npcTypeToUrl(NpcType.Hildeblue);
|
|
|
|
case NpcType.RagRappy2: return npcTypeToUrl(NpcType.RagRappy);
|
|
|
|
case NpcType.Monest2: return npcTypeToUrl(NpcType.Monest);
|
|
|
|
case NpcType.PoisonLily2: return npcTypeToUrl(NpcType.PoisonLily);
|
|
|
|
case NpcType.NarLily2: return npcTypeToUrl(NpcType.NarLily);
|
|
|
|
case NpcType.GrassAssassin2: return npcTypeToUrl(NpcType.GrassAssassin);
|
|
|
|
case NpcType.Dimenian2: return npcTypeToUrl(NpcType.Dimenian);
|
|
|
|
case NpcType.LaDimenian2: return npcTypeToUrl(NpcType.LaDimenian);
|
|
|
|
case NpcType.SoDimenian2: return npcTypeToUrl(NpcType.SoDimenian);
|
|
|
|
case NpcType.DarkBelra2: return npcTypeToUrl(NpcType.DarkBelra);
|
2019-05-29 00:40:29 +08:00
|
|
|
|
|
|
|
// Episode II VR Spaceship
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
case NpcType.SavageWolf2: return npcTypeToUrl(NpcType.SavageWolf);
|
|
|
|
case NpcType.BarbarousWolf2: return npcTypeToUrl(NpcType.BarbarousWolf);
|
|
|
|
case NpcType.PanArms2: return npcTypeToUrl(NpcType.PanArms);
|
|
|
|
case NpcType.Dubchic2: return npcTypeToUrl(NpcType.Dubchic);
|
|
|
|
case NpcType.Gilchic2: return npcTypeToUrl(NpcType.Gilchic);
|
|
|
|
case NpcType.Garanz2: return npcTypeToUrl(NpcType.Garanz);
|
|
|
|
case NpcType.Dubswitch2: return npcTypeToUrl(NpcType.Dubswitch);
|
|
|
|
case NpcType.Delsaber2: return npcTypeToUrl(NpcType.Delsaber);
|
|
|
|
case NpcType.ChaosSorcerer2: return npcTypeToUrl(NpcType.ChaosSorcerer);
|
|
|
|
|
|
|
|
default: return `/npcs/${npcType.code}.nj`;
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-29 07:37:00 +08:00
|
|
|
function objectTypeToUrl(objectType: ObjectType): string {
|
|
|
|
switch (objectType) {
|
2019-05-29 00:40:29 +08:00
|
|
|
case ObjectType.EasterEgg:
|
|
|
|
case ObjectType.ChristmasTree:
|
|
|
|
case ObjectType.ChristmasWreath:
|
|
|
|
case ObjectType.TwentyFirstCentury:
|
|
|
|
case ObjectType.Sonic:
|
|
|
|
case ObjectType.WelcomeBoard:
|
|
|
|
case ObjectType.FloatingJelifish:
|
|
|
|
case ObjectType.RuinsSeal:
|
|
|
|
case ObjectType.Dolphin:
|
|
|
|
case ObjectType.Cacti:
|
|
|
|
case ObjectType.BigBrownRock:
|
|
|
|
case ObjectType.PoisonPlant:
|
|
|
|
case ObjectType.BigBlackRocks:
|
|
|
|
case ObjectType.FallingRock:
|
|
|
|
case ObjectType.DesertFixedTypeBoxBreakableCrystals:
|
|
|
|
case ObjectType.BeeHive:
|
2019-06-26 23:47:53 +08:00
|
|
|
return `/objects/${String(objectType.pso_id)}.nj`;
|
2019-05-29 00:40:29 +08:00
|
|
|
|
|
|
|
default:
|
2019-06-26 23:47:53 +08:00
|
|
|
return `/objects/${String(objectType.pso_id)}.xj`;
|
2019-05-29 00:40:29 +08:00
|
|
|
}
|
|
|
|
}
|