Functioning websocket connections
This commit is contained in:
parent
a227da52bc
commit
30db96a3f7
9 changed files with 104 additions and 182 deletions
|
@ -1,10 +1,12 @@
|
||||||
import Icon from "./Icon"
|
import Icon from "./Icon"
|
||||||
import Player from "./Player"
|
import Player from "./Player"
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import useGameState from "@lib/hooks/useGameState"
|
||||||
|
import useSocket from "@lib/hooks/useSocket"
|
||||||
import { Fragment, useEffect, useState } from "react"
|
import { Fragment, useEffect, useState } from "react"
|
||||||
|
|
||||||
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
const { payload } = useGameState().gameProps
|
const { payload } = useGameState().gameProps
|
||||||
|
useSocket()
|
||||||
const [dots, setDots] = useState(1)
|
const [dots, setDots] = useState(1)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -18,7 +20,8 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
<div className="flex items-center justify-between border-b-2 border-slate-900">
|
<div className="flex items-center justify-between border-b-2 border-slate-900">
|
||||||
<Icon src="speech_bubble.png">Chat</Icon>
|
<Icon src="speech_bubble.png">Chat</Icon>
|
||||||
<h1 className="font-farro text-5xl font-medium">
|
<h1 className="font-farro text-5xl font-medium">
|
||||||
Game-PIN: <span className="underline">{payload?.gamePin?.pin}</span>
|
Game-PIN:{" "}
|
||||||
|
<span className="underline">{payload?.gamePin?.pin ?? "---"}</span>
|
||||||
</h1>
|
</h1>
|
||||||
<Icon src="gear.png" onClick={openSettings}>
|
<Icon src="gear.png" onClick={openSettings}>
|
||||||
Settings
|
Settings
|
||||||
|
|
|
@ -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 <div>SocketIO</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SocketIO
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
||||||
import { User } from "@prisma/client"
|
import { User } from "@prisma/client"
|
||||||
import type { Server as HTTPServer } from "http"
|
import type { Server as HTTPServer } from "http"
|
||||||
import type { Socket as NetSocket } from "net"
|
import type { Socket as NetSocket } from "net"
|
||||||
|
@ -20,19 +21,14 @@ export interface NextApiResponseWithSocket extends NextApiResponse {
|
||||||
export interface ServerToClientEvents {
|
export interface ServerToClientEvents {
|
||||||
// noArg: () => void
|
// noArg: () => void
|
||||||
// basicEmit: (a: number, b: string, c: Buffer) => void
|
// basicEmit: (a: number, b: string, c: Buffer) => void
|
||||||
// withAck: (d: string, callback: (e: number) => void) => void
|
// withAck: (d: string, ) => void
|
||||||
"update-input": (msg: string) => void
|
forbidden: () => void
|
||||||
unauthenticated: () => void
|
update: (game: GamePropsSchema) => void
|
||||||
authenticated: () => void
|
|
||||||
test2: (test: string) => void
|
|
||||||
test: () => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientToServerEvents {
|
export interface ClientToServerEvents {
|
||||||
// hello: () => void
|
join: (userId: string, callback: () => void) => void
|
||||||
"input-change": (msg: string) => void
|
|
||||||
authenticate: (payload: { token: string }) => void
|
authenticate: (payload: { token: string }) => void
|
||||||
test: (payload: any) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InterServerEvents {
|
interface InterServerEvents {
|
||||||
|
@ -41,6 +37,7 @@ interface InterServerEvents {
|
||||||
|
|
||||||
interface SocketData {
|
interface SocketData {
|
||||||
user: User | null
|
user: User | null
|
||||||
|
gameProps: GamePropsSchema
|
||||||
}
|
}
|
||||||
|
|
||||||
export type cServer = Server<
|
export type cServer = Server<
|
||||||
|
|
58
leaky-ships/lib/hooks/useSocket.ts
Normal file
58
leaky-ships/lib/hooks/useSocket.ts
Normal file
|
@ -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
|
6
leaky-ships/lib/socket.ts
Normal file
6
leaky-ships/lib/socket.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { cSocket } from "../interfaces/NextApiSocket"
|
||||||
|
import { io } from "socket.io-client"
|
||||||
|
|
||||||
|
export const socket: cSocket = io({
|
||||||
|
path: "/api/ws2",
|
||||||
|
})
|
|
@ -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
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
NextApiResponseWithSocket,
|
NextApiResponseWithSocket,
|
||||||
cServer,
|
cServer,
|
||||||
} from "../../interfaces/NextApiSocket"
|
} from "../../interfaces/NextApiSocket"
|
||||||
|
import { composeBody, getAnyRunningGame } from "./game/running"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import colors from "colors"
|
import colors from "colors"
|
||||||
import { NextApiRequest } from "next"
|
import { NextApiRequest } from "next"
|
||||||
|
@ -18,7 +19,12 @@ const SocketHandler = async (
|
||||||
console.log("Socket is already running " + req.url)
|
console.log("Socket is already running " + req.url)
|
||||||
} else {
|
} else {
|
||||||
console.log("Socket is initializing " + req.url)
|
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
|
res.socket.server.io = io
|
||||||
|
|
||||||
|
@ -41,21 +47,34 @@ const SocketHandler = async (
|
||||||
})
|
})
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
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) => {
|
socket.on("join", async (userId, cb) => {
|
||||||
// if (!socket.data.isAuthenticated) socket.emit("unauthenticated")
|
console.log(socket.rooms, "join")
|
||||||
// socket.broadcast.emit("update-input", msg)
|
const game = await getAnyRunningGame(userId ?? "")
|
||||||
// io.emit("update-input", msg)
|
if (!game) {
|
||||||
console.log(msg)
|
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) => {
|
socket.on("disconnecting", () => {
|
||||||
console.log("Got test:", payload)
|
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()
|
res.end()
|
||||||
|
|
|
@ -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<HTMLInputElement> = (e) => {
|
|
||||||
setInput(e.target.value)
|
|
||||||
socket?.emit("input-change", e.target.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<input
|
|
||||||
placeholder="Type something"
|
|
||||||
value={input}
|
|
||||||
onChange={onChangeHandler}
|
|
||||||
onDoubleClick={() => setInput(data)}
|
|
||||||
/>
|
|
||||||
<h1>{data}</h1>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Home
|
|
|
@ -1,15 +0,0 @@
|
||||||
import SocketIO from "../components/SocketIO"
|
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<main>
|
|
||||||
<div className="App">
|
|
||||||
<header className="App-header">
|
|
||||||
<SocketIO />
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue