import { useMemo } from "react"; import { Html } from "@react-three/drei"; import { useBiteSizedLayoutsStore } from "../game/biteSizedLayoutsStore"; import { derivePartySpawnSlots } from "../game/partySpawnSlots"; import { biteSizedDefinitionForSelection } from "../game/dungeonRegistry"; import { selectBiteSizedRun, type LayoutVector } from "../../shared/bite-sized-layouts.mjs"; import { MobPopulation } from "./MobPopulation"; import { useGameStore } from "../game/store"; import { resolveDungeonAssets } from "../game/dungeonAssets"; import { cachedPartyNavigationGraph } from "../game/partyNavigationAssetCache"; import { findNearestPartyNavigationSurface } from "../game/partyNavigation"; function Marker({ id, position, yaw, color, label, selected }: { readonly id: string; readonly position: LayoutVector; readonly yaw: number; readonly color: string; readonly label: string; readonly selected: boolean; }) { const choose = () => useBiteSizedLayoutsStore.setState({ editingPointId: id, panelFocused: false }); return { e.stopPropagation(); choose(); }}> { e.stopPropagation(); choose(); }}> {selected && {label}} ; } export function BiteSizedEditorMarkers() { const layouts = useBiteSizedLayoutsStore(); const difficultyId = useGameStore((s) => s.activeDifficultyId); const spot = layouts.draft.spots.find((s) => s.id === layouts.editingSpotId); const preview = useMemo(() => { if (!spot || layouts.editorMode !== "edit") return null; try { return biteSizedDefinitionForSelection(selectBiteSizedRun(layouts.draft, spot.dungeonId, "gm-preview", { spotId: spot.id }), "gm-preview", difficultyId); } catch { return null; } }, [layouts.draft, layouts.editorMode, spot, difficultyId]); if (!spot || layouts.editorMode !== "edit") return null; const navigationUrl = preview && resolveDungeonAssets(preview).navigation; const graph = navigationUrl && preview ? cachedPartyNavigationGraph(navigationUrl, preview.navigationLinks, preview.traversalRamps, true) ?? cachedPartyNavigationGraph(navigationUrl, preview.navigationLinks, preview.traversalRamps) : null; return {preview && g.spawns)]} />} {derivePartySpawnSlots(spot.partySpawn).map((p, i) => 0 && graph ? findNearestPartyNavigationSurface(graph, p.footPosition, 6)?.position ?? p.footPosition : p.footPosition} yaw={p.yaw} color="#55e8ff" label={`Party start ยท seat ${i + 1}`} selected={layouts.editingPointId === "party" && i === 0} />)} {spot.mobs.map((m, i) => )} ; }