From ea80456a567ec9f51cfb73db51406a6c6deb071e Mon Sep 17 00:00:00 2001 From: aronmal Date: Wed, 8 Feb 2023 10:31:03 +0100 Subject: [PATCH] Formatted all files with Prettier --- leaky-ships/.prettierrc.json | 2 +- leaky-ships/components/Bluetooth.tsx | 334 +++++----- leaky-ships/components/BorderTiles.tsx | 96 +-- leaky-ships/components/EventBar.tsx | 63 +- leaky-ships/components/FogImages.tsx | 10 +- leaky-ships/components/Gamefield.tsx | 66 +- leaky-ships/components/GamefieldPointer.tsx | 57 +- leaky-ships/components/Grid.tsx | 177 +++--- leaky-ships/components/Grid2.tsx | 188 +++--- leaky-ships/components/HitElems.tsx | 29 +- leaky-ships/components/Item.tsx | 47 +- leaky-ships/components/Labeling.tsx | 70 ++- leaky-ships/components/Ships.tsx | 46 +- leaky-ships/components/SocketIO.tsx | 60 +- leaky-ships/components/Targets.tsx | 40 +- leaky-ships/global.d.ts | 2 +- leaky-ships/interfaces/NextApiSocket.ts | 10 +- leaky-ships/interfaces/frontend.ts | 54 +- .../components/checkPasswordIsValid.ts | 37 +- .../backend/components/checkTokenIsValid.ts | 42 +- .../backend/components/createAnonymousDB.ts | 46 +- .../lib/backend/components/createPlayerDB.ts | 56 +- .../lib/backend/components/createTokenDB.ts | 58 +- .../lib/backend/components/getPlayerByIdDB.ts | 40 +- .../backend/components/getPlayerByNameDB.ts | 55 +- .../lib/backend/components/getTokenDB.ts | 82 +-- .../backend/components/getTokenFromBody.ts | 24 +- .../backend/components/getTokenFromCookie.ts | 24 +- .../lib/backend/components/loginCheck.ts | 26 +- .../lib/backend/components/sendError.ts | 14 +- .../lib/backend/components/sendResponse.ts | 24 +- leaky-ships/lib/backend/jwtVerifyCatch.ts | 43 +- leaky-ships/lib/backend/logging.ts | 78 +-- leaky-ships/lib/frontend/checkIsLoggedIn.ts | 30 +- leaky-ships/lib/frontend/getAccessToken.ts | 12 +- leaky-ships/lib/hooks/useGameEvent.ts | 328 ++++++---- leaky-ships/lib/prisma.ts | 18 +- leaky-ships/lib/utils/helpers.ts | 73 +-- leaky-ships/package.json | 2 +- leaky-ships/pages/_app.tsx | 12 +- leaky-ships/pages/_document.tsx | 2 +- leaky-ships/pages/api/auth.ts | 64 +- leaky-ships/pages/api/data.ts | 60 +- leaky-ships/pages/api/login.ts | 132 ++-- leaky-ships/pages/api/logout.ts | 52 +- leaky-ships/pages/api/register.ts | 48 +- leaky-ships/pages/api/ws.ts | 20 +- leaky-ships/pages/dev/gamefield.tsx | 4 +- leaky-ships/pages/dev/grid.tsx | 4 +- leaky-ships/pages/dev/grid2.tsx | 4 +- leaky-ships/pages/dev/index.tsx | 92 +-- leaky-ships/pages/dev/socket.tsx | 18 +- leaky-ships/pages/dev/socketio.tsx | 2 +- leaky-ships/pages/index.tsx | 40 +- leaky-ships/styles/App.scss | 32 +- leaky-ships/styles/globals.css | 2 +- leaky-ships/styles/grid.scss | 50 +- leaky-ships/styles/grid2.scss | 144 ++--- leaky-ships/styles/homepage.scss | 584 +++++++++--------- leaky-ships/styles/mixins/CP_Font.scss | 9 +- leaky-ships/styles/mixins/display.scss | 12 +- leaky-ships/styles/mixins/effects.scss | 192 ++++-- leaky-ships/styles/mixins/variables.scss | 4 +- leaky-ships/tailwind.config.js | 2 +- 64 files changed, 2209 insertions(+), 1839 deletions(-) diff --git a/leaky-ships/.prettierrc.json b/leaky-ships/.prettierrc.json index 5b746c7..cce9d3c 100644 --- a/leaky-ships/.prettierrc.json +++ b/leaky-ships/.prettierrc.json @@ -1,3 +1,3 @@ { - "semi": false + "semi": false } diff --git a/leaky-ships/components/Bluetooth.tsx b/leaky-ships/components/Bluetooth.tsx index a52aa4f..ac117db 100644 --- a/leaky-ships/components/Bluetooth.tsx +++ b/leaky-ships/components/Bluetooth.tsx @@ -1,175 +1,189 @@ import { useState } from "react" function Bluetooth() { - const [startDisabled, setStartDisabled] = useState(true) - const [stopDisabled, setStopDisabled] = useState(true) + const [startDisabled, setStartDisabled] = useState(true) + const [stopDisabled, setStopDisabled] = useState(true) - const deviceName = 'Chromecast Remote' - // ble UV Index - const bleService = 'environmental_sensing' - const bleCharacteristic = 'uv_index' + const deviceName = "Chromecast Remote" + // ble UV Index + const bleService = "environmental_sensing" + const bleCharacteristic = "uv_index" - // ble Battery percentage - // const bleService = 'battery_service' - // const bleCharacteristic = 'battery_level' + // ble Battery percentage + // const bleService = 'battery_service' + // const bleCharacteristic = 'battery_level' - // ble Manufacturer Name - // const bleService = 'device_information' - // const bleCharacteristic = 'manufacturer_name_string' - let bluetoothDeviceDetected: BluetoothDevice - let gattCharacteristic: BluetoothRemoteGATTCharacteristic + // ble Manufacturer Name + // const bleService = 'device_information' + // const bleCharacteristic = 'manufacturer_name_string' + let bluetoothDeviceDetected: BluetoothDevice + let gattCharacteristic: BluetoothRemoteGATTCharacteristic - function isWebBluetoothEnabled() { - if (!navigator.bluetooth) { - alert('Web Bluetooth API is not available in this browser!') - return false - } - return true + function isWebBluetoothEnabled() { + if (!navigator.bluetooth) { + alert("Web Bluetooth API is not available in this browser!") + return false } - function getDeviceInfo() { - const options = { - // acceptAllDevices: true, - filters: [ - { name: deviceName } - ], - // optionalServices: ['battery_service'], - } - - console.log('Requesting Bluetooth Device...') - - return navigator.bluetooth - .requestDevice(options) - .then(device => { - bluetoothDeviceDetected = device - console.log('> Name: ' + device.name) - device.addEventListener('gattserverdisconnected', onDisconnected) - }) - .catch(error => console.log('Argh! ' + error)) - } - function read() { - if (!isWebBluetoothEnabled()) - return - return getDeviceInfo() - .then(connectGatt) - .then(_ => { - console.log('Reading UV Index...') - return gattCharacteristic.readValue() - }) - .catch(error => console.log('Waiting to start reading: ' + error)) - } - function connectGatt() { - if (bluetoothDeviceDetected.gatt && bluetoothDeviceDetected.gatt.connected && gattCharacteristic) - return Promise.resolve() - if (!bluetoothDeviceDetected || !bluetoothDeviceDetected.gatt) - return Promise.reject() - return bluetoothDeviceDetected.gatt.connect() - .then(server => { - console.log('Getting GATT Service...') - return server.getPrimaryService(bleService) - }) - .then(service => { - console.log('Getting GATT Characteristic...') - return service.getCharacteristic(bleCharacteristic) - }) - .then(characteristic => { - gattCharacteristic = characteristic - characteristic.addEventListener('characteristicvaluechanged', handleChangedValue) - - setStartDisabled(false) - setStopDisabled(true) - }) - } - function handleChangedValue(event: Event) { - const characteristic = event.target as BluetoothRemoteGATTCharacteristic - if (!characteristic.value) { - console.log('Characteristic undefined!') - return - } - const value = characteristic.value.getUint8(0) - const now = new Date() - // Output the UV Index - console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} UV Index is ${value}`) - - // Output the Battery percentage - // console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Battery percentage is ${value}`) - - // Output the Manufacturer Name - // let decoder = new TextDecoder('utf-8') - // console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Manufacturer Name is ${decoder.decode(characteristic.value)}`) - } - function start() { - if (!isWebBluetoothEnabled()) - return - gattCharacteristic.startNotifications() - .then(_ => { - console.log('Start reading...') - setStartDisabled(true) - setStopDisabled(false) - }) - .catch(error => console.log('[ERROR] Start: ' + error)) - } - function stop() { - if (!isWebBluetoothEnabled()) - return - gattCharacteristic.stopNotifications() - .then(_ => { - console.log('Stop reading...') - setStartDisabled(false) - setStopDisabled(true) - }) - .catch(error => console.log('[ERROR] Stop: ' + error)) - } - function onDisconnected(event: Event) { - alert("Device Disconnected") - // console.log(event) - const device = event.target as BluetoothDevice - console.log(`Device "${device.name}" is disconnected.`) + return true + } + function getDeviceInfo() { + const options = { + // acceptAllDevices: true, + filters: [{ name: deviceName }], + // optionalServices: ['battery_service'], } - return ( -
- - - -

- { navigator.clipboard.writeText("chrome://flags/#enable-experimental-web-platform-features") }} - // target="_blank" - style={{ "cursor": "pointer" }} - // rel="noopener noreferrer" - > - Step 1 - - {" "} - { navigator.clipboard.writeText("chrome://flags/#enable-web-bluetooth-new-permissions-backend") }} - // target="_blank" - style={{ "cursor": "pointer" }} - // rel="noopener noreferrer" + console.log("Requesting Bluetooth Device...") - > - Step 2 - -

-
+ return navigator.bluetooth + .requestDevice(options) + .then((device) => { + bluetoothDeviceDetected = device + console.log("> Name: " + device.name) + device.addEventListener("gattserverdisconnected", onDisconnected) + }) + .catch((error) => console.log("Argh! " + error)) + } + function read() { + if (!isWebBluetoothEnabled()) return + return getDeviceInfo() + .then(connectGatt) + .then((_) => { + console.log("Reading UV Index...") + return gattCharacteristic.readValue() + }) + .catch((error) => console.log("Waiting to start reading: " + error)) + } + function connectGatt() { + if ( + bluetoothDeviceDetected.gatt && + bluetoothDeviceDetected.gatt.connected && + gattCharacteristic + ) + return Promise.resolve() + if (!bluetoothDeviceDetected || !bluetoothDeviceDetected.gatt) + return Promise.reject() + return bluetoothDeviceDetected.gatt + .connect() + .then((server) => { + console.log("Getting GATT Service...") + return server.getPrimaryService(bleService) + }) + .then((service) => { + console.log("Getting GATT Characteristic...") + return service.getCharacteristic(bleCharacteristic) + }) + .then((characteristic) => { + gattCharacteristic = characteristic + characteristic.addEventListener( + "characteristicvaluechanged", + handleChangedValue + ) + + setStartDisabled(false) + setStopDisabled(true) + }) + } + function handleChangedValue(event: Event) { + const characteristic = event.target as BluetoothRemoteGATTCharacteristic + if (!characteristic.value) { + console.log("Characteristic undefined!") + return + } + const value = characteristic.value.getUint8(0) + const now = new Date() + // Output the UV Index + console.log( + `> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} UV Index is ${value}` ) + // Output the Battery percentage + // console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Battery percentage is ${value}`) + + // Output the Manufacturer Name + // let decoder = new TextDecoder('utf-8') + // console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Manufacturer Name is ${decoder.decode(characteristic.value)}`) + } + function start() { + if (!isWebBluetoothEnabled()) return + gattCharacteristic + .startNotifications() + .then((_) => { + console.log("Start reading...") + setStartDisabled(true) + setStopDisabled(false) + }) + .catch((error) => console.log("[ERROR] Start: " + error)) + } + function stop() { + if (!isWebBluetoothEnabled()) return + gattCharacteristic + .stopNotifications() + .then((_) => { + console.log("Stop reading...") + setStartDisabled(false) + setStopDisabled(true) + }) + .catch((error) => console.log("[ERROR] Stop: " + error)) + } + function onDisconnected(event: Event) { + alert("Device Disconnected") + // console.log(event) + const device = event.target as BluetoothDevice + console.log(`Device "${device.name}" is disconnected.`) + } + + return ( +
+ + + +

+ { + navigator.clipboard.writeText( + "chrome://flags/#enable-experimental-web-platform-features" + ) + }} + // target="_blank" + style={{ cursor: "pointer" }} + // rel="noopener noreferrer" + > + Step 1 + {" "} + { + navigator.clipboard.writeText( + "chrome://flags/#enable-web-bluetooth-new-permissions-backend" + ) + }} + // target="_blank" + style={{ cursor: "pointer" }} + // rel="noopener noreferrer" + > + Step 2 + +

