leaky-ships/leaky-ships/components/Gamefield/Gamefield.tsx

145 lines
4 KiB
TypeScript

// import Bluetooth from "./Bluetooth"
// import FogImages from "./FogImages"
import BorderTiles from "@components/Gamefield/BorderTiles"
import EventBar from "@components/Gamefield/EventBar"
import HitElems from "@components/Gamefield/HitElems"
import Targets from "@components/Gamefield/Targets"
import { useDraw } from "@hooks/useDraw"
import { useDrawProps } from "@hooks/useDrawProps"
import { useGameProps } from "@hooks/useGameProps"
import useIndex from "@hooks/useIndex"
import useSocket from "@hooks/useSocket"
import { socket } from "@lib/socket"
import { overlapsWithAnyBorder } from "@lib/utils/helpers"
import { useRouter } from "next/router"
import { CSSProperties, useEffect } from "react"
import { toast } from "react-toastify"
import Labeling from "./Labeling"
import Ships from "./Ships"
export const count = 12
function Gamefield() {
const { selfUser } = useIndex()
const router = useRouter()
const {
userStates,
mode,
target,
mouseCursor,
setMouseCursor,
payload,
setTargetPreview,
full,
reset,
} = useGameProps()
const { isConnected } = useSocket()
const { canvasRef, onMouseDown, clear } = useDraw()
const { enable, color, shouldHide } = useDrawProps()
useEffect(() => {
if (
payload?.game?.state !== "starting" ||
userStates.reduce((prev, curr) => prev || !curr.isReady, false)
)
return
socket.emit("ships", selfUser?.ships ?? [])
socket.emit("gameState", "running")
}, [payload?.game?.state, selfUser?.ships, userStates])
useEffect(() => {
if (payload?.game?.id || !isConnected) return
socket.emit("update", full)
}, [full, payload?.game?.id, isConnected])
useEffect(() => {
if (mode < 0) return
const { x, y, show } = target
const { shouldShow, ...position } = mouseCursor
if (
!shouldShow ||
(payload?.game?.state === "running" &&
overlapsWithAnyBorder(position, mode))
)
setTargetPreview((t) => ({ ...t, show: false }))
else {
setTargetPreview((t) => ({
...t,
...position,
show: !show || x !== position.x || y !== position.y,
}))
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key !== "r") return
if (payload?.game?.state === "starting") {
setTargetPreview((t) => ({
...t,
orientation: t.orientation === "h" ? "v" : "h",
}))
}
if (payload?.game?.state === "running" && (mode === 1 || mode === 2))
useGameProps.setState({ mode: mode === 1 ? 2 : 1 })
}
document.addEventListener("keydown", handleKeyPress)
return () => {
document.removeEventListener("keydown", handleKeyPress)
}
}
}, [mode, mouseCursor, payload?.game?.state, setTargetPreview, target])
useEffect(() => {
if (payload?.game?.state !== "aborted") return
toast.info("Enemy gave up!")
router.push("/")
reset()
}, [payload?.game?.state, reset, router])
useEffect(() => {
if (payload?.game?.id) return
const timeout = setTimeout(() => router.push("/"), 5000)
return () => clearTimeout(timeout)
}, [payload?.game?.id, router])
return (
<div id="gamefield">
{/* <Bluetooth /> */}
<div
id="game-frame"
style={{ "--i": count } as CSSProperties}
onMouseLeave={() =>
setMouseCursor((e) => ({ ...e, shouldShow: false }))
}
>
<BorderTiles />
{/* Collumn lettes and row numbers */}
<Labeling />
<Ships />
<HitElems />
{/* <FogImages /> */}
<Targets />
<canvas
style={
{
opacity: shouldHide ? 0 : 1,
boxShadow: enable ? "inset 0 0 0 2px " + color : "none",
pointerEvents: enable && !shouldHide ? "auto" : "none",
} as CSSProperties
}
ref={canvasRef}
onMouseDown={onMouseDown}
width="648"
height="648"
/>
</div>
<EventBar clear={clear} />
</div>
)
}
export default Gamefield