diff --git a/client/src/components/Map3D.jsx b/client/src/components/Map3D.jsx index deb3092..a26476b 100644 --- a/client/src/components/Map3D.jsx +++ b/client/src/components/Map3D.jsx @@ -1101,10 +1101,60 @@ function Scene({ interactionMode, onInteraction }) { const selectedTurtleId = useTurtleStore((state) => state.selectedTurtleId); const selectTurtle = useTurtleStore((state) => state.selectTurtle); const worldBlocks = useTurtleStore((state) => state.worldBlocks || []); + const sendCommand = useTurtleStore((state) => state.sendCommand); + const setTurtleState = useTurtleStore((state) => state.setTurtleState); // Mining areas state const [miningAreas, setMiningAreas] = useState([]); const [selectedAreaId, setSelectedAreaId] = useState(null); + + // Interaction mode state + const [moveTarget, setMoveTarget] = useState(null); + const [buildPreview, setBuildPreview] = useState(null); + const [selectionStart, setSelectionStart] = useState(null); + const [selectionEnd, setSelectionEnd] = useState(null); + const controlsRef = useRef(); + + // Handle block clicks from interaction modes + const handleBlockClick = useCallback((event) => { + if (event.type === 'move' && selectedTurtleId) { + setMoveTarget(event.target); + // Send the turtle to the clicked position + setTurtleState(selectedTurtleId, 'moving', { + target: event.target + }); + // Clear preview after a moment + setTimeout(() => setMoveTarget(null), 2000); + if (onInteraction) onInteraction({ mode: 'move', target: event.target, turtleId: selectedTurtleId }); + } else if (event.type === 'build') { + setBuildPreview(event.target); + if (onInteraction) onInteraction({ mode: 'build', target: event.target }); + } else if (event.type === 'select') { + if (!selectionStart) { + setSelectionStart(event.block); + setSelectionEnd(null); + } else { + setSelectionEnd(event.block); + if (onInteraction) onInteraction({ + mode: 'select', + start: selectionStart, + end: event.block + }); + // Reset after selection is complete + setTimeout(() => { + setSelectionStart(null); + setSelectionEnd(null); + }, 5000); + } + } + }, [selectedTurtleId, selectionStart, setTurtleState, onInteraction]); + + // Disable orbit controls when in interactive mode + useEffect(() => { + if (controlsRef.current) { + controlsRef.current.enabled = interactionMode === INTERACTION_MODE.LOOK; + } + }, [interactionMode]); // Load mining areas useEffect(() => { @@ -1170,8 +1220,20 @@ function Scene({ interactionMode, onInteraction }) { infiniteGrid /> - {/* Render discovered blocks */} - + {/* Render discovered blocks with chunked rendering */} + + + {/* Interaction mode previews */} + {moveTarget && } + {buildPreview && } + {(selectionStart || selectionEnd) && ( + + )} {/* Mining areas */} {miningAreas.map((area) => { @@ -1209,6 +1271,7 @@ function Scene({ interactionMode, onInteraction }) { {/* Camera controls */}