onClick(props, sessionProps)}
- onMouseEnter={() => onMouseEnter(props, sessionProps)}
- />
- )}
-
- )
-}
-
-export default BorderTiles
diff --git a/leaky-ships/src/components/Gamefield/EventBar.tsx b/leaky-ships/src/components/Gamefield/EventBar.tsx
deleted file mode 100644
index 5d3f19d..0000000
--- a/leaky-ships/src/components/Gamefield/EventBar.tsx
+++ /dev/null
@@ -1,369 +0,0 @@
-import {
- faSquare2,
- faSquare3,
- faSquare4,
-} from "@fortawesome/pro-regular-svg-icons"
-import {
- faBroomWide,
- faCheck,
- faComments,
- faEye,
- faEyeSlash,
- faFlag,
- faGlasses,
- faLock,
- faPalette,
- faReply,
- faRotate,
- faScribble,
- faShip,
- faSparkles,
- faSwords,
- faXmark,
-} from "@fortawesome/pro-solid-svg-icons"
-import { socket } from "~/lib/socket"
-import { modes } from "~/lib/utils/helpers"
-// import { Icons, toast } from "react-toastify"
-import { useNavigate } from "@solidjs/router"
-import { For, Show, createEffect } from "solid-js"
-import { clearDrawing } from "~/hooks/useDraw"
-import {
- color,
- setEnable,
- setShouldHide,
- shouldHide,
-} from "~/hooks/useDrawProps"
-import {
- gameProps,
- reset,
- setGameProps,
- setGameSetting,
- setIsReadyFor,
- setTarget,
- setTargetPreview,
- target,
- users,
-} from "~/hooks/useGameProps"
-import { useSession } from "~/hooks/useSession"
-import { EventBarModes } from "../../interfaces/frontend"
-import Item from "./Item"
-
-function EventBar() {
- const { selfIndex, selfIsActiveIndex, selfUser, ships } = useSession()
- const navigator = useNavigate()
-
- const items = (): EventBarModes => ({
- main: [
- {
- icon: "burger-menu",
- text: "Menu",
- callback: () => {
- setGameProps("menu", "menu")
- },
- },
- {
- icon: faSwords,
- text: "Attack",
- showWhen: () =>
- gameProps.gameState === "running" &&
- (selfIsActiveIndex() || gameProps.menu !== "main"),
- callback: () => {
- setGameProps("menu", "moves")
- },
- },
- {
- icon: faShip,
- text: "Ships",
- showWhen: () => gameProps.gameState !== "running",
- callback: () => {
- setGameProps("menu", "moves")
- },
- },
- {
- icon: "pen",
- text: "Draw",
- callback: () => {
- setGameProps("menu", "draw")
- },
- },
- {
- icon: "gear",
- text: "Settings",
- callback: () => {
- setGameProps("menu", "settings")
- },
- },
- ],
- menu: [
- {
- icon: faFlag,
- text: "Surrender",
- iconColor: "darkred",
- callback: () => {
- setGameProps("menu", "surrender")
- },
- },
- ],
- moves:
- gameProps.gameState === "running"
- ? [
- {
- icon: "scope",
- text: "Fire missile",
- enabled: gameProps.mode === 0,
- callback: () => {
- setGameProps("mode", 0)
- setTarget((t) => ({ ...t, show: false }))
- },
- },
- {
- icon: "torpedo",
- text: "Fire torpedo",
- enabled: gameProps.mode === 1 || gameProps.mode === 2,
- amount:
- 2 -
- (selfUser()?.moves.filter(
- (e) => e.type === "htorpedo" || e.type === "vtorpedo",
- ).length ?? 0),
- callback: () => {
- setGameProps("mode", 1)
- setTarget((t) => ({ ...t, show: false }))
- },
- },
- {
- icon: "radar",
- text: "Radar scan",
- enabled: gameProps.mode === 3,
- amount:
- 1 -
- (selfUser()?.moves.filter((e) => e.type === "radar").length ??
- 0),
- callback: () => {
- setGameProps("mode", 3)
- setTarget((t) => ({ ...t, show: false }))
- },
- },
- ]
- : [
- {
- icon: faSquare2,
- text: "Minensucher",
- amount: 1 - ships().filter((e) => e.size === 2).length,
- callback: () => {
- if (1 - ships().filter((e) => e.size === 2).length === 0) return
- setGameProps("mode", 0)
- },
- },
- {
- icon: faSquare3,
- text: "Kreuzer",
- amount: 3 - ships().filter((e) => e.size === 3).length,
- callback: () => {
- if (3 - ships().filter((e) => e.size === 3).length === 0) return
- setGameProps("mode", 1)
- },
- },
- {
- icon: faSquare4,
- text: "Schlachtschiff",
- amount: 2 - ships().filter((e) => e.size === 4).length,
- callback: () => {
- if (2 - ships().filter((e) => e.size === 4).length === 0) return
- setGameProps("mode", 2)
- },
- },
- {
- icon: faRotate,
- text: "Rotate",
- callback: () => {
- setTargetPreview((t) => ({
- ...t,
- orientation: t.orientation === "h" ? "v" : "h",
- }))
- },
- },
- ],
- draw: [
- {
- icon: faBroomWide,
- text: "Clear",
- showWhen: selfIsActiveIndex,
- callback: () => clearDrawing(selfIndex()),
- },
- {
- icon: faPalette,
- text: "Color",
- showWhen: selfIsActiveIndex,
- iconColor: color(),
- },
- {
- icon: shouldHide() ? faEye : faEyeSlash,
- text: shouldHide() ? "Show" : "Hide",
- callback: () => {
- setShouldHide((e) => !e)
- },
- },
- ],
- settings: [
- {
- icon: faGlasses,
- text: "Spectators",
- disabled: !gameProps.allowSpectators,
- callback: setGameSetting({
- allowSpectators: !gameProps.allowSpectators,
- }),
- },
- {
- icon: faSparkles,
- text: "Specials",
- disabled: !gameProps.allowSpecials,
- callback: setGameSetting({
- allowSpecials: !gameProps.allowSpecials,
- }),
- },
- {
- icon: faComments,
- text: "Chat",
- disabled: !gameProps.allowChat,
- callback: setGameSetting({ allowChat: !gameProps.allowChat }),
- },
- {
- icon: faScribble,
- text: "Mark/Draw",
- disabled: !gameProps.allowMarkDraw,
- callback: setGameSetting({
- allowMarkDraw: !gameProps.allowMarkDraw,
- }),
- },
- ],
- surrender: [
- {
- icon: faCheck,
- text: "Yes",
- iconColor: "green",
- callback: async () => {
- socket.emit("gameState", "aborted")
- navigator("/")
- reset()
- },
- },
- {
- icon: faXmark,
- text: "No",
- iconColor: "red",
- callback: () => {
- setGameProps("menu", "main")
- },
- },
- ],
- })
-
- createEffect(() => {
- if (
- gameProps.menu !== "moves" ||
- gameProps.gameState !== "starting" ||
- gameProps.mode < 0 ||
- items().moves[gameProps.mode].amount
- )
- return
- const index = items().moves.findIndex((e) => e.amount)
- setGameProps("mode", index)
- })
-
- createEffect(() => {
- setEnable(gameProps.menu === "draw")
- })
-
- // createEffect(() => {
- // if (gameProps.gameState !== "running") return
-
- // const toastId = "otherPlayer"
- // if (selfIsActiveIndex) toast.dismiss(toastId)
- // else
- // toast.info("Waiting for other player...", {
- // toastId,
- // position: "top-right",
- // icon: Icons.spinner(),
- // autoClose: false,
- // hideProgressBar: true,
- // closeButton: false,
- // })
-
- // toastId = "connect_error"
- // const isActive = toast.isActive(toastId)
- // console.log(toastId, isActive)
- // if (isActive)
- // toast.update(toastId, {
- // autoClose: 5000,
- // })
- // else
- // toast.warn("Spie", { toastId })
- // })
-
- return (
-
-
- - {
- setGameProps("menu", "main")
- },
- }}
- />
-
-
- {(e) => (
-
-
-
- )}
-
-
- - = 0
- : undefined,
- enabled:
- gameProps.gameState === "running" &&
- gameProps.mode >= 0 &&
- target().show,
- callback: () => {
- const sIndex = selfIndex()
- if (!sIndex) return
- switch (gameProps.gameState) {
- case "starting":
- const isReady = !users[sIndex.i]?.isReady
- setIsReadyFor({ isReady, i: sIndex.i })
- socket.emit("isReady", isReady)
- break
-
- case "running":
- const moves = selfUser()?.moves
- const length = moves?.length
- const props = {
- type: modes[gameProps.mode].type,
- x: target().x,
- y: target().y,
- orientation: target().orientation,
- index: length ?? 0,
- }
- socket.emit("dispatchMove", props)
- setTarget((t) => ({ ...t, show: false }))
- break
- }
- },
- }}
- />
-
-
- )
-}
-
-export default EventBar
diff --git a/leaky-ships/src/components/Gamefield/FogImages.tsx b/leaky-ships/src/components/Gamefield/FogImages.tsx
deleted file mode 100644
index 1c55791..0000000
--- a/leaky-ships/src/components/Gamefield/FogImages.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-function FogImages() {
- return (
- <>
-

-

-

-

-

- >
- )
-}
-
-export default FogImages
diff --git a/leaky-ships/src/components/Gamefield/Gamefield.tsx b/leaky-ships/src/components/Gamefield/Gamefield.tsx
deleted file mode 100644
index 6a0eafb..0000000
--- a/leaky-ships/src/components/Gamefield/Gamefield.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-// import Bluetooth from "./Bluetooth"
-// import FogImages from "./FogImages"
-// import { toast } from "react-toastify"
-import { useNavigate } from "@solidjs/router"
-import { createEffect, onCleanup } from "solid-js"
-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 { DrawingCanvas } from "~/hooks/useDraw"
-import { setFrameSize } from "~/hooks/useDrawProps"
-import {
- full,
- gameProps,
- mouseCursor,
- reset,
- setGameProps,
- setMouseCursor,
- setTargetPreview,
- target,
- users,
-} from "~/hooks/useGameProps"
-import { useSession } from "~/hooks/useSession"
-import useSocket from "~/hooks/useSocket"
-import { socket } from "~/lib/socket"
-import { overlapsWithAnyBorder } from "~/lib/utils/helpers"
-import Labeling from "./Labeling"
-import Ships from "./Ships"
-
-export const count = 12
-
-function Gamefield() {
- let frameRef: HTMLDivElement
- const { ships } = useSession()
- const navigator = useNavigate()
- const { isConnected } = useSocket()
-
- createEffect(() => {
- if (
- gameProps.gameState !== "starting" ||
- !users[0]?.isReady ||
- !users[1]?.isReady
- )
- return
- socket.emit("ships", ships())
- socket.emit("gameState", "running")
- })
-
- createEffect(() => {
- if (gameProps.gameId || !isConnected) return
- socket.emit("update", full)
- })
-
- createEffect(() => {
- if (gameProps.mode < 0) return
- const { x, y, show } = target()
- const { shouldShow, ...position } = mouseCursor()
- if (
- !shouldShow ||
- (gameProps.gameState === "running" &&
- overlapsWithAnyBorder(position, gameProps.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 (gameProps.gameState === "starting") {
- setTargetPreview((t) => ({
- ...t,
- orientation: t.orientation === "h" ? "v" : "h",
- }))
- }
- if (
- gameProps.gameState === "running" &&
- (gameProps.mode === 1 || gameProps.mode === 2)
- )
- setGameProps("mode", gameProps.mode === 1 ? 2 : 1)
- }
- document.addEventListener("keydown", handleKeyPress)
- onCleanup(() => {
- document.removeEventListener("keydown", handleKeyPress)
- })
- }
- })
-
- createEffect(() => {
- if (gameProps.gameState !== "aborted") return
- // toast.info("Enemy gave up!")
- navigator("/")
- reset()
- })
-
- createEffect(() => {
- function handleResize() {
- const rect = frameRef.getBoundingClientRect()
- setFrameSize({ x: rect.width, y: rect.height })
- }
- handleResize()
- window.addEventListener("resize", handleResize)
- onCleanup(() => removeEventListener("resize", handleResize))
- })
-
- return (
-
- {/*
*/}
-
- setMouseCursor((e) => ({ ...e, shouldShow: false }))
- }
- ref={frameRef!}
- >
-
-
- {/* Collumn lettes and row numbers */}
-
-
-
-
-
-
- {/* */}
-
-
-
-
-
-
-
- )
-}
-
-export default Gamefield
diff --git a/leaky-ships/src/components/Gamefield/GamefieldPointer.tsx b/leaky-ships/src/components/Gamefield/GamefieldPointer.tsx
deleted file mode 100644
index fd102c9..0000000
--- a/leaky-ships/src/components/Gamefield/GamefieldPointer.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { faCrosshairs } from "@fortawesome/pro-solid-svg-icons"
-import { faRadar } from "@fortawesome/pro-thin-svg-icons"
-import classNames from "classnames"
-import {} from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { PointerProps } from "../../interfaces/frontend"
-
-function GamefieldPointer(
- props: PointerProps & {
- preview?: boolean
- },
-) {
- const isRadar = () => props.type === "radar"
- const style = () =>
- !(isRadar() && !props.edges.filter((s) => s).length)
- ? { "--x": props.x, "--y": props.y }
- : {
- "--x1": props.x - 1,
- "--x2": props.x + 2,
- "--y1": props.y - 1,
- "--y2": props.y + 2,
- }
-
- return (
-
-
-
- )
-}
-
-export default GamefieldPointer
diff --git a/leaky-ships/src/components/Gamefield/HitElems.tsx b/leaky-ships/src/components/Gamefield/HitElems.tsx
deleted file mode 100644
index 177a64b..0000000
--- a/leaky-ships/src/components/Gamefield/HitElems.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { faBurst, faXmark } from "@fortawesome/pro-solid-svg-icons"
-import { For } from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { useSession } from "~/hooks/useSession"
-import { compiledHits } from "~/lib/utils/helpers"
-import { Hit } from "../../interfaces/frontend"
-
-function HitElems(props: { hits?: Hit[]; colorOverride?: string }) {
- const { activeIndex } = useSession()
- const hits = () => props?.hits
- const colorOverride = () => props?.colorOverride
-
- return (
-
- {(props) => (
-
-
-
- )}
-
- )
-}
-
-export default HitElems
diff --git a/leaky-ships/src/components/Gamefield/Item.tsx b/leaky-ships/src/components/Gamefield/Item.tsx
deleted file mode 100644
index 99a1a94..0000000
--- a/leaky-ships/src/components/Gamefield/Item.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import classNames from "classnames"
-import { BlockPicker } from "solid-color"
-import { Show, createSignal } from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { color, colors, setColor } from "~/hooks/useDrawProps"
-import { ItemProps } from "../../interfaces/frontend"
-
-function Item(props: ItemProps) {
- const isColor = () => props.text === "Color"
- const [active, setActive] = createSignal(false)
- let cpRef: HTMLDivElement
-
- return (
-
-
-
- setColor(e.hex)}
- colors={colors}
- triangle="hide"
- />
-
-
-
-
{props.text}
-
- )
-}
-
-export default Item
diff --git a/leaky-ships/src/components/Gamefield/Labeling.tsx b/leaky-ships/src/components/Gamefield/Labeling.tsx
deleted file mode 100644
index 55fc71e..0000000
--- a/leaky-ships/src/components/Gamefield/Labeling.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import classNames from "classnames"
-import { For } from "solid-js"
-import { fieldIndex } from "~/lib/utils/helpers"
-import { Field } from "../../interfaces/frontend"
-import { count } from "./Gamefield"
-
-function Labeling() {
- let elems: (Field & {
- orientation: string
- })[] = []
- for (let x = 0; x < count; x++) {
- elems.push(
- // Up
- { field: String.fromCharCode(65 + x), x: x + 2, y: 1, orientation: "up" },
- // Left
- { field: (x + 1).toString(), x: 1, y: x + 2, orientation: "left" },
- // Bottom
- {
- field: String.fromCharCode(65 + x),
- x: x + 2,
- y: count + 2,
- orientation: "bottom",
- },
- // Right
- {
- field: (x + 1).toString(),
- x: count + 2,
- y: x + 2,
- orientation: "right",
- },
- )
- }
- elems = elems.sort(
- (a, b) => fieldIndex(count, a.x, a.y) - fieldIndex(count, b.x, b.y),
- )
- return (
-
- {(props) => (
-
- {props.field}
-
- )}
-
- )
-}
-
-export default Labeling
diff --git a/leaky-ships/src/components/Gamefield/Ship.tsx b/leaky-ships/src/components/Gamefield/Ship.tsx
deleted file mode 100644
index 30c96d2..0000000
--- a/leaky-ships/src/components/Gamefield/Ship.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import classNames from "classnames"
-import { createEffect } from "solid-js"
-import { useSession } from "~/hooks/useSession"
-import { ShipProps } from "../../interfaces/frontend"
-
-const sizes: { [n: number]: number } = {
- 2: 96,
- 3: 144,
- 4: 196,
-}
-
-function Ship(
- props: ShipProps & {
- preview?: boolean
- warn?: boolean
- color?: string
- },
-) {
- const { selfIndex } = useSession()
- const filename = () =>
- `ship_${selfIndex()?.i === 1 ? "red" : "blue"}_${props.size}x_${
- props.variant
- }.gif`
- let canvasRef: HTMLCanvasElement
-
- createEffect(() => {
- const canvas = canvasRef
- const ctx = canvas?.getContext("2d")
- if (!canvas || !ctx) return
- const gif = new Image()
- gif.src = "/assets/" + filename()
-
- // Load the GIF and start rendering
- gif.onload = function () {
- // Set the canvas size to match the GIF dimensions
- canvas.width = props.orientation === "h" ? sizes[props.size] : 48
- canvas.height = props.orientation === "v" ? sizes[props.size] : 48
-
- if (props.orientation === "v")
- // Rotate the canvas by 90 degrees
- ctx.rotate((90 * Math.PI) / 180)
-
- // Draw the rotated GIF
- ctx.drawImage(
- gif,
- 0,
- props.orientation === "h" ? 0 : -48,
- sizes[props.size],
- 48,
- )
- }
- })
-
- return (
-
-
-
- )
-}
-
-export default Ship
diff --git a/leaky-ships/src/components/Gamefield/Ships.tsx b/leaky-ships/src/components/Gamefield/Ships.tsx
deleted file mode 100644
index a86fdfd..0000000
--- a/leaky-ships/src/components/Gamefield/Ships.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { For, Show } from "solid-js"
-import { gameProps } from "~/hooks/useGameProps"
-import { useSession } from "~/hooks/useSession"
-import Ship from "./Ship"
-
-function Ships() {
- const { selfIsActiveIndex, selfUser } = useSession()
-
- return (
-
- {(props) => }
-
- )
-}
-
-export default Ships
diff --git a/leaky-ships/src/components/Gamefield/Targets.tsx b/leaky-ships/src/components/Gamefield/Targets.tsx
deleted file mode 100644
index 2283c9b..0000000
--- a/leaky-ships/src/components/Gamefield/Targets.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import { For, Match, Switch } from "solid-js"
-import { gameProps, target, targetPreview } from "~/hooks/useGameProps"
-import { useSession } from "~/hooks/useSession"
-import {
- compiledHits,
- composeTargetTiles,
- intersectingShip,
- shipProps,
-} from "~/lib/utils/helpers"
-import GamefieldPointer from "./GamefieldPointer"
-import HitElems from "./HitElems"
-import Ship from "./Ship"
-
-function Targets() {
- const { activeIndex, ships } = useSession()
-
- const ship = () => shipProps(ships(), gameProps.mode, targetPreview())
- const intersectionProps = () => intersectingShip(ships(), ship())
-
- return (
-
-
-
- {(props) => }
-
-
- {(props) => }
-
-
- = 0 &&
- targetPreview().show
- }
- >
- 0}
- color={
- intersectionProps().fields.length
- ? "red"
- : intersectionProps().borders.length
- ? "orange"
- : undefined
- }
- />
- ({
- ...e,
- i,
- hit: true,
- }))}
- />
- ({
- ...e,
- i,
- hit: true,
- }))}
- colorOverride={"orange"}
- />
-
-
- )
-}
-
-export default Targets
diff --git a/leaky-ships/src/components/Grid.tsx b/leaky-ships/src/components/Grid.tsx
deleted file mode 100644
index 6372c8b..0000000
--- a/leaky-ships/src/components/Grid.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import classNames from "classnames"
-import { For, createEffect, createSignal, onCleanup } from "solid-js"
-
-function Grid() {
- function floorClient(number: number) {
- return Math.floor(number / 50)
- }
-
- const [columns, setColumns] = createSignal(0)
- const [rows, setRows] = createSignal(0)
- const quantity = () => columns() * rows()
- const [position, setPosition] = createSignal([0, 0])
- const [active, setActve] = createSignal(false)
- const [count, setCount] = createSignal(0)
-
- createEffect(() => {
- function handleResize() {
- setColumns(floorClient(document.body.clientWidth))
- setRows(floorClient(document.body.clientHeight))
- }
- handleResize()
- window.addEventListener("resize", handleResize)
- onCleanup(() => removeEventListener("resize", handleResize))
- })
-
- function Tile(props: { index: number }) {
- const x = () => props.index % columns()
- const y = () => Math.floor(props.index / columns())
- const xDiff = () => (x() - position()[0]) / 20
- const yDiff = () => (y() - position()[1]) / 20
- const pos = () =>
- Math.sqrt(xDiff() * xDiff() + yDiff() * yDiff()).toFixed(2)
-
- function doEffect(posX: number, posY: number) {
- if (active()) return
- setPosition([posX, posY])
- setActve(true)
-
- function xDiff(x: number) {
- return (x - posX) / 20
- }
- function yDiff(y: number) {
- return (y - posY) / 20
- }
- function pos(x: number, y: number) {
- return Math.sqrt(xDiff(x) * xDiff(x) + yDiff(y) * yDiff(y))
- }
- const diagonals = [
- pos(0, 0),
- pos(columns(), 0),
- pos(0, rows()),
- pos(columns(), rows()),
- ]
-
- setTimeout(
- () => {
- setActve(false)
- setCount((e) => e + 1)
- },
- Math.max(...diagonals) * 1000 + 300,
- )
- }
-
- return (
-
doEffect(x(), y())}
- />
- )
- }
-
- const colors = [
- "rgb(229, 57, 53)",
- "rgb(253, 216, 53)",
- "rgb(244, 81, 30)",
- "rgb(76, 175, 80)",
- "rgb(33, 150, 243)",
- "rgb(156, 39, 176)",
- ]
-
- return (
-
-
- {(_tile, i) => }
-
-
- )
-}
-
-export default Grid
diff --git a/leaky-ships/src/components/Grid2.tsx b/leaky-ships/src/components/Grid2.tsx
deleted file mode 100644
index 7eaecd5..0000000
--- a/leaky-ships/src/components/Grid2.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import classNames from "classnames"
-import { For, createEffect, createSignal, onCleanup } from "solid-js"
-
-function Grid2() {
- function floorClient(number: number) {
- return Math.floor(number / 50)
- }
-
- const [columns, setColumns] = createSignal(0)
- const [rows, setRows] = createSignal(0)
- const quantity = () => columns() * rows()
- const [position, setPosition] = createSignal([0, 0])
- const [active, setActve] = createSignal(false)
- const [action, setAction] = createSignal(false)
- const [count, setCount] = createSignal(0)
-
- createEffect(() => {
- function handleResize() {
- setColumns(floorClient(document.body.clientWidth))
- setRows(floorClient(document.body.clientHeight))
- }
- handleResize()
- window.addEventListener("resize", handleResize)
- onCleanup(() => removeEventListener("resize", handleResize))
- })
-
- const sentences = [
- "Ethem ...",
- "hat ...",
- "lange ...",
- "Hörner 🐂",
- "Grüße von Mallorca 🌊 🦦 ☀️",
- ]
-
- function Tile(props: { index: number }) {
- const x = () => props.index % columns()
- const y = () => Math.floor(props.index / columns())
- const xDiff = () => (x() - position()[0]) / 20
- const yDiff = () => (y() - position()[1]) / 20
- const pos = () =>
- Math.sqrt(xDiff() * xDiff() + yDiff() * yDiff()).toFixed(2)
-
- function doEffect(posX: number, posY: number) {
- if (action()) return
- setPosition([posX, posY])
- setActve((e) => !e)
- setAction(true)
-
- function xDiff(x: number) {
- return (x - posX) / 20
- }
- function yDiff(y: number) {
- return (y - posY) / 20
- }
- function pos(x: number, y: number) {
- return Math.sqrt(xDiff(x) * xDiff(x) + yDiff(y) * yDiff(y))
- }
- const diagonals = [
- pos(0, 0),
- pos(columns(), 0),
- pos(0, rows()),
- pos(columns(), rows()),
- ]
-
- setTimeout(
- () => {
- setAction(false)
- if (active()) setCount((e) => e + 1)
- },
- Math.max(...diagonals) * 1000 + 1000,
- )
- }
-
- return (
-
doEffect(x(), y())}
- />
- )
- }
-
- return (
-
-
-
- {sentences[count() % sentences.length]}
-
-
-
- {(_tile, i) => }
-
-
- )
-}
-
-export default Grid2
diff --git a/leaky-ships/src/components/Lobby/Button.tsx b/leaky-ships/src/components/Lobby/Button.tsx
deleted file mode 100644
index febd10e..0000000
--- a/leaky-ships/src/components/Lobby/Button.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import classNames from "classnames"
-import { JSX } from "solid-js"
-
-function Button(props: {
- type: "red" | "orange" | "green" | "gray"
- disabled?: boolean
- onClick: () => void
- children: JSX.Element
- latching?: boolean
- isLatched?: boolean
-}) {
- return (
-
- )
-}
-
-export default Button
diff --git a/leaky-ships/src/components/Lobby/Icon.tsx b/leaky-ships/src/components/Lobby/Icon.tsx
deleted file mode 100644
index 0d50a69..0000000
--- a/leaky-ships/src/components/Lobby/Icon.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { JSX } from "solid-js"
-
-function Icon(props: {
- src: string
- children: JSX.Element
- onClick?: () => void
-}) {
- return (
-
- )
-}
-
-export default Icon
diff --git a/leaky-ships/src/components/Lobby/LobbyFrame.tsx b/leaky-ships/src/components/Lobby/LobbyFrame.tsx
deleted file mode 100644
index 87c6d79..0000000
--- a/leaky-ships/src/components/Lobby/LobbyFrame.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-import {
- faRightFromBracket,
- faSpinnerThird,
-} from "@fortawesome/pro-solid-svg-icons"
-import { useNavigate } from "@solidjs/router"
-import { JSX, Show, createEffect, createSignal, onCleanup } from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { full, gameProps, leave, reset, users } from "~/hooks/useGameProps"
-import { useSession } from "~/hooks/useSession"
-import useSocket from "~/hooks/useSocket"
-import { socket } from "~/lib/socket"
-import Button from "./Button"
-import Icon from "./Icon"
-import Player from "./Player"
-
-function WithDots(props: { children: JSX.Element }) {
- const [dots, setDots] = createSignal(1)
-
- createEffect(() => {
- const interval = setInterval(() => setDots((e) => (e % 3) + 1), 1000)
- onCleanup(() => clearInterval(interval))
- })
-
- return (
- <>
- {props.children + " "}
- {Array.from(Array(dots()), () => ".").join("")}
- {Array.from(Array(3 - dots()), () => (
- <> >
- ))}
- >
- )
-}
-
-function LobbyFrame(props: { openSettings: () => void }) {
- const { isConnected } = useSocket()
- const navigator = useNavigate()
- const { session } = useSession()
- const [launchTime, setLaunchTime] = createSignal(3)
- const launching = () => users[0]?.isReady && users[1]?.isReady
-
- createEffect(() => {
- if (!launching() || launchTime() > 0) return
- socket.emit("gameState", "starting")
- })
-
- createEffect(() => {
- if (!launching()) return setLaunchTime(3)
- if (launchTime() < 0) return
-
- const timeout = setTimeout(() => {
- setLaunchTime((e) => e - 1)
- }, 1000)
-
- onCleanup(() => clearTimeout(timeout))
- })
-
- createEffect(() => {
- if (gameProps.gameId || !isConnected) return
- socket.emit("update", full)
- })
-
- createEffect(() => {
- if (gameProps.gameState === "unknown" || gameProps.gameState === "lobby")
- return
- navigator("/gamefield")
- })
-
- return (
-
-
- Chat
-
-
- {launchTime() < 0
- ? "Game starts"
- : "Game is starting in " + launchTime()}
-
- }
- >
- {"Game-PIN: "}
- }
- >
- {gameProps.gamePin ?? "----"}
-
-
-
-
- Settings
-
-
-
-
- Warte auf Verbindung
-
- }
- >
-
- VS
-
- Warte auf Spieler 2
-
- }
- >
-
-
-
-
-
-
-
-
- )
-}
-
-export default LobbyFrame
diff --git a/leaky-ships/src/components/Lobby/Player.tsx b/leaky-ships/src/components/Lobby/Player.tsx
deleted file mode 100644
index a5ea923..0000000
--- a/leaky-ships/src/components/Lobby/Player.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import {
- faCheck,
- faHandPointer,
- faHourglass1,
- faHourglass2,
- faHourglass3,
- faHourglassClock,
-} from "@fortawesome/pro-solid-svg-icons"
-import { faCaretDown } from "@fortawesome/sharp-solid-svg-icons"
-import classNames from "classnames"
-import { Show, createEffect, createSignal, onCleanup } from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { setIsReadyFor, users } from "~/hooks/useGameProps"
-import { socket } from "~/lib/socket"
-import Button from "./Button"
-
-function HourGlass() {
- const [count, setCount] = createSignal(3)
-
- createEffect(() => {
- const interval = setInterval(() => setCount((e) => (e + 1) % 4), 1000)
- onCleanup(() => clearInterval(interval))
- })
-
- const icon = () => {
- switch (count()) {
- case 0:
- return faHourglass3
- case 1:
- return faHourglass1
- case 2:
- return faHourglass2
- case 3:
- return faHourglass3
- default:
- return faHourglassClock
- }
- }
-
- return (
-
- )
-}
-
-function Player(props: { src: string; i: 0 | 1; userId?: string }) {
- const player = () => users[props.i]
- const primary = () => props.userId && props.userId === player()?.id
-
- return (
-
-
- {player()?.name ?? "Spieler " + (props.i === 1 ? "2" : "1")}
-
-
-

-
-
-
-
-
-
- )
-}
-
-export default Player
diff --git a/leaky-ships/src/components/Lobby/SettingsFrame/Setting.tsx b/leaky-ships/src/components/Lobby/SettingsFrame/Setting.tsx
deleted file mode 100644
index f0ec485..0000000
--- a/leaky-ships/src/components/Lobby/SettingsFrame/Setting.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import {
- faToggleLargeOff,
- faToggleLargeOn,
-} from "@fortawesome/pro-solid-svg-icons"
-import classNames from "classnames"
-import { JSX } from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { gameProps, setGameSetting } from "~/hooks/useGameProps"
-import { GameSettingKeys } from "../../../interfaces/frontend"
-
-function Setting(props: { children: JSX.Element; key: GameSettingKeys }) {
- const state = () => gameProps[props.key]
-
- return (
-
- )
-}
-
-export default Setting
diff --git a/leaky-ships/src/components/Lobby/SettingsFrame/Settings.tsx b/leaky-ships/src/components/Lobby/SettingsFrame/Settings.tsx
deleted file mode 100644
index a752428..0000000
--- a/leaky-ships/src/components/Lobby/SettingsFrame/Settings.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import { faRotateLeft } from "@fortawesome/pro-regular-svg-icons"
-import { faXmark } from "@fortawesome/pro-solid-svg-icons"
-import {} from "solid-js"
-import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"
-import { full, setSetting } from "~/hooks/useGameProps"
-import { socket } from "~/lib/socket"
-import { GameSettings } from "../../../interfaces/frontend"
-import Setting from "./Setting"
-
-function Settings(props: { closeSettings: () => void }) {
- const gameSetting = (newSettings: GameSettings) => {
- const hash = setSetting(newSettings)
- socket.emit("gameSetting", newSettings, (newHash) => {
- if (newHash === hash) return
- console.log("hash", hash, newHash)
- socket.emit("update", full)
- })
- }
-
- return (
-
-
-
-
-
- Settings
-
-
-
-
-
-
-
-
- Erlaube Zuschauer
- Erlaube spezial Items
- Erlaube den Chat
- Erlaube zeichen/makieren
-
-
-
-
-
- )
-}
-
-export default Settings
diff --git a/leaky-ships/src/components/Logo.tsx b/leaky-ships/src/components/Logo.tsx
deleted file mode 100644
index 539bd2e..0000000
--- a/leaky-ships/src/components/Logo.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import classNames from "classnames"
-
-function Logo(props: { small?: boolean }) {
- return (
-
-
-
- Leaky
- Ships
-
-
-
-
- )
-}
-
-function Screws(props: { small?: boolean }) {
- return (
- <>
-
-
-
-
- >
- )
-}
-
-function Screw(props: {
- orientation: string
- rotation: string
- small?: boolean
-}) {
- return (
-
-
-
- )
-}
-
-export default Logo
diff --git a/leaky-ships/src/components/OptionButton.tsx b/leaky-ships/src/components/OptionButton.tsx
deleted file mode 100644
index badd46e..0000000
--- a/leaky-ships/src/components/OptionButton.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { IconDefinition } from "@fortawesome/fontawesome-svg-core"
-import classNames from "classnames"
-import { JSX } from "solid-js"
-import { FontAwesomeIcon } from "./FontAwesomeIcon"
-
-const styles = {
- wrapper:
- "flex w-full flex-row items-center justify-between rounded-lg py-2 pl-8 pr-4 text-lg text-grayish duration-100 first:mt-4 last:mt-4 sm:rounded-xl sm:py-4 sm:pl-16 sm:pr-8 sm:text-4xl sm:first:mt-8 sm:last:mt-8",
- enabled:
- "border-b-4 border-shield-gray bg-voidDark active:border-b-0 active:border-t-4",
- disabled: "border-4 border-dashed border-slate-600 bg-red-950",
- icon: "ml-2 w-10 text-xl sm:ml-12 sm:text-4xl",
-}
-
-export function OptionAnchor(props: {
- text: string
- icon: IconDefinition
- href: string
- disabled?: boolean
-}) {
- return (
-
- {props.text}
-
-
- )
-}
-
-export function OptionButton(props: {
- text: string
- icon: IconDefinition
- callback: () => void
- disabled?: boolean
-}) {
- return (
-
- )
-}
-
-export function OptionDiv(props: {
- icon: IconDefinition
- children: JSX.Element
-}) {
- return (
-
- {props.children}
-
-
- )
-}
diff --git a/leaky-ships/src/components/profileImg.tsx b/leaky-ships/src/components/profileImg.tsx
deleted file mode 100644
index a7898a4..0000000
--- a/leaky-ships/src/components/profileImg.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-function profileImg(src: string) {
- return (
-

- )
-}
-
-export default profileImg
diff --git a/leaky-ships/src/drizzle/index.ts b/leaky-ships/src/drizzle/index.ts
deleted file mode 100644
index 4f0addc..0000000
--- a/leaky-ships/src/drizzle/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { drizzle } from "drizzle-orm/postgres-js"
-import postgres from "postgres"
-import * as schema from "./schemas/Tables"
-
-const queryClient = postgres(import.meta.env.VITE_DATABASE_URL ?? "")
-const db = drizzle(queryClient, {
- schema,
-})
-
-export default db
diff --git a/leaky-ships/src/drizzle/schemas/Tables.ts b/leaky-ships/src/drizzle/schemas/Tables.ts
deleted file mode 100644
index e2f417e..0000000
--- a/leaky-ships/src/drizzle/schemas/Tables.ts
+++ /dev/null
@@ -1,194 +0,0 @@
-import type { AdapterAccount } from "@auth/core/adapters"
-import { relations } from "drizzle-orm"
-import {
- boolean,
- integer,
- pgTable,
- primaryKey,
- text,
- timestamp,
- unique,
-} from "drizzle-orm/pg-core"
-import { gameState, moveType, orientation } from "./Types"
-
-export const users = pgTable("user", {
- id: text("id").notNull().primaryKey(),
- name: text("name").notNull(),
- email: text("email").notNull().unique(),
- emailVerified: timestamp("emailVerified", { mode: "date" }),
- image: text("image"),
- createdAt: timestamp("created_at").defaultNow(),
- updatedAt: timestamp("updated_at").notNull().defaultNow(),
-})
-
-export const accounts = pgTable(
- "account",
- {
- userId: text("userId")
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- type: text("type").$type
().notNull(),
- provider: text("provider").notNull(),
- providerAccountId: text("providerAccountId").notNull(),
- refresh_token: text("refresh_token"),
- access_token: text("access_token"),
- expires_at: integer("expires_at"),
- extExpiresIn: integer("ext_expires_in"),
- token_type: text("token_type"),
- scope: text("scope"),
- id_token: text("id_token"),
- session_state: text("session_state"),
- oauthTokenSecret: text("oauth_token_secret"),
- oauthToken: text("oauth_token"),
- },
- (account) => ({
- compoundKey: primaryKey(account.provider, account.providerAccountId),
- }),
-)
-
-export const sessions = pgTable("session", {
- sessionToken: text("sessionToken").notNull().primaryKey(),
- userId: text("userId")
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- expires: timestamp("expires", { mode: "date" }).notNull(),
-})
-
-export const verificationTokens = pgTable(
- "verificationToken",
- {
- identifier: text("identifier").notNull(),
- token: text("token").notNull(),
- expires: timestamp("expires", { mode: "date" }).notNull(),
- },
- (vt) => ({
- compoundKey: primaryKey(vt.identifier, vt.token),
- }),
-)
-
-export const games = pgTable("game", {
- id: text("id").notNull().primaryKey(),
- createdAt: timestamp("created_at").defaultNow(),
- updatedAt: timestamp("updated_at").notNull().defaultNow(),
- state: gameState("state").notNull().default("lobby"),
- allowSpectators: boolean("allow_spectators").notNull().default(true),
- allowSpecials: boolean("allow_specials").notNull().default(true),
- allowChat: boolean("allow_chat").notNull().default(true),
- allowMarkDraw: boolean("allow_mark_draw").notNull().default(true),
-})
-
-export const gamepins = pgTable("gamepin", {
- id: text("id").notNull().primaryKey(),
- createdAt: timestamp("created_at").defaultNow(),
- pin: text("pin").notNull().unique(),
- gameId: text("game_id")
- .notNull()
- .unique()
- .references(() => games.id, { onDelete: "cascade" }),
-})
-
-export const ships = pgTable("ship", {
- id: text("id").notNull().primaryKey(),
- size: integer("size").notNull(),
- variant: integer("variant").notNull(),
- x: integer("x").notNull(),
- y: integer("y").notNull(),
- orientation: orientation("orientation").notNull(),
- user_game_id: text("user_game_id")
- .notNull()
- .references(() => user_games.id, { onDelete: "cascade" }),
-})
-
-export const moves = pgTable("move", {
- id: text("id").notNull().primaryKey(),
- createdAt: timestamp("created_at").defaultNow(),
- index: integer("index").notNull(),
- type: moveType("type").notNull(),
- x: integer("x").notNull(),
- y: integer("y").notNull(),
- orientation: orientation("orientation").notNull(),
- user_game_id: text("user_game_id")
- .notNull()
- .references(() => user_games.id, { onDelete: "cascade" }),
-})
-
-export const chats = pgTable("chat", {
- id: text("id").notNull().primaryKey(),
- createdAt: timestamp("created_at").notNull().defaultNow(),
- message: text("message"),
- event: text("event"),
- user_game_id: text("user_game_id")
- .notNull()
- .references(() => user_games.id, { onDelete: "cascade" }),
-})
-
-export const user_games = pgTable(
- "user_game",
- {
- id: text("id").notNull().primaryKey(),
- createdAt: timestamp("created_at").defaultNow(),
- gameId: text("game_id")
- .notNull()
- .references(() => games.id, { onDelete: "cascade" }),
- userId: text("user_id")
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- index: integer("index").notNull(),
- },
- (t) => ({
- gameIndex: unique().on(t.gameId, t.index),
- }),
-)
-
-export const usersRelations = relations(users, ({ many }) => ({
- user_games: many(user_games),
- sessions: many(sessions),
-}))
-
-export const sessionsRelations = relations(sessions, ({ one }) => ({
- user: one(users, {
- fields: [sessions.userId],
- references: [users.id],
- }),
-}))
-
-export const gamesRelations = relations(games, ({ one, many }) => ({
- gamePin: one(gamepins, {
- fields: [games.id],
- references: [gamepins.gameId],
- }),
- users: many(user_games),
-}))
-
-export const gamepinsRelations = relations(gamepins, ({ one }) => ({
- game: one(games, { fields: [gamepins.gameId], references: [games.id] }),
-}))
-
-export const shipsRelations = relations(ships, ({ one }) => ({
- userGame: one(user_games, {
- fields: [ships.user_game_id],
- references: [user_games.id],
- }),
-}))
-
-export const userGamesRelations = relations(user_games, ({ one, many }) => ({
- user: one(users, { fields: [user_games.userId], references: [users.id] }),
- game: one(games, { fields: [user_games.gameId], references: [games.id] }),
- moves: many(moves),
- ships: many(ships),
- chats: many(chats),
-}))
-
-export const movesRelations = relations(moves, ({ one }) => ({
- userGame: one(user_games, {
- fields: [moves.user_game_id],
- references: [user_games.id],
- }),
-}))
-
-export const chatsRelations = relations(chats, ({ one }) => ({
- userGame: one(user_games, {
- fields: [chats.user_game_id],
- references: [user_games.id],
- }),
-}))
diff --git a/leaky-ships/src/drizzle/schemas/Types.ts b/leaky-ships/src/drizzle/schemas/Types.ts
deleted file mode 100644
index 32cb3a8..0000000
--- a/leaky-ships/src/drizzle/schemas/Types.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { pgEnum } from "drizzle-orm/pg-core"
-
-export const gameState = pgEnum("game_state", [
- "unknown",
- "lobby",
- "starting",
- "running",
- "ended",
- "aborted",
-])
-export const moveType = pgEnum("move_type", [
- "missile",
- "vtorpedo",
- "htorpedo",
- "radar",
-])
-export const orientation = pgEnum("orientation", ["h", "v"])
diff --git a/leaky-ships/src/entry-client.tsx b/leaky-ships/src/entry-client.tsx
deleted file mode 100644
index 38c681e..0000000
--- a/leaky-ships/src/entry-client.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-import { mount, StartClient } from "@solidjs/start/client"
-
-mount(() => , document.getElementById("app")!)
diff --git a/leaky-ships/src/entry-server.tsx b/leaky-ships/src/entry-server.tsx
deleted file mode 100644
index 03a02d4..0000000
--- a/leaky-ships/src/entry-server.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { StartServer, createHandler } from "@solidjs/start/server"
-
-export default createHandler(() => (
- (
-
-
-
-
-
- {assets}
-
-
- {children}
- {scripts}
-
-
- )}
- />
-))
diff --git a/leaky-ships/src/hooks/useDraw.tsx b/leaky-ships/src/hooks/useDraw.tsx
deleted file mode 100644
index 3810845..0000000
--- a/leaky-ships/src/hooks/useDraw.tsx
+++ /dev/null
@@ -1,179 +0,0 @@
-import { createEffect, createSignal, onCleanup } from "solid-js"
-import { socket } from "~/lib/socket"
-import { DrawLineProps, PlayerEvent, Point } from "../interfaces/frontend"
-import { color, enable, frameSize, shouldHide } from "./useDrawProps"
-import { useSession } from "./useSession"
-
-let canvasRef: HTMLCanvasElement
-const strokes: Record<0 | 1, DrawLineProps[]> = { 0: [], 1: [] }
-
-function drawLine(
- { prevPoint, currentPoint, color }: DrawLineProps,
- ctx: CanvasRenderingContext2D,
- i: 0 | 1,
-) {
- strokes[i].push({ prevPoint, currentPoint, color })
-
- const currX = currentPoint.x * frameSize().x
- const currY = currentPoint.y * frameSize().y
-
- const startPoint = prevPoint ?? currentPoint
- const startX = startPoint.x * frameSize().x
- const startY = startPoint.y * frameSize().y
-
- const lineColor = color
- const lineWidth = 5
-
- ctx.beginPath()
- ctx.lineWidth = lineWidth
- ctx.strokeStyle = lineColor
- ctx.moveTo(startX, startY)
- ctx.lineTo(currX, currY)
- ctx.stroke()
-
- ctx.fillStyle = lineColor
- ctx.beginPath()
- ctx.arc(startPoint.x, startPoint.y, 2, 0, 2 * Math.PI)
- ctx.fill()
-}
-
-function clear(sIndex?: { i: 0 | 1 }) {
- const canvas = canvasRef
- if (!canvas) return
-
- if (sIndex) strokes[sIndex.i] = []
-
- const ctx = canvas.getContext("2d")
- if (!ctx) return
-
- ctx.clearRect(0, 0, canvas.width, canvas.height)
-}
-
-export function DrawingCanvas() {
- const [mouseDown, setMouseDown] = createSignal(false)
- const [stateIndex, setStateIndex] = createSignal<{ i: 0 | 1 } | null>(null)
- const { selfIndex, selfIsActiveIndex, activeIndex } = useSession()
-
- createEffect(() => {
- const i = activeIndex()
- const canvas = canvasRef
- if (!canvas || i === stateIndex()?.i) return
-
- const ctx = canvasRef?.getContext("2d")
- if (!ctx) return
-
- clear()
- strokes[i].forEach((props) => drawLine(props, ctx, i))
- setStateIndex({ i })
- })
-
- createEffect(() => {
- let prevPoint: null | Point
-
- const canvas = canvasRef
- if (!canvas) return
-
- const handler = (e: MouseEvent) => {
- const sIndex = selfIndex()
- if (!mouseDown() || !selfIsActiveIndex() || !sIndex) return
-
- const rect = canvas.getBoundingClientRect()
- const x = (e.clientX - rect.left) / frameSize().x
- const y = (e.clientY - rect.top) / frameSize().y
-
- const currentPoint = { x, y }
-
- const ctx = canvasRef?.getContext("2d")
- if (!ctx) return
-
- const props = {
- currentPoint,
- prevPoint,
- color: color(),
- }
- socket.emit("draw-line", props)
- drawLine(props, ctx, sIndex.i)
- prevPoint = currentPoint
- }
-
- const mouseUpHandler = () => {
- setMouseDown(false)
- prevPoint = null
- }
-
- // Add event listeners
- canvas.addEventListener("mousemove", handler)
- window.addEventListener("mouseup", mouseUpHandler)
-
- // Remove event listeners
- onCleanup(() => {
- canvas.removeEventListener("mousemove", handler)
- window.removeEventListener("mouseup", mouseUpHandler)
- })
- })
-
- createEffect(() => {
- const sIndex = selfIndex()
- const canvas = canvasRef
- if (!canvas || !sIndex) return
-
- const ctx = canvas.getContext("2d")
- if (!ctx) return
-
- const playerEvent = (event: PlayerEvent) => {
- if (
- !strokes[sIndex.i].length ||
- !selfIsActiveIndex() ||
- event.type !== "connect"
- )
- return
- console.log("Sending canvas state.")
- socket.emit("canvas-state", strokes[sIndex.i])
- }
-
- const canvasStateFromServer = (state: DrawLineProps[], i: 0 | 1) => {
- console.log("Canvas state received.")
- clear({ i })
- state.forEach((props) => drawLine(props, ctx, i))
- }
-
- const socketDrawLine = (props: DrawLineProps, i: 0 | 1) => {
- drawLine(props, ctx, i)
- }
-
- socket.on("playerEvent", playerEvent)
- socket.on("canvas-state-from-server", canvasStateFromServer)
- socket.on("draw-line", socketDrawLine)
- socket.on("canvas-clear", clear)
-
- onCleanup(() => {
- socket.off("playerEvent", playerEvent)
- socket.off("canvas-state-from-server", canvasStateFromServer)
- socket.off("draw-line", socketDrawLine)
- socket.off("canvas-clear", clear)
- })
- })
-
- return (
-