211 lines
5.6 KiB
TypeScript
211 lines
5.6 KiB
TypeScript
import {
|
|
NextApiResponseWithSocket,
|
|
sServer,
|
|
sSocket,
|
|
} from "../../interfaces/NextApiSocket"
|
|
import {
|
|
composeBody,
|
|
gameSelects,
|
|
getAnyGame,
|
|
getAnyRunningGame,
|
|
} from "./game/running"
|
|
import logging from "@lib/backend/logging"
|
|
import prisma from "@lib/prisma"
|
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
|
import colors from "colors"
|
|
import status from "http-status"
|
|
import { NextApiRequest } from "next"
|
|
import { getSession } from "next-auth/react"
|
|
import { Server } from "socket.io"
|
|
|
|
colors.enable()
|
|
|
|
const SocketHandler = async (
|
|
req: NextApiRequest,
|
|
res: NextApiResponseWithSocket
|
|
) => {
|
|
if (res.socket.server.io) {
|
|
logging("Socket is already running " + req.url, ["infoCyan"], req)
|
|
} else {
|
|
logging("Socket is initializing " + req.url, ["infoCyan"], req)
|
|
const io: sServer = new Server(res.socket.server, {
|
|
path: "/api/ws",
|
|
cors: {
|
|
origin: "https://leaky-ships.mal-noh.de",
|
|
},
|
|
})
|
|
|
|
res.socket.server.io = io
|
|
|
|
// io.use(authenticate)
|
|
io.use(async (socket, next) => {
|
|
try {
|
|
const session = await getSession({
|
|
req: socket.request,
|
|
})
|
|
socket.data.user = await prisma.user.findUnique({
|
|
where: {
|
|
id: session?.user.id,
|
|
},
|
|
})
|
|
|
|
const game = await getAnyRunningGame(socket.data.user?.id ?? "")
|
|
if (!game) {
|
|
logging(
|
|
"Forbidden, no game found: " +
|
|
JSON.stringify(Array.from(socket.rooms)),
|
|
["debug"],
|
|
socket.request
|
|
)
|
|
next(new Error(status["403"]))
|
|
return
|
|
}
|
|
socket.data.gameId = game.id
|
|
socket.join(game.id)
|
|
next()
|
|
} catch (err) {
|
|
logging(status["401"], ["warn"], socket.request)
|
|
next(new Error(status["401"]))
|
|
}
|
|
})
|
|
|
|
io.on("connection", async (socket) => {
|
|
logging(
|
|
`User connected <${socket.data.user?.email}>`.green +
|
|
", " +
|
|
socket.id.cyan,
|
|
["infoGreen"],
|
|
socket.request
|
|
)
|
|
join(socket, io)
|
|
|
|
socket.on("update", async (cb) => {
|
|
const game = await getAnyGame(socket.data.gameId ?? "")
|
|
if (!game) return
|
|
const body = composeBody(game)
|
|
cb(body)
|
|
})
|
|
|
|
socket.on("gameSetting", async (payload, cb) => {
|
|
const game = await prisma.game.update({
|
|
where: { id: socket.data.gameId ?? "" },
|
|
data: payload,
|
|
...gameSelects,
|
|
})
|
|
const { hash } = composeBody(game)
|
|
if (!hash) return
|
|
cb(hash)
|
|
io.to(game.id).emit("gameSetting", payload, hash)
|
|
})
|
|
|
|
socket.on("ping", (count, callback) => {
|
|
callback(count)
|
|
})
|
|
|
|
socket.on("leave", async (cb) => {
|
|
if (!socket.data.gameId || !socket.data.user?.id) return cb(false)
|
|
const user_Game = await prisma.user_Game.delete({
|
|
where: {
|
|
gameId_userId: {
|
|
gameId: socket.data.gameId,
|
|
userId: socket.data.user?.id,
|
|
},
|
|
},
|
|
})
|
|
const enemy = await prisma.user_Game.findFirst({
|
|
where: {
|
|
gameId: socket.data.gameId,
|
|
},
|
|
})
|
|
let body: GamePropsSchema
|
|
if (user_Game.index === "player1" && enemy) {
|
|
body = composeBody(
|
|
(
|
|
await prisma.user_Game.update({
|
|
where: {
|
|
gameId_index: {
|
|
gameId: socket.data.gameId,
|
|
index: "player2",
|
|
},
|
|
},
|
|
data: {
|
|
index: "player1",
|
|
},
|
|
|
|
select: {
|
|
game: { ...gameSelects },
|
|
},
|
|
})
|
|
).game
|
|
)
|
|
} else {
|
|
const game = await prisma.game.findUnique({
|
|
where: {
|
|
id: socket.data.gameId,
|
|
},
|
|
...gameSelects,
|
|
})
|
|
if (!game) return cb(false)
|
|
body = composeBody(game)
|
|
}
|
|
const { payload, hash } = body
|
|
if (!payload || !hash) return cb(false)
|
|
io.to(socket.data.gameId).emit(
|
|
"playerEvent",
|
|
{ player1: payload.player1, player2: payload.player2 },
|
|
hash,
|
|
"leave"
|
|
)
|
|
cb(true)
|
|
|
|
if (!payload?.player1 && !payload?.player2) {
|
|
await prisma.game.delete({
|
|
where: {
|
|
id: socket.data.gameId,
|
|
},
|
|
})
|
|
}
|
|
})
|
|
|
|
socket.on("disconnecting", async () => {
|
|
logging(
|
|
"Disconnecting: " + JSON.stringify(Array.from(socket.rooms)),
|
|
["debug"],
|
|
socket.request
|
|
)
|
|
// if (!socket.data.gameId) return
|
|
// const game = await prisma.game.findUnique({
|
|
// where: {
|
|
// id: socket.data.gameId
|
|
// },
|
|
// ...gameSelects
|
|
// })
|
|
// if (!game) return
|
|
// const { payload, hash } = composeBody(game, socket.data.user?.id ?? "")
|
|
// if (!hash) return
|
|
// io.to(socket.data.gameId).emit("playerEvent", {}, hash, "disconnect")
|
|
})
|
|
|
|
socket.on("disconnect", () => {
|
|
// socket.rooms.size === 0
|
|
logging("Disconnect: " + socket.id, ["debug"], socket.request)
|
|
})
|
|
})
|
|
}
|
|
res.end()
|
|
}
|
|
|
|
async function join(socket: sSocket, io: sServer) {
|
|
const game = await getAnyGame(socket.data.gameId ?? "")
|
|
if (!game) return socket.disconnect()
|
|
const { payload, hash } = composeBody(game)
|
|
if (!hash) return socket.disconnect()
|
|
io.to(game.id).emit(
|
|
"playerEvent",
|
|
{ player1: payload?.player1, player2: payload?.player2 },
|
|
hash,
|
|
"join"
|
|
)
|
|
}
|
|
|
|
export default SocketHandler
|