Fully working ship placement

This commit is contained in:
aronmal 2023-06-13 18:08:09 +02:00
parent c2af2dffa2
commit 0b8fb0a476
Signed by: aronmal
GPG key ID: 816B7707426FC612
15 changed files with 543 additions and 194 deletions

View file

@ -1,7 +1,16 @@
import { MouseCursor } from "../../interfaces/frontend"
import { count } from "./Gamefield"
import { borderCN, cornerCN, fieldIndex } from "@lib/utils/helpers"
import { CSSProperties, Dispatch, SetStateAction } from "react"
import { useGameProps } from "@hooks/useGameProps"
import {
borderCN,
cornerCN,
fieldIndex,
intersectingShip,
isAlreadyHit,
overlapsWithAnyBorder,
shipProps,
targetList,
} from "@lib/utils/helpers"
import { CSSProperties, useCallback } from "react"
type TilesType = {
key: number
@ -11,14 +20,61 @@ type TilesType = {
y: number
}
function BorderTiles({
props: { settingTarget, setMouseCursor },
}: {
props: {
settingTarget: (isGameTile: boolean, x: number, y: number) => void
setMouseCursor: Dispatch<SetStateAction<MouseCursor>>
}
}) {
function BorderTiles() {
const {
DispatchAction,
payload,
mode,
ships,
hits,
target,
targetPreview,
mouseCursor,
setTarget,
addShip,
setMouseCursor,
removeShip,
} = useGameProps()
const settingTarget = useCallback(
(isGameTile: boolean, x: number, y: number) => {
if (payload?.game?.state === "running") {
const list = targetList(targetPreview, mode)
if (
!isGameTile ||
!list.filter(({ x, y }) => !isAlreadyHit(x, y, hits)).length
)
return
if (target.show && target.x == x && target.y == y) {
DispatchAction({
action: "missile",
...target,
})
setTarget((t) => ({ ...t, show: false }))
} else if (!overlapsWithAnyBorder(targetPreview, mode))
setTarget({ show: true, x, y })
} else if (
payload?.game?.state === "starting" &&
targetPreview.show &&
!intersectingShip(ships, shipProps(ships, mode, targetPreview)).score
) {
setMouseCursor((e) => ({ ...e, shouldShow: false }))
addShip(shipProps(ships, mode, targetPreview))
}
},
[
DispatchAction,
addShip,
hits,
mode,
payload?.game?.state,
setMouseCursor,
setTarget,
ships,
target,
targetPreview,
]
)
let tilesProperties: TilesType[] = []
for (let y = 0; y < count + 2; y++) {
@ -49,9 +105,44 @@ function BorderTiles({
key={key}
className={className}
style={{ "--x": x, "--y": y } as CSSProperties}
onClick={() => settingTarget(isGameTile, x, y)}
onClick={() => {
if (payload?.game?.state === "running") {
settingTarget(isGameTile, x, y)
} else if (payload?.game?.state === "starting") {
const { index } = intersectingShip(ships, {
...mouseCursor,
size: 1,
variant: 0,
orientation: "h",
})
if (typeof index === "undefined")
settingTarget(isGameTile, x, y)
else {
const ship = ships[index]
useGameProps.setState({ mode: ship.size - 2 })
removeShip(ship)
setMouseCursor((e) => ({ ...e, shouldShow: true }))
}
}
}}
onMouseEnter={() =>
setMouseCursor({ x, y, shouldShow: isGameTile })
setMouseCursor({
x,
y,
shouldShow:
isGameTile &&
(payload?.game?.state === "starting"
? intersectingShip(
ships,
shipProps(ships, mode, {
x,
y,
orientation: targetPreview.orientation,
}),
true
).score < 2
: true),
})
}
></div>
)

View file

@ -16,6 +16,7 @@ import {
faGlasses,
faPalette,
faReply,
faRotate,
faScribble,
faShip,
faSparkles,
@ -25,6 +26,7 @@ import { useDrawProps } from "@hooks/useDrawProps"
import { useGameProps } from "@hooks/useGameProps"
import { socket } from "@lib/socket"
import { GamePropsSchema } from "@lib/zodSchemas"
import { Orientation } from "@prisma/client"
import { useSession } from "next-auth/react"
import {
Dispatch,
@ -60,20 +62,13 @@ function EventBar({ clear }: { clear: () => void }) {
setSetting,
full,
setTarget,
setTargetPreview,
setIsReady,
} = useGameProps()
const gameSetting = useCallback(
(payload: GameSettings) => setGameSetting(payload, setSetting, full),
[full, setSetting]
)
const setMenu = useCallback(
(menu: keyof EventBarModes) => useGameProps.setState({ menu }),
[]
)
const setMode = useCallback(
(mode: number) => useGameProps.setState({ mode }),
[]
)
const self = useMemo(
() => payload?.users.find((e) => e?.id === session?.user.id),
[payload?.users, session?.user.id]
@ -85,7 +80,7 @@ function EventBar({ clear }: { clear: () => void }) {
icon: "burger-menu",
text: "Menu",
callback: () => {
setMenu("menu")
useGameProps.setState({ menu: "menu" })
},
},
payload?.game?.state === "running"
@ -93,28 +88,28 @@ function EventBar({ clear }: { clear: () => void }) {
icon: faSwords,
text: "Attack",
callback: () => {
setMenu("actions")
useGameProps.setState({ menu: "actions" })
},
}
: {
icon: faShip,
text: "Ships",
callback: () => {
setMenu("actions")
useGameProps.setState({ menu: "actions" })
},
},
{
icon: "pen",
text: "Draw",
callback: () => {
setMenu("draw")
useGameProps.setState({ menu: "draw" })
},
},
{
icon: "gear",
text: "Settings",
callback: () => {
setMenu("settings")
useGameProps.setState({ menu: "settings" })
},
},
],
@ -135,7 +130,7 @@ function EventBar({ clear }: { clear: () => void }) {
icon: "scope",
text: "Fire missile",
callback: () => {
setMode(3)
useGameProps.setState({ mode: 3 })
setTarget((e) => ({ ...e, show: false }))
},
},
@ -148,7 +143,7 @@ function EventBar({ clear }: { clear: () => void }) {
(e) => e.action === "htorpedo" || e.action === "vtorpedo"
).length ?? 0),
callback: () => {
setMode(1)
useGameProps.setState({ mode: 1 })
setTarget((e) => ({ ...e, show: false }))
},
},
@ -159,7 +154,7 @@ function EventBar({ clear }: { clear: () => void }) {
1 -
(self?.moves.filter((e) => e.action === "radar").length ?? 0),
callback: () => {
setMode(0)
useGameProps.setState({ mode: 0 })
setTarget((e) => ({ ...e, show: false }))
},
},
@ -171,7 +166,7 @@ function EventBar({ clear }: { clear: () => void }) {
amount: 1 - ships.filter((e) => e.size === 2).length,
callback: () => {
if (1 - ships.filter((e) => e.size === 2).length === 0) return
setMode(0)
useGameProps.setState({ mode: 0 })
},
},
{
@ -180,7 +175,7 @@ function EventBar({ clear }: { clear: () => void }) {
amount: 3 - ships.filter((e) => e.size === 3).length,
callback: () => {
if (3 - ships.filter((e) => e.size === 3).length === 0) return
setMode(1)
useGameProps.setState({ mode: 1 })
},
},
{
@ -189,7 +184,17 @@ function EventBar({ clear }: { clear: () => void }) {
amount: 2 - ships.filter((e) => e.size === 4).length,
callback: () => {
if (2 - ships.filter((e) => e.size === 4).length === 0) return
setMode(2)
useGameProps.setState({ mode: 2 })
},
},
{
icon: faRotate,
text: "Rotate",
callback: () => {
setTargetPreview((t) => ({
...t,
orientation: t.orientation === "h" ? "v" : "h",
}))
},
},
{
@ -263,9 +268,8 @@ function EventBar({ clear }: { clear: () => void }) {
self?.moves,
session?.user?.id,
setIsReady,
setMenu,
setMode,
setTarget,
setTargetPreview,
ships,
shouldHide,
]
@ -296,7 +300,7 @@ function EventBar({ clear }: { clear: () => void }) {
text: "Return",
iconColor: "#555",
callback: () => {
setMenu("main")
useGameProps.setState({ menu: "main" })
},
}}
></Item>

View file

@ -1,4 +1,3 @@
import { MouseCursor } from "../../interfaces/frontend"
// import Bluetooth from "./Bluetooth"
// import FogImages from "./FogImages"
import Labeling from "./Labeling"
@ -12,31 +11,20 @@ import { useDrawProps } from "@hooks/useDrawProps"
import { useGameProps } from "@hooks/useGameProps"
import useSocket from "@hooks/useSocket"
import { socket } from "@lib/socket"
import {
initlialMouseCursor,
overlapsWithAnyBorder,
isAlreadyHit,
targetList,
shipProps,
} from "@lib/utils/helpers"
import { CSSProperties, useCallback } from "react"
import { useEffect, useState } from "react"
import { overlapsWithAnyBorder } from "@lib/utils/helpers"
import { CSSProperties } from "react"
import { useEffect } from "react"
export const count = 12
function Gamefield() {
const [mouseCursor, setMouseCursor] =
useState<MouseCursor>(initlialMouseCursor)
const {
mode,
hits,
target,
targetPreview,
mouseCursor,
ships,
addShip,
payload,
DispatchAction,
setTarget,
setTargetPreview,
full,
} = useGameProps()
@ -47,53 +35,36 @@ function Gamefield() {
socket.emit("update", full)
}, [full, payload?.game?.id, isConnected])
const settingTarget = useCallback(
(isGameTile: boolean, x: number, y: number) => {
if (payload?.game?.state === "running") {
const list = targetList(targetPreview, mode)
if (
!isGameTile ||
!list.filter(({ x, y }) => !isAlreadyHit(x, y, hits)).length
)
return
if (target.show && target.x == x && target.y == y) {
DispatchAction({
action: "missile",
...target,
})
setTarget((t) => ({ ...t, show: false }))
} else if (!overlapsWithAnyBorder(targetPreview, mode))
setTarget({ show: true, x, y })
} else if (payload?.game?.state === "starting") {
addShip(shipProps(ships, mode, targetPreview))
}
},
[
DispatchAction,
addShip,
hits,
mode,
payload?.game?.state,
setTarget,
ships,
target,
targetPreview,
]
)
useEffect(() => {
if (mode < 0) return
const { x, y, show } = target
const { shouldShow, ...position } = mouseCursor
if (!shouldShow || overlapsWithAnyBorder(position, mode))
setTargetPreview((e) => ({ ...e, show: false }))
if (
!shouldShow ||
(payload?.game?.state === "running" &&
overlapsWithAnyBorder(position, mode))
)
setTargetPreview((t) => ({ ...t, show: false }))
else {
setTargetPreview({
setTargetPreview((t) => ({
...t,
...position,
show: !show || x !== position.x || y !== position.y,
})
}))
if (payload?.game?.state !== "starting") return
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key !== "r") return
setTargetPreview((t) => ({
...t,
orientation: t.orientation === "h" ? "v" : "h",
}))
}
document.addEventListener("keydown", handleKeyPress)
return () => {
document.removeEventListener("keydown", handleKeyPress)
}
}
}, [mode, mouseCursor, setTargetPreview, target])
}, [mode, mouseCursor, payload?.game?.state, setTargetPreview, target])
const { canvasRef, onMouseDown, clear } = useDraw()
const { enable, color, shouldHide } = useDrawProps()
@ -104,19 +75,19 @@ function Gamefield() {
<div
id="game-frame"
style={{ "--i": count } as CSSProperties}
onMouseLeave={() =>
setMouseCursor((e) => ({ ...e, shouldShow: false }))
}
// onMouseLeave={() =>
// setMouseCursor((e) => ({ ...e, shouldShow: false }))
// }
>
{/* Bordes */}
<BorderTiles props={{ settingTarget, setMouseCursor }} />
<BorderTiles />
{/* Collumn lettes and row numbers */}
<Labeling count={count} />
<Labeling />
{/* Ships */}
<Ships />
<HitElems hits={hits} />
<HitElems />
{/* Fog images */}
{/* <FogImages /> */}

View file

@ -1,18 +1,32 @@
import { Hit } from "../../interfaces/frontend"
import { faBurst, faXmark } from "@fortawesome/pro-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { useGameProps } from "@hooks/useGameProps"
import { CSSProperties } from "react"
function HitElems({ hits }: { hits: Hit[] }) {
function HitElems({
props,
}: {
props?: { hits: Hit[]; colorOverride?: string }
}) {
const { hits } = useGameProps()
return (
<>
{hits.map(({ hit, x, y }, i) => (
{(props?.hits ?? hits).map(({ hit, x, y }, i) => (
<div
key={i}
className="hit-svg"
style={{ "--x": x, "--y": y } as CSSProperties}
>
<FontAwesomeIcon icon={hit ? faBurst : faXmark} />
<FontAwesomeIcon
icon={hit ? faBurst : faXmark}
style={
{
color: props?.colorOverride || (hit ? "red" : undefined),
} as CSSProperties
}
/>
</div>
))}
</>

View file

@ -1,9 +1,10 @@
import { Field } from "../../interfaces/frontend"
import { count } from "./Gamefield"
import { fieldIndex } from "@lib/utils/helpers"
import classNames from "classnames"
import { CSSProperties } from "react"
function Labeling({ count }: { count: number }) {
function Labeling() {
let elems: (Field & {
orientation: string
})[] = []

View file

@ -1,32 +1,60 @@
import { ShipProps } from "../../interfaces/frontend"
import { useGameProps } from "@hooks/useGameProps"
import classNames from "classnames"
import React, { CSSProperties } from "react"
import React, { CSSProperties, useEffect, useRef } from "react"
const sizes: { [n: number]: number } = {
2: 96,
3: 144,
4: 196,
}
function Ship({
props: { size, variant, x, y },
props: { size, variant, x, y, orientation },
preview,
warn,
color,
}: {
props: ShipProps
preview?: boolean
warn?: boolean
color?: string
}) {
const { payload, removeShip } = useGameProps()
const filename = `ship_blue_${size}x_${variant}.gif`
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
const canvas = canvasRef.current
const ctx = canvas?.getContext("2d")
if (!canvas || !ctx) return
const gif = new Image()
gif.src = "/assets/" + filename
// Load the GIF and start rendering
gif.onload = function () {
// Set the canvas size to match the GIF dimensions
canvas.width = orientation === "h" ? sizes[size] : 48
canvas.height = orientation === "v" ? sizes[size] : 48
if (orientation === "v")
// Rotate the canvas by 90 degrees
ctx.rotate((90 * Math.PI) / 180)
// Draw the rotated GIF
ctx.drawImage(gif, 0, orientation === "h" ? 0 : -48, sizes[size], 48)
}
}, [filename, orientation, size, x, y])
return (
<div
className={classNames("ship", "s" + size, {
className={classNames("ship", "s" + size, orientation, {
preview: preview,
interactive: payload?.game?.state === "starting",
warn: warn,
})}
style={{ "--x": x, "--y": y } as CSSProperties}
onClick={() => {
if (payload?.game?.state !== "starting") return
removeShip({ size, variant, x, y })
useGameProps.setState({ mode: size - 2 })
}}
style={
{ "--x": x, "--y": y, "--color": color ?? "limegreen" } as CSSProperties
}
>
<img src={"/assets/" + filename} alt={filename} />
<canvas ref={canvasRef} />
</div>
)
}

View file

@ -1,7 +1,12 @@
import GamefieldPointer from "./GamefieldPointer"
import HitElems from "./HitElems"
import Ship from "./Ship"
import { useGameProps } from "@hooks/useGameProps"
import { composeTargetTiles, shipProps } from "@lib/utils/helpers"
import {
composeTargetTiles,
intersectingShip,
shipProps,
} from "@lib/utils/helpers"
function Targets() {
const { payload, target, targetPreview, mode, hits, ships } = useGameProps()
@ -20,8 +25,34 @@ function Targets() {
</>
)
if (payload?.game?.state === "starting" && mode >= 0 && targetPreview.show)
return <Ship preview props={shipProps(ships, mode, targetPreview)} />
if (payload?.game?.state === "starting" && mode >= 0 && targetPreview.show) {
const ship = shipProps(ships, mode, targetPreview)
const { fields, borders, score } = intersectingShip(ships, ship)
return (
<>
<Ship
preview
warn={score > 0}
color={fields.length ? "red" : borders.length ? "orange" : undefined}
key={targetPreview.orientation}
props={ship}
/>
<HitElems
props={{
hits: fields.map((e, i) => ({ ...e, i, hit: true })),
}}
/>
<HitElems
props={{
hits: borders.map((e, i) => ({ ...e, i, hit: true })),
colorOverride: "orange",
}}
/>
</>
)
}
return <></>
}
export default Targets

View file

@ -2,13 +2,19 @@ import {
ActionDispatchProps,
EventBarModes,
Hit,
MouseCursor,
ShipProps,
Target,
TargetPreview,
} from "../interfaces/frontend"
import { GameSettings } from "@components/Lobby/SettingsFrame/Setting"
import { getPayloadwithChecksum } from "@lib/getPayloadwithChecksum"
import { socket } from "@lib/socket"
import { initlialTarget, initlialTargetPreview } from "@lib/utils/helpers"
import {
initlialMouseCursor,
initlialTarget,
initlialTargetPreview,
} from "@lib/utils/helpers"
import {
GamePropsSchema,
optionalGamePropsSchema,
@ -30,7 +36,8 @@ const initialState: optionalGamePropsSchema & {
ships: ShipProps[]
hits: Hit[]
target: Target
targetPreview: Target
targetPreview: TargetPreview
mouseCursor: MouseCursor
} = {
menu: "actions",
mode: 0,
@ -40,6 +47,7 @@ const initialState: optionalGamePropsSchema & {
hits: [],
target: initlialTarget,
targetPreview: initlialTargetPreview,
mouseCursor: initlialMouseCursor,
userStates: Array.from(Array(2), () => ({
isReady: false,
isConnected: false,
@ -51,7 +59,8 @@ export type State = typeof initialState
export type Action = {
DispatchAction: (props: ActionDispatchProps) => void
setTarget: (target: SetStateAction<Target>) => void
setTargetPreview: (targetPreview: SetStateAction<Target>) => void
setTargetPreview: (targetPreview: SetStateAction<TargetPreview>) => void
setMouseCursor: (mouseCursor: SetStateAction<MouseCursor>) => void
setPlayer: (payload: { users: PlayerSchema[] }) => string | null
setSetting: (settings: GameSettings) => string | null
full: (newProps: GamePropsSchema) => void
@ -80,20 +89,28 @@ export const useGameProps = create<State & Action>()(
// }
})
),
setTarget: (target) =>
setTarget: (dispatch) =>
set(
produce((state: State) => {
if (typeof target === "function")
state.target = target(state.target)
else state.target = target
if (typeof dispatch === "function")
state.target = dispatch(state.target)
else state.target = dispatch
})
),
setTargetPreview: (targetPreview) =>
setTargetPreview: (dispatch) =>
set(
produce((state: State) => {
if (typeof targetPreview === "function")
state.targetPreview = targetPreview(state.target)
else state.targetPreview = targetPreview
if (typeof dispatch === "function")
state.targetPreview = dispatch(state.targetPreview)
else state.targetPreview = dispatch
})
),
setMouseCursor: (dispatch) =>
set(
produce((state: State) => {
if (typeof dispatch === "function")
state.mouseCursor = dispatch(state.mouseCursor)
else state.mouseCursor = dispatch
})
),
addShip: (props) =>

View file

@ -1,5 +1,5 @@
import { IconDefinition } from "@fortawesome/pro-solid-svg-icons"
import { MoveType } from "@prisma/client"
import { MoveType, Orientation } from "@prisma/client"
export interface Position {
x: number
@ -8,6 +8,9 @@ export interface Position {
export interface Target extends Position {
show: boolean
}
export interface TargetPreview extends Target {
orientation: Orientation
}
export interface MouseCursor extends Position {
shouldShow: boolean
}
@ -40,24 +43,23 @@ export interface Field extends Position {
export interface Hit extends Position {
hit: boolean
}
export interface Point extends Position {}
export interface DrawLineProps {
currentPoint: Point
prevPoint: Point | null
color: string
}
export interface Draw extends DrawLineProps {
ctx: CanvasRenderingContext2D
}
export interface ShipProps extends Position {
size: number
variant: number
orientation: Orientation
}
export interface IndexedPosition extends Position {
i?: number
}
export interface ActionDispatchProps extends Position {
index?: number
action: MoveType

View file

@ -1,14 +1,16 @@
import type {
Hit,
IndexedPosition,
Mode,
Position,
ShipProps,
Target,
TargetList,
TargetPreview,
} from "../../interfaces/frontend"
import { count } from "@components/Gamefield/Gamefield"
import { PointerProps } from "@components/Gamefield/GamefieldPointer"
import { useGameProps } from "@hooks/useGameProps"
import { Orientation } from "@prisma/client"
export function borderCN(count: number, x: number, y: number) {
if (x === 0) return "left"
@ -47,7 +49,7 @@ const modes: Mode[] = [
},
]
function isBorder(x: number, y: number, count: number) {
function isBorder(x: number, y: number) {
return x < 2 || x > count + 1 || y < 2 || y > count + 1
}
@ -86,8 +88,7 @@ export function targetList(
}
export function overlapsWithAnyBorder(target: Position, mode: number) {
return !!targetList(target, mode).filter(({ x, y }) => isBorder(x, y, count))
.length
return !!targetList(target, mode).filter(({ x, y }) => isBorder(x, y)).length
}
export function composeTargetTiles(
@ -107,16 +108,15 @@ export function composeTargetTiles(
}
export const initlialTarget = {
preview: false,
show: false,
x: 2,
y: 2,
show: false,
}
export const initlialTargetPreview = {
preview: true,
show: false,
x: 2,
y: 2,
show: false,
orientation: Orientation.h,
}
export const initlialMouseCursor = {
shouldShow: false,
@ -127,7 +127,7 @@ export const initlialMouseCursor = {
export const shipProps = (
ships: ShipProps[],
mode: number,
targetPreview: Target
targetPreview: Position & { orientation: Orientation }
) => ({
size: mode + 2,
variant:
@ -135,9 +135,83 @@ export const shipProps = (
.filter((e) => e.size === mode + 2)
.sort((a, b) => a.variant - b.variant)
.reduce((prev, curr) => {
console.log(curr.variant - prev)
return curr.variant - prev < 2 ? curr.variant : prev
}, 0) + 1,
x: targetPreview.x - Math.floor((mode + 2) / 2),
y: targetPreview.y,
x:
targetPreview.orientation === "h"
? targetPreview.x - Math.floor((mode + 2) / 2)
: targetPreview.x,
y:
targetPreview.orientation === "v"
? targetPreview.y - Math.floor((mode + 2) / 2)
: targetPreview.y,
orientation: targetPreview.orientation,
})
export function shipFields(ship: ShipProps, i?: number) {
let fields: IndexedPosition[] = []
let borders: IndexedPosition[] = []
for (
let x = ship.x;
x <= (ship.orientation === "h" ? ship.x + ship.size - 1 : ship.x);
x++
) {
for (
let y = ship.y;
y <= (ship.orientation === "v" ? ship.y + ship.size - 1 : ship.y);
y++
) {
fields.push({ x, y, i })
}
}
for (
let x = ship.x - 1;
x <= (ship.orientation === "h" ? ship.x + ship.size : ship.x + 1);
x++
) {
for (
let y = ship.y - 1;
y <= (ship.orientation === "v" ? ship.y + ship.size : ship.y + 1);
y++
) {
if (isBorder(x, y) || fields.filter((e) => e.x === x && e.y === y).length)
continue
borders.push({ x, y, i })
}
}
return { fields, borders }
}
export function intersectingShip(
ships: ShipProps[],
ship: ShipProps,
withBorder?: boolean
) {
const thisShip = shipFields(ship)
const reducedShips = ships.reduce(
(prev, curr, i) => {
const { fields, borders } = shipFields(curr, i)
return {
fields: [...prev.fields, ...fields],
borders: [...prev.borders, ...borders],
}
},
{ fields: [] as IndexedPosition[], borders: [] as IndexedPosition[] }
)
const fields = reducedShips.fields.filter(
(e) => thisShip.fields.filter((e2) => e2.x === e.x && e2.y === e.y).length
)
const borders = thisShip.fields.filter(
(e) =>
reducedShips.borders.filter((e2) => e2.x === e.x && e2.y === e.y).length
)
const isInBorder = thisShip.fields.filter(
(e) => withBorder && isBorder(e.x, e.y)
)
return {
score: isInBorder.length ? 2 : fields.length || borders.length ? 1 : 0,
index: fields[0]?.i,
fields,
borders,
}
}

View file

@ -1,5 +1,4 @@
import { ShipSchema } from "../prisma/generated/zod"
import { GameState } from "@prisma/client"
import { GameState, MoveType, Orientation } from "@prisma/client"
import { z } from "zod"
export const PlayerSchema = z
@ -19,7 +18,7 @@ export const PlayerSchema = z
.object({
id: z.string(),
index: z.number(),
action: z.string(),
action: z.nativeEnum(MoveType),
x: z.number(),
y: z.number(),
})
@ -45,6 +44,7 @@ export const CreateSchema = z.object({
variant: z.number(),
x: z.number(),
y: z.number(),
orientation: z.nativeEnum(Orientation),
})
.array(),
})

View file

@ -22,6 +22,7 @@ export const gameSelects = {
variant: true,
x: true,
y: true,
orientation: true,
},
},
gamePin: {
@ -48,6 +49,7 @@ export const gameSelects = {
action: true,
x: true,
y: true,
orientation: true,
},
},
user: {

View file

@ -18,11 +18,11 @@ export const GameScalarFieldEnumSchema = z.enum(['id','createdAt','updatedAt','s
export const GamepinScalarFieldEnumSchema = z.enum(['id','createdAt','pin','gameId']);
export const MoveScalarFieldEnumSchema = z.enum(['id','createdAt','index','action','x','y','user_game_id']);
export const MoveScalarFieldEnumSchema = z.enum(['id','createdAt','index','action','x','y','orientation','user_game_id']);
export const SessionScalarFieldEnumSchema = z.enum(['id','sessionToken','userId','expires']);
export const ShipScalarFieldEnumSchema = z.enum(['id','size','variant','x','y','gameId']);
export const ShipScalarFieldEnumSchema = z.enum(['id','size','variant','x','y','orientation','gameId']);
export const SortOrderSchema = z.enum(['asc','desc']);
@ -34,6 +34,10 @@ export const User_GameScalarFieldEnumSchema = z.enum(['id','createdAt','gameId',
export const VerificationTokenScalarFieldEnumSchema = z.enum(['identifier','token','expires']);
export const OrientationSchema = z.enum(['h','v']);
export type OrientationType = `${z.infer<typeof OrientationSchema>}`
export const GameStateSchema = z.enum(['lobby','starting','running','ended']);
export type GameStateType = `${z.infer<typeof GameStateSchema>}`
@ -116,6 +120,7 @@ export type VerificationToken = z.infer<typeof VerificationTokenSchema>
/////////////////////////////////////////
export const ShipSchema = z.object({
orientation: OrientationSchema,
id: z.string().cuid(),
size: z.number().int(),
variant: z.number().int(),
@ -176,6 +181,7 @@ export type User_Game = z.infer<typeof User_GameSchema>
export const MoveSchema = z.object({
action: MoveTypeSchema,
orientation: OrientationSchema,
id: z.string().cuid(),
createdAt: z.coerce.date(),
index: z.number().int(),
@ -321,6 +327,7 @@ export const ShipSelectSchema: z.ZodType<Prisma.ShipSelect> = z.object({
variant: z.boolean().optional(),
x: z.boolean().optional(),
y: z.boolean().optional(),
orientation: z.boolean().optional(),
gameId: z.boolean().optional(),
game: z.union([z.boolean(),z.lazy(() => GameArgsSchema)]).optional(),
}).strict()
@ -441,6 +448,7 @@ export const MoveSelectSchema: z.ZodType<Prisma.MoveSelect> = z.object({
action: z.boolean().optional(),
x: z.boolean().optional(),
y: z.boolean().optional(),
orientation: z.boolean().optional(),
user_game_id: z.boolean().optional(),
user_game: z.union([z.boolean(),z.lazy(() => User_GameArgsSchema)]).optional(),
}).strict()
@ -712,6 +720,7 @@ export const ShipWhereInputSchema: z.ZodType<Prisma.ShipWhereInput> = z.object({
variant: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
x: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
y: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
orientation: z.union([ z.lazy(() => EnumOrientationFilterSchema),z.lazy(() => OrientationSchema) ]).optional(),
gameId: z.union([ z.lazy(() => StringFilterSchema),z.string() ]).optional(),
game: z.union([ z.lazy(() => GameRelationFilterSchema),z.lazy(() => GameWhereInputSchema) ]).optional(),
}).strict();
@ -722,6 +731,7 @@ export const ShipOrderByWithRelationInputSchema: z.ZodType<Prisma.ShipOrderByWit
variant: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
gameId: z.lazy(() => SortOrderSchema).optional(),
game: z.lazy(() => GameOrderByWithRelationInputSchema).optional()
}).strict();
@ -736,6 +746,7 @@ export const ShipOrderByWithAggregationInputSchema: z.ZodType<Prisma.ShipOrderBy
variant: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
gameId: z.lazy(() => SortOrderSchema).optional(),
_count: z.lazy(() => ShipCountOrderByAggregateInputSchema).optional(),
_avg: z.lazy(() => ShipAvgOrderByAggregateInputSchema).optional(),
@ -753,6 +764,7 @@ export const ShipScalarWhereWithAggregatesInputSchema: z.ZodType<Prisma.ShipScal
variant: z.union([ z.lazy(() => IntWithAggregatesFilterSchema),z.number() ]).optional(),
x: z.union([ z.lazy(() => IntWithAggregatesFilterSchema),z.number() ]).optional(),
y: z.union([ z.lazy(() => IntWithAggregatesFilterSchema),z.number() ]).optional(),
orientation: z.union([ z.lazy(() => EnumOrientationWithAggregatesFilterSchema),z.lazy(() => OrientationSchema) ]).optional(),
gameId: z.union([ z.lazy(() => StringWithAggregatesFilterSchema),z.string() ]).optional(),
}).strict();
@ -931,6 +943,7 @@ export const MoveWhereInputSchema: z.ZodType<Prisma.MoveWhereInput> = z.object({
action: z.union([ z.lazy(() => EnumMoveTypeFilterSchema),z.lazy(() => MoveTypeSchema) ]).optional(),
x: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
y: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
orientation: z.union([ z.lazy(() => EnumOrientationFilterSchema),z.lazy(() => OrientationSchema) ]).optional(),
user_game_id: z.union([ z.lazy(() => StringFilterSchema),z.string() ]).optional(),
user_game: z.union([ z.lazy(() => User_GameRelationFilterSchema),z.lazy(() => User_GameWhereInputSchema) ]).optional(),
}).strict();
@ -942,6 +955,7 @@ export const MoveOrderByWithRelationInputSchema: z.ZodType<Prisma.MoveOrderByWit
action: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
user_game_id: z.lazy(() => SortOrderSchema).optional(),
user_game: z.lazy(() => User_GameOrderByWithRelationInputSchema).optional()
}).strict();
@ -959,6 +973,7 @@ export const MoveOrderByWithAggregationInputSchema: z.ZodType<Prisma.MoveOrderBy
action: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
user_game_id: z.lazy(() => SortOrderSchema).optional(),
_count: z.lazy(() => MoveCountOrderByAggregateInputSchema).optional(),
_avg: z.lazy(() => MoveAvgOrderByAggregateInputSchema).optional(),
@ -977,6 +992,7 @@ export const MoveScalarWhereWithAggregatesInputSchema: z.ZodType<Prisma.MoveScal
action: z.union([ z.lazy(() => EnumMoveTypeWithAggregatesFilterSchema),z.lazy(() => MoveTypeSchema) ]).optional(),
x: z.union([ z.lazy(() => IntWithAggregatesFilterSchema),z.number() ]).optional(),
y: z.union([ z.lazy(() => IntWithAggregatesFilterSchema),z.number() ]).optional(),
orientation: z.union([ z.lazy(() => EnumOrientationWithAggregatesFilterSchema),z.lazy(() => OrientationSchema) ]).optional(),
user_game_id: z.union([ z.lazy(() => StringWithAggregatesFilterSchema),z.string() ]).optional(),
}).strict();
@ -1330,6 +1346,7 @@ export const ShipCreateInputSchema: z.ZodType<Prisma.ShipCreateInput> = z.object
variant: z.number().int(),
x: z.number().int(),
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema),
game: z.lazy(() => GameCreateNestedOneWithoutShipsInputSchema)
}).strict();
@ -1339,6 +1356,7 @@ export const ShipUncheckedCreateInputSchema: z.ZodType<Prisma.ShipUncheckedCreat
variant: z.number().int(),
x: z.number().int(),
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema),
gameId: z.string()
}).strict();
@ -1348,6 +1366,7 @@ export const ShipUpdateInputSchema: z.ZodType<Prisma.ShipUpdateInput> = z.object
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
game: z.lazy(() => GameUpdateOneRequiredWithoutShipsNestedInputSchema).optional()
}).strict();
@ -1357,6 +1376,7 @@ export const ShipUncheckedUpdateInputSchema: z.ZodType<Prisma.ShipUncheckedUpdat
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
gameId: z.union([ z.string(),z.lazy(() => StringFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
@ -1366,6 +1386,7 @@ export const ShipCreateManyInputSchema: z.ZodType<Prisma.ShipCreateManyInput> =
variant: z.number().int(),
x: z.number().int(),
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema),
gameId: z.string()
}).strict();
@ -1375,6 +1396,7 @@ export const ShipUpdateManyMutationInputSchema: z.ZodType<Prisma.ShipUpdateManyM
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const ShipUncheckedUpdateManyInputSchema: z.ZodType<Prisma.ShipUncheckedUpdateManyInput> = z.object({
@ -1383,6 +1405,7 @@ export const ShipUncheckedUpdateManyInputSchema: z.ZodType<Prisma.ShipUncheckedU
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
gameId: z.union([ z.string(),z.lazy(() => StringFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
@ -1592,6 +1615,7 @@ export const MoveCreateInputSchema: z.ZodType<Prisma.MoveCreateInput> = z.object
action: z.lazy(() => MoveTypeSchema),
x: z.number().int(),
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema),
user_game: z.lazy(() => User_GameCreateNestedOneWithoutMovesInputSchema)
}).strict();
@ -1602,6 +1626,7 @@ export const MoveUncheckedCreateInputSchema: z.ZodType<Prisma.MoveUncheckedCreat
action: z.lazy(() => MoveTypeSchema),
x: z.number().int(),
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema),
user_game_id: z.string()
}).strict();
@ -1612,6 +1637,7 @@ export const MoveUpdateInputSchema: z.ZodType<Prisma.MoveUpdateInput> = z.object
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
user_game: z.lazy(() => User_GameUpdateOneRequiredWithoutMovesNestedInputSchema).optional()
}).strict();
@ -1622,6 +1648,7 @@ export const MoveUncheckedUpdateInputSchema: z.ZodType<Prisma.MoveUncheckedUpdat
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
user_game_id: z.union([ z.string(),z.lazy(() => StringFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
@ -1632,6 +1659,7 @@ export const MoveCreateManyInputSchema: z.ZodType<Prisma.MoveCreateManyInput> =
action: z.lazy(() => MoveTypeSchema),
x: z.number().int(),
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema),
user_game_id: z.string()
}).strict();
@ -1642,6 +1670,7 @@ export const MoveUpdateManyMutationInputSchema: z.ZodType<Prisma.MoveUpdateManyM
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const MoveUncheckedUpdateManyInputSchema: z.ZodType<Prisma.MoveUncheckedUpdateManyInput> = z.object({
@ -1651,6 +1680,7 @@ export const MoveUncheckedUpdateManyInputSchema: z.ZodType<Prisma.MoveUncheckedU
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
user_game_id: z.union([ z.string(),z.lazy(() => StringFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
@ -2037,6 +2067,13 @@ export const IntFilterSchema: z.ZodType<Prisma.IntFilter> = z.object({
not: z.union([ z.number(),z.lazy(() => NestedIntFilterSchema) ]).optional(),
}).strict();
export const EnumOrientationFilterSchema: z.ZodType<Prisma.EnumOrientationFilter> = z.object({
equals: z.lazy(() => OrientationSchema).optional(),
in: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
notIn: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
not: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => NestedEnumOrientationFilterSchema) ]).optional(),
}).strict();
export const GameRelationFilterSchema: z.ZodType<Prisma.GameRelationFilter> = z.object({
is: z.lazy(() => GameWhereInputSchema).optional(),
isNot: z.lazy(() => GameWhereInputSchema).optional()
@ -2048,6 +2085,7 @@ export const ShipCountOrderByAggregateInputSchema: z.ZodType<Prisma.ShipCountOrd
variant: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
gameId: z.lazy(() => SortOrderSchema).optional()
}).strict();
@ -2064,6 +2102,7 @@ export const ShipMaxOrderByAggregateInputSchema: z.ZodType<Prisma.ShipMaxOrderBy
variant: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
gameId: z.lazy(() => SortOrderSchema).optional()
}).strict();
@ -2073,6 +2112,7 @@ export const ShipMinOrderByAggregateInputSchema: z.ZodType<Prisma.ShipMinOrderBy
variant: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
gameId: z.lazy(() => SortOrderSchema).optional()
}).strict();
@ -2099,6 +2139,16 @@ export const IntWithAggregatesFilterSchema: z.ZodType<Prisma.IntWithAggregatesFi
_max: z.lazy(() => NestedIntFilterSchema).optional()
}).strict();
export const EnumOrientationWithAggregatesFilterSchema: z.ZodType<Prisma.EnumOrientationWithAggregatesFilter> = z.object({
equals: z.lazy(() => OrientationSchema).optional(),
in: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
notIn: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
not: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => NestedEnumOrientationWithAggregatesFilterSchema) ]).optional(),
_count: z.lazy(() => NestedIntFilterSchema).optional(),
_min: z.lazy(() => NestedEnumOrientationFilterSchema).optional(),
_max: z.lazy(() => NestedEnumOrientationFilterSchema).optional()
}).strict();
export const EnumGameStateFilterSchema: z.ZodType<Prisma.EnumGameStateFilter> = z.object({
equals: z.lazy(() => GameStateSchema).optional(),
in: z.union([ z.lazy(() => GameStateSchema).array(),z.lazy(() => GameStateSchema) ]).optional(),
@ -2290,6 +2340,7 @@ export const MoveCountOrderByAggregateInputSchema: z.ZodType<Prisma.MoveCountOrd
action: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
user_game_id: z.lazy(() => SortOrderSchema).optional()
}).strict();
@ -2306,6 +2357,7 @@ export const MoveMaxOrderByAggregateInputSchema: z.ZodType<Prisma.MoveMaxOrderBy
action: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
user_game_id: z.lazy(() => SortOrderSchema).optional()
}).strict();
@ -2316,6 +2368,7 @@ export const MoveMinOrderByAggregateInputSchema: z.ZodType<Prisma.MoveMinOrderBy
action: z.lazy(() => SortOrderSchema).optional(),
x: z.lazy(() => SortOrderSchema).optional(),
y: z.lazy(() => SortOrderSchema).optional(),
orientation: z.lazy(() => SortOrderSchema).optional(),
user_game_id: z.lazy(() => SortOrderSchema).optional()
}).strict();
@ -2551,6 +2604,10 @@ export const IntFieldUpdateOperationsInputSchema: z.ZodType<Prisma.IntFieldUpdat
divide: z.number().optional()
}).strict();
export const EnumOrientationFieldUpdateOperationsInputSchema: z.ZodType<Prisma.EnumOrientationFieldUpdateOperationsInput> = z.object({
set: z.lazy(() => OrientationSchema).optional()
}).strict();
export const GameUpdateOneRequiredWithoutShipsNestedInputSchema: z.ZodType<Prisma.GameUpdateOneRequiredWithoutShipsNestedInput> = z.object({
create: z.union([ z.lazy(() => GameCreateWithoutShipsInputSchema),z.lazy(() => GameUncheckedCreateWithoutShipsInputSchema) ]).optional(),
connectOrCreate: z.lazy(() => GameCreateOrConnectWithoutShipsInputSchema).optional(),
@ -3002,6 +3059,13 @@ export const NestedDateTimeNullableWithAggregatesFilterSchema: z.ZodType<Prisma.
_max: z.lazy(() => NestedDateTimeNullableFilterSchema).optional()
}).strict();
export const NestedEnumOrientationFilterSchema: z.ZodType<Prisma.NestedEnumOrientationFilter> = z.object({
equals: z.lazy(() => OrientationSchema).optional(),
in: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
notIn: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
not: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => NestedEnumOrientationFilterSchema) ]).optional(),
}).strict();
export const NestedIntWithAggregatesFilterSchema: z.ZodType<Prisma.NestedIntWithAggregatesFilter> = z.object({
equals: z.number().optional(),
in: z.union([ z.number().array(),z.number() ]).optional(),
@ -3029,6 +3093,16 @@ export const NestedFloatFilterSchema: z.ZodType<Prisma.NestedFloatFilter> = z.ob
not: z.union([ z.number(),z.lazy(() => NestedFloatFilterSchema) ]).optional(),
}).strict();
export const NestedEnumOrientationWithAggregatesFilterSchema: z.ZodType<Prisma.NestedEnumOrientationWithAggregatesFilter> = z.object({
equals: z.lazy(() => OrientationSchema).optional(),
in: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
notIn: z.union([ z.lazy(() => OrientationSchema).array(),z.lazy(() => OrientationSchema) ]).optional(),
not: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => NestedEnumOrientationWithAggregatesFilterSchema) ]).optional(),
_count: z.lazy(() => NestedIntFilterSchema).optional(),
_min: z.lazy(() => NestedEnumOrientationFilterSchema).optional(),
_max: z.lazy(() => NestedEnumOrientationFilterSchema).optional()
}).strict();
export const NestedEnumGameStateFilterSchema: z.ZodType<Prisma.NestedEnumGameStateFilter> = z.object({
equals: z.lazy(() => GameStateSchema).optional(),
in: z.union([ z.lazy(() => GameStateSchema).array(),z.lazy(() => GameStateSchema) ]).optional(),
@ -3443,7 +3517,8 @@ export const ShipCreateWithoutGameInputSchema: z.ZodType<Prisma.ShipCreateWithou
size: z.number().int(),
variant: z.number().int(),
x: z.number().int(),
y: z.number().int()
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema)
}).strict();
export const ShipUncheckedCreateWithoutGameInputSchema: z.ZodType<Prisma.ShipUncheckedCreateWithoutGameInput> = z.object({
@ -3451,7 +3526,8 @@ export const ShipUncheckedCreateWithoutGameInputSchema: z.ZodType<Prisma.ShipUnc
size: z.number().int(),
variant: z.number().int(),
x: z.number().int(),
y: z.number().int()
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema)
}).strict();
export const ShipCreateOrConnectWithoutGameInputSchema: z.ZodType<Prisma.ShipCreateOrConnectWithoutGameInput> = z.object({
@ -3534,6 +3610,7 @@ export const ShipScalarWhereInputSchema: z.ZodType<Prisma.ShipScalarWhereInput>
variant: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
x: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
y: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
orientation: z.union([ z.lazy(() => EnumOrientationFilterSchema),z.lazy(() => OrientationSchema) ]).optional(),
gameId: z.union([ z.lazy(() => StringFilterSchema),z.string() ]).optional(),
}).strict();
@ -3638,7 +3715,8 @@ export const MoveCreateWithoutUser_gameInputSchema: z.ZodType<Prisma.MoveCreateW
index: z.number().int(),
action: z.lazy(() => MoveTypeSchema),
x: z.number().int(),
y: z.number().int()
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema)
}).strict();
export const MoveUncheckedCreateWithoutUser_gameInputSchema: z.ZodType<Prisma.MoveUncheckedCreateWithoutUser_gameInput> = z.object({
@ -3647,7 +3725,8 @@ export const MoveUncheckedCreateWithoutUser_gameInputSchema: z.ZodType<Prisma.Mo
index: z.number().int(),
action: z.lazy(() => MoveTypeSchema),
x: z.number().int(),
y: z.number().int()
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema)
}).strict();
export const MoveCreateOrConnectWithoutUser_gameInputSchema: z.ZodType<Prisma.MoveCreateOrConnectWithoutUser_gameInput> = z.object({
@ -3770,6 +3849,7 @@ export const MoveScalarWhereInputSchema: z.ZodType<Prisma.MoveScalarWhereInput>
action: z.union([ z.lazy(() => EnumMoveTypeFilterSchema),z.lazy(() => MoveTypeSchema) ]).optional(),
x: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
y: z.union([ z.lazy(() => IntFilterSchema),z.number() ]).optional(),
orientation: z.union([ z.lazy(() => EnumOrientationFilterSchema),z.lazy(() => OrientationSchema) ]).optional(),
user_game_id: z.union([ z.lazy(() => StringFilterSchema),z.string() ]).optional(),
}).strict();
@ -4081,7 +4161,8 @@ export const ShipCreateManyGameInputSchema: z.ZodType<Prisma.ShipCreateManyGameI
size: z.number().int(),
variant: z.number().int(),
x: z.number().int(),
y: z.number().int()
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema)
}).strict();
export const User_GameCreateManyGameInputSchema: z.ZodType<Prisma.User_GameCreateManyGameInput> = z.object({
@ -4097,6 +4178,7 @@ export const ShipUpdateWithoutGameInputSchema: z.ZodType<Prisma.ShipUpdateWithou
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const ShipUncheckedUpdateWithoutGameInputSchema: z.ZodType<Prisma.ShipUncheckedUpdateWithoutGameInput> = z.object({
@ -4105,6 +4187,7 @@ export const ShipUncheckedUpdateWithoutGameInputSchema: z.ZodType<Prisma.ShipUnc
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const ShipUncheckedUpdateManyWithoutShipsInputSchema: z.ZodType<Prisma.ShipUncheckedUpdateManyWithoutShipsInput> = z.object({
@ -4113,6 +4196,7 @@ export const ShipUncheckedUpdateManyWithoutShipsInputSchema: z.ZodType<Prisma.Sh
variant: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const User_GameUpdateWithoutGameInputSchema: z.ZodType<Prisma.User_GameUpdateWithoutGameInput> = z.object({
@ -4146,7 +4230,8 @@ export const MoveCreateManyUser_gameInputSchema: z.ZodType<Prisma.MoveCreateMany
index: z.number().int(),
action: z.lazy(() => MoveTypeSchema),
x: z.number().int(),
y: z.number().int()
y: z.number().int(),
orientation: z.lazy(() => OrientationSchema)
}).strict();
export const ChatCreateManyUser_gameInputSchema: z.ZodType<Prisma.ChatCreateManyUser_gameInput> = z.object({
@ -4163,6 +4248,7 @@ export const MoveUpdateWithoutUser_gameInputSchema: z.ZodType<Prisma.MoveUpdateW
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const MoveUncheckedUpdateWithoutUser_gameInputSchema: z.ZodType<Prisma.MoveUncheckedUpdateWithoutUser_gameInput> = z.object({
@ -4172,6 +4258,7 @@ export const MoveUncheckedUpdateWithoutUser_gameInputSchema: z.ZodType<Prisma.Mo
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const MoveUncheckedUpdateManyWithoutMovesInputSchema: z.ZodType<Prisma.MoveUncheckedUpdateManyWithoutMovesInput> = z.object({
@ -4181,6 +4268,7 @@ export const MoveUncheckedUpdateManyWithoutMovesInputSchema: z.ZodType<Prisma.Mo
action: z.union([ z.lazy(() => MoveTypeSchema),z.lazy(() => EnumMoveTypeFieldUpdateOperationsInputSchema) ]).optional(),
x: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
y: z.union([ z.number().int(),z.lazy(() => IntFieldUpdateOperationsInputSchema) ]).optional(),
orientation: z.union([ z.lazy(() => OrientationSchema),z.lazy(() => EnumOrientationFieldUpdateOperationsInputSchema) ]).optional(),
}).strict();
export const ChatUpdateWithoutUser_gameInputSchema: z.ZodType<Prisma.ChatUpdateWithoutUser_gameInput> = z.object({

View file

@ -68,6 +68,22 @@ model VerificationToken {
@@map("verificationtokens")
}
enum Orientation {
h
v
}
model Ship {
id String @id @default(cuid())
size Int
variant Int
x Int
y Int
orientation Orientation
gameId String
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
}
enum GameState {
lobby
starting
@ -75,16 +91,6 @@ enum GameState {
ended
}
model Ship {
id String @id @default(cuid())
size Int
variant Int
x Int
y Int
gameId String
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
}
model Game {
id String @id @default(cuid())
createdAt DateTime @default(now())
@ -130,14 +136,15 @@ enum MoveType {
}
model Move {
id String @id @default(cuid())
createdAt DateTime @default(now())
id String @id @default(cuid())
createdAt DateTime @default(now())
index Int
action MoveType
x Int
y Int
orientation Orientation
user_game_id String
user_game User_Game @relation(fields: [user_game_id], references: [id], onDelete: Cascade)
user_game User_Game @relation(fields: [user_game_id], references: [id], onDelete: Cascade)
@@unique([user_game_id, index])
@@unique([action, x, y])

View file

@ -76,6 +76,8 @@ body {
> .label {
grid-column: var(--x);
grid-row: var(--y);
font-size: initial;
transform: scale(1.8);
}
> .border-tile {
@ -108,42 +110,63 @@ body {
position: relative;
@include flex-col;
align-items: center;
grid-row: var(--y);
justify-content: center;
pointer-events: none;
transform-origin: 24px 50%;
img {
canvas {
@include pixelart;
position: absolute;
// height: 90%;
width: 90%;
// object-fit: cover;
}
&.interactive:not(.preview) {
pointer-events: auto;
}
&.preview {
border: 2px dashed orange;
border-radius: 0.5rem;
animation: blink 0.5s ease-in-out alternate infinite;
@keyframes blink {
from {
opacity: 0.2;
outline: 3px dashed var(--color);
&.warn {
animation: blink 0.5s ease-in-out alternate-reverse infinite;
@keyframes blink {
from {
opacity: 0.2;
}
}
}
}
&.h {
grid-row: var(--y);
canvas {
width: 90%;
}
&.s2 {
grid-column: var(--x) / calc(var(--x) + 2);
&.s2 {
grid-column: var(--x) / calc(var(--x) + 2);
}
&.s3 {
grid-column: var(--x) / calc(var(--x) + 3);
}
&.s4 {
grid-column: var(--x) / calc(var(--x) + 4);
}
}
&.v {
grid-column: var(--x);
canvas {
height: 90%;
}
&.s3 {
grid-column: var(--x) / calc(var(--x) + 3);
}
&.s2 {
grid-row: var(--y) / calc(var(--y) + 2);
}
&.s4 {
grid-column: var(--x) / calc(var(--x) + 4);
&.s3 {
grid-row: var(--y) / calc(var(--y) + 3);
}
&.s4 {
grid-row: var(--y) / calc(var(--y) + 4);
}
}
}
@ -170,10 +193,6 @@ body {
box-sizing: border-box;
padding: 25%;
&.fa-burst {
color: red;
}
}
&.target {