"use client"; import { useRef, useEffect, Suspense } from "react"; import { useGLTF } from "@react-three/drei"; import { RigidBody, CuboidCollider, BallCollider, CapsuleCollider, } from "@react-three/rapier"; import type * as THREE from "three"; import { useEditorStore } from "@/lib/store"; interface PhysicsProps { mass?: number | null; isStatic?: boolean | null; restitution?: number | null; friction?: number | null; colliderType?: string | null; } interface DamageProps { amount?: number | null; enabled?: boolean | null; } interface GameModelProps { position?: [number, number, number] | null; rotation?: [number, number, number] | null; scale?: [number, number, number] | null; castShadow?: boolean | null; receiveShadow?: boolean | null; url: string; physics?: PhysicsProps | null; damage?: DamageProps | null; objectId?: string | null; } function ModelInner({ url, userData, }: { url: string; userData: Record; }) { const groupRef = useRef(null); const { scene } = useGLTF(url); const setIsLoading = useEditorStore((s) => s.setIsLoading); const model = scene.clone(); useEffect(() => { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- @types/three version mismatch model.traverse((node: any) => { if (node.isMesh) { node.castShadow = true; node.receiveShadow = true; } }); }, [model]); useEffect(() => { if (groupRef.current) { Object.assign(groupRef.current.userData, userData); } }, [userData]); useEffect(() => { const timer = setTimeout(() => setIsLoading(false), 100); return () => clearTimeout(timer); }, [setIsLoading]); return ( ); } export function GameModel({ position, rotation, scale, url, physics, damage, objectId, }: GameModelProps) { const isPlaying = useEditorStore((s) => s.isPlaying); const takeDamage = useEditorStore((s) => s.takeDamage); const setIsLoading = useEditorStore((s) => s.setIsLoading); const pos: [number, number, number] = position ?? [0, 0, 0]; const rot: [number, number, number] = rotation ?? [0, 0, 0]; const scl: [number, number, number] = scale ?? [1, 1, 1]; const hasPhysics = isPlaying && physics && physics.colliderType && physics.colliderType !== "none"; const hasDamage = damage?.enabled && (damage.amount ?? 0) > 0; useEffect(() => { if (url) setIsLoading(true); }, [url, setIsLoading]); if (!url) { return ( ); } const inner = ( ); if (!hasPhysics) { return ( {inner} ); } const collider = physics!.colliderType === "ball" ? ( ) : physics!.colliderType === "capsule" ? ( ) : ( ); return ( takeDamage(damage!.amount!) : undefined } > {inner} {collider} ); }