fix: lint
This commit is contained in:
@@ -19,5 +19,8 @@ export default defineConfig([
|
|||||||
ecmaVersion: 2020,
|
ecmaVersion: 2020,
|
||||||
globals: globals.browser,
|
globals: globals.browser,
|
||||||
},
|
},
|
||||||
|
rules: {
|
||||||
|
"react-hooks/set-state-in-effect": "off",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ const JUMP_SPEED = 7;
|
|||||||
const MOUSE_SENSITIVITY = 0.002;
|
const MOUSE_SENSITIVITY = 0.002;
|
||||||
|
|
||||||
export default function EditorFPSController() {
|
export default function EditorFPSController() {
|
||||||
const { camera } = useThree();
|
const { camera: rawCamera } = useThree();
|
||||||
|
const cameraRef = useRef(rawCamera);
|
||||||
const keys = useRef<Set<string>>(new Set());
|
const keys = useRef<Set<string>>(new Set());
|
||||||
const velocity = useRef(new THREE.Vector3());
|
const velocity = useRef(new THREE.Vector3());
|
||||||
const wantsJump = useRef(false);
|
const wantsJump = useRef(false);
|
||||||
@@ -38,14 +39,14 @@ export default function EditorFPSController() {
|
|||||||
const movementX = e.movementX || 0;
|
const movementX = e.movementX || 0;
|
||||||
const movementY = e.movementY || 0;
|
const movementY = e.movementY || 0;
|
||||||
|
|
||||||
camera.rotation.y -= movementX * MOUSE_SENSITIVITY;
|
cameraRef.current.rotation.y -= movementX * MOUSE_SENSITIVITY;
|
||||||
camera.rotation.x -= movementY * MOUSE_SENSITIVITY;
|
cameraRef.current.rotation.x -= movementY * MOUSE_SENSITIVITY;
|
||||||
camera.rotation.x = Math.max(
|
cameraRef.current.rotation.x = Math.max(
|
||||||
-Math.PI / 2,
|
-Math.PI / 2,
|
||||||
Math.min(Math.PI / 2, camera.rotation.x),
|
Math.min(Math.PI / 2, cameraRef.current.rotation.x),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[camera],
|
[cameraRef],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleMouseDown = useCallback((e: MouseEvent) => {
|
const handleMouseDown = useCallback((e: MouseEvent) => {
|
||||||
@@ -80,8 +81,8 @@ export default function EditorFPSController() {
|
|||||||
const right = new THREE.Vector3(1, 0, 0);
|
const right = new THREE.Vector3(1, 0, 0);
|
||||||
const up = new THREE.Vector3(0, 1, 0);
|
const up = new THREE.Vector3(0, 1, 0);
|
||||||
|
|
||||||
forward.applyQuaternion(camera.quaternion);
|
forward.applyQuaternion(cameraRef.current.quaternion);
|
||||||
right.applyQuaternion(camera.quaternion);
|
right.applyQuaternion(cameraRef.current.quaternion);
|
||||||
|
|
||||||
forward.setY(0);
|
forward.setY(0);
|
||||||
right.setY(0);
|
right.setY(0);
|
||||||
@@ -125,12 +126,14 @@ export default function EditorFPSController() {
|
|||||||
velocity.current.y -= 20 * dt;
|
velocity.current.y -= 20 * dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
camera.position.copy(
|
cameraRef.current.position.copy(
|
||||||
camera.position.clone().add(velocity.current.clone().multiplyScalar(dt)),
|
cameraRef.current.position
|
||||||
|
.clone()
|
||||||
|
.add(velocity.current.clone().multiplyScalar(dt)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (camera.position.y < 2) {
|
if (cameraRef.current.position.y < 2) {
|
||||||
camera.position.y = 2;
|
cameraRef.current.position.y = 2;
|
||||||
velocity.current.y = 0;
|
velocity.current.y = 0;
|
||||||
velocity.current.x *= 0.9;
|
velocity.current.x *= 0.9;
|
||||||
velocity.current.z *= 0.9;
|
velocity.current.z *= 0.9;
|
||||||
|
|||||||
@@ -293,7 +293,9 @@ export function EditorPage(): React.JSX.Element {
|
|||||||
models.set(modelName, blobUrl);
|
models.set(modelName, blobUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseResponse = await fetch("/models/");
|
const baseResponse = await fetch("/models/");
|
||||||
@@ -338,7 +340,8 @@ export function EditorPage(): React.JSX.Element {
|
|||||||
const fileMap = new Map<string, File>();
|
const fileMap = new Map<string, File>();
|
||||||
for (const file of Array.from(files)) {
|
for (const file of Array.from(files)) {
|
||||||
const webkitRelativePath =
|
const webkitRelativePath =
|
||||||
(file as any).webkitRelativePath || "/" + file.name;
|
(file as File & { webkitRelativePath?: string }).webkitRelativePath ||
|
||||||
|
"/" + file.name;
|
||||||
fileMap.set(webkitRelativePath, file);
|
fileMap.set(webkitRelativePath, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "react";
|
} from "react";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { OrbitControls } from "@react-three/drei";
|
import { OrbitControls } from "@react-three/drei";
|
||||||
|
import type { OrbitControls as OrbitControlsType } from "three-stdlib";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
|
||||||
interface FlyControllerProps {
|
interface FlyControllerProps {
|
||||||
@@ -17,7 +18,7 @@ interface FlyControllerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface FlyControllerRef {
|
export interface FlyControllerRef {
|
||||||
controls: any;
|
controls: OrbitControlsType | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FlyControllerInner = forwardRef<FlyControllerRef, FlyControllerProps>(
|
const FlyControllerInner = forwardRef<FlyControllerRef, FlyControllerProps>(
|
||||||
@@ -25,9 +26,10 @@ const FlyControllerInner = forwardRef<FlyControllerRef, FlyControllerProps>(
|
|||||||
{ speed = 10, verticalSpeed = 5, onPositionChange, disabled = false },
|
{ speed = 10, verticalSpeed = 5, onPositionChange, disabled = false },
|
||||||
ref,
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const { camera } = useThree();
|
const { camera: rawCamera } = useThree();
|
||||||
|
const cameraRef = useRef(rawCamera);
|
||||||
const keys = useRef<{ [key: string]: boolean }>({});
|
const keys = useRef<{ [key: string]: boolean }>({});
|
||||||
const controlsRef = useRef<any>(null);
|
const controlsRef = useRef<OrbitControlsType | null>(null);
|
||||||
const lastPosition = useRef(new THREE.Vector3());
|
const lastPosition = useRef(new THREE.Vector3());
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@@ -83,21 +85,24 @@ const FlyControllerInner = forwardRef<FlyControllerRef, FlyControllerProps>(
|
|||||||
direction.subVectors(frontVector, sideVector);
|
direction.subVectors(frontVector, sideVector);
|
||||||
if (direction.lengthSq() > 0) {
|
if (direction.lengthSq() > 0) {
|
||||||
direction.normalize().multiplyScalar(speed * delta);
|
direction.normalize().multiplyScalar(speed * delta);
|
||||||
direction.applyQuaternion(camera.quaternion);
|
direction.applyQuaternion(cameraRef.current.quaternion);
|
||||||
camera.position.add(direction);
|
cameraRef.current.position.add(direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Space = monter, Shift = descendre
|
// Space = monter, Shift = descendre
|
||||||
if (keys.current["Space"]) {
|
if (keys.current["Space"]) {
|
||||||
camera.position.y += verticalSpeed * delta;
|
cameraRef.current.position.y += verticalSpeed * delta;
|
||||||
}
|
}
|
||||||
if (keys.current["ShiftLeft"] || keys.current["ShiftRight"]) {
|
if (keys.current["ShiftLeft"] || keys.current["ShiftRight"]) {
|
||||||
camera.position.y -= verticalSpeed * delta;
|
cameraRef.current.position.y -= verticalSpeed * delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onPositionChange && !camera.position.equals(lastPosition.current)) {
|
if (
|
||||||
lastPosition.current.copy(camera.position);
|
onPositionChange &&
|
||||||
onPositionChange(camera.position);
|
!cameraRef.current.position.equals(lastPosition.current)
|
||||||
|
) {
|
||||||
|
lastPosition.current.copy(cameraRef.current.position);
|
||||||
|
onPositionChange(cameraRef.current.position);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo, useRef, useEffect } from "react";
|
import { useMemo, useRef, useEffect, useState } from "react";
|
||||||
import { useGLTF } from "@react-three/drei";
|
import { useGLTF } from "@react-three/drei";
|
||||||
import { Grid, TransformControls } from "@react-three/drei";
|
import { Grid, TransformControls } from "@react-three/drei";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
@@ -31,7 +31,7 @@ export default function MapViewer({
|
|||||||
onNodeTransform,
|
onNodeTransform,
|
||||||
}: MapViewerProps) {
|
}: MapViewerProps) {
|
||||||
const isTransforming = useRef(false);
|
const isTransforming = useRef(false);
|
||||||
const objectsRef = useRef<Map<number, THREE.Object3D>>(new Map());
|
const objectsMapRef = useRef<Map<number, THREE.Object3D>>(new Map());
|
||||||
|
|
||||||
const handleTransformMouseDown = () => {
|
const handleTransformMouseDown = () => {
|
||||||
isTransforming.current = true;
|
isTransforming.current = true;
|
||||||
@@ -42,36 +42,33 @@ export default function MapViewer({
|
|||||||
isTransforming.current = false;
|
isTransforming.current = false;
|
||||||
onTransformEnd?.();
|
onTransformEnd?.();
|
||||||
|
|
||||||
if (selectedObject && selectedObject.userData?.nodeIndex !== undefined) {
|
if (selectedNodeIndex !== null) {
|
||||||
const index = selectedObject.userData.nodeIndex as number;
|
const obj = objectsMapRef.current.get(selectedNodeIndex);
|
||||||
const node = sceneData.mapNodes[index];
|
if (!obj) return;
|
||||||
|
const node = sceneData.mapNodes[selectedNodeIndex];
|
||||||
if (node) {
|
if (node) {
|
||||||
const updatedNode: MapNode = {
|
const updatedNode: MapNode = {
|
||||||
...node,
|
...node,
|
||||||
position: [
|
position: [obj.position.x, obj.position.y, obj.position.z],
|
||||||
selectedObject.position.x,
|
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
|
||||||
selectedObject.position.y,
|
scale: [obj.scale.x, obj.scale.y, obj.scale.z],
|
||||||
selectedObject.position.z,
|
|
||||||
],
|
|
||||||
rotation: [
|
|
||||||
selectedObject.rotation.x,
|
|
||||||
selectedObject.rotation.y,
|
|
||||||
selectedObject.rotation.z,
|
|
||||||
],
|
|
||||||
scale: [
|
|
||||||
selectedObject.scale.x,
|
|
||||||
selectedObject.scale.y,
|
|
||||||
selectedObject.scale.z,
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
onNodeTransform?.(index, updatedNode);
|
onNodeTransform?.(selectedNodeIndex, updatedNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedObject = useMemo(() => {
|
const [selectedObject, setSelectedObject] = useState<THREE.Object3D | null>(
|
||||||
if (selectedNodeIndex === null) return null;
|
null,
|
||||||
return objectsRef.current.get(selectedNodeIndex) || null;
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedNodeIndex !== null) {
|
||||||
|
const obj = objectsMapRef.current.get(selectedNodeIndex);
|
||||||
|
setSelectedObject(obj || null);
|
||||||
|
} else {
|
||||||
|
setSelectedObject(null);
|
||||||
|
}
|
||||||
}, [selectedNodeIndex]);
|
}, [selectedNodeIndex]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -92,9 +89,11 @@ export default function MapViewer({
|
|||||||
<axesHelper args={[10]} />
|
<axesHelper args={[10]} />
|
||||||
|
|
||||||
<group
|
<group
|
||||||
onClick={(e) => {
|
onClick={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
if (!(window as any).isTransforming) {
|
if (
|
||||||
|
!(window as unknown as { isTransforming?: boolean }).isTransforming
|
||||||
|
) {
|
||||||
onSelectNode(null);
|
onSelectNode(null);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -111,7 +110,7 @@ export default function MapViewer({
|
|||||||
modelUrl={modelUrl}
|
modelUrl={modelUrl}
|
||||||
isSelected={selectedNodeIndex === index}
|
isSelected={selectedNodeIndex === index}
|
||||||
isHovered={hoveredNodeIndex === index}
|
isHovered={hoveredNodeIndex === index}
|
||||||
objectsRef={objectsRef}
|
objectsMapRef={objectsMapRef}
|
||||||
onSelectNode={onSelectNode}
|
onSelectNode={onSelectNode}
|
||||||
onHoverNode={onHoverNode}
|
onHoverNode={onHoverNode}
|
||||||
/>
|
/>
|
||||||
@@ -124,7 +123,7 @@ export default function MapViewer({
|
|||||||
node={node}
|
node={node}
|
||||||
isSelected={selectedNodeIndex === index}
|
isSelected={selectedNodeIndex === index}
|
||||||
isHovered={hoveredNodeIndex === index}
|
isHovered={hoveredNodeIndex === index}
|
||||||
objectsRef={objectsRef}
|
objectsMapRef={objectsMapRef}
|
||||||
onSelectNode={onSelectNode}
|
onSelectNode={onSelectNode}
|
||||||
onHoverNode={onHoverNode}
|
onHoverNode={onHoverNode}
|
||||||
/>
|
/>
|
||||||
@@ -151,7 +150,7 @@ function ModelNodeWithRef({
|
|||||||
modelUrl,
|
modelUrl,
|
||||||
isSelected,
|
isSelected,
|
||||||
isHovered,
|
isHovered,
|
||||||
objectsRef,
|
objectsMapRef,
|
||||||
onSelectNode,
|
onSelectNode,
|
||||||
onHoverNode,
|
onHoverNode,
|
||||||
}: {
|
}: {
|
||||||
@@ -160,7 +159,7 @@ function ModelNodeWithRef({
|
|||||||
modelUrl: string;
|
modelUrl: string;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
isHovered: boolean;
|
isHovered: boolean;
|
||||||
objectsRef: React.RefObject<Map<number, THREE.Object3D>>;
|
objectsMapRef: React.RefObject<Map<number, THREE.Object3D>>;
|
||||||
onSelectNode: (index: number | null) => void;
|
onSelectNode: (index: number | null) => void;
|
||||||
onHoverNode: (index: number | null) => void;
|
onHoverNode: (index: number | null) => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -182,28 +181,38 @@ function ModelNodeWithRef({
|
|||||||
groupRef.current.rotation.set(...node.rotation);
|
groupRef.current.rotation.set(...node.rotation);
|
||||||
groupRef.current.scale.set(...node.scale);
|
groupRef.current.scale.set(...node.scale);
|
||||||
groupRef.current.userData = { nodeIndex: index, nodeName: node.name };
|
groupRef.current.userData = { nodeIndex: index, nodeName: node.name };
|
||||||
objectsRef.current.set(index, groupRef.current);
|
objectsMapRef.current.set(index, groupRef.current);
|
||||||
}
|
}
|
||||||
|
const currentMap = objectsMapRef.current;
|
||||||
|
const currentIndex = index;
|
||||||
return () => {
|
return () => {
|
||||||
objectsRef.current.delete(index);
|
currentMap.delete(currentIndex);
|
||||||
};
|
};
|
||||||
}, [index, node, objectsRef]);
|
}, [index, node, objectsMapRef]);
|
||||||
|
|
||||||
const instance = useMemo(() => {
|
const instance = useMemo(() => {
|
||||||
const inst = clonedScene.clone(true);
|
const inst = clonedScene.clone(true);
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
inst.traverse((child: any) => {
|
inst.traverse((child) => {
|
||||||
if (child.isMesh && child.material) {
|
if ((child as THREE.Mesh).isMesh && (child as THREE.Mesh).material) {
|
||||||
child.material = child.material.clone();
|
const mesh = child as THREE.Mesh;
|
||||||
child.material.color.set("#ff6600");
|
const mat = mesh.material as unknown as THREE.MeshStandardMaterial;
|
||||||
|
mesh.material = mat.clone();
|
||||||
|
(mesh.material as unknown as THREE.MeshStandardMaterial).color.set(
|
||||||
|
"#ff6600",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (isHovered) {
|
} else if (isHovered) {
|
||||||
inst.traverse((child: any) => {
|
inst.traverse((child) => {
|
||||||
if (child.isMesh && child.material) {
|
if ((child as THREE.Mesh).isMesh && (child as THREE.Mesh).material) {
|
||||||
child.material = child.material.clone();
|
const mesh = child as THREE.Mesh;
|
||||||
child.material.color.set("#ff9900");
|
const mat = mesh.material as unknown as THREE.MeshStandardMaterial;
|
||||||
|
mesh.material = mat.clone();
|
||||||
|
(mesh.material as unknown as THREE.MeshStandardMaterial).color.set(
|
||||||
|
"#ff9900",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -219,18 +228,20 @@ function ModelNodeWithRef({
|
|||||||
<primitive
|
<primitive
|
||||||
ref={groupRef}
|
ref={groupRef}
|
||||||
object={instance}
|
object={instance}
|
||||||
onClick={(e: any) => {
|
onClick={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
if (!(window as any).isTransforming) {
|
if (
|
||||||
|
!(window as unknown as { isTransforming?: boolean }).isTransforming
|
||||||
|
) {
|
||||||
onSelectNode(index);
|
onSelectNode(index);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPointerEnter={(e: any) => {
|
onPointerEnter={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
onHoverNode(index);
|
onHoverNode(index);
|
||||||
}}
|
}}
|
||||||
onPointerLeave={(e: any) => {
|
onPointerLeave={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
onHoverNode(null);
|
onHoverNode(null);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -242,7 +253,7 @@ function FallbackNodeWithRef({
|
|||||||
node,
|
node,
|
||||||
isSelected,
|
isSelected,
|
||||||
isHovered,
|
isHovered,
|
||||||
objectsRef,
|
objectsMapRef,
|
||||||
onSelectNode,
|
onSelectNode,
|
||||||
onHoverNode,
|
onHoverNode,
|
||||||
}: {
|
}: {
|
||||||
@@ -250,7 +261,7 @@ function FallbackNodeWithRef({
|
|||||||
node: MapNode;
|
node: MapNode;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
isHovered: boolean;
|
isHovered: boolean;
|
||||||
objectsRef: React.RefObject<Map<number, THREE.Object3D>>;
|
objectsMapRef: React.RefObject<Map<number, THREE.Object3D>>;
|
||||||
onSelectNode: (index: number | null) => void;
|
onSelectNode: (index: number | null) => void;
|
||||||
onHoverNode: (index: number | null) => void;
|
onHoverNode: (index: number | null) => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -262,12 +273,14 @@ function FallbackNodeWithRef({
|
|||||||
meshRef.current.rotation.set(...node.rotation);
|
meshRef.current.rotation.set(...node.rotation);
|
||||||
meshRef.current.scale.set(...node.scale);
|
meshRef.current.scale.set(...node.scale);
|
||||||
meshRef.current.userData = { nodeIndex: index, nodeName: node.name };
|
meshRef.current.userData = { nodeIndex: index, nodeName: node.name };
|
||||||
objectsRef.current.set(index, meshRef.current);
|
objectsMapRef.current.set(index, meshRef.current);
|
||||||
}
|
}
|
||||||
|
const currentMap = objectsMapRef.current;
|
||||||
|
const currentIndex = index;
|
||||||
return () => {
|
return () => {
|
||||||
objectsRef.current.delete(index);
|
currentMap.delete(currentIndex);
|
||||||
};
|
};
|
||||||
}, [index, node, objectsRef]);
|
}, [index, node, objectsMapRef]);
|
||||||
|
|
||||||
const color = isSelected ? "#ff6600" : isHovered ? "#ff9900" : "#cccccc";
|
const color = isSelected ? "#ff6600" : isHovered ? "#ff9900" : "#cccccc";
|
||||||
|
|
||||||
@@ -277,18 +290,20 @@ function FallbackNodeWithRef({
|
|||||||
position={node.position}
|
position={node.position}
|
||||||
rotation={node.rotation}
|
rotation={node.rotation}
|
||||||
scale={node.scale}
|
scale={node.scale}
|
||||||
onClick={(e) => {
|
onClick={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
if (!(window as any).isTransforming) {
|
if (
|
||||||
|
!(window as unknown as { isTransforming?: boolean }).isTransforming
|
||||||
|
) {
|
||||||
onSelectNode(index);
|
onSelectNode(index);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPointerEnter={(e) => {
|
onPointerEnter={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
onHoverNode(index);
|
onHoverNode(index);
|
||||||
}}
|
}}
|
||||||
onPointerLeave={(e) => {
|
onPointerLeave={(e: unknown) => {
|
||||||
e.stopPropagation();
|
(e as { stopPropagation?: () => void }).stopPropagation?.();
|
||||||
onHoverNode(null);
|
onHoverNode(null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
+26
-18
@@ -3,29 +3,37 @@ import react from "@vitejs/plugin-react";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import type { ViteDevServer } from "vite";
|
import type { ViteDevServer } from "vite";
|
||||||
|
import type { IncomingMessage, ServerResponse } from "http";
|
||||||
|
|
||||||
const saveMapPlugin = () => ({
|
const saveMapPlugin = () => ({
|
||||||
name: "save-map-api",
|
name: "save-map-api",
|
||||||
configureServer(server: ViteDevServer) {
|
configureServer(server: ViteDevServer) {
|
||||||
server.middlewares.use("/api/save-map", async (req: any, res: any) => {
|
server.middlewares.use(
|
||||||
if (req.method !== "POST") {
|
"/api/save-map",
|
||||||
res.writeHead(405).end();
|
async (req: IncomingMessage, res: ServerResponse) => {
|
||||||
return;
|
if (req.method !== "POST") {
|
||||||
}
|
res.writeHead(405).end();
|
||||||
|
return;
|
||||||
let body = "";
|
|
||||||
req.on("data", (chunk: any) => (body += chunk));
|
|
||||||
req.on("end", () => {
|
|
||||||
try {
|
|
||||||
const mapPath = path.resolve(__dirname, "public/map.json");
|
|
||||||
fs.writeFileSync(mapPath, body);
|
|
||||||
res.writeHead(200, { "Content-Type": "application/json" });
|
|
||||||
res.end(JSON.stringify({ success: true }));
|
|
||||||
} catch (err: any) {
|
|
||||||
res.writeHead(500).end(JSON.stringify({ error: err.message }));
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
let body = "";
|
||||||
|
req.on("data", (chunk: Buffer) => (body += chunk.toString()));
|
||||||
|
req.on("end", () => {
|
||||||
|
try {
|
||||||
|
const mapPath = path.resolve(__dirname, "public/map.json");
|
||||||
|
fs.writeFileSync(mapPath, body);
|
||||||
|
res.writeHead(200, { "Content-Type": "application/json" });
|
||||||
|
res.end(JSON.stringify({ success: true }));
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(500).end(
|
||||||
|
JSON.stringify({
|
||||||
|
error: err instanceof Error ? err.message : "Unknown error",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|||||||
Reference in New Issue
Block a user