+
+ ) } -export default Bluetooth \ No newline at end of file +export default Bluetooth diff --git a/leaky-ships/components/BorderTiles.tsx b/leaky-ships/components/BorderTiles.tsx index 580eb45..eef503b 100644 --- a/leaky-ships/components/BorderTiles.tsx +++ b/leaky-ships/components/BorderTiles.tsx @@ -1,53 +1,65 @@ -import { CSSProperties, Dispatch, SetStateAction } from 'react' -import { borderCN, cornerCN, fieldIndex } from '../lib/utils/helpers' -import { Position, MouseCursor } from '../interfaces/frontend' +import { CSSProperties, Dispatch, SetStateAction } from "react" +import { borderCN, cornerCN, fieldIndex } from "../lib/utils/helpers" +import { Position, MouseCursor } from "../interfaces/frontend" type TilesType = { - key: number, - isGameTile: boolean, - classNameString: string, - x: number, - y: number + key: number + isGameTile: boolean + classNameString: string + x: number + y: number } -function BorderTiles({ props: { count, settingTarget, setMouseCursor, setLastLeftTile } }: { - props: { - count: number, - settingTarget: (isGameTile: boolean, x: number, y: number) => void, - setMouseCursor: Dispatch>, - setLastLeftTile: Dispatch> - } +function BorderTiles({ + props: { count, settingTarget, setMouseCursor, setLastLeftTile }, +}: { + props: { + count: number + settingTarget: (isGameTile: boolean, x: number, y: number) => void + setMouseCursor: Dispatch> + setLastLeftTile: Dispatch> + } }) { - let tilesProperties: TilesType[] = [] + let tilesProperties: TilesType[] = [] - for (let y = 0; y < count + 2; y++) { - for (let x = 0; x < count + 2; x++) { - const key = fieldIndex(count, x, y) - const cornerReslt = cornerCN(count, x, y) - const borderType = cornerReslt ? cornerReslt : borderCN(count, x, y) - const isGameTile = x > 0 && x < count + 1 && y > 0 && y < count + 1 - const classNames = ['border-tile'] - if (borderType) - classNames.push('edge', borderType) - if (isGameTile) - classNames.push('game-tile') - const classNameString = classNames.join(' ') - tilesProperties.push({ key, classNameString, isGameTile, x: x + 1, y: y + 1 }) - } + for (let y = 0; y < count + 2; y++) { + for (let x = 0; x < count + 2; x++) { + const key = fieldIndex(count, x, y) + const cornerReslt = cornerCN(count, x, y) + const borderType = cornerReslt ? cornerReslt : borderCN(count, x, y) + const isGameTile = x > 0 && x < count + 1 && y > 0 && y < count + 1 + const classNames = ["border-tile"] + if (borderType) classNames.push("edge", borderType) + if (isGameTile) classNames.push("game-tile") + const classNameString = classNames.join(" ") + tilesProperties.push({ + key, + classNameString, + isGameTile, + x: x + 1, + y: y + 1, + }) } + } - return (<> - {tilesProperties.map(({ key, classNameString, isGameTile, x, y }) => { - return
settingTarget(isGameTile, x, y)} - onMouseEnter={() => setMouseCursor({ x, y, shouldShow: isGameTile })} - onMouseLeave={() => setLastLeftTile({ x, y })} - >
- })} - ) + return ( + <> + {tilesProperties.map(({ key, classNameString, isGameTile, x, y }) => { + return ( +
settingTarget(isGameTile, x, y)} + onMouseEnter={() => + setMouseCursor({ x, y, shouldShow: isGameTile }) + } + onMouseLeave={() => setLastLeftTile({ x, y })} + >
+ ) + })} + + ) } export default BorderTiles diff --git a/leaky-ships/components/EventBar.tsx b/leaky-ships/components/EventBar.tsx index 5b55bda..cdb1353 100644 --- a/leaky-ships/components/EventBar.tsx +++ b/leaky-ships/components/EventBar.tsx @@ -1,33 +1,38 @@ -import React, { Dispatch, SetStateAction } from 'react' -import { Items, Target } from '../interfaces/frontend' -import Item from './Item' +import React, { Dispatch, SetStateAction } from "react" +import { Items, Target } from "../interfaces/frontend" +import Item from "./Item" -function EventBar({ props: { setMode, setTarget } }: { - props: { - setMode: Dispatch>, - setTarget: Dispatch> - } +function EventBar({ + props: { setMode, setTarget }, +}: { + props: { + setMode: Dispatch> + setTarget: Dispatch> + } }) { - const items: Items[] = [ - { icon: 'burger-menu', text: 'Menu' }, - { icon: 'radar', text: 'Radar scan', mode: 0, amount: 1 }, - { icon: 'torpedo', text: 'Fire torpedo', mode: 1, amount: 1 }, - { icon: 'scope', text: 'Fire missile', mode: 2 }, - { icon: 'gear', text: 'Settings' } - ] - return ( -
- {items.map((e, i) => ( - { - if (e.mode !== undefined) - setMode(e.mode) - setTarget(e => ({ ...e, show: false })) - } - }} /> - ))} -
- ) + const items: Items[] = [ + { icon: "burger-menu", text: "Menu" }, + { icon: "radar", text: "Radar scan", mode: 0, amount: 1 }, + { icon: "torpedo", text: "Fire torpedo", mode: 1, amount: 1 }, + { icon: "scope", text: "Fire missile", mode: 2 }, + { icon: "gear", text: "Settings" }, + ] + return ( +
+ {items.map((e, i) => ( + { + if (e.mode !== undefined) setMode(e.mode) + setTarget((e) => ({ ...e, show: false })) + }, + }} + /> + ))} +
+ ) } -export default EventBar \ No newline at end of file +export default EventBar diff --git a/leaky-ships/components/FogImages.tsx b/leaky-ships/components/FogImages.tsx index 9d75c1b..06ba202 100644 --- a/leaky-ships/components/FogImages.tsx +++ b/leaky-ships/components/FogImages.tsx @@ -1,11 +1,13 @@ import Image from "next/image" function FogImages() { - return <> - {`fog1.png`} - {`fog1.png`} - {`fog4.png`} + return ( + <> + {`fog1.png`} + {`fog1.png`} + {`fog4.png`} + ) } export default FogImages diff --git a/leaky-ships/components/Gamefield.tsx b/leaky-ships/components/Gamefield.tsx index 8f0b65f..8a9b630 100644 --- a/leaky-ships/components/Gamefield.tsx +++ b/leaky-ships/components/Gamefield.tsx @@ -1,47 +1,41 @@ -import { CSSProperties } from 'react' +import { CSSProperties } from "react" // import Bluetooth from './Bluetooth' -import BorderTiles from './BorderTiles' -import EventBar from './EventBar' +import BorderTiles from "./BorderTiles" +import EventBar from "./EventBar" // import FogImages from './FogImages' -import HitElems from './HitElems' -import Labeling from './Labeling' -import Ships from './Ships' -import useGameEvent from '../lib/hooks/useGameEvent' -import Targets from './Targets' +import HitElems from "./HitElems" +import Labeling from "./Labeling" +import Ships from "./Ships" +import useGameEvent from "../lib/hooks/useGameEvent" +import Targets from "./Targets" function Gamefield() { + const count = 12 + const { pointersProps, targetsProps, tilesProps, hits } = useGameEvent(count) - const count = 12 - const { - pointersProps, - targetsProps, - tilesProps, - hits - } = useGameEvent(count) + return ( +
+ {/* */} +
+ {/* Bordes */} + - return ( -
- {/* */} -
- {/* Bordes */} - + {/* Collumn lettes and row numbers */} + - {/* Collumn lettes and row numbers */} - + {/* Ships */} + - {/* Ships */} - + - - - {/* Fog images */} - {/* */} - - {/* Debug */} -
- -
- ) + {/* Fog images */} + {/* */} + + {/* Debug */} +
+ +
+ ) } -export default Gamefield \ No newline at end of file +export default Gamefield diff --git a/leaky-ships/components/GamefieldPointer.tsx b/leaky-ships/components/GamefieldPointer.tsx index 9222d8e..c90cc9e 100644 --- a/leaky-ships/components/GamefieldPointer.tsx +++ b/leaky-ships/components/GamefieldPointer.tsx @@ -1,30 +1,39 @@ -import { faCrosshairs } from '@fortawesome/pro-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { CSSProperties } from 'react' -import classNames from 'classnames' -import { faRadar } from '@fortawesome/pro-thin-svg-icons' -import { Target, TargetList } from '../interfaces/frontend' +import { faCrosshairs } from "@fortawesome/pro-solid-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { CSSProperties } from "react" +import classNames from "classnames" +import { faRadar } from "@fortawesome/pro-thin-svg-icons" +import { Target, TargetList } from "../interfaces/frontend" export interface PointerProps extends Target, TargetList { - imply: boolean; + imply: boolean } -function GamefieldPointer({ props: { - preview, - x, - y, - show, - type, - edges, - imply -} }: { props: PointerProps }) { - const isRadar = type === 'radar' - const style = !(isRadar && !edges.filter(s => s).length) ? { '--x': x, '--y': y } : { '--x1': x - 1, '--x2': x + 2, '--y1': y - 1, '--y2': y + 2 } - return ( -
- -
- ) +function GamefieldPointer({ + props: { preview, x, y, show, type, edges, imply }, +}: { + props: PointerProps +}) { + const isRadar = type === "radar" + const style = !(isRadar && !edges.filter((s) => s).length) + ? { "--x": x, "--y": y } + : { "--x1": x - 1, "--x2": x + 2, "--y1": y - 1, "--y2": y + 2 } + return ( +
+ +
+ ) } -export default GamefieldPointer \ No newline at end of file +export default GamefieldPointer diff --git a/leaky-ships/components/Grid.tsx b/leaky-ships/components/Grid.tsx index 3d5dde4..e39e9fc 100644 --- a/leaky-ships/components/Grid.tsx +++ b/leaky-ships/components/Grid.tsx @@ -1,95 +1,112 @@ -import classNames from 'classnames' -import { CSSProperties, useEffect, useMemo, useState } from 'react' +import classNames from "classnames" +import { CSSProperties, useEffect, useMemo, useState } from "react" function Grid() { + function floorClient(number: number) { + return Math.floor(number / 50) + } - function floorClient(number: number) { - return Math.floor(number / 50) + const [columns, setColumns] = useState(0) + const [rows, setRows] = useState(0) + const [params, setParams] = useState({ + columns, + rows, + quantity: columns * rows, + }) + const [position, setPosition] = useState([0, 0]) + const [active, setActve] = useState(false) + const [count, setCount] = useState(0) + + useEffect(() => { + function handleResize() { + setColumns(floorClient(document.body.clientWidth)) + setRows(floorClient(document.body.clientHeight)) } + handleResize() + window.addEventListener("resize", handleResize) + }, []) - const [columns, setColumns] = useState(0) - const [rows, setRows] = useState(0) - const [params, setParams] = useState({ columns, rows, quantity: columns * rows }) - const [position, setPosition] = useState([0, 0]) - const [active, setActve] = useState(false) - const [count, setCount] = useState(0) + useEffect(() => { + const timeout = setTimeout(() => { + setParams({ columns, rows, quantity: columns * rows }) + }, 500) + return () => clearTimeout(timeout) + }, [columns, rows]) - useEffect(() => { - function handleResize() { - setColumns(floorClient(document.body.clientWidth)) - setRows(floorClient(document.body.clientHeight)) + const createTiles = useMemo(() => { + const colors = [ + "rgb(229, 57, 53)", + "rgb(253, 216, 53)", + "rgb(244, 81, 30)", + "rgb(76, 175, 80)", + "rgb(33, 150, 243)", + "rgb(156, 39, 176)", + ] + + function createTile(index: number) { + const x = index % params.columns + const y = Math.floor(index / params.columns) + const xDiff = (x - position[0]) / 20 + const yDiff = (y - position[1]) / 20 + const pos = Math.sqrt(xDiff * xDiff + yDiff * yDiff).toFixed(2) + + function doEffect(posX: number, posY: number) { + if (active) return + setPosition([posX, posY]) + setActve(true) + + function xDiff(x: number) { + return (x - posX) / 20 } - handleResize() - window.addEventListener('resize', handleResize) - }, []) - - useEffect(() => { - const timeout = setTimeout(() => { - setParams({ columns, rows, quantity: columns * rows }) - }, 500) - return () => clearTimeout(timeout) - }, [columns, rows]) - - const createTiles = useMemo(() => { - - const colors = [ - 'rgb(229, 57, 53)', - 'rgb(253, 216, 53)', - 'rgb(244, 81, 30)', - 'rgb(76, 175, 80)', - 'rgb(33, 150, 243)', - 'rgb(156, 39, 176)' + function yDiff(y: number) { + return (y - posY) / 20 + } + function pos(x: number, y: number) { + return Math.sqrt(xDiff(x) * xDiff(x) + yDiff(y) * yDiff(y)) + } + const diagonals = [ + pos(0, 0), + pos(params.columns, 0), + pos(0, params.rows), + pos(params.columns, params.rows), ] - function createTile(index: number) { + setTimeout(() => { + setActve(false) + setCount((e) => e + 1) + }, Math.max(...diagonals) * 1000 + 300) + } - const x = index % params.columns - const y = Math.floor(index / params.columns) - const xDiff = (x - position[0]) / 20 - const yDiff = (y - position[1]) / 20 - const pos = (Math.sqrt(xDiff * xDiff + yDiff * yDiff)).toFixed(2) + return ( +
doEffect(x, y)} + >
+ ) + } - function doEffect(posX: number, posY: number) { - if (active) - return - setPosition([posX, posY]) - setActve(true) - - function xDiff(x: number) { - return (x - posX) / 20 - } - function yDiff(y: number) { - return (y - posY) / 20 - } - function pos(x: number, y: number) { - return Math.sqrt(xDiff(x) * xDiff(x) + yDiff(y) * yDiff(y)) - } - const diagonals = [pos(0, 0), pos(params.columns, 0), pos(0, params.rows), pos(params.columns, params.rows)] - - setTimeout(() => { - setActve(false) - setCount(e => e + 1) - }, Math.max(...diagonals) * 1000 + 300) - } - - return ( -
doEffect(x, y)} - >
- ) + return ( +
+ {Array.from(Array(params.quantity), (_tile, index) => + createTile(index) + )} +
+ ) + }, [params, position, active, count]) - return ( -
- {Array.from(Array(params.quantity), (_tile, index) => createTile(index))} -
- ) - }, [params, position, active, count]) - - return createTiles + return createTiles } -export default Grid \ No newline at end of file +export default Grid diff --git a/leaky-ships/components/Grid2.tsx b/leaky-ships/components/Grid2.tsx index 54a1dd6..7dda33c 100644 --- a/leaky-ships/components/Grid2.tsx +++ b/leaky-ships/components/Grid2.tsx @@ -1,100 +1,118 @@ -import classNames from 'classnames' -import { CSSProperties, useEffect, useMemo, useState } from 'react' +import classNames from "classnames" +import { CSSProperties, useEffect, useMemo, useState } from "react" function Grid2() { + function floorClient(number: number) { + return Math.floor(number / 50) + } - function floorClient(number: number) { - return Math.floor(number / 50) + const [columns, setColumns] = useState(0) + const [rows, setRows] = useState(0) + const [params, setParams] = useState({ + columns, + rows, + quantity: columns * rows, + }) + const [position, setPosition] = useState([0, 0]) + const [active, setActve] = useState(false) + const [action, setAction] = useState(false) + const [count, setCount] = useState(0) + + useEffect(() => { + function handleResize() { + setColumns(floorClient(document.body.clientWidth)) + setRows(floorClient(document.body.clientHeight)) } + handleResize() + window.addEventListener("resize", handleResize) + }, []) - const [columns, setColumns] = useState(0) - const [rows, setRows] = useState(0) - const [params, setParams] = useState({ columns, rows, quantity: columns * rows }) - const [position, setPosition] = useState([0, 0]) - const [active, setActve] = useState(false) - const [action, setAction] = useState(false) - const [count, setCount] = useState(0) + useEffect(() => { + const timeout = setTimeout(() => { + setParams({ columns, rows, quantity: columns * rows }) + }, 500) + return () => clearTimeout(timeout) + }, [columns, rows]) - useEffect(() => { - function handleResize() { - setColumns(floorClient(document.body.clientWidth)) - setRows(floorClient(document.body.clientHeight)) + const createTiles = useMemo(() => { + const sentences = [ + "Ethem ...", + "hat ...", + "lange ...", + "Hörner 🐂", + "Grüße von Mallorca 🌊 🦦 ☀️", + ] + + function createTile(index: number) { + const x = index % params.columns + const y = Math.floor(index / params.columns) + const xDiff = (x - position[0]) / 20 + const yDiff = (y - position[1]) / 20 + const pos = Math.sqrt(xDiff * xDiff + yDiff * yDiff).toFixed(2) + + function doEffect(posX: number, posY: number) { + if (action) return + setPosition([posX, posY]) + setActve((e) => !e) + setAction(true) + + function xDiff(x: number) { + return (x - posX) / 20 } - handleResize() - window.addEventListener('resize', handleResize) - }, []) - - useEffect(() => { - const timeout = setTimeout(() => { - setParams({ columns, rows, quantity: columns * rows }) - }, 500) - return () => clearTimeout(timeout) - }, [columns, rows]) - - const createTiles = useMemo(() => { - - const sentences = [ - 'Ethem ...', - 'hat ...', - 'lange ...', - 'Hörner 🐂', - 'Grüße von Mallorca 🌊 🦦 ☀️' + function yDiff(y: number) { + return (y - posY) / 20 + } + function pos(x: number, y: number) { + return Math.sqrt(xDiff(x) * xDiff(x) + yDiff(y) * yDiff(y)) + } + const diagonals = [ + pos(0, 0), + pos(params.columns, 0), + pos(0, params.rows), + pos(params.columns, params.rows), ] - function createTile(index: number) { + setTimeout(() => { + setAction(false) + if (active) setCount((e) => e + 1) + }, Math.max(...diagonals) * 1000 + 1000) + } - const x = index % params.columns - const y = Math.floor(index / params.columns) - const xDiff = (x - position[0]) / 20 - const yDiff = (y - position[1]) / 20 - const pos = (Math.sqrt(xDiff * xDiff + yDiff * yDiff)).toFixed(2) + return ( +
doEffect(x, y)} + >
+ ) + } - function doEffect(posX: number, posY: number) { - if (action) - return - setPosition([posX, posY]) - setActve(e => !e) - setAction(true) - - function xDiff(x: number) { - return (x - posX) / 20 - } - function yDiff(y: number) { - return (y - posY) / 20 - } - function pos(x: number, y: number) { - return Math.sqrt(xDiff(x) * xDiff(x) + yDiff(y) * yDiff(y)) - } - const diagonals = [pos(0, 0), pos(params.columns, 0), pos(0, params.rows), pos(params.columns, params.rows)] - - setTimeout(() => { - setAction(false) - if (active) - setCount(e => e + 1) - }, Math.max(...diagonals) * 1000 + 1000) - } - - return ( -
doEffect(x, y)} - >
- ) + return ( +
+
+

+ {sentences[count % sentences.length]} +

+
+ {Array.from(Array(params.quantity), (_tile, index) => + createTile(index) + )} +
+ ) + }, [params, position, active, action, count]) - return ( -
-
-

{sentences[count % sentences.length]}

-
- {Array.from(Array(params.quantity), (_tile, index) => createTile(index))} -
- ) - }, [params, position, active, action, count]) - - return createTiles + return createTiles } -export default Grid2 \ No newline at end of file +export default Grid2 diff --git a/leaky-ships/components/HitElems.tsx b/leaky-ships/components/HitElems.tsx index a657da5..0a39749 100644 --- a/leaky-ships/components/HitElems.tsx +++ b/leaky-ships/components/HitElems.tsx @@ -1,17 +1,22 @@ -import { faBurst, faXmark } from '@fortawesome/pro-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { CSSProperties } from 'react' -import { Hit } from '../interfaces/frontend' +import { faBurst, faXmark } from "@fortawesome/pro-solid-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { CSSProperties } from "react" +import { Hit } from "../interfaces/frontend" -function HitElems({hits}: {hits: Hit[]}) { - - return <> - {hits.map(({hit, x, y}, i) => -
- -
- )} +function HitElems({ hits }: { hits: Hit[] }) { + return ( + <> + {hits.map(({ hit, x, y }, i) => ( +
+ +
+ ))} + ) } export default HitElems diff --git a/leaky-ships/components/Item.tsx b/leaky-ships/components/Item.tsx index 9218365..13b7cb3 100644 --- a/leaky-ships/components/Item.tsx +++ b/leaky-ships/components/Item.tsx @@ -1,22 +1,33 @@ -import classNames from 'classnames' -import React, { CSSProperties } from 'react' +import classNames from "classnames" +import React, { CSSProperties } from "react" -function Item({ props: { icon, text, amount, callback } }: { - props: { - icon: string, - text: string, - amount?: number, - callback: () => void - } +function Item({ + props: { icon, text, amount, callback }, +}: { + props: { + icon: string + text: string + amount?: number + callback: () => void + } }) { - return ( -
-
- {`${icon}.png`} -
- {text} -
- ) + return ( +
+
+ {`${icon}.png`} +
+ {text} +
+ ) } -export default Item \ No newline at end of file +export default Item diff --git a/leaky-ships/components/Labeling.tsx b/leaky-ships/components/Labeling.tsx index 7c093de..6244ed5 100644 --- a/leaky-ships/components/Labeling.tsx +++ b/leaky-ships/components/Labeling.tsx @@ -1,30 +1,50 @@ -import classNames from 'classnames' -import { CSSProperties } from 'react' -import { fieldIndex } from '../lib/utils/helpers' -import { Field } from '../interfaces/frontend' +import classNames from "classnames" +import { CSSProperties } from "react" +import { fieldIndex } from "../lib/utils/helpers" +import { Field } from "../interfaces/frontend" -function Labeling({count}: {count: number}) { - let elems: (Field & { - orientation: string - })[] = [] - for (let x = 0; x < count; x++) { - elems.push( - // Up - {field: String.fromCharCode(65+x), x: x+2, y: 1, orientation: 'up'}, - // Left - {field: (x+1).toString(), x: 1, y: x+2, orientation: 'left'}, - // Bottom - {field: String.fromCharCode(65+x), x: x+2, y: count+2, orientation: 'bottom'}, - // Right - {field: (x+1).toString(), x: count+2, y: x+2, orientation: 'right'} - ) - } - elems = elems.sort((a, b) => fieldIndex(count, a.x, a.y)-fieldIndex(count, b.x, b.y)) - return <> - {elems.map(({field, x, y, orientation}, i) => - {field} - )} +function Labeling({ count }: { count: number }) { + let elems: (Field & { + orientation: string + })[] = [] + for (let x = 0; x < count; x++) { + elems.push( + // Up + { field: String.fromCharCode(65 + x), x: x + 2, y: 1, orientation: "up" }, + // Left + { field: (x + 1).toString(), x: 1, y: x + 2, orientation: "left" }, + // Bottom + { + field: String.fromCharCode(65 + x), + x: x + 2, + y: count + 2, + orientation: "bottom", + }, + // Right + { + field: (x + 1).toString(), + x: count + 2, + y: x + 2, + orientation: "right", + } + ) + } + elems = elems.sort( + (a, b) => fieldIndex(count, a.x, a.y) - fieldIndex(count, b.x, b.y) + ) + return ( + <> + {elems.map(({ field, x, y, orientation }, i) => ( + + {field} + + ))} + ) } export default Labeling diff --git a/leaky-ships/components/Ships.tsx b/leaky-ships/components/Ships.tsx index a9e89f3..016ca5c 100644 --- a/leaky-ships/components/Ships.tsx +++ b/leaky-ships/components/Ships.tsx @@ -1,26 +1,34 @@ -import classNames from 'classnames' -import { CSSProperties } from 'react' +import classNames from "classnames" +import { CSSProperties } from "react" function Ships() { - let shipIndexes = [ - { size: 2, index: null }, - { size: 3, index: 1 }, - { size: 3, index: 2 }, - { size: 3, index: 3 }, - { size: 4, index: 1 }, - { size: 4, index: 2 } - ] + let shipIndexes = [ + { size: 2, index: null }, + { size: 3, index: 1 }, + { size: 3, index: 2 }, + { size: 3, index: 3 }, + { size: 4, index: 1 }, + { size: 4, index: 2 }, + ] - return <> - {shipIndexes.map(({ size, index }, i) => { - const filename = `/assets/ship_blue_${size}x${index ? '_' + index : ''}.gif` - return ( -
- {filename} -
- ) - })} + return ( + <> + {shipIndexes.map(({ size, index }, i) => { + const filename = `/assets/ship_blue_${size}x${ + index ? "_" + index : "" + }.gif` + return ( +
+ {filename} +
+ ) + })} + ) } export default Ships diff --git a/leaky-ships/components/SocketIO.tsx b/leaky-ships/components/SocketIO.tsx index dca3aca..6267cc0 100644 --- a/leaky-ships/components/SocketIO.tsx +++ b/leaky-ships/components/SocketIO.tsx @@ -1,40 +1,38 @@ -import { useEffect } from 'react' -import { io } from 'socket.io-client' +import { useEffect } from "react" +import { io } from "socket.io-client" function SocketIO() { - useEffect(() => { - socketInitializer() - }, []) + useEffect(() => { + socketInitializer() + }, []) - const socketInitializer = async () => { - await fetch('/api/ws') + const socketInitializer = async () => { + await fetch("/api/ws") - const socket = io() - socket.on('test2', (warst) => { - console.log('Test2:', warst, socket.id) - }) - socket.on("connect", () => { - console.log(socket.connected) // true - setTimeout(() => { - socket.emit('test', "warst") - socket.emit('test', "tsra") - socket.emit('test', "1234") - // socket.disconnect() - }, 1000) - }) + const socket = io() + socket.on("test2", (warst) => { + console.log("Test2:", warst, socket.id) + }) + socket.on("connect", () => { + console.log(socket.connected) // true + setTimeout(() => { + socket.emit("test", "warst") + socket.emit("test", "tsra") + socket.emit("test", "1234") + // socket.disconnect() + }, 1000) + }) - socket.on("test", () => { - console.log("Got test1234") // false - }) + socket.on("test", () => { + console.log("Got test1234") // false + }) - socket.on("disconnect", () => { - console.log(socket.connected) // false - }) - } + socket.on("disconnect", () => { + console.log(socket.connected) // false + }) + } - return ( -
SocketIO
- ) + return
SocketIO
} -export default SocketIO \ No newline at end of file +export default SocketIO diff --git a/leaky-ships/components/Targets.tsx b/leaky-ships/components/Targets.tsx index 1139860..6388a5b 100644 --- a/leaky-ships/components/Targets.tsx +++ b/leaky-ships/components/Targets.tsx @@ -1,20 +1,28 @@ -import React from 'react' -import { Target } from '../interfaces/frontend' -import GamefieldPointer, { PointerProps } from './GamefieldPointer' +import React from "react" +import { Target } from "../interfaces/frontend" +import GamefieldPointer, { PointerProps } from "./GamefieldPointer" -function Targets({ props: { composeTargetTiles, target, targetPreview } }: { - props: { - composeTargetTiles: (target: Target) => PointerProps[], - target: Target, - targetPreview: Target - } +function Targets({ + props: { composeTargetTiles, target, targetPreview }, +}: { + props: { + composeTargetTiles: (target: Target) => PointerProps[] + target: Target + targetPreview: Target + } }) { - return (<> - {[ - ...composeTargetTiles(target).map((props, i) => ), - ...composeTargetTiles(targetPreview).map((props, i) => ) - ]} - ) + return ( + <> + {[ + ...composeTargetTiles(target).map((props, i) => ( + + )), + ...composeTargetTiles(targetPreview).map((props, i) => ( + + )), + ]} + + ) } -export default Targets \ No newline at end of file +export default Targets diff --git a/leaky-ships/global.d.ts b/leaky-ships/global.d.ts index 9ad9a7a..1a8523e 100644 --- a/leaky-ships/global.d.ts +++ b/leaky-ships/global.d.ts @@ -1,3 +1,3 @@ declare module globalThis { - var prismaClient: PrismaClient + var prismaClient: PrismaClient } diff --git a/leaky-ships/interfaces/NextApiSocket.ts b/leaky-ships/interfaces/NextApiSocket.ts index 01e1ca2..3020036 100644 --- a/leaky-ships/interfaces/NextApiSocket.ts +++ b/leaky-ships/interfaces/NextApiSocket.ts @@ -1,7 +1,7 @@ -import type { Server as HTTPServer } from 'http' -import type { NextApiResponse } from 'next' -import type { Socket as NetSocket } from 'net' -import type { Server as IOServer } from 'socket.io' +import type { Server as HTTPServer } from "http" +import type { NextApiResponse } from "next" +import type { Socket as NetSocket } from "net" +import type { Server as IOServer } from "socket.io" interface SocketServer extends HTTPServer { io?: IOServer | undefined @@ -13,4 +13,4 @@ interface SocketWithIO extends NetSocket { export interface NextApiResponseWithSocket extends NextApiResponse { socket: SocketWithIO -} \ No newline at end of file +} diff --git a/leaky-ships/interfaces/frontend.ts b/leaky-ships/interfaces/frontend.ts index 85d78d0..9d0bb9a 100644 --- a/leaky-ships/interfaces/frontend.ts +++ b/leaky-ships/interfaces/frontend.ts @@ -1,50 +1,50 @@ export interface Position { - x: number, - y: number + x: number + y: number } export interface Target extends Position { - preview: boolean, - show: boolean + preview: boolean + show: boolean } export interface MouseCursor extends Position { - shouldShow: boolean + shouldShow: boolean } export interface TargetList extends Position { - type: string, - edges: string[] + type: string + edges: string[] } export interface Mode { - pointerGrid: any[][], - type: string + pointerGrid: any[][] + type: string } export interface Items { - icon: string, - text: string, - mode?: number, - amount?: number, + icon: string + text: string + mode?: number + amount?: number } export interface Field extends Position { - field: string + field: string } export interface Hit extends Position { - hit: boolean + hit: boolean } interface fireMissile { - type: 'fireMissile', - payload: { - x: number, - y: number, - hit: boolean - } + type: "fireMissile" + payload: { + x: number + y: number + hit: boolean + } } interface removeMissile { - type: 'removeMissile', - payload: { - x: number, - y: number, - hit: boolean - } + type: "removeMissile" + payload: { + x: number + y: number + hit: boolean + } } export type HitDispatch = fireMissile | removeMissile diff --git a/leaky-ships/lib/backend/components/checkPasswordIsValid.ts b/leaky-ships/lib/backend/components/checkPasswordIsValid.ts index eb4d3f1..55639d5 100644 --- a/leaky-ships/lib/backend/components/checkPasswordIsValid.ts +++ b/leaky-ships/lib/backend/components/checkPasswordIsValid.ts @@ -1,22 +1,23 @@ import { Player } from "@prisma/client" import bcrypt from "bcrypt" -export default async function checkPasswordIsValid(payload: T & { player: Player, password: string }) { - const { player, password } = payload +export default async function checkPasswordIsValid( + payload: T & { player: Player; password: string } +) { + const { player, password } = payload - // Validate for correct password - return bcrypt.compare(password, player.passwordHash) - .then(async result => { - if (!result) { - return Promise.reject({ - message: 'Passwords do not match!', - statusCode: 401, - solved: true, - }) - } - return { - ...payload, - passwordIsValid: true - } - }) -} \ No newline at end of file + // Validate for correct password + return bcrypt.compare(password, player.passwordHash).then(async (result) => { + if (!result) { + return Promise.reject({ + message: "Passwords do not match!", + statusCode: 401, + solved: true, + }) + } + return { + ...payload, + passwordIsValid: true, + } + }) +} diff --git a/leaky-ships/lib/backend/components/checkTokenIsValid.ts b/leaky-ships/lib/backend/components/checkTokenIsValid.ts index 3fb5001..d24d22e 100644 --- a/leaky-ships/lib/backend/components/checkTokenIsValid.ts +++ b/leaky-ships/lib/backend/components/checkTokenIsValid.ts @@ -2,27 +2,29 @@ import { Token } from "@prisma/client" import jwt from "jsonwebtoken" import jwtVerifyCatch from "../jwtVerifyCatch" -async function checkTokenIsValid(payload: T & { token: string, tokenType: Token['type'] }) { - const { token, tokenType } = payload +async function checkTokenIsValid( + payload: T & { token: string; tokenType: Token["type"] } +) { + const { token, tokenType } = payload - // Verify the token and get the payload - let tokenData: string | jwt.JwtPayload - try { - tokenData = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET as string) - } catch (err: any) { - // Deal with the problem in more detail - return Promise.reject(jwtVerifyCatch(tokenType, err)) - } - // Making sure the token data is not a string (because it should be an object) - if (typeof tokenData === 'string') { - return Promise.reject({ - message: tokenType + '-Token data was a string. Token: ' + token, - statusCode: 401, - solved: false - }) - } + // Verify the token and get the payload + let tokenData: string | jwt.JwtPayload + try { + tokenData = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET as string) + } catch (err: any) { + // Deal with the problem in more detail + return Promise.reject(jwtVerifyCatch(tokenType, err)) + } + // Making sure the token data is not a string (because it should be an object) + if (typeof tokenData === "string") { + return Promise.reject({ + message: tokenType + "-Token data was a string. Token: " + token, + statusCode: 401, + solved: false, + }) + } - return { ...payload, tokenBody: token, tokenIsValid: true } + return { ...payload, tokenBody: token, tokenIsValid: true } } -export default checkTokenIsValid \ No newline at end of file +export default checkTokenIsValid diff --git a/leaky-ships/lib/backend/components/createAnonymousDB.ts b/leaky-ships/lib/backend/components/createAnonymousDB.ts index 65c486d..ef83488 100644 --- a/leaky-ships/lib/backend/components/createAnonymousDB.ts +++ b/leaky-ships/lib/backend/components/createAnonymousDB.ts @@ -1,28 +1,28 @@ import prisma from "../../prisma" async function createAnonymousDB(payload: T) { - const player = await prisma.player.create({ - data: { - anonymous: true - } - }) - // .catch((err: any) => { - // if (err.code === 11000) { - // return Promise.reject({ - // message: `Duplicate key error while creating Player in DB!`, - // statusCode: 409, - // solved: true, - // type: 'warn' - // }) - // } else { - // console.log(err) - // return Promise.reject({ - // message: `Unknown error while creating Player in DB.`, - // solved: false - // }) - // } - // }) - return { ...payload, player } + const player = await prisma.player.create({ + data: { + anonymous: true, + }, + }) + // .catch((err: any) => { + // if (err.code === 11000) { + // return Promise.reject({ + // message: `Duplicate key error while creating Player in DB!`, + // statusCode: 409, + // solved: true, + // type: 'warn' + // }) + // } else { + // console.log(err) + // return Promise.reject({ + // message: `Unknown error while creating Player in DB.`, + // solved: false + // }) + // } + // }) + return { ...payload, player } } -export default createAnonymousDB \ No newline at end of file +export default createAnonymousDB diff --git a/leaky-ships/lib/backend/components/createPlayerDB.ts b/leaky-ships/lib/backend/components/createPlayerDB.ts index ba5ea01..e9c9ff2 100644 --- a/leaky-ships/lib/backend/components/createPlayerDB.ts +++ b/leaky-ships/lib/backend/components/createPlayerDB.ts @@ -1,34 +1,38 @@ import bcrypt from "bcrypt" import prisma from "../../prisma" -async function createPlayerDB(payload: T & { username: string, password: string }) { - const { username, password } = payload +async function createPlayerDB( + payload: T & { username: string; password: string } +) { + const { username, password } = payload - return await prisma.player.create({ - data: { - username, - passwordHash: await bcrypt.hash(password, 10), - anonymous: false - } + return await prisma.player + .create({ + data: { + username, + passwordHash: await bcrypt.hash(password, 10), + anonymous: false, + }, }) - .then(player => { - return { ...payload, player } - }).catch((err: any) => { - if (err.code === 11000) { - return Promise.reject({ - message: `Duplicate key error while creating Player in DB!`, - statusCode: 409, - solved: true, - type: 'warn' - }) - } else { - console.log(err) - return Promise.reject({ - message: `Unknown error while creating Player in DB.`, - solved: false - }) - } + .then((player) => { + return { ...payload, player } + }) + .catch((err: any) => { + if (err.code === 11000) { + return Promise.reject({ + message: `Duplicate key error while creating Player in DB!`, + statusCode: 409, + solved: true, + type: "warn", }) + } else { + console.log(err) + return Promise.reject({ + message: `Unknown error while creating Player in DB.`, + solved: false, + }) + } + }) } -export default createPlayerDB \ No newline at end of file +export default createPlayerDB diff --git a/leaky-ships/lib/backend/components/createTokenDB.ts b/leaky-ships/lib/backend/components/createTokenDB.ts index cdee377..9ded9c4 100644 --- a/leaky-ships/lib/backend/components/createTokenDB.ts +++ b/leaky-ships/lib/backend/components/createTokenDB.ts @@ -4,33 +4,39 @@ import { v4 as uuidv4 } from "uuid" import prisma from "../../prisma" const tokenLifetime = { - REFRESH: 172800, - ACCESS: 15 -}; + REFRESH: 172800, + ACCESS: 15, +} -export default async function createTokenDB(payload: T & { player: Player, newTokenType: Token['type'] }) { - const { player, newTokenType } = payload +export default async function createTokenDB( + payload: T & { player: Player; newTokenType: Token["type"] } +) { + const { player, newTokenType } = payload - // Sign a new access token - const newToken = jwt.sign({ uuid: uuidv4(), user: player.id }, process.env.ACCESS_TOKEN_SECRET as string, { expiresIn: tokenLifetime[newTokenType] }) + // Sign a new access token + const newToken = jwt.sign( + { uuid: uuidv4(), user: player.id }, + process.env.ACCESS_TOKEN_SECRET as string, + { expiresIn: tokenLifetime[newTokenType] } + ) - // Save token to DB - const newTokenDB = await prisma.token.create({ - data: { - token: newToken, - type: newTokenType, - expires: new Date(Date.now() + tokenLifetime[newTokenType] + '000'), - owner: { - connect: { - id: player.id - } - } - } - }) + // Save token to DB + const newTokenDB = await prisma.token.create({ + data: { + token: newToken, + type: newTokenType, + expires: new Date(Date.now() + tokenLifetime[newTokenType] + "000"), + owner: { + connect: { + id: player.id, + }, + }, + }, + }) - return { - ...payload, - newToken, - newTokenDB - } -} \ No newline at end of file + return { + ...payload, + newToken, + newTokenDB, + } +} diff --git a/leaky-ships/lib/backend/components/getPlayerByIdDB.ts b/leaky-ships/lib/backend/components/getPlayerByIdDB.ts index ec1a5d9..a3814cc 100644 --- a/leaky-ships/lib/backend/components/getPlayerByIdDB.ts +++ b/leaky-ships/lib/backend/components/getPlayerByIdDB.ts @@ -1,24 +1,26 @@ import { Token } from "@prisma/client" import prisma from "../../prisma" -export default async function getPlayerByIdDB(payload: T & { tokenDB: Token }) { - const { tokenDB } = payload - // Find Host in DB if it still exists (just to make sure) - const player = await prisma.player.findUnique({ - where: { - id: tokenDB.ownerId - } +export default async function getPlayerByIdDB( + payload: T & { tokenDB: Token } +) { + const { tokenDB } = payload + // Find Host in DB if it still exists (just to make sure) + const player = await prisma.player.findUnique({ + where: { + id: tokenDB.ownerId, + }, + }) + if (!player) { + return Promise.reject({ + message: "Player not found in DB!", + statusCode: 401, + solved: false, }) - if (!player) { - return Promise.reject({ - message: 'Player not found in DB!', - statusCode: 401, - solved: false - }) - } + } - return { - ...payload, - player - } -} \ No newline at end of file + return { + ...payload, + player, + } +} diff --git a/leaky-ships/lib/backend/components/getPlayerByNameDB.ts b/leaky-ships/lib/backend/components/getPlayerByNameDB.ts index 82d79d6..3de1a82 100644 --- a/leaky-ships/lib/backend/components/getPlayerByNameDB.ts +++ b/leaky-ships/lib/backend/components/getPlayerByNameDB.ts @@ -1,29 +1,32 @@ import prisma from "../../prisma" -export default async function getPlayerByNameDB(payload: T & { username: string }) { - const { username } = payload - // Find Player in DB if it still exists (just to make sure) - const player = await Promise.any([ - prisma.player.findUnique({ - where: { - username: username - } - }), prisma.player.findUnique({ - where: { - email: username - } - }) - ]) - if (!player) { - return Promise.reject({ - message: 'Player not found in DB!', - statusCode: 401, - solved: false - }) - } +export default async function getPlayerByNameDB( + payload: T & { username: string } +) { + const { username } = payload + // Find Player in DB if it still exists (just to make sure) + const player = await Promise.any([ + prisma.player.findUnique({ + where: { + username: username, + }, + }), + prisma.player.findUnique({ + where: { + email: username, + }, + }), + ]) + if (!player) { + return Promise.reject({ + message: "Player not found in DB!", + statusCode: 401, + solved: false, + }) + } - return { - ...payload, - player - } -} \ No newline at end of file + return { + ...payload, + player, + } +} diff --git a/leaky-ships/lib/backend/components/getTokenDB.ts b/leaky-ships/lib/backend/components/getTokenDB.ts index 69d8456..4c21da4 100644 --- a/leaky-ships/lib/backend/components/getTokenDB.ts +++ b/leaky-ships/lib/backend/components/getTokenDB.ts @@ -1,52 +1,54 @@ import { NextApiRequest, NextApiResponse } from "next" import prisma from "../../prisma" -async function getTokenDB(payload: T & { +async function getTokenDB( + payload: T & { tokenBody: string - tokenIsValid: boolean, - req: NextApiRequest, - res: NextApiResponse, -}) { - const { tokenBody } = payload + tokenIsValid: boolean + req: NextApiRequest + res: NextApiResponse + } +) { + const { tokenBody } = payload - // Find refresh token in DB - const tokenDB = await prisma.token.findUnique({ - where: { - token: tokenBody - } + // Find refresh token in DB + const tokenDB = await prisma.token.findUnique({ + where: { + token: tokenBody, + }, + }) + if (!tokenDB) { + return Promise.reject({ + message: "Access-Token not found in DB!", + statusCode: 401, + solved: true, + type: "warn", }) - if (!tokenDB) { - return Promise.reject({ - message: 'Access-Token not found in DB!', - statusCode: 401, - solved: true, - type: 'warn' - }) - } + } - if (tokenDB.used) { - return Promise.reject({ - message: 'DBToken was already used!', - statusCode: 401, - solved: true - }) - } - - await prisma.token.update({ - where: { - token: tokenBody - }, - data: { - used: true - } + if (tokenDB.used) { + return Promise.reject({ + message: "DBToken was already used!", + statusCode: 401, + solved: true, }) + } - // await logging('Old token has been invalidated.', ['debug'], req) + await prisma.token.update({ + where: { + token: tokenBody, + }, + data: { + used: true, + }, + }) - return { - ...payload, - tokenDB - } + // await logging('Old token has been invalidated.', ['debug'], req) + + return { + ...payload, + tokenDB, + } } -export default getTokenDB \ No newline at end of file +export default getTokenDB diff --git a/leaky-ships/lib/backend/components/getTokenFromBody.ts b/leaky-ships/lib/backend/components/getTokenFromBody.ts index 61ebd9d..2e12e0a 100644 --- a/leaky-ships/lib/backend/components/getTokenFromBody.ts +++ b/leaky-ships/lib/backend/components/getTokenFromBody.ts @@ -1,19 +1,19 @@ import { NextApiRequest } from "next" async function getTokenFromBody(payload: T & { req: NextApiRequest }) { - const { req } = payload - const token: string = req.body.token + const { req } = payload + const token: string = req.body.token - // Checking for cookie presens, because it is necessary - if (!token) { - return Promise.reject({ - message: 'Unauthorized. No Access-Token.', - statusCode: 401, - solved: true, - }) - } + // Checking for cookie presens, because it is necessary + if (!token) { + return Promise.reject({ + message: "Unauthorized. No Access-Token.", + statusCode: 401, + solved: true, + }) + } - return { ...payload, token } + return { ...payload, token } } -export default getTokenFromBody \ No newline at end of file +export default getTokenFromBody diff --git a/leaky-ships/lib/backend/components/getTokenFromCookie.ts b/leaky-ships/lib/backend/components/getTokenFromCookie.ts index e8caa89..4798e29 100644 --- a/leaky-ships/lib/backend/components/getTokenFromCookie.ts +++ b/leaky-ships/lib/backend/components/getTokenFromCookie.ts @@ -2,19 +2,19 @@ import { Token } from "@prisma/client" import { NextApiRequest } from "next" async function getTokenFromCookie(payload: T & { req: NextApiRequest }) { - const { req } = payload - const token = req.cookies.token + const { req } = payload + const token = req.cookies.token - // Checking for cookie presens, because it is necessary - if (!token) { - return Promise.reject({ - message: 'Unauthorized. No cookie.', - statusCode: 401, - solved: true, - }) - } + // Checking for cookie presens, because it is necessary + if (!token) { + return Promise.reject({ + message: "Unauthorized. No cookie.", + statusCode: 401, + solved: true, + }) + } - return { ...payload, token, tokenType: 'REFRESH' as Token['type'] } + return { ...payload, token, tokenType: "REFRESH" as Token["type"] } } -export default getTokenFromCookie \ No newline at end of file +export default getTokenFromCookie diff --git a/leaky-ships/lib/backend/components/loginCheck.ts b/leaky-ships/lib/backend/components/loginCheck.ts index 36ef428..4cd9cc2 100644 --- a/leaky-ships/lib/backend/components/loginCheck.ts +++ b/leaky-ships/lib/backend/components/loginCheck.ts @@ -1,15 +1,17 @@ import { Token } from "@prisma/client" import { Logging } from "../logging" -export default async function loginCheck(payload: T & { loginCheck: boolean, tokenDB: Token, tokenType: 'REFRESH' }) { - const { loginCheck, tokenDB } = payload - // True login check response - if (loginCheck) { - return Promise.resolve({ - message: 'loginCheck ' + loginCheck + ' of ' + tokenDB.id, - body: { loggedIn: true }, - type: ['debug', 'info.cyan'] as Logging[] - }) - } - return payload -} \ No newline at end of file +export default async function loginCheck( + payload: T & { loginCheck: boolean; tokenDB: Token; tokenType: "REFRESH" } +) { + const { loginCheck, tokenDB } = payload + // True login check response + if (loginCheck) { + return Promise.resolve({ + message: "loginCheck " + loginCheck + " of " + tokenDB.id, + body: { loggedIn: true }, + type: ["debug", "info.cyan"] as Logging[], + }) + } + return payload +} diff --git a/leaky-ships/lib/backend/components/sendError.ts b/leaky-ships/lib/backend/components/sendError.ts index 7d54118..92db74c 100644 --- a/leaky-ships/lib/backend/components/sendError.ts +++ b/leaky-ships/lib/backend/components/sendError.ts @@ -2,11 +2,11 @@ import { NextApiRequest, NextApiResponse } from "next" import logging from "../logging" export default function sendError( - req: NextApiRequest, - res: NextApiResponse, - err: any + req: NextApiRequest, + res: NextApiResponse, + err: any ) { - // If something went wrong, let the client know with status 500 - res.status(err.statusCode ?? 500).end() - logging(err.message, [err.type ?? (err.solved ? 'debug' : 'error')], req) -} \ No newline at end of file + // If something went wrong, let the client know with status 500 + res.status(err.statusCode ?? 500).end() + logging(err.message, [err.type ?? (err.solved ? "debug" : "error")], req) +} diff --git a/leaky-ships/lib/backend/components/sendResponse.ts b/leaky-ships/lib/backend/components/sendResponse.ts index e3b2eda..2defd35 100644 --- a/leaky-ships/lib/backend/components/sendResponse.ts +++ b/leaky-ships/lib/backend/components/sendResponse.ts @@ -2,21 +2,19 @@ import { NextApiRequest, NextApiResponse } from "next" import logging, { Logging } from "../logging" export interface Result { - message: string, - statusCode?: number, - body?: T, - type?: Logging[], + message: string + statusCode?: number + body?: T + type?: Logging[] } export default function sendResponse(payload: { - req: NextApiRequest, - res: NextApiResponse, - result: Result + req: NextApiRequest + res: NextApiResponse + result: Result }) { - const { req, res, result } = payload - res.status(result.statusCode ?? 200) - result.body ? - res.json(result.body) : - res.end() - logging(result.message, result.type ?? ['debug'], req) + const { req, res, result } = payload + res.status(result.statusCode ?? 200) + result.body ? res.json(result.body) : res.end() + logging(result.message, result.type ?? ["debug"], req) } diff --git a/leaky-ships/lib/backend/jwtVerifyCatch.ts b/leaky-ships/lib/backend/jwtVerifyCatch.ts index 2f89e8f..2354fe0 100644 --- a/leaky-ships/lib/backend/jwtVerifyCatch.ts +++ b/leaky-ships/lib/backend/jwtVerifyCatch.ts @@ -1,21 +1,36 @@ import { Token } from "@prisma/client" export default async function jwtVerifyCatch( - tokenType: Token['type'], - err: Error + tokenType: Token["type"], + err: Error ) { - switch (err.message) { - case 'jwt expired': - return { message: `JWT (${tokenType}) expired!`, statusCode: 403, solved: true, type: 'warn' } + switch (err.message) { + case "jwt expired": + return { + message: `JWT (${tokenType}) expired!`, + statusCode: 403, + solved: true, + type: "warn", + } - case 'invalid signature': - return { message: `Invalid JWT (${tokenType}) signature! Token: `, statusCode: 401, solved: true, type: 'error' } + case "invalid signature": + return { + message: `Invalid JWT (${tokenType}) signature! Token: `, + statusCode: 401, + solved: true, + type: "error", + } - case 'jwt must be provided': - return { message: `No JWT (${tokenType}) given.`, statusCode: 401, solved: true, type: 'warn' } + case "jwt must be provided": + return { + message: `No JWT (${tokenType}) given.`, + statusCode: 401, + solved: true, + type: "warn", + } - default: - console.log(err) - return { message: `Unknown error on 'JWT.verify()'.`, solved: false } - } -} \ No newline at end of file + default: + console.log(err) + return { message: `Unknown error on 'JWT.verify()'.`, solved: false } + } +} diff --git a/leaky-ships/lib/backend/logging.ts b/leaky-ships/lib/backend/logging.ts index 9109d7c..2869641 100644 --- a/leaky-ships/lib/backend/logging.ts +++ b/leaky-ships/lib/backend/logging.ts @@ -1,17 +1,17 @@ -import fs from 'fs' -import colors, { Color } from 'colors' -import { NextApiRequest } from 'next' -import { IncomingMessage } from 'http' +import fs from "fs" +import colors, { Color } from "colors" +import { NextApiRequest } from "next" +import { IncomingMessage } from "http" colors.enable() const loggingTemplates: { [key: string]: LoggingType } = { - 'system': ['SYSTEM', 'green'], - 'info.green': ['INFO', 'green'], - 'info.cyan': ['INFO', 'cyan'], - 'debug': ['Debug', 'grey'], - 'post': ['Post', 'white'], - 'warn': ['WARN', 'yellow'], - 'error': ['ERROR', 'red'] + system: ["SYSTEM", "green"], + "info.green": ["INFO", "green"], + "info.cyan": ["INFO", "cyan"], + debug: ["Debug", "grey"], + post: ["Post", "white"], + warn: ["WARN", "yellow"], + error: ["ERROR", "red"], } type LoggingType = [string, keyof Color] @@ -20,32 +20,40 @@ export type Logging = keyof typeof loggingTemplates | LoggingType let started: boolean = false async function logStartup() { - await fs.promises.stat('log').catch(async () => { - await fs.promises.mkdir('log') - await logging(`Created 'log' Folder.`, ['info.cyan', 'system']) - }) - started = true + await fs.promises.stat("log").catch(async () => { + await fs.promises.mkdir("log") + await logging(`Created 'log' Folder.`, ["info.cyan", "system"]) + }) + started = true } -async function logging(message: string, types: Logging[], req?: NextApiRequest | IncomingMessage) { - if (!started) - await logStartup() - const messages = { console: message, file: message } - types.slice().reverse().forEach(async (type) => { - const [name, color] = typeof type === 'object' ? type : loggingTemplates[type] - messages.console = `[${name}] `[color] + messages.console - messages.file = `[${name}] ` + messages.file +async function logging( + message: string, + types: Logging[], + req?: NextApiRequest | IncomingMessage +) { + if (!started) await logStartup() + const messages = { console: message, file: message } + types + .slice() + .reverse() + .forEach(async (type) => { + const [name, color] = + typeof type === "object" ? type : loggingTemplates[type] + messages.console = `[${name}] `[color] + messages.console + messages.file = `[${name}] ` + messages.file }) - messages.console = `[${new Date().toString().slice(0, 33)}] ` + messages.console - messages.file = `[${new Date().toString().slice(0, 33)}] ` + messages.file - if (req) { - const forwardedFor: any = req.headers['x-forwarded-for'] - const ip = (forwardedFor || '127.0.0.1, 192.168.178.1').split(',') - messages.console = ip[0].yellow + ' - ' + messages.console - messages.file = ip[0] + ' - ' + messages.file - } - await fs.promises.appendFile('log/log.txt', messages.file + '\n') - console.log(messages.console) + messages.console = + `[${new Date().toString().slice(0, 33)}] ` + messages.console + messages.file = `[${new Date().toString().slice(0, 33)}] ` + messages.file + if (req) { + const forwardedFor: any = req.headers["x-forwarded-for"] + const ip = (forwardedFor || "127.0.0.1, 192.168.178.1").split(",") + messages.console = ip[0].yellow + " - " + messages.console + messages.file = ip[0] + " - " + messages.file + } + await fs.promises.appendFile("log/log.txt", messages.file + "\n") + console.log(messages.console) } -export default logging \ No newline at end of file +export default logging diff --git a/leaky-ships/lib/frontend/checkIsLoggedIn.ts b/leaky-ships/lib/frontend/checkIsLoggedIn.ts index a90efae..040a28e 100644 --- a/leaky-ships/lib/frontend/checkIsLoggedIn.ts +++ b/leaky-ships/lib/frontend/checkIsLoggedIn.ts @@ -6,18 +6,24 @@ import getTokenDB from "../backend/components/getTokenDB" import getPlayerByIdDB from "../backend/components/getPlayerByIdDB" import logging from "../backend/logging" -export default async function checkIsLoggedIn(context: GetServerSidePropsContext) { - const req: any = context.req - const res: any = context.res +export default async function checkIsLoggedIn( + context: GetServerSidePropsContext +) { + const req: any = context.req + const res: any = context.res - const isLoggedIn = await getTokenFromCookie({ req, res }) - .then(checkTokenIsValid) - .then(getTokenDB) - .then(getPlayerByIdDB) - .then(({ player }) => !!player) - .catch(() => false) + const isLoggedIn = await getTokenFromCookie({ req, res }) + .then(checkTokenIsValid) + .then(getTokenDB) + .then(getPlayerByIdDB) + .then(({ player }) => !!player) + .catch(() => false) - logging('loginCheck ' + (isLoggedIn ? true : '-> loggedIn: ' + false), ['debug', 'info.cyan'], req) + logging( + "loginCheck " + (isLoggedIn ? true : "-> loggedIn: " + false), + ["debug", "info.cyan"], + req + ) - return isLoggedIn -} \ No newline at end of file + return isLoggedIn +} diff --git a/leaky-ships/lib/frontend/getAccessToken.ts b/leaky-ships/lib/frontend/getAccessToken.ts index 85919f3..00105ea 100644 --- a/leaky-ships/lib/frontend/getAccessToken.ts +++ b/leaky-ships/lib/frontend/getAccessToken.ts @@ -1,7 +1,7 @@ export default function getAccessToken(): Promise { - return fetch('/api/auth', { - method: 'GET', - }) - .then(res => res.json()) - .then(res => res.newAccessToken) -} \ No newline at end of file + return fetch("/api/auth", { + method: "GET", + }) + .then((res) => res.json()) + .then((res) => res.newAccessToken) +} diff --git a/leaky-ships/lib/hooks/useGameEvent.ts b/leaky-ships/lib/hooks/useGameEvent.ts index 31b5fd3..64f28cd 100644 --- a/leaky-ships/lib/hooks/useGameEvent.ts +++ b/leaky-ships/lib/hooks/useGameEvent.ts @@ -1,150 +1,222 @@ -import { useCallback, useEffect, useMemo, useReducer, useState } from 'react' -import { hitReducer, initlialLastLeftTile, initlialTarget, initlialTargetPreview, initlialMouseCursor } from '../utils/helpers' -import { Hit, Mode, MouseCursor, Target, Position } from '../../interfaces/frontend' -import { PointerProps } from '../../components/GamefieldPointer' +import { useCallback, useEffect, useMemo, useReducer, useState } from "react" +import { + hitReducer, + initlialLastLeftTile, + initlialTarget, + initlialTargetPreview, + initlialMouseCursor, +} from "../utils/helpers" +import { + Hit, + Mode, + MouseCursor, + Target, + Position, +} from "../../interfaces/frontend" +import { PointerProps } from "../../components/GamefieldPointer" const modes: Mode[] = [ - { pointerGrid: Array.from(Array(3), () => Array.from(Array(3))), type: 'radar' }, - { pointerGrid: Array.from(Array(3), () => Array.from(Array(1))), type: 'htorpedo' }, - { pointerGrid: Array.from(Array(1), () => Array.from(Array(3))), type: 'vtorpedo' }, - { pointerGrid: [[{ x: 0, y: 0 }]], type: 'missile' } + { + pointerGrid: Array.from(Array(3), () => Array.from(Array(3))), + type: "radar", + }, + { + pointerGrid: Array.from(Array(3), () => Array.from(Array(1))), + type: "htorpedo", + }, + { + pointerGrid: Array.from(Array(1), () => Array.from(Array(3))), + type: "vtorpedo", + }, + { pointerGrid: [[{ x: 0, y: 0 }]], type: "missile" }, ] function useGameEvent(count: number) { - const [lastLeftTile, setLastLeftTile] = useState(initlialLastLeftTile) - const [target, setTarget] = useState(initlialTarget) - const [eventReady, setEventReady] = useState(false) - const [appearOK, setAppearOK] = useState(false) - const [targetPreview, setTargetPreview] = useState(initlialTargetPreview) - const [mouseCursor, setMouseCursor] = useState(initlialMouseCursor) - const [hits, DispatchHits] = useReducer(hitReducer, [] as Hit[]) - const [mode, setMode] = useState(0) + const [lastLeftTile, setLastLeftTile] = + useState(initlialLastLeftTile) + const [target, setTarget] = useState(initlialTarget) + const [eventReady, setEventReady] = useState(false) + const [appearOK, setAppearOK] = useState(false) + const [targetPreview, setTargetPreview] = useState( + initlialTargetPreview + ) + const [mouseCursor, setMouseCursor] = + useState(initlialMouseCursor) + const [hits, DispatchHits] = useReducer(hitReducer, [] as Hit[]) + const [mode, setMode] = useState(0) - const targetList = useCallback((target: Position) => { - const { pointerGrid, type } = modes[mode] - const xLength = pointerGrid.length - const yLength = pointerGrid[0].length - const { x: targetX, y: targetY } = target - return pointerGrid.map((arr, i) => { - return arr.map((_, i2) => { - const relativeX = -Math.floor(xLength / 2) + i - const relativeY = -Math.floor(yLength / 2) + i2 - const x = targetX + (relativeX ?? 0) - const y = targetY + (relativeY ?? 0) - return { - x, - y, - type, - edges: [ - i === 0 ? 'left' : '', - i === xLength - 1 ? 'right' : '', - i2 === 0 ? 'top' : '', - i2 === yLength - 1 ? 'bottom' : '', - ] - } - }) - }) - .reduce((prev, curr) => [...prev, ...curr], []) - }, [mode]) - - const isHit = useCallback((x: number, y: number) => { - return hits.filter(h => h.x === x && h.y === y) - }, [hits]) - - const settingTarget = useCallback((isGameTile: boolean, x: number, y: number) => { - if (!isGameTile || isHit(x, y).length) - return - setMouseCursor(e => ({ ...e, shouldShow: false })) - setTarget(t => { - if (t.x === x && t.y === y && t.show) { - DispatchHits({ type: 'fireMissile', payload: { hit: (x + y) % 2 !== 0, x, y } }) - return { preview: false, show: false, x, y } - } else { - const target = { preview: false, show: true, x, y } - const hasAnyBorder = targetList(target).filter(({ x, y }) => isBorder(x, y, count)).length - if (hasAnyBorder) - return t - return target - - } - }) - }, [count, isHit, targetList]) - - const isSet = useCallback((x: number, y: number) => { - return !!targetList(target).filter(field => x === field.x && y === field.y).length && target.show - }, [target, targetList]) - - const composeTargetTiles = useCallback((target: Target): PointerProps[] => { - const { preview, show } = target - const result = targetList(target).map(({ x, y, type, edges }) => { + const targetList = useCallback( + (target: Position) => { + const { pointerGrid, type } = modes[mode] + const xLength = pointerGrid.length + const yLength = pointerGrid[0].length + const { x: targetX, y: targetY } = target + return pointerGrid + .map((arr, i) => { + return arr.map((_, i2) => { + const relativeX = -Math.floor(xLength / 2) + i + const relativeY = -Math.floor(yLength / 2) + i2 + const x = targetX + (relativeX ?? 0) + const y = targetY + (relativeY ?? 0) return { - preview, - x, - y, - show, - type, - edges, - imply: !!isHit(x, y).length || (!!isSet(x, y) && preview) + x, + y, + type, + edges: [ + i === 0 ? "left" : "", + i === xLength - 1 ? "right" : "", + i2 === 0 ? "top" : "", + i2 === yLength - 1 ? "bottom" : "", + ], } + }) }) - return result - }, [isHit, isSet, targetList]) + .reduce((prev, curr) => [...prev, ...curr], []) + }, + [mode] + ) - // handle visibility and position change of targetPreview - useEffect(() => { - const { show, x, y } = targetPreview - // if mouse has moved too quickly and last event was entering and leaving the same field, it must have gone outside the grid - const hasLeft = x === lastLeftTile.x && y === lastLeftTile.y - const isSet = x === target.x && y === target.y && target.show + const isHit = useCallback( + (x: number, y: number) => { + return hits.filter((h) => h.x === x && h.y === y) + }, + [hits] + ) - if (show && !appearOK) - setTargetPreview(e => ({ ...e, show: false })) - if (!show && mouseCursor.shouldShow && eventReady && appearOK && !isHit(x, y).length && !isSet && !hasLeft) - setTargetPreview(e => ({ ...e, show: true })) - }, [targetPreview, mouseCursor.shouldShow, isHit, eventReady, appearOK, lastLeftTile, target]) - - // enable targetPreview event again after 200 ms. - useEffect(() => { - setEventReady(false) - const previewTarget = { x: mouseCursor.x, y: mouseCursor.y } - const hasAnyBorder = targetList(previewTarget).filter(({ x, y }) => isBorder(x, y, count)).length - if (targetPreview.show || !appearOK || hasAnyBorder) - return - const autoTimeout = setTimeout(() => { - setTargetPreview(e => ({ ...e, ...previewTarget })) - setEventReady(true) - setAppearOK(true) - }, 300) - - // or abort if state has changed early - return () => { - clearTimeout(autoTimeout) + const settingTarget = useCallback( + (isGameTile: boolean, x: number, y: number) => { + if (!isGameTile || isHit(x, y).length) return + setMouseCursor((e) => ({ ...e, shouldShow: false })) + setTarget((t) => { + if (t.x === x && t.y === y && t.show) { + DispatchHits({ + type: "fireMissile", + payload: { hit: (x + y) % 2 !== 0, x, y }, + }) + return { preview: false, show: false, x, y } + } else { + const target = { preview: false, show: true, x, y } + const hasAnyBorder = targetList(target).filter(({ x, y }) => + isBorder(x, y, count) + ).length + if (hasAnyBorder) return t + return target } - }, [appearOK, count, mouseCursor.x, mouseCursor.y, targetList, targetPreview.show]) + }) + }, + [count, isHit, targetList] + ) - // approve targetPreview new position after 200 mil. sec. - useEffect(() => { - // early return to start cooldown only when about to show up - const autoTimeout = setTimeout(() => { - setAppearOK(!targetPreview.show) - }, targetPreview.show ? 500 : 300) + const isSet = useCallback( + (x: number, y: number) => { + return ( + !!targetList(target).filter((field) => x === field.x && y === field.y) + .length && target.show + ) + }, + [target, targetList] + ) - // or abort if movement is repeated early - return () => { - clearTimeout(autoTimeout) + const composeTargetTiles = useCallback( + (target: Target): PointerProps[] => { + const { preview, show } = target + const result = targetList(target).map(({ x, y, type, edges }) => { + return { + preview, + x, + y, + show, + type, + edges, + imply: !!isHit(x, y).length || (!!isSet(x, y) && preview), } - }, [targetPreview.show]) + }) + return result + }, + [isHit, isSet, targetList] + ) - return { - tilesProps: { count, settingTarget, setMouseCursor, setLastLeftTile }, - pointersProps: { composeTargetTiles, target, targetPreview }, - targetsProps: { setMode, setTarget }, - hits + // handle visibility and position change of targetPreview + useEffect(() => { + const { show, x, y } = targetPreview + // if mouse has moved too quickly and last event was entering and leaving the same field, it must have gone outside the grid + const hasLeft = x === lastLeftTile.x && y === lastLeftTile.y + const isSet = x === target.x && y === target.y && target.show + + if (show && !appearOK) setTargetPreview((e) => ({ ...e, show: false })) + if ( + !show && + mouseCursor.shouldShow && + eventReady && + appearOK && + !isHit(x, y).length && + !isSet && + !hasLeft + ) + setTargetPreview((e) => ({ ...e, show: true })) + }, [ + targetPreview, + mouseCursor.shouldShow, + isHit, + eventReady, + appearOK, + lastLeftTile, + target, + ]) + + // enable targetPreview event again after 200 ms. + useEffect(() => { + setEventReady(false) + const previewTarget = { x: mouseCursor.x, y: mouseCursor.y } + const hasAnyBorder = targetList(previewTarget).filter(({ x, y }) => + isBorder(x, y, count) + ).length + if (targetPreview.show || !appearOK || hasAnyBorder) return + const autoTimeout = setTimeout(() => { + setTargetPreview((e) => ({ ...e, ...previewTarget })) + setEventReady(true) + setAppearOK(true) + }, 300) + + // or abort if state has changed early + return () => { + clearTimeout(autoTimeout) } + }, [ + appearOK, + count, + mouseCursor.x, + mouseCursor.y, + targetList, + targetPreview.show, + ]) + + // approve targetPreview new position after 200 mil. sec. + useEffect(() => { + // early return to start cooldown only when about to show up + const autoTimeout = setTimeout( + () => { + setAppearOK(!targetPreview.show) + }, + targetPreview.show ? 500 : 300 + ) + + // or abort if movement is repeated early + return () => { + clearTimeout(autoTimeout) + } + }, [targetPreview.show]) + + return { + tilesProps: { count, settingTarget, setMouseCursor, setLastLeftTile }, + pointersProps: { composeTargetTiles, target, targetPreview }, + targetsProps: { setMode, setTarget }, + hits, + } } function isBorder(x: number, y: number, count: number) { - return x < 2 || x > count + 1 || y < 2 || y > count + 1 + return x < 2 || x > count + 1 || y < 2 || y > count + 1 } -export default useGameEvent \ No newline at end of file +export default useGameEvent diff --git a/leaky-ships/lib/prisma.ts b/leaky-ships/lib/prisma.ts index 42a3070..5f7a05b 100644 --- a/leaky-ships/lib/prisma.ts +++ b/leaky-ships/lib/prisma.ts @@ -1,15 +1,15 @@ // lib/prisma.ts -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from "@prisma/client" -let prisma: PrismaClient; +let prisma: PrismaClient -if (process.env.NODE_ENV === 'production') { - prisma = new PrismaClient(); +if (process.env.NODE_ENV === "production") { + prisma = new PrismaClient() } else { - if (!global.prismaClient) { - global.prismaClient = new PrismaClient(); - } - prisma = global.prismaClient; + if (!global.prismaClient) { + global.prismaClient = new PrismaClient() + } + prisma = global.prismaClient } -export default prisma; +export default prisma diff --git a/leaky-ships/lib/utils/helpers.ts b/leaky-ships/lib/utils/helpers.ts index a88dc5c..1c51fa7 100644 --- a/leaky-ships/lib/utils/helpers.ts +++ b/leaky-ships/lib/utils/helpers.ts @@ -1,60 +1,51 @@ import { Hit, HitDispatch } from "../../interfaces/frontend" export function borderCN(count: number, x: number, y: number) { - if (x === 0) - return 'left' - if (y === 0) - return 'top' - if (x === count + 1) - return 'right' - if (y === count + 1) - return 'bottom' - return '' + if (x === 0) return "left" + if (y === 0) return "top" + if (x === count + 1) return "right" + if (y === count + 1) return "bottom" + return "" } export function cornerCN(count: number, x: number, y: number) { - if (x === 0 && y === 0) - return 'left-top-corner' - if (x === count + 1 && y === 0) - return 'right-top-corner' - if (x === 0 && y === count + 1) - return 'left-bottom-corner' - if (x === count + 1 && y === count + 1) - return 'right-bottom-corner' - return '' + if (x === 0 && y === 0) return "left-top-corner" + if (x === count + 1 && y === 0) return "right-top-corner" + if (x === 0 && y === count + 1) return "left-bottom-corner" + if (x === count + 1 && y === count + 1) return "right-bottom-corner" + return "" } export function fieldIndex(count: number, x: number, y: number) { - return y * (count + 2) + x + return y * (count + 2) + x } export function hitReducer(formObject: Hit[], action: HitDispatch) { - switch (action.type) { - - case 'fireMissile': { - const result = [...formObject, action.payload] - return result - } - - default: - return formObject + switch (action.type) { + case "fireMissile": { + const result = [...formObject, action.payload] + return result } + + default: + return formObject + } } export const initlialLastLeftTile = { - x: 0, - y: 0 + x: 0, + y: 0, } export const initlialTarget = { - preview: false, - show: false, - x: 2, - y: 2 + preview: false, + show: false, + x: 2, + y: 2, } export const initlialTargetPreview = { - preview: true, - show: false, - x: 2, - y: 2 + preview: true, + show: false, + x: 2, + y: 2, } export const initlialMouseCursor = { - shouldShow: false, - x: 0, - y: 0 + shouldShow: false, + x: 0, + y: 0, } diff --git a/leaky-ships/package.json b/leaky-ships/package.json index 51f210a..8f011dd 100644 --- a/leaky-ships/package.json +++ b/leaky-ships/package.json @@ -51,4 +51,4 @@ "sass": "^1.57.1", "tailwindcss": "^3.2.4" } -} \ No newline at end of file +} diff --git a/leaky-ships/pages/_app.tsx b/leaky-ships/pages/_app.tsx index 8f7c337..b439e1a 100644 --- a/leaky-ships/pages/_app.tsx +++ b/leaky-ships/pages/_app.tsx @@ -1,9 +1,9 @@ -import '../styles/App.scss' -import '../styles/grid.scss' -import '../styles/grid2.scss' -import '../styles/homepage.scss' -import '../styles/globals.css' -import type { AppProps } from 'next/app' +import "../styles/App.scss" +import "../styles/grid.scss" +import "../styles/grid2.scss" +import "../styles/homepage.scss" +import "../styles/globals.css" +import type { AppProps } from "next/app" export default function App({ Component, pageProps }: AppProps) { return diff --git a/leaky-ships/pages/_document.tsx b/leaky-ships/pages/_document.tsx index 54e8bf3..097cb7f 100644 --- a/leaky-ships/pages/_document.tsx +++ b/leaky-ships/pages/_document.tsx @@ -1,4 +1,4 @@ -import { Html, Head, Main, NextScript } from 'next/document' +import { Html, Head, Main, NextScript } from "next/document" export default function Document() { return ( diff --git a/leaky-ships/pages/api/auth.ts b/leaky-ships/pages/api/auth.ts index 502aafe..fefcdda 100644 --- a/leaky-ships/pages/api/auth.ts +++ b/leaky-ships/pages/api/auth.ts @@ -10,40 +10,48 @@ import { Logging } from "../../lib/backend/logging" import { Token } from "@prisma/client" interface Data { - token: string + token: string } export default async function auth( - req: NextApiRequest, - res: NextApiResponse + req: NextApiRequest, + res: NextApiResponse ) { - return getTokenFromCookie({ req, res, newTokenType: 'ACCESS' as Token['type'] }) - .then(checkTokenIsValid) - .then(getTokenDB) - .then(getPlayerByIdDB) - .then(createTokenDB) - .then(authResponse) - .then(sendResponse) - .catch(err => sendError(req, res, err)) + return getTokenFromCookie({ + req, + res, + newTokenType: "ACCESS" as Token["type"], + }) + .then(checkTokenIsValid) + .then(getTokenDB) + .then(getPlayerByIdDB) + .then(createTokenDB) + .then(authResponse) + .then(sendResponse) + .catch((err) => sendError(req, res, err)) } async function authResponse(payload: { - newToken: string, - newTokenDB: Token, - tokenDB: Token, - req: NextApiRequest, - res: NextApiResponse + newToken: string + newTokenDB: Token + tokenDB: Token + req: NextApiRequest + res: NextApiResponse }) { - const { newToken, newTokenDB, tokenDB, req, res } = payload + const { newToken, newTokenDB, tokenDB, req, res } = payload - // Successfull response - return { - req, - res, - result: { - message: 'Access-Token generated: ' + newTokenDB.id + ' with Refreshtoken-Token: ' + tokenDB.id, - body: { token: newToken }, - type: ['debug', 'info.cyan'] as Logging[] - } - } -} \ No newline at end of file + // Successfull response + return { + req, + res, + result: { + message: + "Access-Token generated: " + + newTokenDB.id + + " with Refreshtoken-Token: " + + tokenDB.id, + body: { token: newToken }, + type: ["debug", "info.cyan"] as Logging[], + }, + } +} diff --git a/leaky-ships/pages/api/data.ts b/leaky-ships/pages/api/data.ts index 5a452ef..46c542a 100644 --- a/leaky-ships/pages/api/data.ts +++ b/leaky-ships/pages/api/data.ts @@ -9,40 +9,44 @@ import { Logging } from "../../lib/backend/logging" import { Game, Player, Token } from "@prisma/client" interface Data { - games: Game[] + games: Game[] } export default async function data( - req: NextApiRequest, - res: NextApiResponse + req: NextApiRequest, + res: NextApiResponse ) { - return getTokenFromBody({ req, res, tokenType: 'ACCESS' as Token['type'] }) - .then(checkTokenIsValid) - .then(getTokenDB) - .then(getPlayerByIdDB) - .then(dataResponse) - .then(sendResponse) - .catch(err => sendError(req, res, err)) + return getTokenFromBody({ req, res, tokenType: "ACCESS" as Token["type"] }) + .then(checkTokenIsValid) + .then(getTokenDB) + .then(getPlayerByIdDB) + .then(dataResponse) + .then(sendResponse) + .catch((err) => sendError(req, res, err)) } async function dataResponse(payload: { - player: Player, - tokenDB: Token, - // games: Game[], - req: NextApiRequest, - res: NextApiResponse + player: Player + tokenDB: Token + // games: Game[], + req: NextApiRequest + res: NextApiResponse }) { - const { player, tokenDB, req, res } = payload + const { player, tokenDB, req, res } = payload - const games: any = {} - // Successfull response - return { - req, - res, - result: { - message: 'Requested data of user: ' + player.id + ' with Access-Token: ' + tokenDB.id, - body: { games }, - type: ['debug', 'info.cyan'] as Logging[] - } - } -} \ No newline at end of file + const games: any = {} + // Successfull response + return { + req, + res, + result: { + message: + "Requested data of user: " + + player.id + + " with Access-Token: " + + tokenDB.id, + body: { games }, + type: ["debug", "info.cyan"] as Logging[], + }, + } +} diff --git a/leaky-ships/pages/api/login.ts b/leaky-ships/pages/api/login.ts index 34d7573..7662533 100644 --- a/leaky-ships/pages/api/login.ts +++ b/leaky-ships/pages/api/login.ts @@ -10,77 +10,89 @@ import { Player, Token } from "@prisma/client" import prisma from "../../lib/prisma" interface Data { - loggedIn: boolean + loggedIn: boolean } export default async function login( - req: NextApiRequest, - res: NextApiResponse + req: NextApiRequest, + res: NextApiResponse ) { - const { username, password } = req.body - return preCheck({ req, res, username, password, newTokenType: 'REFRESH' as Token['type'] }) - .then(getPlayerByNameDB) - .then(checkPasswordIsValid) - .then(createTokenDB) - .then(loginResponse) - .then(sendResponse) - .catch(err => sendError(req, res, err)) + const { username, password } = req.body + return preCheck({ + req, + res, + username, + password, + newTokenType: "REFRESH" as Token["type"], + }) + .then(getPlayerByNameDB) + .then(checkPasswordIsValid) + .then(createTokenDB) + .then(loginResponse) + .then(sendResponse) + .catch((err) => sendError(req, res, err)) } -async function preCheck(payload: T & { - req: NextApiRequest, +async function preCheck( + payload: T & { + req: NextApiRequest res: NextApiResponse -}) { - const { req } = payload - const oldRefreshToken = req.cookies.token - // Check for old cookie, if unused invalidate it - const oldDBToken = await prisma.token.findUnique({ - where: { - token: oldRefreshToken - } + } +) { + const { req } = payload + const oldRefreshToken = req.cookies.token + // Check for old cookie, if unused invalidate it + const oldDBToken = await prisma.token.findUnique({ + where: { + token: oldRefreshToken, + }, + }) + if (oldDBToken?.used) { + await prisma.token.update({ + where: { + token: oldRefreshToken, + }, + data: { + used: true, + }, }) - if (oldDBToken?.used) { - await prisma.token.update({ - where: { - token: oldRefreshToken - }, - data: { - used: true - } - }) - await logging('Old token has been invalidated.', ['debug'], req) - } - return { ...payload, noCookiePresent: true } + await logging("Old token has been invalidated.", ["debug"], req) + } + return { ...payload, noCookiePresent: true } } async function loginResponse(payload: { - player: Player, - passwordIsValid: boolean, - refreshToken: string, - refreshTokenDB: Token, - req: NextApiRequest, - res: NextApiResponse + player: Player + passwordIsValid: boolean + refreshToken: string + refreshTokenDB: Token + req: NextApiRequest + res: NextApiResponse }) { - const { player, refreshToken, refreshTokenDB, req, res } = payload + const { player, refreshToken, refreshTokenDB, req, res } = payload - // Set login cookie - setCookie('token', refreshToken, { - req, - res, - maxAge: 172800000, - httpOnly: true, - sameSite: true, - secure: true, - }) + // Set login cookie + setCookie("token", refreshToken, { + req, + res, + maxAge: 172800000, + httpOnly: true, + sameSite: true, + secure: true, + }) - // Successfull response - return { - req, - res, - result: { - message: 'User ' + player.id + ' logged in and generated Refresh-Token: ' + refreshTokenDB.id, - body: { loggedIn: true }, - type: ['debug', 'info.cyan'] as Logging[] - } - } -} \ No newline at end of file + // Successfull response + return { + req, + res, + result: { + message: + "User " + + player.id + + " logged in and generated Refresh-Token: " + + refreshTokenDB.id, + body: { loggedIn: true }, + type: ["debug", "info.cyan"] as Logging[], + }, + } +} diff --git a/leaky-ships/pages/api/logout.ts b/leaky-ships/pages/api/logout.ts index c3e03db..98b010c 100644 --- a/leaky-ships/pages/api/logout.ts +++ b/leaky-ships/pages/api/logout.ts @@ -9,39 +9,39 @@ import getTokenFromCookie from "../../lib/backend/components/getTokenFromCookie" import logging, { Logging } from "../../lib/backend/logging" interface Data { - loggedOut: boolean + loggedOut: boolean } export default async function logout( - req: NextApiRequest, - res: NextApiResponse + req: NextApiRequest, + res: NextApiResponse ) { - return getTokenFromCookie({ req, res }) - .then(checkTokenIsValid) - .then(getTokenDB) - .then(logoutResponse) - .then(sendResponse) - .catch(err => sendError(req, res, err)) + return getTokenFromCookie({ req, res }) + .then(checkTokenIsValid) + .then(getTokenDB) + .then(logoutResponse) + .then(sendResponse) + .catch((err) => sendError(req, res, err)) } async function logoutResponse(payload: { - tokenDB: Token, - req: NextApiRequest, - res: NextApiResponse + tokenDB: Token + req: NextApiRequest + res: NextApiResponse }) { - const { tokenDB, req, res } = payload + const { tokenDB, req, res } = payload - // Set login cookie - deleteCookie('token', { req, res }) + // Set login cookie + deleteCookie("token", { req, res }) - // Successfull response - return { - req, - res, - result: { - message: 'User of Token ' + tokenDB.id + ' logged out.', - body: { loggedOut: true }, - type: ['debug', 'info.cyan'] as Logging[] - } - } -} \ No newline at end of file + // Successfull response + return { + req, + res, + result: { + message: "User of Token " + tokenDB.id + " logged out.", + body: { loggedOut: true }, + type: ["debug", "info.cyan"] as Logging[], + }, + } +} diff --git a/leaky-ships/pages/api/register.ts b/leaky-ships/pages/api/register.ts index 7895e33..d5e45e9 100644 --- a/leaky-ships/pages/api/register.ts +++ b/leaky-ships/pages/api/register.ts @@ -6,36 +6,36 @@ import { Logging } from "../../lib/backend/logging" import { Player } from "@prisma/client" interface Data { - registered: boolean + registered: boolean } export default async function register( - req: NextApiRequest, - res: NextApiResponse + req: NextApiRequest, + res: NextApiResponse ) { - const { username, password } = req.body - return createPlayerDB({ req, res, username, password }) - .then(registerResponse) - .then(sendResponse) - .catch(err => sendError(req, res, err)) + const { username, password } = req.body + return createPlayerDB({ req, res, username, password }) + .then(registerResponse) + .then(sendResponse) + .catch((err) => sendError(req, res, err)) } async function registerResponse(payload: { - player: Player, - req: NextApiRequest, - res: NextApiResponse + player: Player + req: NextApiRequest + res: NextApiResponse }) { - const { player, req, res } = payload + const { player, req, res } = payload - // Successfull response - return { - req, - res, - result: { - message: 'Player created : ' + player.id, - statusCode: 201, - body: { registered: true }, - type: ['debug', 'info.cyan'] as Logging[] - } - } -} \ No newline at end of file + // Successfull response + return { + req, + res, + result: { + message: "Player created : " + player.id, + statusCode: 201, + body: { registered: true }, + type: ["debug", "info.cyan"] as Logging[], + }, + } +} diff --git a/leaky-ships/pages/api/ws.ts b/leaky-ships/pages/api/ws.ts index 8b73f7d..f6f5a11 100644 --- a/leaky-ships/pages/api/ws.ts +++ b/leaky-ships/pages/api/ws.ts @@ -1,18 +1,18 @@ -import type { NextApiRequest } from 'next' -import { Server } from 'socket.io' -import { NextApiResponseWithSocket } from '../../interfaces/NextApiSocket' +import type { NextApiRequest } from "next" +import { Server } from "socket.io" +import { NextApiResponseWithSocket } from "../../interfaces/NextApiSocket" const SocketHandler = (req: NextApiRequest, res: NextApiResponseWithSocket) => { if (res.socket.server.io) { - console.log('Socket is already running ' + req.url) + console.log("Socket is already running " + req.url) } else { - console.log('Socket is initializing ' + req.url) + console.log("Socket is initializing " + req.url) const io = new Server(res.socket.server) res.socket.server.io = io - io.on('connection', socket => { - socket.on('input-change', msg => { - socket.broadcast.emit('update-input', msg) + io.on("connection", (socket) => { + socket.on("input-change", (msg) => { + socket.broadcast.emit("update-input", msg) }) // console.log(socket.id) // console.log(socket) @@ -23,10 +23,10 @@ const SocketHandler = (req: NextApiRequest, res: NextApiResponseWithSocket) => { // ... }) - socket.emit('test2', 'lol') + socket.emit("test2", "lol") }) } res.end() } -export default SocketHandler \ No newline at end of file +export default SocketHandler diff --git a/leaky-ships/pages/dev/gamefield.tsx b/leaky-ships/pages/dev/gamefield.tsx index b7abb82..b44a91d 100644 --- a/leaky-ships/pages/dev/gamefield.tsx +++ b/leaky-ships/pages/dev/gamefield.tsx @@ -1,5 +1,5 @@ -import Head from 'next/head' -import Gamefield from '../../components/Gamefield' +import Head from "next/head" +import Gamefield from "../../components/Gamefield" export default function Home() { return ( diff --git a/leaky-ships/pages/dev/grid.tsx b/leaky-ships/pages/dev/grid.tsx index b7b52a5..73d3b9f 100644 --- a/leaky-ships/pages/dev/grid.tsx +++ b/leaky-ships/pages/dev/grid.tsx @@ -1,5 +1,5 @@ -import Head from 'next/head' -import Grid from '../../components/Grid' +import Head from "next/head" +import Grid from "../../components/Grid" export default function Home() { return ( diff --git a/leaky-ships/pages/dev/grid2.tsx b/leaky-ships/pages/dev/grid2.tsx index 69afcf9..9e1b598 100644 --- a/leaky-ships/pages/dev/grid2.tsx +++ b/leaky-ships/pages/dev/grid2.tsx @@ -1,5 +1,5 @@ -import Head from 'next/head' -import Grid2 from '../../components/Grid2' +import Head from "next/head" +import Grid2 from "../../components/Grid2" export default function Home() { return ( diff --git a/leaky-ships/pages/dev/index.tsx b/leaky-ships/pages/dev/index.tsx index b7ff43d..2ee42c0 100644 --- a/leaky-ships/pages/dev/index.tsx +++ b/leaky-ships/pages/dev/index.tsx @@ -1,48 +1,52 @@ -import { faPlus, faUserPlus } from '@fortawesome/pro-solid-svg-icons' -import { faEye, faLeftLong } from '@fortawesome/pro-regular-svg-icons' -import { faCirclePlay } from '@fortawesome/pro-thin-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { useState } from 'react' +import { faPlus, faUserPlus } from "@fortawesome/pro-solid-svg-icons" +import { faEye, faLeftLong } from "@fortawesome/pro-regular-svg-icons" +import { faCirclePlay } from "@fortawesome/pro-thin-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { useState } from "react" export default function Home() { - const [heWantsToPlay, setHeWantsToPlay] = useState(false) - return ( -
- +
+
+

Leaky

+

Ships

+
+
+ {!heWantsToPlay ? ( + <> +
+ +
+ + + ) : ( +
+ +
+ -
-
-

Leaky

-

Ships

-
-
- {!heWantsToPlay ? - <> -
- -
- - : -
- -
- - - -
-
} -
- ) + + +
+
+ )} + + ) } diff --git a/leaky-ships/pages/dev/socket.tsx b/leaky-ships/pages/dev/socket.tsx index 7b3d227..31e3be2 100644 --- a/leaky-ships/pages/dev/socket.tsx +++ b/leaky-ships/pages/dev/socket.tsx @@ -1,30 +1,30 @@ -import { ChangeEventHandler, useEffect, useState } from 'react' -import { io } from 'socket.io-client' +import { ChangeEventHandler, useEffect, useState } from "react" +import { io } from "socket.io-client" let socket: ReturnType const Home = () => { - const [input, setInput] = useState('') + const [input, setInput] = useState("") useEffect(() => { socketInitializer() }, []) const socketInitializer = async () => { - await fetch('/api/ws') + await fetch("/api/ws") socket = io() - socket.on('connect', () => { - console.log('connected') + socket.on("connect", () => { + console.log("connected") }) - socket.on('update-input', msg => { + socket.on("update-input", (msg) => { setInput(msg) }) } const onChangeHandler: ChangeEventHandler = (e) => { setInput(e.target.value) - socket.emit('input-change', e.target.value) + socket.emit("input-change", e.target.value) } return ( @@ -36,4 +36,4 @@ const Home = () => { ) } -export default Home \ No newline at end of file +export default Home diff --git a/leaky-ships/pages/dev/socketio.tsx b/leaky-ships/pages/dev/socketio.tsx index 12b7789..ac90b34 100644 --- a/leaky-ships/pages/dev/socketio.tsx +++ b/leaky-ships/pages/dev/socketio.tsx @@ -1,4 +1,4 @@ -import SocketIO from '../../components/SocketIO' +import SocketIO from "../../components/SocketIO" export default function Home() { return ( diff --git a/leaky-ships/pages/index.tsx b/leaky-ships/pages/index.tsx index 2a63814..755105b 100644 --- a/leaky-ships/pages/index.tsx +++ b/leaky-ships/pages/index.tsx @@ -1,5 +1,5 @@ -import Head from 'next/head' -import Link from 'next/link' +import Head from "next/head" +import Link from "next/link" export default function Home() { return ( @@ -11,12 +11,36 @@ export default function Home() {
-

Gamefield

-

Homepage

-

Grid Effect

-

Grid Effect with Content

-

Socket

-

SocketIO

+

+ + Gamefield + +

+

+ + Homepage + +

+

+ + Grid Effect + +

+

+ + Grid Effect with Content + +

+

+ + Socket + +

+

+ + SocketIO + +

) diff --git a/leaky-ships/styles/App.scss b/leaky-ships/styles/App.scss index 00b66ac..e162bf7 100644 --- a/leaky-ships/styles/App.scss +++ b/leaky-ships/styles/App.scss @@ -1,6 +1,6 @@ -@use './mixins/display' as *; -@use './mixins/effects' as *; -@import './mixins/variables'; +@use "./mixins/display" as *; +@use "./mixins/effects" as *; +@import "./mixins/variables"; html, body, @@ -10,8 +10,8 @@ body, body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; } @@ -69,15 +69,15 @@ body { display: grid; align-items: center; justify-items: center; - grid-template-rows: .75fr repeat(12, 1fr) .75fr; - grid-template-columns: .75fr repeat(12, 1fr) .75fr; + grid-template-rows: 0.75fr repeat(12, 1fr) 0.75fr; + grid-template-columns: 0.75fr repeat(12, 1fr) 0.75fr; - >.label { + > .label { grid-column: var(--x); grid-row: var(--y); } - >.border-tile { + > .border-tile { box-sizing: border-box; border: 1px solid blue; height: 100%; @@ -96,7 +96,7 @@ body { box-sizing: border-box; } - >span { + > span { vertical-align: center; user-select: none; } @@ -172,7 +172,7 @@ body { &.preview { opacity: 0; - @include transition(.5s); + @include transition(0.5s); } &.radar { @@ -184,7 +184,7 @@ body { &:not(.left):not(.right):not(.top):not(.bottom) { // border: 5px solid var(--color); - grid-area: var(--y1) /var(--x1) /var(--y2) /var(--x2); + grid-area: var(--y1) / var(--x1) / var(--y2) / var(--x2); svg { opacity: 1; @@ -207,7 +207,7 @@ body { opacity: 1; } - &.imply>svg { + &.imply > svg { opacity: 0; } @@ -300,7 +300,7 @@ body { .item { @include flex-col; align-items: center; - gap: .5rem; + gap: 0.5rem; width: 128px; .container { @@ -332,8 +332,8 @@ body { span { color: black; - font-size: .75em; + font-size: 0.75em; font-weight: bold; } } -} \ No newline at end of file +} diff --git a/leaky-ships/styles/globals.css b/leaky-ships/styles/globals.css index bd6213e..b5c61c9 100644 --- a/leaky-ships/styles/globals.css +++ b/leaky-ships/styles/globals.css @@ -1,3 +1,3 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; diff --git a/leaky-ships/styles/grid.scss b/leaky-ships/styles/grid.scss index 2177422..461dfac 100644 --- a/leaky-ships/styles/grid.scss +++ b/leaky-ships/styles/grid.scss @@ -1,36 +1,34 @@ -@use './mixins/effects' as *; +@use "./mixins/effects" as *; #tiles { - height: 100vh; - width: 100vw; - display: grid; - grid-template-columns: repeat(var(--columns), 1fr); - grid-template-rows: repeat(var(--rows), 1fr); + height: 100vh; + width: 100vw; + display: grid; + grid-template-columns: repeat(var(--columns), 1fr); + grid-template-rows: repeat(var(--rows), 1fr); - .tile { - background-color: var(--bg-color-1); + .tile { + background-color: var(--bg-color-1); - &.active { - animation: bright .3s forwards; - animation-delay: var(--delay); - } + &.active { + animation: bright 0.3s forwards; + animation-delay: var(--delay); } + } } @keyframes bright { - 0% { - background-color: var(--bg-color-1); - } + 0% { + background-color: var(--bg-color-1); + } - 50% { + 50% { + background-color: var(--bg-color-2); + filter: brightness(130%); + outline: 1px solid white; + } - background-color: var(--bg-color-2); - filter: brightness(130%); - outline: 1px solid white; - } - - 100% { - - background-color: var(--bg-color-2); - } -} \ No newline at end of file + 100% { + background-color: var(--bg-color-2); + } +} diff --git a/leaky-ships/styles/grid2.scss b/leaky-ships/styles/grid2.scss index b405784..2909df8 100644 --- a/leaky-ships/styles/grid2.scss +++ b/leaky-ships/styles/grid2.scss @@ -1,94 +1,94 @@ -@use './mixins/effects' as *; +@use "./mixins/effects" as *; $g1: rgb(98, 0, 234); $g2: rgb(236, 64, 122); #tiles { + height: 100vh; + width: 100vw; + display: grid; + grid-template-columns: repeat(var(--columns), 1fr); + grid-template-rows: repeat(var(--rows), 1fr); + background: linear-gradient(to right, $g1, $g2, $g1); + background-size: 200%; + animation: background-pan 10s linear infinite; + + .tile { + position: relative; + + &::before { + position: absolute; + content: ""; + background-color: rgb(20, 20, 20); + inset: 1px; + } + + &.active { + opacity: 1; + animation: hide 0.2s forwards; + animation-delay: var(--delay); + } + + &.inactive { + opacity: 0; + animation: show 0.2s forwards; + animation-delay: var(--delay); + } + } + + .center-div { + position: absolute; height: 100vh; width: 100vw; - display: grid; - grid-template-columns: repeat(var(--columns), 1fr); - grid-template-rows: repeat(var(--rows), 1fr); - background: linear-gradient(to right, $g1, $g2, $g1); - background-size: 200%; - animation: background-pan 10s linear infinite; + display: inherit; - .tile { - position: relative; + .headline { + margin: auto; + font-size: 5em; + background-color: rgba(20, 20, 20, 0.2); + padding: 0.25em 0.5em; + border-radius: 0.25em; - &::before { - position: absolute; - content: ''; - background-color: rgb(20, 20, 20); - inset: 1px; - } + &.active { + opacity: 1; + animation: hide 2s forwards; + // animation-delay: 1s; + } - &.active { - opacity: 1; - animation: hide .2s forwards; - animation-delay: var(--delay); - } - - &.inactive { - opacity: 0; - animation: show .2s forwards; - animation-delay: var(--delay); - } - } - - .center-div { - position: absolute; - height: 100vh; - width: 100vw; - display: inherit; - - .headline { - margin: auto; - font-size: 5em; - background-color: rgba(20, 20, 20, 0.2); - padding: .25em .5em; - border-radius: .25em; - - &.active { - opacity: 1; - animation: hide 2s forwards; - // animation-delay: 1s; - } - - &.inactive { - opacity: 0; - animation: show 2s forwards; - // animation-delay: 1s; - } - } + &.inactive { + opacity: 0; + animation: show 2s forwards; + // animation-delay: 1s; + } } + } } @keyframes background-pan { - from { - background-position: 0% center; - } + from { + background-position: 0% center; + } - to { - background-position: -200% center; - } + to { + background-position: -200% center; + } } @keyframes hide { - 0% { - opacity: 1; - } + 0% { + opacity: 1; + } - 100% { - opacity: 0; - } + 100% { + opacity: 0; + } } @keyframes show { - 0% { - opacity: 0; - } + 0% { + opacity: 0; + } - 100% { - opacity: 1; - } -} \ No newline at end of file + 100% { + opacity: 1; + } +} diff --git a/leaky-ships/styles/homepage.scss b/leaky-ships/styles/homepage.scss index a84823d..d54cc1d 100644 --- a/leaky-ships/styles/homepage.scss +++ b/leaky-ships/styles/homepage.scss @@ -1,338 +1,330 @@ -@use './mixins/display' as *; -@use './mixins/effects' as *; -@use './mixins/CP_Font' as *; -@import './mixins/variables'; +@use "./mixins/display" as *; +@use "./mixins/effects" as *; +@use "./mixins/CP_Font" as *; +@import "./mixins/variables"; - -@import url('https://fonts.googleapis.com/css2?family=Farro:wght@300;400;500;700&display=swap'); +@import url("https://fonts.googleapis.com/css2?family=Farro:wght@300;400;500;700&display=swap"); #box { - min-height: 100%; - background-color: #282c34; - @include flex-col; + min-height: 100%; + background-color: #282c34; + @include flex-col; + align-items: center; + justify-content: space-around; + + #navExpand { + @include flex; align-items: center; - justify-content: space-around; + justify-content: center; + position: absolute; + top: 64px; + left: 64px; + width: 96px; + height: 96px; + background-color: $grayish; + border-radius: 8px; + box-shadow: 0 0 2px 2px #0008 inset; - #navExpand { - @include flex; - align-items: center; - justify-content: center; - position: absolute; - top: 64px; - left: 64px; - width: 96px; - height: 96px; - background-color: $grayish; - border-radius: 8px; - box-shadow: 0 0 2px 2px #0008 inset; + #burgerMenu { + @include pixelart; + height: 84px; + width: 84px; + } + } - #burgerMenu { - @include pixelart; - height: 84px; - width: 84px; + #shield { + @include flex-row; + justify-content: center; + height: 250px; + width: 700px; + background-image: url("/assets/shield.png"); + background-repeat: no-repeat; + background-size: contain; + + #width { + @include flex-col; + justify-content: space-between; + + h1 { + @include CP_Font; + margin: 3%; + width: 100%; + text-align: center; + font-size: 5.8em; + letter-spacing: 6px; + + &:first-child { + border-top: 5px solid black; } + + &:last-child { + border-bottom: 5px solid black; + } + } + } + } + + #videoWrapper { + position: relative; + display: flex; + align-items: center; + justify-content: center; + height: 350px; + width: 700px; + background-color: #2227; + border: 4px solid black; + border-radius: 8px; + + svg { + font-size: 6em; + color: #231f20; + + path { + stroke: black; + stroke-width: 2px; + stroke-linejoin: round; + } + } + } + + #startButton { + font-family: "Farro", sans-serif; + font-weight: bold; + font-size: 3em; + color: black; + background-color: $warn; + border: none; + border-radius: 8px; + padding: calc(2rem + 8px) 6rem 2rem 6rem; + } + + #startBox { + display: flex; + flex-direction: column; + align-items: center; + background-color: $grayish; + box-shadow: 0 0 2px 2px #fffb inset, 0 0 2px 2px #fff2; + border: 4px solid black; + padding: 3rem; + border-radius: 8px; + min-width: 60vw; + gap: 2rem; + + #back { + font-size: 3em; + color: $grayish; + align-self: flex-start; + background-color: #000c; + border: none; + border-radius: 8px; + padding: 0 0.5rem; + margin-top: -1.5rem; + width: 10rem; + box-shadow: 0 0 2px 2px #fff6 inset; + border: 2px solid #000c; } - #shield { + #sameWidth { + display: flex; + flex-direction: column; + align-items: center; + gap: 3rem; + + .optionButton { @include flex-row; - justify-content: center; - height: 250px; - width: 700px; - background-image: url("/assets/shield.png"); - background-repeat: no-repeat; - background-size: contain; - - #width { - @include flex-col; - justify-content: space-between; - - h1 { - @include CP_Font; - margin: 3%; - width: 100%; - text-align: center; - font-size: 5.8em; - letter-spacing: 6px; - - &:first-child { - border-top: 5px solid black; - } - - &:last-child { - border-bottom: 5px solid black; - } - } - } - } - - #videoWrapper { - position: relative; - display: flex; + justify-content: space-between; align-items: center; - justify-content: center; - height: 350px; - width: 700px; - background-color: #2227; - border: 4px solid black; - border-radius: 8px; - - svg { - font-size: 6em; - color: #231f20; - - path { - stroke: black; - stroke-width: 2px; - stroke-linejoin: round; - } - } - } - - #startButton { - font-family: 'Farro', sans-serif; - font-weight: bold; - font-size: 3em; - color: black; - background-color: $warn; + font-size: 2.5em; + color: $grayish; + background-color: #000c; border: none; border-radius: 8px; - padding: calc(2rem + 8px) 6rem 2rem 6rem; - } + padding: 1rem 2rem 1rem 4rem; + width: 100%; + box-shadow: 0 0 2px 2px #fff6 inset; + border: 2px solid #000c; - #startBox { - display: flex; - flex-direction: column; - align-items: center; - background-color: $grayish; - box-shadow: 0 0 2px 2px #fffb inset, 0 0 2px 2px #fff2; - border: 4px solid black; - padding: 3rem; - border-radius: 8px; - min-width: 60vw; - gap: 2rem; - - #back { - font-size: 3em; - color: $grayish; - align-self: flex-start; - background-color: #000C; - border: none; - border-radius: 8px; - padding: 0 .5rem; - margin-top: -1.5rem; - width: 10rem; - box-shadow: 0 0 2px 2px #fff6 inset; - border: 2px solid #000C; + &:last-child { + margin-top: 2rem; } - #sameWidth { - display: flex; - flex-direction: column; - align-items: center; - gap: 3rem; - - .optionButton { - @include flex-row; - justify-content: space-between; - align-items: center; - font-size: 2.5em; - color: $grayish; - background-color: #000C; - border: none; - border-radius: 8px; - padding: 1rem 2rem 1rem 4rem; - width: 100%; - box-shadow: 0 0 2px 2px #fff6 inset; - border: 2px solid #000C; - - &:last-child { - margin-top: 2rem; - } - - span { - margin: 0 auto; - } - - svg { - margin-left: 3rem; - font-size: 2em; - width: 2.5rem; - height: inherit; - } - } - + span { + margin: 0 auto; } + svg { + margin-left: 3rem; + font-size: 2em; + width: 2.5rem; + height: inherit; + } + } } + } } @media (max-width: 2000px) { - #box { - #shield { - height: 200px; - width: 560px; + #box { + #shield { + height: 200px; + width: 560px; - #width { + #width { + h1 { + font-size: 4.5em; + letter-spacing: 4px; - h1 { - font-size: 4.5em; - letter-spacing: 4px; + &:first-child { + border-top: 4px solid black; + } - &:first-child { - border-top: 4px solid black; - } - - &:last-child { - border-bottom: 4px solid black; - } - } - } + &:last-child { + border-bottom: 4px solid black; + } } + } } + } } @media (max-width: 1000px) { - #box { - #navExpand { - top: 32px; - left: 32px; - width: 80px; - height: 80px; + #box { + #navExpand { + top: 32px; + left: 32px; + width: 80px; + height: 80px; - #burgerMenu { - height: 64px; - width: 64px; - } - } - - #shield { - height: 160px; - width: 450px; - - #width { - - h1 { - font-size: 3.6em; - letter-spacing: 3px; - - &:first-child { - border-top: 3px solid black; - } - - &:last-child { - border-bottom: 3px solid black; - } - } - } - } - - #videoWrapper { - height: 300px; - width: 600px; - } + #burgerMenu { + height: 64px; + width: 64px; + } } + + #shield { + height: 160px; + width: 450px; + + #width { + h1 { + font-size: 3.6em; + letter-spacing: 3px; + + &:first-child { + border-top: 3px solid black; + } + + &:last-child { + border-bottom: 3px solid black; + } + } + } + } + + #videoWrapper { + height: 300px; + width: 600px; + } + } } @media (max-width: 700px) { - #box { - justify-content: space-evenly; + #box { + justify-content: space-evenly; - #navExpand { - top: 16px; - left: 16px; - width: 64px; - height: 64px; + #navExpand { + top: 16px; + left: 16px; + width: 64px; + height: 64px; - #burgerMenu { - height: 44px; - width: 44px; - } - } - - #shield { - height: 100px; - width: 280px; - - #width { - - h1 { - font-size: 2.2em; - letter-spacing: 2px; - - &:first-child { - border-top: 2px solid black; - } - - &:last-child { - border-bottom: 2px solid black; - } - } - } - } - - #videoWrapper { - height: 250px; - width: 450px; - - svg { - font-size: 4em; - } - } - - #startButton { - font-size: 2em; - padding: calc(1rem + 8px) 3rem 1rem 3rem; - } - - #startBox { - max-width: 90vw; - padding: 2rem; - - #back { - margin-top: -1rem; - font-size: 2em; - width: 7rem; - padding: .125rem; - } - - #sameWidth { - max-width: 100%; - - .optionButton { - font-size: 2em; - padding: 1rem 2rem; - - svg { - margin-left: 2rem; - font-size: 1.5em; - width: 2rem; - } - } - } - } + #burgerMenu { + height: 44px; + width: 44px; + } } + + #shield { + height: 100px; + width: 280px; + + #width { + h1 { + font-size: 2.2em; + letter-spacing: 2px; + + &:first-child { + border-top: 2px solid black; + } + + &:last-child { + border-bottom: 2px solid black; + } + } + } + } + + #videoWrapper { + height: 250px; + width: 450px; + + svg { + font-size: 4em; + } + } + + #startButton { + font-size: 2em; + padding: calc(1rem + 8px) 3rem 1rem 3rem; + } + + #startBox { + max-width: 90vw; + padding: 2rem; + + #back { + margin-top: -1rem; + font-size: 2em; + width: 7rem; + padding: 0.125rem; + } + + #sameWidth { + max-width: 100%; + + .optionButton { + font-size: 2em; + padding: 1rem 2rem; + + svg { + margin-left: 2rem; + font-size: 1.5em; + width: 2rem; + } + } + } + } + } } - @media (max-width: 500px) { - #box { - #videoWrapper { - height: 150px; - width: 300px; - } - - #startBox { - #sameWidth { - - .optionButton { - font-size: 1.5em; - - svg { - margin-left: 1rem; - font-size: 1em; - } - } - } - } + #box { + #videoWrapper { + height: 150px; + width: 300px; } -} \ No newline at end of file + + #startBox { + #sameWidth { + .optionButton { + font-size: 1.5em; + + svg { + margin-left: 1rem; + font-size: 1em; + } + } + } + } + } +} diff --git a/leaky-ships/styles/mixins/CP_Font.scss b/leaky-ships/styles/mixins/CP_Font.scss index 02cef59..cefb5a9 100644 --- a/leaky-ships/styles/mixins/CP_Font.scss +++ b/leaky-ships/styles/mixins/CP_Font.scss @@ -1,9 +1,8 @@ @font-face { - font-family: "CP_Font"; - src: url("/fonts/cpfont_ote/CP Font.otf") format("opentype"); + font-family: "CP_Font"; + src: url("/fonts/cpfont_ote/CP Font.otf") format("opentype"); } - @mixin CP_Font { - font-family: "CP_Font", sans-serif; -} \ No newline at end of file + font-family: "CP_Font", sans-serif; +} diff --git a/leaky-ships/styles/mixins/display.scss b/leaky-ships/styles/mixins/display.scss index 6edb39c..9fe7df2 100644 --- a/leaky-ships/styles/mixins/display.scss +++ b/leaky-ships/styles/mixins/display.scss @@ -1,11 +1,11 @@ @mixin flex { - display: flex; + display: flex; } @mixin flex-col { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } @mixin flex-row { - display: flex; - flex-direction: row; -} \ No newline at end of file + display: flex; + flex-direction: row; +} diff --git a/leaky-ships/styles/mixins/effects.scss b/leaky-ships/styles/mixins/effects.scss index 28598d0..82956ff 100644 --- a/leaky-ships/styles/mixins/effects.scss +++ b/leaky-ships/styles/mixins/effects.scss @@ -1,61 +1,157 @@ @mixin transition($timing) { - -moz-transition: $timing; - -webkit-transition: $timing; - -o-transition: $timing; - -ms-transition: $timing; - transition: $timing; + -moz-transition: $timing; + -webkit-transition: $timing; + -o-transition: $timing; + -ms-transition: $timing; + transition: $timing; } @mixin appear($timing) { - animation: appear $timing forwards; + animation: appear $timing forwards; } @keyframes appear { - From { - opacity: 0; - } - To { - opacity: 1; - } + from { + opacity: 0; + } + to { + opacity: 1; + } } @mixin gradient-edge { - &.left-top-corner { - mask-image: -webkit-gradient(linear, right bottom, left top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, right bottom, left top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - } - &.right-top-corner { - mask-image: -webkit-gradient(linear, left bottom, right top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, left bottom, right top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - } - &.left-bottom-corner { - mask-image: -webkit-gradient(linear, right top, left bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, right top, left bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - } - &.right-bottom-corner { - mask-image: -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0))); - } + &.left-top-corner { + mask-image: -webkit-gradient( + linear, + right bottom, + left top, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + right bottom, + left top, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + } + &.right-top-corner { + mask-image: -webkit-gradient( + linear, + left bottom, + right top, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + left bottom, + right top, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + } + &.left-bottom-corner { + mask-image: -webkit-gradient( + linear, + right top, + left bottom, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + right top, + left bottom, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + } + &.right-bottom-corner { + mask-image: -webkit-gradient( + linear, + left top, + right bottom, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + left top, + right bottom, + color-stop(0, rgba(0, 0, 0, 1)), + color-stop(0.5, rgba(0, 0, 0, 0)) + ); + } - &.left { - mask-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - } - &.right { - mask-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - } - &.top { - mask-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - } - &.bottom { - mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - -webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); - } + &.left { + mask-image: -webkit-gradient( + linear, + right top, + left top, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + right top, + left top, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + } + &.right { + mask-image: -webkit-gradient( + linear, + left top, + right top, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + left top, + right top, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + } + &.top { + mask-image: -webkit-gradient( + linear, + left bottom, + left top, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + left bottom, + left top, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + } + &.bottom { + mask-image: -webkit-gradient( + linear, + left top, + left bottom, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + -webkit-mask-image: -webkit-gradient( + linear, + left top, + left bottom, + from(rgba(0, 0, 0, 1)), + to(rgba(0, 0, 0, 0)) + ); + } } // Pixelart sharpness (no interpolation) // https://css-tricks.com/keep-pixelated-images-pixelated-as-they-scale/ @mixin pixelart { - image-rendering: pixelated; - image-rendering: -moz-crisp-edges; - image-rendering: crisp-edges; -} \ No newline at end of file + image-rendering: pixelated; + image-rendering: -moz-crisp-edges; + image-rendering: crisp-edges; +} diff --git a/leaky-ships/styles/mixins/variables.scss b/leaky-ships/styles/mixins/variables.scss index a29f8c6..e8d7033 100644 --- a/leaky-ships/styles/mixins/variables.scss +++ b/leaky-ships/styles/mixins/variables.scss @@ -1,3 +1,3 @@ $theme: #282c34; -$grayish: #B1B2B5CC; -$warn: #fabd04; \ No newline at end of file +$grayish: #b1b2b5cc; +$warn: #fabd04; diff --git a/leaky-ships/tailwind.config.js b/leaky-ships/tailwind.config.js index 812b8ed..f8ecd2c 100644 --- a/leaky-ships/tailwind.config.js +++ b/leaky-ships/tailwind.config.js @@ -8,4 +8,4 @@ module.exports = { extend: {}, }, plugins: [], -} \ No newline at end of file +}