t2-mapper/src/components/Item.tsx
2025-11-19 01:49:42 -05:00

87 lines
2.6 KiB
TypeScript

import { Suspense, useMemo } from "react";
import { ErrorBoundary } from "react-error-boundary";
import {
ConsoleObject,
getPosition,
getProperty,
getRotation,
getScale,
} from "../mission";
import { ShapeModel, ShapePlaceholder } from "./GenericShape";
const dataBlockToShapeName = {
AmmoPack: "pack_upgrade_ammo.dts",
Beacon: "beacon.dts",
Chaingun: "weapon_chaingun.dts",
ChaingunAmmo: "ammo_chaingun.dts",
CloakingPack: "pack_upgrade_cloaking.dts",
ConcussionGrenade: "grenade.dts",
DiscAmmo: "ammo_disc.dts",
ELFGun: "weapon_elf.dts",
EnergyPack: "pack_upgrade_energy.dts",
Flag: "flag.dts",
FlareGrenade: "grenade.dts",
Grenade: "grenade.dts",
GrenadeLauncher: "weapon_grenade_launcher.dts",
GrenadeLauncherAmmo: "ammo_grenade.dts",
InventoryDeployable: "pack_deploy_inventory.dts",
Mine: "ammo_mine.dts",
MotionSensorDeployable: "pack_deploy_sensor_motion.dts",
Plasma: "weapon_plasma.dts",
PlasmaAmmo: "ammo_plasma.dts",
PulseSensorDeployable: "pack_deploy_sensor_pulse.dts",
RepairKit: "repair_kit.dts",
RepairPack: "pack_upgrade_repair.dts",
RepairPatch: "repair_patch.dts",
SatchelCharge: "pack_upgrade_satchel.dts",
SensorJammerPack: "pack_upgrade_sensorjammer.dts",
ShieldPack: "pack_upgrade_shield.dts",
ShockLance: "weapon_shocklance.dts",
SniperRifle: "weapon_sniper.dts",
};
let _caseInsensitiveLookup: Record<string, string>;
function getDataBlockShape(dataBlock: string) {
if (!_caseInsensitiveLookup) {
_caseInsensitiveLookup = Object.fromEntries(
Object.entries(dataBlockToShapeName).map(([key, value]) => {
return [key.toLowerCase(), value];
})
);
}
return _caseInsensitiveLookup[dataBlock.toLowerCase()];
}
export function Item({ object }: { object: ConsoleObject }) {
const dataBlock = getProperty(object, "dataBlock").value;
const [z, y, x] = useMemo(() => getPosition(object), [object]);
const [scaleX, scaleY, scaleZ] = useMemo(() => getScale(object), [object]);
const q = useMemo(() => getRotation(object, true), [object]);
const shapeName = getDataBlockShape(dataBlock);
if (!shapeName) {
console.error(`<Item> missing shape for dataBlock: ${dataBlock}`);
}
return (
<group
quaternion={q}
position={[x - 1024, y, z - 1024]}
scale={[scaleX, scaleY, scaleZ]}
>
{shapeName ? (
<ErrorBoundary fallback={<ShapePlaceholder color="red" />}>
<Suspense fallback={<ShapePlaceholder color="pink" />}>
<ShapeModel shapeName={shapeName} />
</Suspense>
</ErrorBoundary>
) : (
<ShapePlaceholder color="orange" />
)}
</group>
);
}