From 30db96a3f7cc3aad3df1a1bdc4ea3c2b04a39429 Mon Sep 17 00:00:00 2001 From: aronmal Date: Thu, 27 Apr 2023 17:41:16 +0200 Subject: [PATCH] Functioning websocket connections --- leaky-ships/components/Lobby/LobbyFrame.tsx | 5 +- leaky-ships/components/SocketIO.tsx | 44 -------------- leaky-ships/interfaces/NextApiSocket.ts | 15 ++--- leaky-ships/lib/hooks/useSocket.ts | 58 ++++++++++++++++++ leaky-ships/lib/socket.ts | 6 ++ leaky-ships/pages/api/ws.ts | 37 ------------ leaky-ships/pages/api/ws2.ts | 41 +++++++++---- leaky-ships/pages/socket.tsx | 65 --------------------- leaky-ships/pages/socketio.tsx | 15 ----- 9 files changed, 104 insertions(+), 182 deletions(-) delete mode 100644 leaky-ships/components/SocketIO.tsx create mode 100644 leaky-ships/lib/hooks/useSocket.ts create mode 100644 leaky-ships/lib/socket.ts delete mode 100644 leaky-ships/pages/api/ws.ts delete mode 100644 leaky-ships/pages/socket.tsx delete mode 100644 leaky-ships/pages/socketio.tsx diff --git a/leaky-ships/components/Lobby/LobbyFrame.tsx b/leaky-ships/components/Lobby/LobbyFrame.tsx index fffb44d..4c0becf 100644 --- a/leaky-ships/components/Lobby/LobbyFrame.tsx +++ b/leaky-ships/components/Lobby/LobbyFrame.tsx @@ -1,10 +1,12 @@ import Icon from "./Icon" import Player from "./Player" import useGameState from "@lib/hooks/useGameState" +import useSocket from "@lib/hooks/useSocket" import { Fragment, useEffect, useState } from "react" function LobbyFrame({ openSettings }: { openSettings: () => void }) { const { payload } = useGameState().gameProps + useSocket() const [dots, setDots] = useState(1) useEffect(() => { @@ -18,7 +20,8 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
Chat

- Game-PIN: {payload?.gamePin?.pin} + Game-PIN:{" "} + {payload?.gamePin?.pin ?? "---"}

Settings diff --git a/leaky-ships/components/SocketIO.tsx b/leaky-ships/components/SocketIO.tsx deleted file mode 100644 index fdabef1..0000000 --- a/leaky-ships/components/SocketIO.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { cSocket } from "../interfaces/NextApiSocket" -import useGameState from "@lib/hooks/useGameState" -import { useEffect } from "react" -import { io } from "socket.io-client" - -let socket: cSocket - -function SocketIO() { - const { session, status } = useGameState() - - useEffect(() => { - if (status === "loading" || socket) return - socket = io({ - path: "/api/ws2", - }) - - socket.on("connect", () => { - console.log("connected") - }) - - socket.on("authenticated", () => { - console.log("Yay!") - }) - - socket.on("unauthenticated", () => { - console.log("No... pls work") - }) - - return () => { - socket.off("connect") - socket.off("authenticated") - socket.off("unauthenticated") - } - }, [status]) - - useEffect(() => { - console.log(4, socket) - socket?.emit("authenticate", { token: `hello from ${session?.user.email}` }) - }, [session?.user.email, status]) - - return
SocketIO
-} - -export default SocketIO diff --git a/leaky-ships/interfaces/NextApiSocket.ts b/leaky-ships/interfaces/NextApiSocket.ts index 9e31ec9..de80804 100644 --- a/leaky-ships/interfaces/NextApiSocket.ts +++ b/leaky-ships/interfaces/NextApiSocket.ts @@ -1,3 +1,4 @@ +import { GamePropsSchema } from "@lib/zodSchemas" import { User } from "@prisma/client" import type { Server as HTTPServer } from "http" import type { Socket as NetSocket } from "net" @@ -20,19 +21,14 @@ export interface NextApiResponseWithSocket extends NextApiResponse { export interface ServerToClientEvents { // noArg: () => void // basicEmit: (a: number, b: string, c: Buffer) => void - // withAck: (d: string, callback: (e: number) => void) => void - "update-input": (msg: string) => void - unauthenticated: () => void - authenticated: () => void - test2: (test: string) => void - test: () => void + // withAck: (d: string, ) => void + forbidden: () => void + update: (game: GamePropsSchema) => void } export interface ClientToServerEvents { - // hello: () => void - "input-change": (msg: string) => void + join: (userId: string, callback: () => void) => void authenticate: (payload: { token: string }) => void - test: (payload: any) => void } interface InterServerEvents { @@ -41,6 +37,7 @@ interface InterServerEvents { interface SocketData { user: User | null + gameProps: GamePropsSchema } export type cServer = Server< diff --git a/leaky-ships/lib/hooks/useSocket.ts b/leaky-ships/lib/hooks/useSocket.ts new file mode 100644 index 0000000..de8ebcb --- /dev/null +++ b/leaky-ships/lib/hooks/useSocket.ts @@ -0,0 +1,58 @@ +import useGameState from "@lib/hooks/useGameState" +import { socket } from "@lib/socket" +import { useEffect, useState } from "react" + +function useSocket() { + const [isConnected, setIsConnected] = useState(socket.connected) + const [hasJoined, setHasJoined] = useState(false) + // const [fooEvents, setFooEvents] = useState([]) + const { session, status, setGameProps } = useGameState() + + useEffect(() => { + if (status === "loading") return + + socket.on("connect", () => { + console.log("connected") + setIsConnected(true) + }) + socket.on("connect_error", () => { + console.log("connect_error") + }) + + socket.on("disconnect", () => { + console.log("disconnect") + setIsConnected(false) + }) + + socket.on("forbidden", () => { + console.log("forbidden") + }) + + socket.on("update", (body) => { + console.log("update") + setGameProps(body) + }) + + return () => { + // for all events + socket.removeAllListeners() + } + }, [status, setGameProps]) + + useEffect(() => { + if (session?.user.id && !hasJoined) { + socket?.emit("join", session?.user.id, () => { + setHasJoined(true) + }) + } + }, [session?.user.id, hasJoined]) + + useEffect(() => { + if (!isConnected) return + socket?.emit("authenticate", { token: `hello from ${session?.user.email}` }) + }, [isConnected, status, session?.user.email]) + + return socket +} + +export default useSocket diff --git a/leaky-ships/lib/socket.ts b/leaky-ships/lib/socket.ts new file mode 100644 index 0000000..9e71296 --- /dev/null +++ b/leaky-ships/lib/socket.ts @@ -0,0 +1,6 @@ +import { cSocket } from "../interfaces/NextApiSocket" +import { io } from "socket.io-client" + +export const socket: cSocket = io({ + path: "/api/ws2", +}) diff --git a/leaky-ships/pages/api/ws.ts b/leaky-ships/pages/api/ws.ts deleted file mode 100644 index e2b9e96..0000000 --- a/leaky-ships/pages/api/ws.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { - NextApiResponseWithSocket, - cServer, -} from "../../interfaces/NextApiSocket" -import type { NextApiRequest } from "next" -import { Server } from "socket.io" - -const SocketHandler = (req: NextApiRequest, res: NextApiResponseWithSocket) => { - if (res.socket.server.io) { - console.log("Socket is already running " + req.url) - } else { - console.log("Socket is initializing " + req.url) - const io: cServer = new Server(res.socket.server, { - path: "/api/ws", - }) - res.socket.server.io = io - - // io.use(authenticate) - io.on("connection", (socket) => { - socket.on("input-change", (msg) => { - if (!socket.data.user) socket.emit("unauthenticated") - // socket.broadcast.emit("update-input", msg) - io.emit("update-input", msg) - }) - - socket.on("test", (payload) => { - console.log("Got test:", payload) - // ... - }) - - socket.emit("test2", "lol") - }) - } - res.end() -} - -export default SocketHandler diff --git a/leaky-ships/pages/api/ws2.ts b/leaky-ships/pages/api/ws2.ts index 06437ef..a32c5c7 100644 --- a/leaky-ships/pages/api/ws2.ts +++ b/leaky-ships/pages/api/ws2.ts @@ -2,6 +2,7 @@ import { NextApiResponseWithSocket, cServer, } from "../../interfaces/NextApiSocket" +import { composeBody, getAnyRunningGame } from "./game/running" import prisma from "@lib/prisma" import colors from "colors" import { NextApiRequest } from "next" @@ -18,7 +19,12 @@ const SocketHandler = async ( console.log("Socket is already running " + req.url) } else { console.log("Socket is initializing " + req.url) - const io: cServer = new Server(res.socket.server, { path: "/api/ws2" }) + const io: cServer = new Server(res.socket.server, { + path: "/api/ws2", + cors: { + origin: "https://leaky-ships.mal-noh.de", + }, + }) res.socket.server.io = io @@ -41,21 +47,34 @@ const SocketHandler = async ( }) io.on("connection", (socket) => { - console.log(`User connected <${socket.data.user?.email}>`.green) + console.log( + `User connected <${socket.data.user?.email}>`.green, + socket.id + ) - socket.on("authenticate", (msg) => { - // if (!socket.data.isAuthenticated) socket.emit("unauthenticated") - // socket.broadcast.emit("update-input", msg) - // io.emit("update-input", msg) - console.log(msg) + socket.on("join", async (userId, cb) => { + console.log(socket.rooms, "join") + const game = await getAnyRunningGame(userId ?? "") + if (!game) { + const warst = socket.emit("forbidden") + console.log("forbidden", warst) + return + } + cb() + socket.join(userId) + const body = composeBody(game) + socket.data.gameProps = body + io.to(userId).emit("update", body) }) - socket.on("test", (payload) => { - console.log("Got test:", payload) - // ... + socket.on("disconnecting", () => { + console.log("disconnecting", socket.rooms) // the Set contains at least the socket ID }) - socket.emit("test2", "lol") + socket.on("disconnect", () => { + // socket.rooms.size === 0 + console.log("disconnect", socket.id) + }) }) } res.end() diff --git a/leaky-ships/pages/socket.tsx b/leaky-ships/pages/socket.tsx deleted file mode 100644 index fc00e5f..0000000 --- a/leaky-ships/pages/socket.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { cSocket } from "../interfaces/NextApiSocket" -import useGameState from "@lib/hooks/useGameState" -import { ChangeEventHandler, useEffect, useState } from "react" -import { io } from "socket.io-client" - -let socket: cSocket - -const Home = () => { - const [input, setInput] = useState("") - const [data, setData] = useState("") - - const { status } = useGameState() - - useEffect(() => { - if (status === "loading") return - if (!socket) { - console.log("Socket init.") - socket = io({ - path: "/api/ws", - }) - } else console.log("Socket present.") - - socket.on("connect", () => { - console.log("connected") - }) - - socket.on("authenticated", () => { - console.log("Yay!") - }) - - socket.on("unauthenticated", () => { - console.log("No... pls work") - }) - - socket.on("update-input", (msg) => { - setData(msg) - }) - - return () => { - socket.off("connect") - socket.off("authenticated") - socket.off("unauthenticated") - socket.off("update-input") - } - }, [status, setData]) - - const onChangeHandler: ChangeEventHandler = (e) => { - setInput(e.target.value) - socket?.emit("input-change", e.target.value) - } - - return ( - <> - setInput(data)} - /> -

{data}

- - ) -} - -export default Home diff --git a/leaky-ships/pages/socketio.tsx b/leaky-ships/pages/socketio.tsx deleted file mode 100644 index b6d516a..0000000 --- a/leaky-ships/pages/socketio.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import SocketIO from "../components/SocketIO" - -export default function Home() { - return ( - <> -
-
-
- -
-
-
- - ) -}