Game settings and better socket performance
- Added game settings - Reworked GamePropsSchema for only relevant information -> Prisma schema and zod object - Imporved toast notifications - No duplicate socket connections anymore - Using now Zustand for the gameProps instead of React Context & State
This commit is contained in:
parent
12295b316f
commit
61ae4b901d
31 changed files with 652 additions and 350 deletions
|
@ -2,7 +2,7 @@
|
||||||
// import FogImages from './FogImages'
|
// import FogImages from './FogImages'
|
||||||
import Labeling from "./Labeling"
|
import Labeling from "./Labeling"
|
||||||
import Ships from "./Ships"
|
import Ships from "./Ships"
|
||||||
import useGameEvent from "@lib/hooks/useGameEvent"
|
import useGameEvent from "@hooks/useGameEvent"
|
||||||
import { CSSProperties } from "react"
|
import { CSSProperties } from "react"
|
||||||
|
|
||||||
function Gamefield() {
|
function Gamefield() {
|
||||||
|
|
|
@ -2,32 +2,17 @@ import Icon from "./Icon"
|
||||||
import Player from "./Player"
|
import Player from "./Player"
|
||||||
import { faSpinnerThird } from "@fortawesome/pro-solid-svg-icons"
|
import { faSpinnerThird } from "@fortawesome/pro-solid-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import { useGameProps } from "@hooks/useGameProps"
|
||||||
import useSocket from "@lib/hooks/useSocket"
|
import useSocket from "@hooks/useSocket"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
import { Fragment, useEffect, useState } from "react"
|
import { Fragment, useEffect, useState } from "react"
|
||||||
import { toast } from "react-toastify"
|
|
||||||
|
|
||||||
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
const { payload } = useGameState().gameProps
|
const { payload } = useGameProps()
|
||||||
const { isConnected, hasJoined } = useSocket()
|
|
||||||
const [dots, setDots] = useState(3)
|
const [dots, setDots] = useState(3)
|
||||||
|
const { isConnected } = useSocket()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isConnected && hasJoined) return
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
toast("Es konnte keine Echtzeitverbindung aufgebaute werden.", {
|
|
||||||
toastId: "connection_error",
|
|
||||||
type: "error",
|
|
||||||
autoClose: 10000,
|
|
||||||
})
|
|
||||||
router.push("/start")
|
|
||||||
}, 15000)
|
|
||||||
|
|
||||||
return () => clearTimeout(timeout)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (payload?.player2) return
|
if (payload?.player2) return
|
||||||
const interval = setInterval(() => setDots((e) => (e % 3) + 1), 1000)
|
const interval = setInterval(() => setDots((e) => (e % 3) + 1), 1000)
|
||||||
|
@ -41,7 +26,7 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
<h1 className="font-farro text-5xl font-medium">
|
<h1 className="font-farro text-5xl font-medium">
|
||||||
Game-PIN:{" "}
|
Game-PIN:{" "}
|
||||||
{isConnected ? (
|
{isConnected ? (
|
||||||
<span className="underline">{payload?.gamePin?.pin ?? "---"}</span>
|
<span className="underline">{payload?.gamePin ?? "----"}</span>
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faSpinnerThird} spin={true} />
|
<FontAwesomeIcon icon={faSpinnerThird} spin={true} />
|
||||||
)}
|
)}
|
||||||
|
@ -65,7 +50,7 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<p className="font-farro w-96 text-center text-4xl font-medium">
|
<p className="font-farro w-96 text-center text-4xl font-medium">
|
||||||
Warte auf {isConnected && hasJoined ? "Spieler 2" : "Verbindung"}{" "}
|
Warte auf {isConnected ? "Spieler 2" : "Verbindung"}{" "}
|
||||||
{Array.from(Array(dots), () => ".").join("")}
|
{Array.from(Array(dots), () => ".").join("")}
|
||||||
{Array.from(Array(3 - dots), (_, i) => (
|
{Array.from(Array(3 - dots), (_, i) => (
|
||||||
<Fragment key={i}> </Fragment>
|
<Fragment key={i}> </Fragment>
|
||||||
|
@ -74,7 +59,10 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-center border-t-2 border-slate-900">
|
<div className="flex items-center justify-center border-t-2 border-slate-900">
|
||||||
<button className="font-farro m-4 rounded-xl border-b-4 border-orange-400 bg-warn px-12 py-4 text-5xl font-medium duration-100 active:border-t-4 active:border-b-0">
|
<button
|
||||||
|
className="font-farro m-4 rounded-xl border-b-4 border-orange-400 bg-warn px-12 py-4 text-5xl font-medium duration-100 active:border-t-4 active:border-b-0"
|
||||||
|
onClick={() => router.push("/")}
|
||||||
|
>
|
||||||
START
|
START
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,38 +3,69 @@ import {
|
||||||
faToggleLargeOn,
|
faToggleLargeOn,
|
||||||
} from "@fortawesome/pro-solid-svg-icons"
|
} from "@fortawesome/pro-solid-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
|
import { useGameProps } from "@hooks/useGameProps"
|
||||||
|
import { socket } from "@lib/socket"
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
|
import { ReactNode, useMemo } from "react"
|
||||||
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
|
type GameSettingKeys =
|
||||||
|
| "allowSpectators"
|
||||||
|
| "allowSpecials"
|
||||||
|
| "allowChat"
|
||||||
|
| "allowMarkDraw"
|
||||||
|
|
||||||
|
export type GameSettings = { [key in GameSettingKeys]?: boolean }
|
||||||
|
|
||||||
|
export const gameSetting = (payload: GameSettings) => {
|
||||||
|
socket.emit("gameSetting", payload, ({ ack }) => {
|
||||||
|
if (ack) return
|
||||||
|
toast.warn("Something is wrong... ", {
|
||||||
|
toastId: "st_wrong",
|
||||||
|
theme: "colored",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function Setting({
|
function Setting({
|
||||||
props: { key, state, onClick },
|
children,
|
||||||
|
prop,
|
||||||
}: {
|
}: {
|
||||||
props: {
|
children: ReactNode
|
||||||
key: string
|
prop: GameSettingKeys
|
||||||
state: boolean
|
|
||||||
onClick: () => void
|
|
||||||
}
|
|
||||||
}) {
|
}) {
|
||||||
|
const { payload, setSetting } = useGameProps()
|
||||||
|
const state = useMemo(() => payload?.game?.[prop], [payload?.game, prop])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className="flex items-center justify-between" htmlFor={key}>
|
<label className="flex items-center justify-between" htmlFor={prop}>
|
||||||
<span className="col-span-2 w-96 select-none text-5xl text-white drop-shadow-md">
|
<span className="col-span-2 w-96 select-none text-5xl text-white drop-shadow-md">
|
||||||
{key}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"text-md mx-auto w-24 rounded-full px-4 drop-shadow-md transition-all",
|
"text-md mx-auto rounded-full px-4 drop-shadow-md transition-all",
|
||||||
state ? "text-blue-500" : "text-gray-800",
|
state ? "text-blue-500" : "text-gray-800",
|
||||||
{
|
{
|
||||||
"bg-gray-300 ": state,
|
"bg-gray-300 ": state,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
size="3x"
|
||||||
icon={state ? faToggleLargeOn : faToggleLargeOff}
|
icon={state ? faToggleLargeOn : faToggleLargeOff}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
className="bg-none"
|
className="bg-none"
|
||||||
checked={state}
|
checked={state}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id={key}
|
id={prop}
|
||||||
onChange={onClick}
|
onChange={() => {
|
||||||
|
const payload = {
|
||||||
|
[prop]: !state,
|
||||||
|
}
|
||||||
|
|
||||||
|
setSetting(payload)
|
||||||
|
gameSetting(payload)
|
||||||
|
}}
|
||||||
hidden={true}
|
hidden={true}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
import Setting from "./Setting"
|
import Setting, { gameSetting } from "./Setting"
|
||||||
import { faRotateLeft } from "@fortawesome/pro-regular-svg-icons"
|
import { faRotateLeft } from "@fortawesome/pro-regular-svg-icons"
|
||||||
import { faXmark } from "@fortawesome/pro-solid-svg-icons"
|
import { faXmark } from "@fortawesome/pro-solid-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { useState } from "react"
|
import { useGameProps } from "@hooks/useGameProps"
|
||||||
|
|
||||||
const settingOptionsInit: { [key: string]: boolean } = {
|
|
||||||
allowSpectators: false,
|
|
||||||
allowSpecials: false,
|
|
||||||
allowChat: false,
|
|
||||||
allowMarkDraw: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
function Settings({ closeSettings }: { closeSettings: () => void }) {
|
function Settings({ closeSettings }: { closeSettings: () => void }) {
|
||||||
const [settingOptions, setSettingOptions] = useState(settingOptionsInit)
|
const { payload, setSetting } = useGameProps()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute inset-0 flex flex-col items-center justify-center bg-black/40">
|
<div className="absolute inset-0 flex flex-col items-center justify-center bg-black/40">
|
||||||
<div className="w-full max-w-screen-lg">
|
<div className="w-full max-w-screen-lg">
|
||||||
|
@ -27,6 +21,7 @@ function Settings({ closeSettings }: { closeSettings: () => void }) {
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
className="h-full w-full text-gray-800 drop-shadow-md"
|
className="h-full w-full text-gray-800 drop-shadow-md"
|
||||||
|
size="3x"
|
||||||
icon={faXmark}
|
icon={faXmark}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
@ -35,21 +30,29 @@ function Settings({ closeSettings }: { closeSettings: () => void }) {
|
||||||
<div className="flex items-center justify-end">
|
<div className="flex items-center justify-end">
|
||||||
<button
|
<button
|
||||||
className="top-8 right-12 h-14 w-14"
|
className="top-8 right-12 h-14 w-14"
|
||||||
onClick={() => setSettingOptions(settingOptionsInit)}
|
onClick={() => {
|
||||||
|
const payload = {
|
||||||
|
allowSpectators: true,
|
||||||
|
allowSpecials: true,
|
||||||
|
allowChat: true,
|
||||||
|
allowMarkDraw: true,
|
||||||
|
}
|
||||||
|
setSetting(payload)
|
||||||
|
gameSetting(payload)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
className="h-full w-full text-gray-800 drop-shadow-md"
|
className="h-full w-full text-gray-800 drop-shadow-md"
|
||||||
|
size="3x"
|
||||||
icon={faRotateLeft}
|
icon={faRotateLeft}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
{Object.keys(settingOptions).map((key) => {
|
<Setting prop="allowSpectators">Erlaube Zuschauer</Setting>
|
||||||
const state = settingOptions[key]
|
<Setting prop="allowSpecials">Erlaube spezial Items</Setting>
|
||||||
const onClick = () =>
|
<Setting prop="allowChat">Erlaube den Chat</Setting>
|
||||||
setSettingOptions((e) => ({ ...e, [key]: !e[key] }))
|
<Setting prop="allowMarkDraw">Erlaube zeichen/makieren</Setting>
|
||||||
return <Setting key={key} props={{ key, state, onClick }} />
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
13
leaky-ships/components/profileImg.tsx
Normal file
13
leaky-ships/components/profileImg.tsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
function profileImg(src: string) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
style={{ transform: "scale(1.5)", borderRadius: "100%" }}
|
||||||
|
src={src}
|
||||||
|
alt="profile picture"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default profileImg
|
|
@ -1,22 +1,22 @@
|
||||||
import BorderTiles from "../../components/Gamefield/BorderTiles"
|
|
||||||
import EventBar from "../../components/Gamefield/EventBar"
|
|
||||||
import type { PointerProps } from "../../components/Gamefield/GamefieldPointer"
|
|
||||||
import HitElems from "../../components/Gamefield/HitElems"
|
|
||||||
import Targets from "../../components/Gamefield/Targets"
|
|
||||||
import {
|
import {
|
||||||
Hit,
|
Hit,
|
||||||
Mode,
|
Mode,
|
||||||
MouseCursor,
|
MouseCursor,
|
||||||
Target,
|
Target,
|
||||||
Position,
|
Position,
|
||||||
} from "../../interfaces/frontend"
|
} from "../interfaces/frontend"
|
||||||
|
import BorderTiles from "@components/Gamefield/BorderTiles"
|
||||||
|
import EventBar from "@components/Gamefield/EventBar"
|
||||||
|
import type { PointerProps } from "@components/Gamefield/GamefieldPointer"
|
||||||
|
import HitElems from "@components/Gamefield/HitElems"
|
||||||
|
import Targets from "@components/Gamefield/Targets"
|
||||||
import {
|
import {
|
||||||
hitReducer,
|
hitReducer,
|
||||||
initlialLastLeftTile,
|
initlialLastLeftTile,
|
||||||
initlialTarget,
|
initlialTarget,
|
||||||
initlialTargetPreview,
|
initlialTargetPreview,
|
||||||
initlialMouseCursor,
|
initlialMouseCursor,
|
||||||
} from "../utils/helpers"
|
} from "@lib/utils/helpers"
|
||||||
import { useCallback, useEffect, useReducer, useState } from "react"
|
import { useCallback, useEffect, useReducer, useState } from "react"
|
||||||
|
|
||||||
const modes: Mode[] = [
|
const modes: Mode[] = [
|
58
leaky-ships/hooks/useGameProps.ts
Normal file
58
leaky-ships/hooks/useGameProps.ts
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import { GameSettings } from "@components/Lobby/SettingsFrame/Setting"
|
||||||
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
||||||
|
import { produce } from "immer"
|
||||||
|
import { create } from "zustand"
|
||||||
|
import { devtools } from "zustand/middleware"
|
||||||
|
|
||||||
|
const initialState: GamePropsSchema = { payload: null, hash: null }
|
||||||
|
|
||||||
|
type State = GamePropsSchema
|
||||||
|
|
||||||
|
type Action = {
|
||||||
|
setSetting: (by: GameSettings) => void
|
||||||
|
full: (newProps: GamePropsSchema) => void
|
||||||
|
reset: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useGameProps = create<State & Action>()(
|
||||||
|
devtools(
|
||||||
|
(set) => ({
|
||||||
|
...initialState,
|
||||||
|
setSetting: (settings) =>
|
||||||
|
set(
|
||||||
|
produce((state: State) => {
|
||||||
|
if (!state.payload?.game) return
|
||||||
|
Object.assign(state.payload.game, settings)
|
||||||
|
})
|
||||||
|
),
|
||||||
|
full: (newGameProps) =>
|
||||||
|
set((state) => {
|
||||||
|
if (state.hash === newGameProps.hash) {
|
||||||
|
console.log("Everything up to date.")
|
||||||
|
} else {
|
||||||
|
console.log("Update was needed.", state.hash, newGameProps.hash)
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.payload?.game?.id &&
|
||||||
|
state.payload?.game?.id !== newGameProps.payload?.game?.id
|
||||||
|
) {
|
||||||
|
console.warn(
|
||||||
|
"Different gameId detected on update: ",
|
||||||
|
state.payload?.game?.id,
|
||||||
|
newGameProps.payload?.game?.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newGameProps
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}),
|
||||||
|
reset: () => {
|
||||||
|
set(initialState)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "gameState",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
105
leaky-ships/hooks/useSocket.ts
Normal file
105
leaky-ships/hooks/useSocket.ts
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import { useGameProps } from "@hooks/useGameProps"
|
||||||
|
import { socket } from "@lib/socket"
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
|
/** This function should only be called once per page, otherwise there will be multiple socket connections and duplicate event listeners. */
|
||||||
|
function useSocket() {
|
||||||
|
const [isConnected, setIsConnected] = useState(false)
|
||||||
|
const { full } = useGameProps()
|
||||||
|
|
||||||
|
useEffect(() => setIsConnected(socket.connected), [socket.connected])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
socket.connect()
|
||||||
|
|
||||||
|
socket.on("connect", () => {
|
||||||
|
console.log("connected")
|
||||||
|
|
||||||
|
const toastId = "connect_error"
|
||||||
|
toast.dismiss(toastId)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("connect_error", () => {
|
||||||
|
const toastId = "connect_error"
|
||||||
|
const isActive = toast.isActive(toastId)
|
||||||
|
if (isActive)
|
||||||
|
toast.update(toastId, {
|
||||||
|
autoClose: 5000,
|
||||||
|
})
|
||||||
|
else
|
||||||
|
toast.warn("Es gibt Probleme mit der Echtzeitverbindung.", { toastId })
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("disconnect", () => {
|
||||||
|
console.log("disconnect")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("update", (body) => {
|
||||||
|
console.log("update")
|
||||||
|
full(body)
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.removeAllListeners()
|
||||||
|
socket.disconnect()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const toastId = "realtime"
|
||||||
|
|
||||||
|
// toast("Echtzeitverbindung wird hergestellt...", {
|
||||||
|
// icon: Icons.spinner(),
|
||||||
|
// toastId,
|
||||||
|
// autoClose: false,
|
||||||
|
// hideProgressBar: true,
|
||||||
|
// closeButton: false,
|
||||||
|
// })
|
||||||
|
// socket.emit("join", ({ ack }) => {
|
||||||
|
// if (!ack) {
|
||||||
|
// toast.update(toastId, {
|
||||||
|
// render: "Bei der Echtzeitverbindung ist ein Fehler aufgetreten 🤯",
|
||||||
|
// type: "error",
|
||||||
|
// icon: Icons.error,
|
||||||
|
// theme: "colored",
|
||||||
|
// autoClose: 5000,
|
||||||
|
// hideProgressBar: false,
|
||||||
|
// closeButton: true,
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// setHasJoined(true)
|
||||||
|
// toast.update(toastId, {
|
||||||
|
// render: "Echtzeitverbindung hergestellt 👌",
|
||||||
|
// type: "info",
|
||||||
|
// icon: Icons.success,
|
||||||
|
// autoClose: 5000,
|
||||||
|
// hideProgressBar: false,
|
||||||
|
// closeButton: true,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }, [])
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!isConnected) return
|
||||||
|
// socket.emit("authenticate", { token: `hello from ${session?.user.email}` })
|
||||||
|
// }, [isConnected, status, session?.user.email])
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!isConnected) return
|
||||||
|
// let count = 0
|
||||||
|
// const interval = setInterval(() => {
|
||||||
|
// const start = Date.now()
|
||||||
|
// socket.volatile.emit("ping", ++count, (count) => {
|
||||||
|
// const duration = Date.now() - start
|
||||||
|
// console.log("ping", count, duration)
|
||||||
|
// })
|
||||||
|
// }, 5000)
|
||||||
|
// return () => clearInterval(interval)
|
||||||
|
// }, [isConnected])
|
||||||
|
|
||||||
|
return { isConnected }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useSocket
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { GameSettings } from "@components/Lobby/SettingsFrame/Setting"
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
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"
|
||||||
|
@ -22,13 +23,16 @@ 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, ) => void
|
// withAck: (d: string, ) => void
|
||||||
forbidden: () => void
|
|
||||||
update: (game: GamePropsSchema) => void
|
update: (game: GamePropsSchema) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientToServerEvents {
|
export interface ClientToServerEvents {
|
||||||
join: (userId: string, callback: () => void) => void
|
ping: (count: number, callback: (count: number) => void) => void
|
||||||
authenticate: (payload: { token: string }) => void
|
join: (withAck: ({ ack }: { ack: boolean }) => void) => void
|
||||||
|
gameSetting: (
|
||||||
|
payload: GameSettings,
|
||||||
|
withAck: ({ ack }: { ack: boolean }) => void
|
||||||
|
) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InterServerEvents {
|
interface InterServerEvents {
|
||||||
|
@ -37,7 +41,7 @@ interface InterServerEvents {
|
||||||
|
|
||||||
interface SocketData {
|
interface SocketData {
|
||||||
user: User | null
|
user: User | null
|
||||||
gameProps: GamePropsSchema
|
gameId: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type cServer = Server<
|
export type cServer = Server<
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
import { GamePropsSchema } from "./zodSchemas"
|
||||||
import crypto from "crypto"
|
import crypto from "crypto"
|
||||||
|
|
||||||
export function getObjectChecksum(obj: Object) {
|
export function getPayloadwithChecksum(
|
||||||
const objString = JSON.stringify(obj)
|
payload: GamePropsSchema["payload"] | null
|
||||||
|
): GamePropsSchema {
|
||||||
|
if (payload === null) return { payload: null, hash: null }
|
||||||
|
const objString = JSON.stringify(payload)
|
||||||
const hash = crypto.createHash("md5").update(objString).digest("hex")
|
const hash = crypto.createHash("md5").update(objString).digest("hex")
|
||||||
return hash
|
return { payload, hash }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
|
||||||
import { useSession } from "next-auth/react"
|
|
||||||
import {
|
|
||||||
Dispatch,
|
|
||||||
ReactNode,
|
|
||||||
createContext,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useReducer,
|
|
||||||
} from "react"
|
|
||||||
import { toast } from "react-toastify"
|
|
||||||
|
|
||||||
const initialValue: GamePropsSchema = { payload: null, hash: null }
|
|
||||||
|
|
||||||
interface gameContext {
|
|
||||||
gameProps: GamePropsSchema
|
|
||||||
setGameProps: Dispatch<GamePropsSchema>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const gameContext = createContext<gameContext>({
|
|
||||||
gameProps: initialValue,
|
|
||||||
setGameProps: () => {},
|
|
||||||
})
|
|
||||||
|
|
||||||
function updateProps(state: GamePropsSchema, body: GamePropsSchema) {
|
|
||||||
if (state.hash === body.hash) {
|
|
||||||
console.log("Everything up to date.")
|
|
||||||
return state
|
|
||||||
} else {
|
|
||||||
console.log("Update was needed.", state.hash, body.hash)
|
|
||||||
|
|
||||||
if (
|
|
||||||
state.payload?.game?.id &&
|
|
||||||
state.payload?.game?.id !== body.payload?.game?.id
|
|
||||||
) {
|
|
||||||
console.warn(
|
|
||||||
"Different gameId detected on update: ",
|
|
||||||
state.payload?.game?.id,
|
|
||||||
body.payload?.game?.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function GameContextProvider({ children }: { children: ReactNode }) {
|
|
||||||
const [gameProps, setGameProps] = useReducer(updateProps, initialValue)
|
|
||||||
|
|
||||||
const value = useMemo<gameContext>(
|
|
||||||
() => ({ gameProps, setGameProps }),
|
|
||||||
[gameProps, setGameProps]
|
|
||||||
)
|
|
||||||
|
|
||||||
return <gameContext.Provider value={value}>{children}</gameContext.Provider>
|
|
||||||
}
|
|
||||||
|
|
||||||
function useGameState() {
|
|
||||||
const { gameProps, setGameProps } = useContext(gameContext)
|
|
||||||
const { data: session, status } = useSession()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (status === "loading") return
|
|
||||||
if (!session)
|
|
||||||
toast("Nicht angemeldet.", {
|
|
||||||
toastId: "user",
|
|
||||||
position: "top-center",
|
|
||||||
})
|
|
||||||
else
|
|
||||||
toast(session.user.email, {
|
|
||||||
toastId: "user",
|
|
||||||
position: "top-center",
|
|
||||||
icon: session.user.image ? (
|
|
||||||
<img
|
|
||||||
style={{ transform: "scale(1.5)", borderRadius: "100%" }}
|
|
||||||
src={session.user.image}
|
|
||||||
alt="profile picture"
|
|
||||||
/>
|
|
||||||
) : undefined,
|
|
||||||
})
|
|
||||||
}, [session, status])
|
|
||||||
|
|
||||||
return {
|
|
||||||
gameProps,
|
|
||||||
setGameProps,
|
|
||||||
session,
|
|
||||||
status,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useGameState
|
|
|
@ -1,58 +0,0 @@
|
||||||
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 { isConnected, hasJoined }
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useSocket
|
|
|
@ -3,4 +3,5 @@ import { io } from "socket.io-client"
|
||||||
|
|
||||||
export const socket: cSocket = io({
|
export const socket: cSocket = io({
|
||||||
path: "/api/ws",
|
path: "/api/ws",
|
||||||
|
autoConnect: false,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,23 +1,41 @@
|
||||||
import {
|
import { GameState, PlayerN } from "@prisma/client"
|
||||||
GameSchema,
|
|
||||||
GamepinSchema,
|
|
||||||
User_GameSchema,
|
|
||||||
} from "../prisma/generated/zod"
|
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
export const PlayerSchema = z
|
export const PlayerSchema = z.object({
|
||||||
.object({
|
id: z.string(),
|
||||||
email: z.string().nullable(),
|
name: z.string().nullable(),
|
||||||
name: z.string().nullable(),
|
index: z.nativeEnum(PlayerN),
|
||||||
})
|
chats: z
|
||||||
.and(User_GameSchema)
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
event: z.string().nullable(),
|
||||||
|
message: z.string().nullable(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
})
|
||||||
|
.array(),
|
||||||
|
moves: z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
index: z.number(),
|
||||||
|
})
|
||||||
|
.array(),
|
||||||
|
})
|
||||||
|
|
||||||
export const CreateSchema = z
|
export const CreateSchema = z
|
||||||
.object({
|
.object({
|
||||||
game: GameSchema.nullish(),
|
game: z
|
||||||
gamePin: GamepinSchema.nullish(),
|
.object({
|
||||||
player1: PlayerSchema.nullish(),
|
id: z.string(),
|
||||||
player2: PlayerSchema.nullish(),
|
state: z.nativeEnum(GameState),
|
||||||
|
allowSpectators: z.boolean(),
|
||||||
|
allowSpecials: z.boolean(),
|
||||||
|
allowChat: z.boolean(),
|
||||||
|
allowMarkDraw: z.boolean(),
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
gamePin: z.string().nullable(),
|
||||||
|
player1: PlayerSchema.nullable(),
|
||||||
|
player2: PlayerSchema.nullable(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"eslint": "8.31.0",
|
"eslint": "8.31.0",
|
||||||
"eslint-config-next": "13.1.1",
|
"eslint-config-next": "13.1.1",
|
||||||
"http-status": "^1.6.2",
|
"http-status": "^1.6.2",
|
||||||
|
"immer": "^10.0.2",
|
||||||
"next": "13.1.1",
|
"next": "13.1.1",
|
||||||
"next-auth": "^4.22.1",
|
"next-auth": "^4.22.1",
|
||||||
"nodemailer": "^6.9.1",
|
"nodemailer": "^6.9.1",
|
||||||
|
@ -38,7 +39,8 @@
|
||||||
"typescript": "4.9.4",
|
"typescript": "4.9.4",
|
||||||
"unique-names-generator": "^4.7.1",
|
"unique-names-generator": "^4.7.1",
|
||||||
"zod": "^3.21.1",
|
"zod": "^3.21.1",
|
||||||
"zod-prisma-types": "^2.5.6"
|
"zod-prisma-types": "^2.5.6",
|
||||||
|
"zustand": "^4.3.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@total-typescript/ts-reset": "^0.3.7",
|
"@total-typescript/ts-reset": "^0.3.7",
|
||||||
|
|
|
@ -3,7 +3,6 @@ import "../styles/globals.scss"
|
||||||
import "../styles/grid2.scss"
|
import "../styles/grid2.scss"
|
||||||
import "../styles/grid.scss"
|
import "../styles/grid.scss"
|
||||||
import "@fortawesome/fontawesome-svg-core/styles.css"
|
import "@fortawesome/fontawesome-svg-core/styles.css"
|
||||||
import { GameContextProvider } from "@lib/hooks/useGameState"
|
|
||||||
import { SessionProvider } from "next-auth/react"
|
import { SessionProvider } from "next-auth/react"
|
||||||
import type { AppProps } from "next/app"
|
import type { AppProps } from "next/app"
|
||||||
import { ToastContainer } from "react-toastify"
|
import { ToastContainer } from "react-toastify"
|
||||||
|
@ -15,10 +14,8 @@ export default function App({
|
||||||
}: AppProps) {
|
}: AppProps) {
|
||||||
return (
|
return (
|
||||||
<SessionProvider session={session}>
|
<SessionProvider session={session}>
|
||||||
<GameContextProvider>
|
<Component {...pageProps} />
|
||||||
<Component {...pageProps} />
|
<ToastContainer />
|
||||||
<ToastContainer />
|
|
||||||
</GameContextProvider>
|
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { authOptions } from "../auth/[...nextauth]"
|
import { authOptions } from "../auth/[...nextauth]"
|
||||||
import { composeBody, gameIncludes, getAnyRunningGame } from "./running"
|
import { composeBody, gameSelects, getAnyRunningGame } from "./running"
|
||||||
import sendResponse from "@backend/sendResponse"
|
import sendResponse from "@backend/sendResponse"
|
||||||
import { rejectionErrors } from "@lib/backend/errors"
|
import { rejectionErrors } from "@lib/backend/errors"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
|
@ -46,7 +46,7 @@ export default async function create(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
...gameIncludes,
|
...gameSelects,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { authOptions } from "../auth/[...nextauth]"
|
import { authOptions } from "../auth/[...nextauth]"
|
||||||
import { composeBody, gameIncludes } from "./running"
|
import { composeBody, gameSelects } from "./running"
|
||||||
import sendError from "@backend/sendError"
|
import sendError from "@backend/sendError"
|
||||||
import sendResponse from "@backend/sendResponse"
|
import sendResponse from "@backend/sendResponse"
|
||||||
import { rejectionErrors } from "@lib/backend/errors"
|
import { rejectionErrors } from "@lib/backend/errors"
|
||||||
|
@ -46,7 +46,7 @@ export default async function join(
|
||||||
index: "player2",
|
index: "player2",
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
game: gameIncludes,
|
game: gameSelects,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,46 @@
|
||||||
import { authOptions } from "../auth/[...nextauth]"
|
import { authOptions } from "../auth/[...nextauth]"
|
||||||
import sendResponse from "@backend/sendResponse"
|
import sendResponse from "@backend/sendResponse"
|
||||||
import { rejectionErrors } from "@lib/backend/errors"
|
import { rejectionErrors } from "@lib/backend/errors"
|
||||||
import { getObjectChecksum } from "@lib/getObjectChecksum"
|
import { getPayloadwithChecksum } from "@lib/getObjectChecksum"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
import { getServerSession } from "next-auth"
|
import { getServerSession } from "next-auth"
|
||||||
|
|
||||||
export const gameIncludes = {
|
export const gameSelects = {
|
||||||
include: {
|
select: {
|
||||||
gamePin: true,
|
id: true,
|
||||||
|
allowChat: true,
|
||||||
|
allowMarkDraw: true,
|
||||||
|
allowSpecials: true,
|
||||||
|
allowSpectators: true,
|
||||||
|
state: true,
|
||||||
|
gamePin: {
|
||||||
|
select: {
|
||||||
|
pin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
users: {
|
users: {
|
||||||
include: {
|
select: {
|
||||||
|
id: true,
|
||||||
|
index: true,
|
||||||
|
chats: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
event: true,
|
||||||
|
message: true,
|
||||||
|
createdAt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
moves: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
name: true,
|
name: true,
|
||||||
email: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -31,7 +56,7 @@ export const getAnyGame = (gameId: string) => {
|
||||||
},
|
},
|
||||||
id: gameId,
|
id: gameId,
|
||||||
},
|
},
|
||||||
...gameIncludes,
|
...gameSelects,
|
||||||
})
|
})
|
||||||
return game
|
return game
|
||||||
}
|
}
|
||||||
|
@ -48,14 +73,14 @@ export const getAnyRunningGame = (userId: string) => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
...gameIncludes,
|
...gameSelects,
|
||||||
})
|
})
|
||||||
return game
|
return game
|
||||||
}
|
}
|
||||||
|
|
||||||
export function composeBody(
|
export function composeBody(
|
||||||
gameDB: NonNullable<Awaited<ReturnType<typeof getAnyRunningGame>>>
|
gameDB: NonNullable<Awaited<ReturnType<typeof getAnyRunningGame>>>
|
||||||
) {
|
): GamePropsSchema {
|
||||||
const { gamePin, ...game } = gameDB
|
const { gamePin, ...game } = gameDB
|
||||||
const users = gameDB.users.map(({ user, ...props }) => ({
|
const users = gameDB.users.map(({ user, ...props }) => ({
|
||||||
...props,
|
...props,
|
||||||
|
@ -64,13 +89,12 @@ export function composeBody(
|
||||||
const player1 = users.find((user) => user.index === "player1")
|
const player1 = users.find((user) => user.index === "player1")
|
||||||
const player2 = users.find((user) => user.index === "player2")
|
const player2 = users.find((user) => user.index === "player2")
|
||||||
const payload = {
|
const payload = {
|
||||||
game,
|
game: game,
|
||||||
gamePin,
|
gamePin: gamePin?.pin ?? null,
|
||||||
player1,
|
player1: player1 ?? null,
|
||||||
player2,
|
player2: player2 ?? null,
|
||||||
}
|
}
|
||||||
const hash = getObjectChecksum(payload)
|
return getPayloadwithChecksum(payload)
|
||||||
return { payload, hash }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function running(
|
export default async function running(
|
||||||
|
|
|
@ -2,7 +2,12 @@ import {
|
||||||
NextApiResponseWithSocket,
|
NextApiResponseWithSocket,
|
||||||
cServer,
|
cServer,
|
||||||
} from "../../interfaces/NextApiSocket"
|
} from "../../interfaces/NextApiSocket"
|
||||||
import { composeBody, getAnyRunningGame } from "./game/running"
|
import {
|
||||||
|
composeBody,
|
||||||
|
gameSelects,
|
||||||
|
getAnyGame,
|
||||||
|
getAnyRunningGame,
|
||||||
|
} from "./game/running"
|
||||||
import logging from "@lib/backend/logging"
|
import logging from "@lib/backend/logging"
|
||||||
import prisma from "@lib/prisma"
|
import prisma from "@lib/prisma"
|
||||||
import colors from "colors"
|
import colors from "colors"
|
||||||
|
@ -40,31 +45,9 @@ const SocketHandler = async (
|
||||||
id: session?.user.id,
|
id: session?.user.id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
next()
|
|
||||||
} catch (err) {
|
|
||||||
logging("Unauthorized", ["warn"], socket.request)
|
|
||||||
next(new Error("Unauthorized"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
const game = await getAnyRunningGame(socket.data.user?.id ?? "")
|
||||||
logging(
|
|
||||||
`User connected <${socket.data.user?.email}>`.green +
|
|
||||||
", " +
|
|
||||||
socket.id.cyan,
|
|
||||||
["infoGreen"],
|
|
||||||
socket.request
|
|
||||||
)
|
|
||||||
|
|
||||||
socket.on("join", async (userId, cb) => {
|
|
||||||
logging(
|
|
||||||
"Join: " + JSON.stringify(Array.from(socket.rooms)),
|
|
||||||
["debug"],
|
|
||||||
socket.request
|
|
||||||
)
|
|
||||||
const game = await getAnyRunningGame(userId ?? "")
|
|
||||||
if (!game) {
|
if (!game) {
|
||||||
socket.emit("forbidden")
|
|
||||||
logging(
|
logging(
|
||||||
"Forbidden, no game found: " +
|
"Forbidden, no game found: " +
|
||||||
JSON.stringify(Array.from(socket.rooms)),
|
JSON.stringify(Array.from(socket.rooms)),
|
||||||
|
@ -73,11 +56,46 @@ const SocketHandler = async (
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cb()
|
socket.data.gameId = game.id
|
||||||
socket.join(userId)
|
socket.join(game.id)
|
||||||
|
next()
|
||||||
|
} catch (err) {
|
||||||
|
logging("Unauthorized", ["warn"], socket.request)
|
||||||
|
next(new Error("Unauthorized"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
io.on("connection", async (socket) => {
|
||||||
|
logging(
|
||||||
|
`User connected <${socket.data.user?.email}>`.green +
|
||||||
|
", " +
|
||||||
|
socket.id.cyan,
|
||||||
|
["infoGreen"],
|
||||||
|
socket.request
|
||||||
|
)
|
||||||
|
const game = await getAnyGame(socket.data.gameId ?? "")
|
||||||
|
if (!socket.data.user || !socket.data.gameId || !game)
|
||||||
|
return socket.disconnect()
|
||||||
|
const body = composeBody(game)
|
||||||
|
io.to(socket.data.gameId).emit("update", body)
|
||||||
|
|
||||||
|
socket.on("gameSetting", async (payload, cb) => {
|
||||||
|
if (!socket.data.gameId) {
|
||||||
|
cb({ ack: false })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const game = await prisma.game.update({
|
||||||
|
where: { id: socket.data.gameId },
|
||||||
|
data: payload,
|
||||||
|
...gameSelects,
|
||||||
|
})
|
||||||
const body = composeBody(game)
|
const body = composeBody(game)
|
||||||
socket.data.gameProps = body
|
cb({ ack: true })
|
||||||
io.to(userId).emit("update", body)
|
io.to(game.id).emit("update", body)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("ping", (count, callback) => {
|
||||||
|
callback(count)
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on("disconnecting", () => {
|
socket.on("disconnecting", () => {
|
||||||
|
|
|
@ -1,33 +1,36 @@
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import { useGameProps } from "@hooks/useGameProps"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
import React, { useEffect } from "react"
|
import React, { useEffect } from "react"
|
||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
export default function Game() {
|
export default function Game() {
|
||||||
const { gameProps, session } = useGameState()
|
const { payload } = useGameProps()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { data: session } = useSession()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const gameId = gameProps.payload?.game?.id
|
const gameId = payload?.game?.id
|
||||||
const path = gameId ? "/game" : "/start"
|
const path = gameId ? "/game" : "/start"
|
||||||
toast.promise(router.push(path), {
|
toast.promise(router.push(path), {
|
||||||
pending: {
|
pending: {
|
||||||
render: "Wird weitergeleitet...",
|
render: "Wird weitergeleitet...",
|
||||||
toastId: "redirect",
|
toastId: "pageLoad",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
render: gameId
|
render: gameId
|
||||||
? "Spiel gefunden!"
|
? "Spiel gefunden!"
|
||||||
: session?.user
|
: session?.user.id
|
||||||
? "Kein laufendes Spiel."
|
? "Kein laufendes Spiel."
|
||||||
: "Kein laufendes Spiel. Bitte anmelden.",
|
: "Kein laufendes Spiel. Bitte anmelden.",
|
||||||
toastId: session?.user ? "postRedirect" : "user",
|
toastId: "pageLoad",
|
||||||
theme: session?.user ? "dark" : undefined,
|
theme: session?.user.id ? "dark" : undefined,
|
||||||
type: gameId ? "success" : "info",
|
type: gameId ? "success" : "info",
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
render: "Es ist ein Fehler aufgetreten 🤯",
|
render: "Es ist ein Fehler aufgetreten 🤯",
|
||||||
type: "error",
|
type: "error",
|
||||||
|
toastId: "pageLoad",
|
||||||
theme: "colored",
|
theme: "colored",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Gamefield from "../components/Gamefield/Gamefield"
|
import Gamefield from "@components/Gamefield/Gamefield"
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Grid from "../components/Grid"
|
import Grid from "@components/Grid"
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Grid2 from "../components/Grid2"
|
import Grid2 from "@components/Grid2"
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import BurgerMenu from "../components/BurgerMenu"
|
import BurgerMenu from "@components/BurgerMenu"
|
||||||
import Logo from "../components/Logo"
|
import Logo from "@components/Logo"
|
||||||
import { faCirclePlay } from "@fortawesome/pro-thin-svg-icons"
|
import { faCirclePlay } from "@fortawesome/pro-thin-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import BurgerMenu from "../components/BurgerMenu"
|
import BurgerMenu from "@components/BurgerMenu"
|
||||||
import LobbyFrame from "../components/Lobby/LobbyFrame"
|
import LobbyFrame from "@components/Lobby/LobbyFrame"
|
||||||
import Settings from "../components/Lobby/SettingsFrame/Settings"
|
import Settings from "@components/Lobby/SettingsFrame/Settings"
|
||||||
import Logo from "../components/Logo"
|
import Logo from "@components/Logo"
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
export default function Lobby() {
|
export default function Lobby() {
|
||||||
useGameState()
|
|
||||||
const [settings, setSettings] = useState(false)
|
const [settings, setSettings] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import BurgerMenu from "../components/BurgerMenu"
|
import BurgerMenu from "@components/BurgerMenu"
|
||||||
import Logo from "../components/Logo"
|
import Logo from "@components/Logo"
|
||||||
import OptionButton from "../components/OptionButton"
|
import OptionButton from "@components/OptionButton"
|
||||||
import { faEye, faLeftLong } from "@fortawesome/pro-regular-svg-icons"
|
import { faEye, faLeftLong } from "@fortawesome/pro-regular-svg-icons"
|
||||||
import { faPlus, faUserPlus } from "@fortawesome/pro-solid-svg-icons"
|
import { faPlus, faUserPlus } from "@fortawesome/pro-solid-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import useGameState from "@lib/hooks/useGameState"
|
import { useGameProps } from "@hooks/useGameProps"
|
||||||
import { GamePropsSchema } from "@lib/zodSchemas"
|
import { GamePropsSchema } from "@lib/zodSchemas"
|
||||||
import status from "http-status"
|
import status from "http-status"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||||
import OtpInput from "react-otp-input"
|
import OtpInput from "react-otp-input"
|
||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
import { Icons } from "react-toastify"
|
||||||
|
|
||||||
function isInputOnlyNumbers(input: string) {
|
function isInputOnlyNumbers(input: string) {
|
||||||
return /^\d+$/.test(input)
|
return /^\d+$/.test(input)
|
||||||
|
@ -45,8 +47,9 @@ const handleConfirmation = () => {
|
||||||
|
|
||||||
export default function Start() {
|
export default function Start() {
|
||||||
const [otp, setOtp] = useState("")
|
const [otp, setOtp] = useState("")
|
||||||
const { session, setGameProps } = useGameState()
|
const { full } = useGameProps()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { data: session } = useSession()
|
||||||
|
|
||||||
const query = useMemo((): { join?: boolean; watch?: boolean } => {
|
const query = useMemo((): { join?: boolean; watch?: boolean } => {
|
||||||
switch (router.query.q) {
|
switch (router.query.q) {
|
||||||
|
@ -68,43 +71,58 @@ export default function Start() {
|
||||||
.then(isAuthenticated)
|
.then(isAuthenticated)
|
||||||
.then((game) => GamePropsSchema.parse(game))
|
.then((game) => GamePropsSchema.parse(game))
|
||||||
|
|
||||||
const toastId = !pin ? "erstellt" : "angefragt"
|
const action = !pin ? "erstellt" : "angefragt"
|
||||||
const res = await toast.promise(gamePromise, {
|
const toastId = "pageLoad"
|
||||||
pending: {
|
toast("Raum wird " + action, {
|
||||||
render: "Raum wird " + toastId,
|
icon: Icons.spinner(),
|
||||||
toastId,
|
toastId,
|
||||||
},
|
autoClose: false,
|
||||||
success: {
|
hideProgressBar: true,
|
||||||
render: "Raum " + (!pin ? "erstellt" : "angefragt") + " 👌",
|
closeButton: false,
|
||||||
type: "info",
|
})
|
||||||
theme: "colored",
|
const res = await gamePromise.catch(() =>
|
||||||
toastId,
|
toast.update(toastId, {
|
||||||
},
|
|
||||||
error: {
|
|
||||||
render: "Es ist ein Fehler aufgetreten 🤯",
|
render: "Es ist ein Fehler aufgetreten 🤯",
|
||||||
type: "error",
|
type: "error",
|
||||||
|
icon: Icons.error,
|
||||||
theme: "colored",
|
theme: "colored",
|
||||||
toastId,
|
autoClose: 5000,
|
||||||
},
|
hideProgressBar: false,
|
||||||
|
closeButton: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
if (!res) return
|
||||||
|
full(res)
|
||||||
|
|
||||||
|
toast.update(toastId, {
|
||||||
|
render: "Weiterleitung",
|
||||||
})
|
})
|
||||||
|
|
||||||
setGameProps(res)
|
router
|
||||||
|
.push("/lobby")
|
||||||
await toast.promise(router.push("/lobby"), {
|
.then(() =>
|
||||||
pending: {
|
toast.update(toastId, {
|
||||||
render: "Raum wird beigetreten",
|
render: "Raum begetreten 👌",
|
||||||
},
|
type: "info",
|
||||||
success: {
|
icon: Icons.success,
|
||||||
render: "Raum begetreten 👌",
|
autoClose: 5000,
|
||||||
type: "info",
|
hideProgressBar: false,
|
||||||
},
|
closeButton: true,
|
||||||
error: {
|
})
|
||||||
render: "Es ist ein Fehler aufgetreten 🤯",
|
)
|
||||||
type: "error",
|
.catch(() =>
|
||||||
},
|
toast.update(toastId, {
|
||||||
})
|
render: "Es ist ein Fehler aufgetreten 🤯",
|
||||||
|
type: "error",
|
||||||
|
icon: Icons.error,
|
||||||
|
theme: "colored",
|
||||||
|
autoClose: 5000,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeButton: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
},
|
},
|
||||||
[router, setGameProps]
|
[router, full]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -151,7 +169,7 @@ export default function Start() {
|
||||||
icon={faUserPlus}
|
icon={faUserPlus}
|
||||||
disabled={!session}
|
disabled={!session}
|
||||||
>
|
>
|
||||||
{query.join && session?.user ? (
|
{query.join && session ? (
|
||||||
<OtpInput
|
<OtpInput
|
||||||
shouldAutoFocus
|
shouldAutoFocus
|
||||||
containerStyle={{ color: "initial" }}
|
containerStyle={{ color: "initial" }}
|
||||||
|
@ -167,7 +185,7 @@ export default function Start() {
|
||||||
)}
|
)}
|
||||||
</OptionButton>
|
</OptionButton>
|
||||||
<OptionButton icon={faEye}>
|
<OptionButton icon={faEye}>
|
||||||
{query.watch && session?.user ? (
|
{query.watch ? (
|
||||||
<OtpInput
|
<OtpInput
|
||||||
shouldAutoFocus
|
shouldAutoFocus
|
||||||
containerStyle={{ color: "initial" }}
|
containerStyle={{ color: "initial" }}
|
||||||
|
|
35
leaky-ships/pnpm-lock.yaml
generated
35
leaky-ships/pnpm-lock.yaml
generated
|
@ -49,6 +49,9 @@ dependencies:
|
||||||
http-status:
|
http-status:
|
||||||
specifier: ^1.6.2
|
specifier: ^1.6.2
|
||||||
version: 1.6.2
|
version: 1.6.2
|
||||||
|
immer:
|
||||||
|
specifier: ^10.0.2
|
||||||
|
version: 10.0.2
|
||||||
next:
|
next:
|
||||||
specifier: 13.1.1
|
specifier: 13.1.1
|
||||||
version: 13.1.1(react-dom@18.2.0)(react@18.2.0)(sass@1.61.0)
|
version: 13.1.1(react-dom@18.2.0)(react@18.2.0)(sass@1.61.0)
|
||||||
|
@ -91,6 +94,9 @@ dependencies:
|
||||||
zod-prisma-types:
|
zod-prisma-types:
|
||||||
specifier: ^2.5.6
|
specifier: ^2.5.6
|
||||||
version: 2.5.6
|
version: 2.5.6
|
||||||
|
zustand:
|
||||||
|
specifier: ^4.3.8
|
||||||
|
version: 4.3.8(immer@10.0.2)(react@18.2.0)
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@total-typescript/ts-reset':
|
'@total-typescript/ts-reset':
|
||||||
|
@ -1861,6 +1867,10 @@ packages:
|
||||||
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
/immer@10.0.2:
|
||||||
|
resolution: {integrity: sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/immutable@4.3.0:
|
/immutable@4.3.0:
|
||||||
resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
|
resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
|
||||||
|
|
||||||
|
@ -3180,6 +3190,14 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.0
|
punycode: 2.3.0
|
||||||
|
|
||||||
|
/use-sync-external-store@1.2.0(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/util-deprecate@1.0.2:
|
/util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -3289,3 +3307,20 @@ packages:
|
||||||
/zod@3.21.4:
|
/zod@3.21.4:
|
||||||
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/zustand@4.3.8(immer@10.0.2)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-4h28KCkHg5ii/wcFFJ5Fp+k1J3gJoasaIbppdgZFO4BPJnsNxL0mQXBSFgOgAdCdBj35aDTPvdAJReTMntFPGg==}
|
||||||
|
engines: {node: '>=12.7.0'}
|
||||||
|
peerDependencies:
|
||||||
|
immer: '>=9.0'
|
||||||
|
react: '>=16.8'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
immer:
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
immer: 10.0.2
|
||||||
|
react: 18.2.0
|
||||||
|
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const AccountScalarFieldEnumSchema = z.enum(['id','userId','type','provid
|
||||||
|
|
||||||
export const ChatScalarFieldEnumSchema = z.enum(['id','createdAt','message','event','user_game_id']);
|
export const ChatScalarFieldEnumSchema = z.enum(['id','createdAt','message','event','user_game_id']);
|
||||||
|
|
||||||
export const GameScalarFieldEnumSchema = z.enum(['id','createdAt','updatedAt','state']);
|
export const GameScalarFieldEnumSchema = z.enum(['id','createdAt','updatedAt','state','allowSpectators','allowSpecials','allowChat','allowMarkDraw']);
|
||||||
|
|
||||||
export const GamepinScalarFieldEnumSchema = z.enum(['id','createdAt','pin','gameId']);
|
export const GamepinScalarFieldEnumSchema = z.enum(['id','createdAt','pin','gameId']);
|
||||||
|
|
||||||
|
@ -118,6 +118,10 @@ export const GameSchema = z.object({
|
||||||
id: z.string().cuid(),
|
id: z.string().cuid(),
|
||||||
createdAt: z.coerce.date(),
|
createdAt: z.coerce.date(),
|
||||||
updatedAt: z.coerce.date(),
|
updatedAt: z.coerce.date(),
|
||||||
|
allowSpectators: z.boolean(),
|
||||||
|
allowSpecials: z.boolean(),
|
||||||
|
allowChat: z.boolean(),
|
||||||
|
allowMarkDraw: z.boolean(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type Game = z.infer<typeof GameSchema>
|
export type Game = z.infer<typeof GameSchema>
|
||||||
|
@ -306,6 +310,10 @@ export const GameSelectSchema: z.ZodType<Prisma.GameSelect> = z.object({
|
||||||
createdAt: z.boolean().optional(),
|
createdAt: z.boolean().optional(),
|
||||||
updatedAt: z.boolean().optional(),
|
updatedAt: z.boolean().optional(),
|
||||||
state: z.boolean().optional(),
|
state: z.boolean().optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
gamePin: z.union([z.boolean(),z.lazy(() => GamepinArgsSchema)]).optional(),
|
gamePin: z.union([z.boolean(),z.lazy(() => GamepinArgsSchema)]).optional(),
|
||||||
users: z.union([z.boolean(),z.lazy(() => User_GameFindManyArgsSchema)]).optional(),
|
users: z.union([z.boolean(),z.lazy(() => User_GameFindManyArgsSchema)]).optional(),
|
||||||
_count: z.union([z.boolean(),z.lazy(() => GameCountOutputTypeArgsSchema)]).optional(),
|
_count: z.union([z.boolean(),z.lazy(() => GameCountOutputTypeArgsSchema)]).optional(),
|
||||||
|
@ -655,6 +663,10 @@ export const GameWhereInputSchema: z.ZodType<Prisma.GameWhereInput> = z.object({
|
||||||
createdAt: z.union([ z.lazy(() => DateTimeFilterSchema),z.coerce.date() ]).optional(),
|
createdAt: z.union([ z.lazy(() => DateTimeFilterSchema),z.coerce.date() ]).optional(),
|
||||||
updatedAt: z.union([ z.lazy(() => DateTimeFilterSchema),z.coerce.date() ]).optional(),
|
updatedAt: z.union([ z.lazy(() => DateTimeFilterSchema),z.coerce.date() ]).optional(),
|
||||||
state: z.union([ z.lazy(() => EnumGameStateFilterSchema),z.lazy(() => GameStateSchema) ]).optional(),
|
state: z.union([ z.lazy(() => EnumGameStateFilterSchema),z.lazy(() => GameStateSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.lazy(() => BoolFilterSchema),z.boolean() ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.lazy(() => BoolFilterSchema),z.boolean() ]).optional(),
|
||||||
|
allowChat: z.union([ z.lazy(() => BoolFilterSchema),z.boolean() ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.lazy(() => BoolFilterSchema),z.boolean() ]).optional(),
|
||||||
gamePin: z.union([ z.lazy(() => GamepinRelationFilterSchema),z.lazy(() => GamepinWhereInputSchema) ]).optional().nullable(),
|
gamePin: z.union([ z.lazy(() => GamepinRelationFilterSchema),z.lazy(() => GamepinWhereInputSchema) ]).optional().nullable(),
|
||||||
users: z.lazy(() => User_GameListRelationFilterSchema).optional()
|
users: z.lazy(() => User_GameListRelationFilterSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
@ -664,6 +676,10 @@ export const GameOrderByWithRelationInputSchema: z.ZodType<Prisma.GameOrderByWit
|
||||||
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
state: z.lazy(() => SortOrderSchema).optional(),
|
state: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpectators: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpecials: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowChat: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowMarkDraw: z.lazy(() => SortOrderSchema).optional(),
|
||||||
gamePin: z.lazy(() => GamepinOrderByWithRelationInputSchema).optional(),
|
gamePin: z.lazy(() => GamepinOrderByWithRelationInputSchema).optional(),
|
||||||
users: z.lazy(() => User_GameOrderByRelationAggregateInputSchema).optional()
|
users: z.lazy(() => User_GameOrderByRelationAggregateInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
@ -677,6 +693,10 @@ export const GameOrderByWithAggregationInputSchema: z.ZodType<Prisma.GameOrderBy
|
||||||
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
state: z.lazy(() => SortOrderSchema).optional(),
|
state: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpectators: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpecials: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowChat: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowMarkDraw: z.lazy(() => SortOrderSchema).optional(),
|
||||||
_count: z.lazy(() => GameCountOrderByAggregateInputSchema).optional(),
|
_count: z.lazy(() => GameCountOrderByAggregateInputSchema).optional(),
|
||||||
_max: z.lazy(() => GameMaxOrderByAggregateInputSchema).optional(),
|
_max: z.lazy(() => GameMaxOrderByAggregateInputSchema).optional(),
|
||||||
_min: z.lazy(() => GameMinOrderByAggregateInputSchema).optional()
|
_min: z.lazy(() => GameMinOrderByAggregateInputSchema).optional()
|
||||||
|
@ -690,6 +710,10 @@ export const GameScalarWhereWithAggregatesInputSchema: z.ZodType<Prisma.GameScal
|
||||||
createdAt: z.union([ z.lazy(() => DateTimeWithAggregatesFilterSchema),z.coerce.date() ]).optional(),
|
createdAt: z.union([ z.lazy(() => DateTimeWithAggregatesFilterSchema),z.coerce.date() ]).optional(),
|
||||||
updatedAt: z.union([ z.lazy(() => DateTimeWithAggregatesFilterSchema),z.coerce.date() ]).optional(),
|
updatedAt: z.union([ z.lazy(() => DateTimeWithAggregatesFilterSchema),z.coerce.date() ]).optional(),
|
||||||
state: z.union([ z.lazy(() => EnumGameStateWithAggregatesFilterSchema),z.lazy(() => GameStateSchema) ]).optional(),
|
state: z.union([ z.lazy(() => EnumGameStateWithAggregatesFilterSchema),z.lazy(() => GameStateSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.lazy(() => BoolWithAggregatesFilterSchema),z.boolean() ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.lazy(() => BoolWithAggregatesFilterSchema),z.boolean() ]).optional(),
|
||||||
|
allowChat: z.union([ z.lazy(() => BoolWithAggregatesFilterSchema),z.boolean() ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.lazy(() => BoolWithAggregatesFilterSchema),z.boolean() ]).optional(),
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const GamepinWhereInputSchema: z.ZodType<Prisma.GamepinWhereInput> = z.object({
|
export const GamepinWhereInputSchema: z.ZodType<Prisma.GamepinWhereInput> = z.object({
|
||||||
|
@ -1187,6 +1211,10 @@ export const GameCreateInputSchema: z.ZodType<Prisma.GameCreateInput> = z.object
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional(),
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
gamePin: z.lazy(() => GamepinCreateNestedOneWithoutGameInputSchema).optional(),
|
gamePin: z.lazy(() => GamepinCreateNestedOneWithoutGameInputSchema).optional(),
|
||||||
users: z.lazy(() => User_GameCreateNestedManyWithoutGameInputSchema).optional()
|
users: z.lazy(() => User_GameCreateNestedManyWithoutGameInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
@ -1196,6 +1224,10 @@ export const GameUncheckedCreateInputSchema: z.ZodType<Prisma.GameUncheckedCreat
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional(),
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
gamePin: z.lazy(() => GamepinUncheckedCreateNestedOneWithoutGameInputSchema).optional(),
|
gamePin: z.lazy(() => GamepinUncheckedCreateNestedOneWithoutGameInputSchema).optional(),
|
||||||
users: z.lazy(() => User_GameUncheckedCreateNestedManyWithoutGameInputSchema).optional()
|
users: z.lazy(() => User_GameUncheckedCreateNestedManyWithoutGameInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
@ -1205,6 +1237,10 @@ export const GameUpdateInputSchema: z.ZodType<Prisma.GameUpdateInput> = z.object
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
gamePin: z.lazy(() => GamepinUpdateOneWithoutGameNestedInputSchema).optional(),
|
gamePin: z.lazy(() => GamepinUpdateOneWithoutGameNestedInputSchema).optional(),
|
||||||
users: z.lazy(() => User_GameUpdateManyWithoutGameNestedInputSchema).optional()
|
users: z.lazy(() => User_GameUpdateManyWithoutGameNestedInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
@ -1214,6 +1250,10 @@ export const GameUncheckedUpdateInputSchema: z.ZodType<Prisma.GameUncheckedUpdat
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
gamePin: z.lazy(() => GamepinUncheckedUpdateOneWithoutGameNestedInputSchema).optional(),
|
gamePin: z.lazy(() => GamepinUncheckedUpdateOneWithoutGameNestedInputSchema).optional(),
|
||||||
users: z.lazy(() => User_GameUncheckedUpdateManyWithoutGameNestedInputSchema).optional()
|
users: z.lazy(() => User_GameUncheckedUpdateManyWithoutGameNestedInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
@ -1222,7 +1262,11 @@ export const GameCreateManyInputSchema: z.ZodType<Prisma.GameCreateManyInput> =
|
||||||
id: z.string().cuid().optional(),
|
id: z.string().cuid().optional(),
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional()
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const GameUpdateManyMutationInputSchema: z.ZodType<Prisma.GameUpdateManyMutationInput> = z.object({
|
export const GameUpdateManyMutationInputSchema: z.ZodType<Prisma.GameUpdateManyMutationInput> = z.object({
|
||||||
|
@ -1230,6 +1274,10 @@ export const GameUpdateManyMutationInputSchema: z.ZodType<Prisma.GameUpdateManyM
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const GameUncheckedUpdateManyInputSchema: z.ZodType<Prisma.GameUncheckedUpdateManyInput> = z.object({
|
export const GameUncheckedUpdateManyInputSchema: z.ZodType<Prisma.GameUncheckedUpdateManyInput> = z.object({
|
||||||
|
@ -1237,6 +1285,10 @@ export const GameUncheckedUpdateManyInputSchema: z.ZodType<Prisma.GameUncheckedU
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const GamepinCreateInputSchema: z.ZodType<Prisma.GamepinCreateInput> = z.object({
|
export const GamepinCreateInputSchema: z.ZodType<Prisma.GamepinCreateInput> = z.object({
|
||||||
|
@ -1776,6 +1828,11 @@ export const EnumGameStateFilterSchema: z.ZodType<Prisma.EnumGameStateFilter> =
|
||||||
not: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => NestedEnumGameStateFilterSchema) ]).optional(),
|
not: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => NestedEnumGameStateFilterSchema) ]).optional(),
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
export const BoolFilterSchema: z.ZodType<Prisma.BoolFilter> = z.object({
|
||||||
|
equals: z.boolean().optional(),
|
||||||
|
not: z.union([ z.boolean(),z.lazy(() => NestedBoolFilterSchema) ]).optional(),
|
||||||
|
}).strict();
|
||||||
|
|
||||||
export const GamepinRelationFilterSchema: z.ZodType<Prisma.GamepinRelationFilter> = z.object({
|
export const GamepinRelationFilterSchema: z.ZodType<Prisma.GamepinRelationFilter> = z.object({
|
||||||
is: z.lazy(() => GamepinWhereInputSchema).optional().nullable(),
|
is: z.lazy(() => GamepinWhereInputSchema).optional().nullable(),
|
||||||
isNot: z.lazy(() => GamepinWhereInputSchema).optional().nullable()
|
isNot: z.lazy(() => GamepinWhereInputSchema).optional().nullable()
|
||||||
|
@ -1785,21 +1842,33 @@ export const GameCountOrderByAggregateInputSchema: z.ZodType<Prisma.GameCountOrd
|
||||||
id: z.lazy(() => SortOrderSchema).optional(),
|
id: z.lazy(() => SortOrderSchema).optional(),
|
||||||
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
state: z.lazy(() => SortOrderSchema).optional()
|
state: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpectators: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpecials: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowChat: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowMarkDraw: z.lazy(() => SortOrderSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const GameMaxOrderByAggregateInputSchema: z.ZodType<Prisma.GameMaxOrderByAggregateInput> = z.object({
|
export const GameMaxOrderByAggregateInputSchema: z.ZodType<Prisma.GameMaxOrderByAggregateInput> = z.object({
|
||||||
id: z.lazy(() => SortOrderSchema).optional(),
|
id: z.lazy(() => SortOrderSchema).optional(),
|
||||||
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
state: z.lazy(() => SortOrderSchema).optional()
|
state: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpectators: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpecials: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowChat: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowMarkDraw: z.lazy(() => SortOrderSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const GameMinOrderByAggregateInputSchema: z.ZodType<Prisma.GameMinOrderByAggregateInput> = z.object({
|
export const GameMinOrderByAggregateInputSchema: z.ZodType<Prisma.GameMinOrderByAggregateInput> = z.object({
|
||||||
id: z.lazy(() => SortOrderSchema).optional(),
|
id: z.lazy(() => SortOrderSchema).optional(),
|
||||||
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
createdAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
updatedAt: z.lazy(() => SortOrderSchema).optional(),
|
||||||
state: z.lazy(() => SortOrderSchema).optional()
|
state: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpectators: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowSpecials: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowChat: z.lazy(() => SortOrderSchema).optional(),
|
||||||
|
allowMarkDraw: z.lazy(() => SortOrderSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
export const EnumGameStateWithAggregatesFilterSchema: z.ZodType<Prisma.EnumGameStateWithAggregatesFilter> = z.object({
|
export const EnumGameStateWithAggregatesFilterSchema: z.ZodType<Prisma.EnumGameStateWithAggregatesFilter> = z.object({
|
||||||
|
@ -1812,6 +1881,14 @@ export const EnumGameStateWithAggregatesFilterSchema: z.ZodType<Prisma.EnumGameS
|
||||||
_max: z.lazy(() => NestedEnumGameStateFilterSchema).optional()
|
_max: z.lazy(() => NestedEnumGameStateFilterSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
export const BoolWithAggregatesFilterSchema: z.ZodType<Prisma.BoolWithAggregatesFilter> = z.object({
|
||||||
|
equals: z.boolean().optional(),
|
||||||
|
not: z.union([ z.boolean(),z.lazy(() => NestedBoolWithAggregatesFilterSchema) ]).optional(),
|
||||||
|
_count: z.lazy(() => NestedIntFilterSchema).optional(),
|
||||||
|
_min: z.lazy(() => NestedBoolFilterSchema).optional(),
|
||||||
|
_max: z.lazy(() => NestedBoolFilterSchema).optional()
|
||||||
|
}).strict();
|
||||||
|
|
||||||
export const GameRelationFilterSchema: z.ZodType<Prisma.GameRelationFilter> = z.object({
|
export const GameRelationFilterSchema: z.ZodType<Prisma.GameRelationFilter> = z.object({
|
||||||
is: z.lazy(() => GameWhereInputSchema).optional(),
|
is: z.lazy(() => GameWhereInputSchema).optional(),
|
||||||
isNot: z.lazy(() => GameWhereInputSchema).optional()
|
isNot: z.lazy(() => GameWhereInputSchema).optional()
|
||||||
|
@ -2207,6 +2284,10 @@ export const EnumGameStateFieldUpdateOperationsInputSchema: z.ZodType<Prisma.Enu
|
||||||
set: z.lazy(() => GameStateSchema).optional()
|
set: z.lazy(() => GameStateSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
export const BoolFieldUpdateOperationsInputSchema: z.ZodType<Prisma.BoolFieldUpdateOperationsInput> = z.object({
|
||||||
|
set: z.boolean().optional()
|
||||||
|
}).strict();
|
||||||
|
|
||||||
export const GamepinUpdateOneWithoutGameNestedInputSchema: z.ZodType<Prisma.GamepinUpdateOneWithoutGameNestedInput> = z.object({
|
export const GamepinUpdateOneWithoutGameNestedInputSchema: z.ZodType<Prisma.GamepinUpdateOneWithoutGameNestedInput> = z.object({
|
||||||
create: z.union([ z.lazy(() => GamepinCreateWithoutGameInputSchema),z.lazy(() => GamepinUncheckedCreateWithoutGameInputSchema) ]).optional(),
|
create: z.union([ z.lazy(() => GamepinCreateWithoutGameInputSchema),z.lazy(() => GamepinUncheckedCreateWithoutGameInputSchema) ]).optional(),
|
||||||
connectOrCreate: z.lazy(() => GamepinCreateOrConnectWithoutGameInputSchema).optional(),
|
connectOrCreate: z.lazy(() => GamepinCreateOrConnectWithoutGameInputSchema).optional(),
|
||||||
|
@ -2589,6 +2670,11 @@ export const NestedEnumGameStateFilterSchema: z.ZodType<Prisma.NestedEnumGameSta
|
||||||
not: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => NestedEnumGameStateFilterSchema) ]).optional(),
|
not: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => NestedEnumGameStateFilterSchema) ]).optional(),
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
export const NestedBoolFilterSchema: z.ZodType<Prisma.NestedBoolFilter> = z.object({
|
||||||
|
equals: z.boolean().optional(),
|
||||||
|
not: z.union([ z.boolean(),z.lazy(() => NestedBoolFilterSchema) ]).optional(),
|
||||||
|
}).strict();
|
||||||
|
|
||||||
export const NestedEnumGameStateWithAggregatesFilterSchema: z.ZodType<Prisma.NestedEnumGameStateWithAggregatesFilter> = z.object({
|
export const NestedEnumGameStateWithAggregatesFilterSchema: z.ZodType<Prisma.NestedEnumGameStateWithAggregatesFilter> = z.object({
|
||||||
equals: z.lazy(() => GameStateSchema).optional(),
|
equals: z.lazy(() => GameStateSchema).optional(),
|
||||||
in: z.lazy(() => GameStateSchema).array().optional(),
|
in: z.lazy(() => GameStateSchema).array().optional(),
|
||||||
|
@ -2599,6 +2685,14 @@ export const NestedEnumGameStateWithAggregatesFilterSchema: z.ZodType<Prisma.Nes
|
||||||
_max: z.lazy(() => NestedEnumGameStateFilterSchema).optional()
|
_max: z.lazy(() => NestedEnumGameStateFilterSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
export const NestedBoolWithAggregatesFilterSchema: z.ZodType<Prisma.NestedBoolWithAggregatesFilter> = z.object({
|
||||||
|
equals: z.boolean().optional(),
|
||||||
|
not: z.union([ z.boolean(),z.lazy(() => NestedBoolWithAggregatesFilterSchema) ]).optional(),
|
||||||
|
_count: z.lazy(() => NestedIntFilterSchema).optional(),
|
||||||
|
_min: z.lazy(() => NestedBoolFilterSchema).optional(),
|
||||||
|
_max: z.lazy(() => NestedBoolFilterSchema).optional()
|
||||||
|
}).strict();
|
||||||
|
|
||||||
export const NestedEnumPlayerNFilterSchema: z.ZodType<Prisma.NestedEnumPlayerNFilter> = z.object({
|
export const NestedEnumPlayerNFilterSchema: z.ZodType<Prisma.NestedEnumPlayerNFilter> = z.object({
|
||||||
equals: z.lazy(() => PlayerNSchema).optional(),
|
equals: z.lazy(() => PlayerNSchema).optional(),
|
||||||
in: z.lazy(() => PlayerNSchema).array().optional(),
|
in: z.lazy(() => PlayerNSchema).array().optional(),
|
||||||
|
@ -3026,6 +3120,10 @@ export const GameCreateWithoutGamePinInputSchema: z.ZodType<Prisma.GameCreateWit
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional(),
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
users: z.lazy(() => User_GameCreateNestedManyWithoutGameInputSchema).optional()
|
users: z.lazy(() => User_GameCreateNestedManyWithoutGameInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3034,6 +3132,10 @@ export const GameUncheckedCreateWithoutGamePinInputSchema: z.ZodType<Prisma.Game
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional(),
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
users: z.lazy(() => User_GameUncheckedCreateNestedManyWithoutGameInputSchema).optional()
|
users: z.lazy(() => User_GameUncheckedCreateNestedManyWithoutGameInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3052,6 +3154,10 @@ export const GameUpdateWithoutGamePinInputSchema: z.ZodType<Prisma.GameUpdateWit
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
users: z.lazy(() => User_GameUpdateManyWithoutGameNestedInputSchema).optional()
|
users: z.lazy(() => User_GameUpdateManyWithoutGameNestedInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3060,6 +3166,10 @@ export const GameUncheckedUpdateWithoutGamePinInputSchema: z.ZodType<Prisma.Game
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
users: z.lazy(() => User_GameUncheckedUpdateManyWithoutGameNestedInputSchema).optional()
|
users: z.lazy(() => User_GameUncheckedUpdateManyWithoutGameNestedInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3114,6 +3224,10 @@ export const GameCreateWithoutUsersInputSchema: z.ZodType<Prisma.GameCreateWitho
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional(),
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
gamePin: z.lazy(() => GamepinCreateNestedOneWithoutGameInputSchema).optional()
|
gamePin: z.lazy(() => GamepinCreateNestedOneWithoutGameInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3122,6 +3236,10 @@ export const GameUncheckedCreateWithoutUsersInputSchema: z.ZodType<Prisma.GameUn
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
state: z.lazy(() => GameStateSchema).optional(),
|
state: z.lazy(() => GameStateSchema).optional(),
|
||||||
|
allowSpectators: z.boolean().optional(),
|
||||||
|
allowSpecials: z.boolean().optional(),
|
||||||
|
allowChat: z.boolean().optional(),
|
||||||
|
allowMarkDraw: z.boolean().optional(),
|
||||||
gamePin: z.lazy(() => GamepinUncheckedCreateNestedOneWithoutGameInputSchema).optional()
|
gamePin: z.lazy(() => GamepinUncheckedCreateNestedOneWithoutGameInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3222,6 +3340,10 @@ export const GameUpdateWithoutUsersInputSchema: z.ZodType<Prisma.GameUpdateWitho
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
gamePin: z.lazy(() => GamepinUpdateOneWithoutGameNestedInputSchema).optional()
|
gamePin: z.lazy(() => GamepinUpdateOneWithoutGameNestedInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
@ -3230,6 +3352,10 @@ export const GameUncheckedUpdateWithoutUsersInputSchema: z.ZodType<Prisma.GameUn
|
||||||
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
createdAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
updatedAt: z.union([ z.coerce.date(),z.lazy(() => DateTimeFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
state: z.union([ z.lazy(() => GameStateSchema),z.lazy(() => EnumGameStateFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpectators: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowSpecials: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowChat: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
|
allowMarkDraw: z.union([ z.boolean(),z.lazy(() => BoolFieldUpdateOperationsInputSchema) ]).optional(),
|
||||||
gamePin: z.lazy(() => GamepinUncheckedUpdateOneWithoutGameNestedInputSchema).optional()
|
gamePin: z.lazy(() => GamepinUncheckedUpdateOneWithoutGameNestedInputSchema).optional()
|
||||||
}).strict();
|
}).strict();
|
||||||
|
|
||||||
|
|
|
@ -75,12 +75,16 @@ enum GameState {
|
||||||
}
|
}
|
||||||
|
|
||||||
model Game {
|
model Game {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
state GameState @default(launching)
|
state GameState @default(launching)
|
||||||
gamePin Gamepin?
|
allowSpectators Boolean @default(true)
|
||||||
users User_Game[]
|
allowSpecials Boolean @default(true)
|
||||||
|
allowChat Boolean @default(true)
|
||||||
|
allowMarkDraw Boolean @default(true)
|
||||||
|
gamePin Gamepin?
|
||||||
|
users User_Game[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Gamepin {
|
model Gamepin {
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@lib/*": ["./lib/*"],
|
"@lib/*": ["./lib/*"],
|
||||||
|
"@hooks/*": ["./hooks/*"],
|
||||||
|
"@components/*": ["./components/*"],
|
||||||
"@backend/*": ["./lib/backend/*"]
|
"@backend/*": ["./lib/backend/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue