Update Healer Man server

This commit is contained in:
phenom committed 2026-09-26 17:51:56 -04:00
1 parent 9c5fb4c614
commit bd073fb00f
113 files changed
+4902 -273

No files matched your search

+59 -3
View File
@@ -53,7 +53,9 @@ function prepareVisual(root: Object3D, definition: DungeonDefinition) {
instanced.computeBoundingSphere();
}
});
instanceRepeatedStaticMeshes(clone);
// Scholomance's compact visual has thousands of opaque repetitions. Grouping
// them across the level saves draw calls without expanding a large triangle set.
instanceRepeatedStaticMeshes(clone, 3, undefined, definition.id === "scholomance");
const cells = createStaticVisibilityCells(clone);
cacheStaticMatrices(clone);
return { visual: clone, cells };
@@ -163,6 +165,46 @@ function CollisionChunk({
);
}
function NavigationGround({
url,
definition,
registerPrepared,
}: {
readonly url: string;
readonly definition: DungeonDefinition;
readonly registerPrepared: (url: string, ready: boolean) => void;
}) {
const gltf = useGameGLTF(url);
const ground = useMemo(() => prepareCollision(gltf.scene), [gltf.scene]);
const trimeshes = useMemo(() => collisionTrimeshes(ground), [ground]);
useEffect(() => () => {
disposeObject3DResources(ground, { materials: false, textures: false, skeletons: false });
}, [ground]);
useEffect(() => {
registerPrepared(url, trimeshes.length > 0);
return () => registerPrepared(url, false);
}, [registerPrepared, trimeshes.length, url]);
const { position, rotation, scale } = definition.transform;
return (
<RigidBody
type="fixed"
colliders={false}
name={`${definition.id}-navigation-ground`}
position={position}
rotation={rotation}
scale={scale}
>
{trimeshes.map((trimesh) => (
<TrimeshCollider
key={trimesh.id}
args={[trimesh.vertices, trimesh.indices]}
collisionGroups={DUNGEON_PHYSICAL_COLLISION_GROUPS}
/>
))}
</RigidBody>
);
}
export function ProductionDungeon({
definition,
assets,
@@ -175,6 +217,11 @@ export function ProductionDungeon({
if (!assets.visual.length || !assets.collision.length) {
throw new Error(`${definition.title} mounted without its required visual and collision GLBs.`);
}
// Raksha's WDB collision omits the walkable entrance floor present in its navmesh.
const navigationGroundUrl = definition.id === "raksha-temple" ? assets.navigation : null;
if (definition.id === "raksha-temple" && !navigationGroundUrl) {
throw new Error("Raksha Temple mounted without its required navigation ground GLB.");
}
const [loadedVisualCount, setLoadedVisualCount] = useState(0);
const [loadedCollisionCount, setLoadedCollisionCount] = useState(0);
const preparedCollisions = useRef(new Set<string>());
@@ -229,10 +276,10 @@ export function ProductionDungeon({
}
preparedCollisions.current.add(url);
if (signalledFirstFrame.current) return;
if (preparedCollisions.current.size < assets.collision.length) return;
if (preparedCollisions.current.size < assets.collision.length + (navigationGroundUrl ? 1 : 0)) return;
signalledFirstFrame.current = true;
onReady?.();
}, [assets.collision.length, onReady]);
}, [assets.collision.length, navigationGroundUrl, onReady]);
return (
<group name={`${definition.id}-production`}>
@@ -247,6 +294,15 @@ export function ProductionDungeon({
registerPrepared={registerPrepared}
/>
))}
{navigationGroundUrl && (
<Suspense fallback={null}>
<NavigationGround
url={navigationGroundUrl}
definition={definition}
registerPrepared={registerPrepared}
/>
</Suspense>
)}
<AssetBatchLoader
key={`${loadedVisualCount}:${loadedCollisionCount}:${pendingUrls.join("|")}`}
urls={pendingUrls}