Update Healer Man server

This commit is contained in:
phenom committed 2026-09-27 18:46:30 -04:00
1 parent e284f4fc76
commit 15a5254380
52 files changed
+637 -80

No files matched your search

+7 -38
View File
@@ -1,21 +1,15 @@
import { useEffect, useRef, useState, useSyncExternalStore } from "react";
import { useFrame } from "@react-three/fiber";
import { DoubleSide, Group, SRGBColorSpace, Texture, TextureLoader } from "three";
import { DoubleSide, Group } from "three";
import { subscribeContentManager } from "../content/contentManager";
import { fetchCombatMediaAsset, combatMediaPackReady } from "../game/combatMediaPack";
import { preloadCombatEffectManifest, shadowfiendOriginalModelAsset } from "../game/combatPresentation";
import { combatMediaPackReady } from "../game/combatMediaPack";
import { type CombatSummon, useCombatStore } from "../game/combatStore";
import { getMobPosition } from "../game/mobRuntimeRegistry";
import { OriginalWowModel } from "./OriginalWowModel";
import { parseOriginalWowModelGraph, type OriginalWowModelGraph } from "./originalWowModelRuntime";
import { getPreparedShadowfiendMedia, preloadShadowfiendMedia } from "./shadowfiendMedia";
const SHADOWFIEND_CREATURE_ID = 19668;
interface ShadowfiendMedia {
readonly graph: OriginalWowModelGraph;
readonly textures: ReadonlyMap<number, Texture>;
}
function ShadowfiendFallback() {
return <group name="shadowfiend-fallback">
<mesh position={[0, 0.66, 0]} scale={[0.56, 0.77, 0.46]}>
@@ -39,7 +33,7 @@ function ShadowfiendFallback() {
}
function ShadowfiendMember({ summon, active }: { readonly summon: CombatSummon; readonly active: boolean }) {
const [media, setMedia] = useState<ShadowfiendMedia | null>(null);
const [media, setMedia] = useState(getPreparedShadowfiendMedia);
const mediaReady = useSyncExternalStore(subscribeContentManager, combatMediaPackReady, () => false);
const group = useRef<Group>(null);
const playback = useRef({ elapsedMs: 0, decaying: false });
@@ -50,36 +44,11 @@ function ShadowfiendMember({ summon, active }: { readonly summon: CombatSummon;
return;
}
let cancelled = false;
const ownedTextures: Texture[] = [];
void (async () => {
await preloadCombatEffectManifest();
const url = shadowfiendOriginalModelAsset()?.effectGraphUrl;
if (!url) return;
const response = await fetchCombatMediaAsset(url);
if (!response.ok) throw new Error(`Shadowfiend model request failed: ${response.status}`);
const graph = parseOriginalWowModelGraph(await response.json());
const textures = new Map<number, Texture>();
const loader = new TextureLoader();
for (const [index, source] of graph.textures.entries()) {
if (!source.url) continue;
const image = await fetchCombatMediaAsset(source.url);
if (!image.ok) throw new Error(`Shadowfiend texture request failed: ${image.status}`);
const objectUrl = URL.createObjectURL(await image.blob());
try {
const texture = await loader.loadAsync(objectUrl);
texture.colorSpace = SRGBColorSpace;
ownedTextures.push(texture);
textures.set(index, texture);
} finally {
URL.revokeObjectURL(objectUrl);
}
}
if (cancelled) ownedTextures.forEach((texture) => texture.dispose());
else setMedia({ graph, textures });
})().catch(() => { if (cancelled) ownedTextures.forEach((texture) => texture.dispose()); });
void preloadShadowfiendMedia().then((ready) => {
if (!cancelled) setMedia(ready);
}).catch(() => { if (!cancelled) setMedia(null); });
return () => {
cancelled = true;
ownedTextures.forEach((texture) => texture.dispose());
};
}, [mediaReady]);