From 252f6f60286cca2c60253cdb4dc78f300e356aea Mon Sep 17 00:00:00 2001 From: aronmal Date: Fri, 8 Sep 2023 18:55:59 +0200 Subject: [PATCH] Replace gameProp signals with store --- .../src/components/Gamefield/BorderTiles.tsx | 44 ++-- .../src/components/Gamefield/EventBar.tsx | 123 ++++++----- .../src/components/Gamefield/Gamefield.tsx | 32 +-- .../src/components/Gamefield/Ships.tsx | 6 +- .../src/components/Gamefield/Targets.tsx | 27 ++- .../src/components/Lobby/LobbyFrame.tsx | 25 +-- leaky-ships/src/components/Lobby/Player.tsx | 22 +- leaky-ships/src/hooks/useGameProps.ts | 203 ++++++++---------- leaky-ships/src/hooks/useSession.tsx | 26 +-- leaky-ships/src/hooks/useSocket.ts | 18 +- leaky-ships/src/interfaces/ApiSocket.ts | 8 +- leaky-ships/src/interfaces/frontend.ts | 8 +- leaky-ships/src/lib/getPayloadFromProps.ts | 46 ++-- leaky-ships/src/lib/utils/helpers.ts | 82 ++++--- 14 files changed, 331 insertions(+), 339 deletions(-) diff --git a/leaky-ships/src/components/Gamefield/BorderTiles.tsx b/leaky-ships/src/components/Gamefield/BorderTiles.tsx index 5a29274..2dcab34 100644 --- a/leaky-ships/src/components/Gamefield/BorderTiles.tsx +++ b/leaky-ships/src/components/Gamefield/BorderTiles.tsx @@ -1,10 +1,9 @@ import { For } from "solid-js" import { - gameState, - mode, + gameProps, mouseCursor, removeShip, - setMode, + setGameProps, setMouseCursor, setShips, setTarget, @@ -13,6 +12,7 @@ import { import { useSession } from "~/hooks/useSession" import { borderCN, + compiledHits, cornerCN, fieldIndex, intersectingShip, @@ -32,19 +32,21 @@ type TilesType = { } function BorderTiles() { - const { selfIndex, activeUser, ships } = useSession() + const { selfIndex, ships } = useSession() const settingTarget = (isGameTile: boolean, x: number, y: number) => { - if (gameState() === "running") { - const list = targetList(targetPreview(), mode()) + const sIndex = selfIndex() + if (sIndex === -1) return + if (gameProps.gameState === "running") { + const list = targetList(targetPreview(), gameProps.mode) if ( !isGameTile || !list.filter( - ({ x, y }) => !isAlreadyHit(x, y, activeUser()?.hits() ?? []), + ({ x, y }) => !isAlreadyHit(x, y, compiledHits(sIndex === 0 ? 1 : 0)), ).length ) return - if (!overlapsWithAnyBorder(targetPreview(), mode())) + if (!overlapsWithAnyBorder(targetPreview(), gameProps.mode)) setTarget({ show: true, x, @@ -52,15 +54,17 @@ function BorderTiles() { orientation: targetPreview().orientation, }) } else if ( - gameState() === "starting" && + gameProps.gameState === "starting" && targetPreview().show && - !intersectingShip(ships(), shipProps(ships(), mode(), targetPreview())) - .score + !intersectingShip( + ships(), + shipProps(ships(), gameProps.mode, targetPreview()), + ).score ) { setMouseCursor((e) => ({ ...e, shouldShow: false })) setShips( - [...ships(), shipProps(ships(), mode(), targetPreview())], - selfIndex(), + [...ships(), shipProps(ships(), gameProps.mode, targetPreview())], + sIndex, ) } } @@ -94,9 +98,11 @@ function BorderTiles() { class={props.className} style={{ "--x": props.x, "--y": props.y }} onClick={() => { - if (gameState() === "running") { + const sIndex = selfIndex() + if (sIndex === -1) return + if (gameProps.gameState === "running") { settingTarget(props.isGameTile, props.x, props.y) - } else if (gameState() === "starting") { + } else if (gameProps.gameState === "starting") { const { index } = intersectingShip(ships(), { ...mouseCursor(), size: 1, @@ -107,8 +113,8 @@ function BorderTiles() { settingTarget(props.isGameTile, props.x, props.y) else { const ship = ships()[index] - setMode(ship.size - 2) - removeShip(ship, selfIndex()) + setGameProps("mode", ship.size - 2) + removeShip(ship, sIndex) setMouseCursor((e) => ({ ...e, shouldShow: true })) } } @@ -119,10 +125,10 @@ function BorderTiles() { y: props.y, shouldShow: props.isGameTile && - (gameState() === "starting" + (gameProps.gameState === "starting" ? intersectingShip( ships(), - shipProps(ships(), mode(), { + shipProps(ships(), gameProps.mode, { x: props.x, y: props.y, orientation: targetPreview().orientation, diff --git a/leaky-ships/src/components/Gamefield/EventBar.tsx b/leaky-ships/src/components/Gamefield/EventBar.tsx index 8b164a8..80d3a1d 100644 --- a/leaky-ships/src/components/Gamefield/EventBar.tsx +++ b/leaky-ships/src/components/Gamefield/EventBar.tsx @@ -28,18 +28,11 @@ import { For, Show, createEffect } from "solid-js" import { useNavigate } from "solid-start" import { useDrawProps } from "~/hooks/useDrawProps" import { - allowChat, - allowMarkDraw, - allowSpecials, - allowSpectators, - gameState, - menu, - mode, + gameProps, reset, + setGameProps, setGameSetting, setIsReadyFor, - setMenu, - setMode, setTarget, setTargetPreview, target, @@ -60,36 +53,36 @@ function EventBar(props: { clear: () => void }) { icon: "burger-menu", text: "Menu", callback: () => { - setMenu("menu") + setGameProps("menu", "menu") }, }, - gameState() === "running" + gameProps.gameState === "running" ? { icon: faSwords, text: "Attack", callback: () => { - setMenu("moves") + setGameProps("menu", "moves") }, } : { icon: faShip, text: "Ships", callback: () => { - setMenu("moves") + setGameProps("menu", "moves") }, }, { icon: "pen", text: "Draw", callback: () => { - setMenu("draw") + setGameProps("menu", "draw") }, }, { icon: "gear", text: "Settings", callback: () => { - setMenu("settings") + setGameProps("menu", "settings") }, }, ], @@ -99,48 +92,46 @@ function EventBar(props: { clear: () => void }) { text: "Surrender", iconColor: "darkred", callback: () => { - setMenu("surrender") + setGameProps("menu", "surrender") }, }, ], moves: - gameState() === "running" + gameProps.gameState === "running" ? [ { icon: "scope", text: "Fire missile", - enabled: mode() === 0, + enabled: gameProps.mode === 0, callback: () => { - setMode(0) + setGameProps("mode", 0) setTarget((t) => ({ ...t, show: false })) }, }, { icon: "torpedo", text: "Fire torpedo", - enabled: mode() === 1 || mode() === 2, + enabled: gameProps.mode === 1 || gameProps.mode === 2, amount: 2 - - (selfUser() - ?.moves() - .filter((e) => e.type === "htorpedo" || e.type === "vtorpedo") - .length ?? 0), + (selfUser()?.moves.filter( + (e) => e.type === "htorpedo" || e.type === "vtorpedo", + ).length ?? 0), callback: () => { - setMode(1) + setGameProps("mode", 1) setTarget((t) => ({ ...t, show: false })) }, }, { icon: "radar", text: "Radar scan", - enabled: mode() === 3, + enabled: gameProps.mode === 3, amount: 1 - - (selfUser() - ?.moves() - .filter((e) => e.type === "radar").length ?? 0), + (selfUser()?.moves.filter((e) => e.type === "radar").length ?? + 0), callback: () => { - setMode(3) + setGameProps("mode", 3) setTarget((t) => ({ ...t, show: false })) }, }, @@ -152,7 +143,7 @@ function EventBar(props: { clear: () => void }) { amount: 1 - ships().filter((e) => e.size === 2).length, callback: () => { if (1 - ships().filter((e) => e.size === 2).length === 0) return - setMode(0) + setGameProps("mode", 0) }, }, { @@ -161,7 +152,7 @@ function EventBar(props: { clear: () => void }) { amount: 3 - ships().filter((e) => e.size === 3).length, callback: () => { if (3 - ships().filter((e) => e.size === 3).length === 0) return - setMode(1) + setGameProps("mode", 1) }, }, { @@ -170,7 +161,7 @@ function EventBar(props: { clear: () => void }) { amount: 2 - ships().filter((e) => e.size === 4).length, callback: () => { if (2 - ships().filter((e) => e.size === 4).length === 0) return - setMode(2) + setGameProps("mode", 2) }, }, { @@ -199,31 +190,31 @@ function EventBar(props: { clear: () => void }) { { icon: faGlasses, text: "Spectators", - disabled: !allowSpectators(), + disabled: !gameProps.allowSpectators, callback: setGameSetting({ - allowSpectators: !allowSpectators(), + allowSpectators: !gameProps.allowSpectators, }), }, { icon: faSparkles, text: "Specials", - disabled: !allowSpecials(), + disabled: !gameProps.allowSpecials, callback: setGameSetting({ - allowSpecials: !allowSpecials(), + allowSpecials: !gameProps.allowSpecials, }), }, { icon: faComments, text: "Chat", - disabled: !allowChat(), - callback: setGameSetting({ allowChat: !allowChat() }), + disabled: !gameProps.allowChat, + callback: setGameSetting({ allowChat: !gameProps.allowChat }), }, { icon: faScribble, text: "Mark/Draw", - disabled: !allowMarkDraw(), + disabled: !gameProps.allowMarkDraw, callback: setGameSetting({ - allowMarkDraw: !allowMarkDraw(), + allowMarkDraw: !gameProps.allowMarkDraw, }), }, ], @@ -243,7 +234,7 @@ function EventBar(props: { clear: () => void }) { text: "No", iconColor: "red", callback: () => { - setMenu("main") + setGameProps("menu", "main") }, }, ], @@ -251,22 +242,22 @@ function EventBar(props: { clear: () => void }) { createEffect(() => { if ( - menu() !== "moves" || - gameState() !== "starting" || - mode() < 0 || - items().moves[mode()].amount + gameProps.menu !== "moves" || + gameProps.gameState !== "starting" || + gameProps.mode < 0 || + items().moves[gameProps.mode].amount ) return const index = items().moves.findIndex((e) => e.amount) - setMode(index) + setGameProps("mode", index) }) createEffect(() => { - setEnable(menu() === "draw") + setEnable(gameProps.menu === "draw") }) // createEffect(() => { - // if (gameState() !== "running") return + // if (gameProps.gameState !== "running") return // const toastId = "otherPlayer" // if (isActiveIndex) toast.dismiss(toastId) @@ -293,47 +284,55 @@ function EventBar(props: { clear: () => void }) { return (
- + { - setMenu("main") + setGameProps("menu", "main") }, }} /> - + {(e, i) => ( - + )} - + = 0 : undefined, - enabled: gameState() === "running" && mode() >= 0 && target().show, + icon: selfUser()?.isReady ? faLock : faCheck, + text: selfUser()?.isReady ? "unready" : "Done", + disabled: + gameProps.gameState === "starting" + ? gameProps.mode >= 0 + : undefined, + enabled: + gameProps.gameState === "running" && + gameProps.mode >= 0 && + target().show, callback: () => { const i = selfIndex() if (i === -1) return - switch (gameState()) { + switch (gameProps.gameState) { case "starting": - const isReady = !users[i].isReady() + const isReady = !users[i]?.isReady setIsReadyFor({ isReady, i }) socket.emit("isReady", isReady) break case "running": - const moves = selfUser()?.moves() + const moves = selfUser()?.moves const length = moves?.length const props = { - type: modes[mode()].type, + type: modes[gameProps.mode].type, x: target().x, y: target().y, orientation: target().orientation, diff --git a/leaky-ships/src/components/Gamefield/Gamefield.tsx b/leaky-ships/src/components/Gamefield/Gamefield.tsx index f2205fb..fefb352 100644 --- a/leaky-ships/src/components/Gamefield/Gamefield.tsx +++ b/leaky-ships/src/components/Gamefield/Gamefield.tsx @@ -11,12 +11,10 @@ import { useDraw } from "~/hooks/useDraw" import { useDrawProps } from "~/hooks/useDrawProps" import { full, - gameId, - gameState, - mode, + gameProps, mouseCursor, reset, - setMode, + setGameProps, setMouseCursor, setTargetPreview, target, @@ -40,27 +38,28 @@ function Gamefield() { createEffect(() => { if ( - gameState() !== "starting" || - !users[0].isReady() || - !users[1].isReady() + gameProps.gameState !== "starting" || + !users[0]?.isReady || + !users[1]?.isReady ) return - socket.emit("ships", ships() ?? []) + socket.emit("ships", ships()) socket.emit("gameState", "running") }) createEffect(() => { - if (gameId() || !isConnected()) return + if (gameProps.gameId || !isConnected) return socket.emit("update", full) }) createEffect(() => { - if (mode() < 0) return + if (gameProps.mode < 0) return const { x, y, show } = target() const { shouldShow, ...position } = mouseCursor() if ( !shouldShow || - (gameState() === "running" && overlapsWithAnyBorder(position, mode())) + (gameProps.gameState === "running" && + overlapsWithAnyBorder(position, gameProps.mode)) ) setTargetPreview((t) => ({ ...t, show: false })) else { @@ -71,14 +70,17 @@ function Gamefield() { })) const handleKeyPress = (event: KeyboardEvent) => { if (event.key !== "r") return - if (gameState() === "starting") { + if (gameProps.gameState === "starting") { setTargetPreview((t) => ({ ...t, orientation: t.orientation === "h" ? "v" : "h", })) } - if (gameState() === "running" && (mode() === 1 || mode() === 2)) - setMode(mode() === 1 ? 2 : 1) + if ( + gameProps.gameState === "running" && + (gameProps.mode === 1 || gameProps.mode === 2) + ) + setGameProps("mode", gameProps.mode === 1 ? 2 : 1) } document.addEventListener("keydown", handleKeyPress) onCleanup(() => { @@ -88,7 +90,7 @@ function Gamefield() { }) createEffect(() => { - if (gameState() !== "aborted") return + if (gameProps.gameState !== "aborted") return // toast.info("Enemy gave up!") navigator("/") reset() diff --git a/leaky-ships/src/components/Gamefield/Ships.tsx b/leaky-ships/src/components/Gamefield/Ships.tsx index 3686cc9..76235ac 100644 --- a/leaky-ships/src/components/Gamefield/Ships.tsx +++ b/leaky-ships/src/components/Gamefield/Ships.tsx @@ -1,5 +1,5 @@ import { For, Show } from "solid-js" -import { gameState } from "~/hooks/useGameProps" +import { gameProps } from "~/hooks/useGameProps" import { useSession } from "~/hooks/useSession" import Ship from "./Ship" @@ -7,8 +7,8 @@ function Ships() { const { isActiveIndex, selfUser } = useSession() return ( - - {(props) => } + + {(props) => } ) } diff --git a/leaky-ships/src/components/Gamefield/Targets.tsx b/leaky-ships/src/components/Gamefield/Targets.tsx index d4dab9b..d1f255f 100644 --- a/leaky-ships/src/components/Gamefield/Targets.tsx +++ b/leaky-ships/src/components/Gamefield/Targets.tsx @@ -1,7 +1,8 @@ import { For, Match, Switch } from "solid-js" -import { gameState, mode, target, targetPreview } from "~/hooks/useGameProps" +import { gameProps, target, targetPreview } from "~/hooks/useGameProps" import { useSession } from "~/hooks/useSession" import { + compiledHits, composeTargetTiles, intersectingShip, shipProps, @@ -11,29 +12,39 @@ import HitElems from "./HitElems" import Ship from "./Ship" function Targets() { - const { activeUser, ships } = useSession() + const { activeIndex, ships } = useSession() - const ship = () => shipProps(ships(), mode(), targetPreview()) + const ship = () => shipProps(ships(), gameProps.mode, targetPreview()) const intersectionProps = () => intersectingShip(ships(), ship()) return ( - - + + {(props) => } {(props) => } = 0 && targetPreview().show} + when={ + gameProps.gameState === "starting" && + gameProps.mode >= 0 && + targetPreview().show + } > void }) { const navigator = useNavigate() const { session } = useSession() const [launchTime, setLaunchTime] = createSignal(3) - const launching = () => users[0].isReady() && users[1].isReady() + const launching = () => users[0]?.isReady && users[1]?.isReady createEffect(() => { if (!launching() || launchTime() > 0) return @@ -64,12 +56,13 @@ function LobbyFrame(props: { openSettings: () => void }) { }) createEffect(() => { - if (gameId() || !isConnected()) return + if (gameProps.gameId || !isConnected) return socket.emit("update", full) }) createEffect(() => { - if (gameState() === "unknown" || gameState() === "lobby") return + if (gameProps.gameState === "unknown" || gameProps.gameState === "lobby") + return navigator("/gamefield") }) @@ -90,10 +83,10 @@ function LobbyFrame(props: { openSettings: () => void }) { > {"Game-PIN: "} } > - {gamePin() ?? "----"} + {gameProps.gamePin ?? "----"} @@ -103,7 +96,7 @@ function LobbyFrame(props: { openSettings: () => void }) {
Warte auf Verbindung @@ -113,7 +106,7 @@ function LobbyFrame(props: { openSettings: () => void }) { <>

VS

- {users[1].id() ? ( + {users[1] ? ( ) : (

diff --git a/leaky-ships/src/components/Lobby/Player.tsx b/leaky-ships/src/components/Lobby/Player.tsx index f8ca028..6d3b768 100644 --- a/leaky-ships/src/components/Lobby/Player.tsx +++ b/leaky-ships/src/components/Lobby/Player.tsx @@ -44,9 +44,7 @@ function HourGlass() { function Player(props: { src: string; i: 0 | 1; userId?: string }) { const player = () => users[props.i] - const isReady = () => users[props.i].isReady() - const isConnected = () => users[props.i].isConnected() - const primary = () => props.userId && props.userId === users[props.i].id() + const primary = () => props.userId && props.userId === player()?.id return (

@@ -56,7 +54,7 @@ function Player(props: { src: string; i: 0 | 1; userId?: string }) { primary() ? "font-semibold" : "font-normal", )} > - {player().name() ?? "Spieler " + (props.i === 1 ? "2" : "1")} + {player()?.name ?? "Spieler " + (props.i === 1 ? "2" : "1")}