diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..1103a9f --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 300, + "trailingComma": "none" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0aee5c5..46481c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,25 +5,26 @@ "packages": { "": { "dependencies": { - "@prisma/client": "^5.13.0", + "@prisma/client": "^5.17.0", "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "jsonwebtoken": "^9.0.2", - "prisma": "^5.13.0", + "prisma": "^5.17.0", "sharp": "^0.33.4", "socket.io": "^4.7.5", "ts-node": "^10.9.2", - "typescript": "^5.4.5", + "typescript": "^5.5.3", "zod": "^3.23.8" }, "devDependencies": { "@types/bcryptjs": "^2.4.6", "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.6", - "@types/node": "^20.12.11", - "nodemon": "^3.1.0" + "@types/node": "^20.14.11", + "nodemon": "^3.1.4", + "prettier": "^3.3.3" } }, "node_modules/@cspotcode/source-map-support": { @@ -1886,6 +1887,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prisma": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.17.0.tgz", diff --git a/package.json b/package.json index 7cc09f7..d5d6a60 100644 --- a/package.json +++ b/package.json @@ -2,27 +2,29 @@ "scripts": { "start": "npx prisma migrate deploy && node dist/server.js", "dev": "nodemon --exec ts-node src/server.ts", - "build": "tsc" + "build": "tsc", + "format": "prettier --write src/" }, "dependencies": { - "@prisma/client": "^5.13.0", + "@prisma/client": "^5.17.0", "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "jsonwebtoken": "^9.0.2", - "prisma": "^5.13.0", + "prisma": "^5.17.0", "sharp": "^0.33.4", "socket.io": "^4.7.5", "ts-node": "^10.9.2", - "typescript": "^5.4.5", + "typescript": "^5.5.3", "zod": "^3.23.8" }, "devDependencies": { "@types/bcryptjs": "^2.4.6", "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.6", - "@types/node": "^20.12.11", - "nodemon": "^3.1.0" + "@types/node": "^20.14.11", + "nodemon": "^3.1.4", + "prettier": "^3.3.3" } } diff --git a/src/commands/alert.ts b/src/commands/alert.ts index 2ededa8..779bbd2 100644 --- a/src/commands/alert.ts +++ b/src/commands/alert.ts @@ -1,9 +1,9 @@ -import { Server } from "socket.io"; +import { Server } from 'socket.io' type CommandInput = string[] export default function (input: CommandInput, io: Server) { - const message: string = input.join(' ') ?? null; - if (!message) return console.log('message is required'); - io.emit('notification', {message: message}); -}; \ No newline at end of file + const message: string = input.join(' ') ?? null + if (!message) return console.log('message is required') + io.emit('notification', { message: message }) +} diff --git a/src/commands/listZones.ts b/src/commands/listZones.ts index 33a17bf..ef77824 100644 --- a/src/commands/listZones.ts +++ b/src/commands/listZones.ts @@ -1,8 +1,8 @@ -import { Server } from "socket.io"; -import ZoneManager from "../managers/ZoneManager"; +import { Server } from 'socket.io' +import ZoneManager from '../managers/ZoneManager' type CommandInput = string[] export default function (input: CommandInput, io: Server) { - console.log(ZoneManager.getLoadedZones()) -}; \ No newline at end of file + console.log(ZoneManager.getLoadedZones()) +} diff --git a/src/events/Disconnect.ts b/src/events/Disconnect.ts index fc8e287..7e1eeff 100644 --- a/src/events/Disconnect.ts +++ b/src/events/Disconnect.ts @@ -1,23 +1,23 @@ -import { Server } from "socket.io"; -import {TSocket} from "../utilities/Types"; -import ZoneManager from "../managers/ZoneManager"; +import { Server } from 'socket.io' +import { TSocket } from '../utilities/Types' +import ZoneManager from '../managers/ZoneManager' export default function (socket: TSocket, io: Server) { - socket.on('disconnect', (data: any) => { - if (!socket.user) { - console.log('User disconnected but had no user set'); - return; - } + socket.on('disconnect', (data: any) => { + if (!socket.user) { + console.log('User disconnected but had no user set') + return + } - io.emit('user:disconnect', socket.user.id); + io.emit('user:disconnect', socket.user.id) - if (!socket.character) { - console.log('User disconnected but had no character set'); - return; - } + if (!socket.character) { + console.log('User disconnected but had no character set') + return + } - ZoneManager.removeCharacterFromZone(socket.character.zoneId, socket.character); + ZoneManager.removeCharacterFromZone(socket.character.zoneId, socket.character) - io.emit('character:disconnect', socket.character.id); - }); -} \ No newline at end of file + io.emit('character:disconnect', socket.character.id) + }) +} diff --git a/src/events/Login.ts b/src/events/Login.ts index d5bb1c2..423388d 100644 --- a/src/events/Login.ts +++ b/src/events/Login.ts @@ -1,9 +1,9 @@ -import { Server } from "socket.io"; -import {TSocket} from "../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../utilities/Types' export default function (socket: TSocket, io: Server) { - socket.on('login', () => { - // return user data - socket.emit('logged_in', {user: socket.user}); - }); -} \ No newline at end of file + socket.on('login', () => { + // return user data + socket.emit('logged_in', { user: socket.user }) + }) +} diff --git a/src/events/character/CharacterConnect.ts b/src/events/character/CharacterConnect.ts index 0af0a03..e476d90 100644 --- a/src/events/character/CharacterConnect.ts +++ b/src/events/character/CharacterConnect.ts @@ -1,20 +1,20 @@ -import { Socket, Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import CharacterRepository from "../../repositories/CharacterRepository"; -import {Character, User} from "@prisma/client"; +import { Socket, Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' +import CharacterRepository from '../../repositories/CharacterRepository' +import { Character, User } from '@prisma/client' type SocketResponseT = { - character_id: number + character_id: number } export default function (socket: TSocket, io: Server) { - socket.on('character:connect', async (data: SocketResponseT) => { - console.log('character:connect requested', data); - try { - socket.character = await CharacterRepository.getByUserAndId(socket.user?.id as number, data.character_id) as Character; - socket.emit('character:connect', socket.character) - } catch (error: any) { - console.log('character:connect error', error); - } - }); -} \ No newline at end of file + socket.on('character:connect', async (data: SocketResponseT) => { + console.log('character:connect requested', data) + try { + socket.character = (await CharacterRepository.getByUserAndId(socket.user?.id as number, data.character_id)) as Character + socket.emit('character:connect', socket.character) + } catch (error: any) { + console.log('character:connect error', error) + } + }) +} diff --git a/src/events/character/CharacterCreate.ts b/src/events/character/CharacterCreate.ts index 1f77c71..a55ae46 100644 --- a/src/events/character/CharacterCreate.ts +++ b/src/events/character/CharacterCreate.ts @@ -1,37 +1,37 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import {Character} from "@prisma/client"; -import CharacterRepository from "../../repositories/CharacterRepository"; -import {ZCharacterCreate} from "../../utilities/ZodTypes"; +import { Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' +import { Character } from '@prisma/client' +import CharacterRepository from '../../repositories/CharacterRepository' +import { ZCharacterCreate } from '../../utilities/ZodTypes' export default function (socket: TSocket, io: Server) { - socket.on('character:create', async (data: any) => { - // zod validate - try { - data = ZCharacterCreate.parse(data); + socket.on('character:create', async (data: any) => { + // zod validate + try { + data = ZCharacterCreate.parse(data) - const user_id = socket.user?.id as number; + const user_id = socket.user?.id as number - // Check if character name already exists - const characterExists = await CharacterRepository.getByName(data.name); + // Check if character name already exists + const characterExists = await CharacterRepository.getByName(data.name) - if (characterExists) { - return socket.emit('notification', {message: 'Character name already exists'}); - } + if (characterExists) { + return socket.emit('notification', { message: 'Character name already exists' }) + } - let characters: Character[] = await CharacterRepository.getByUserId(user_id) as Character[]; + let characters: Character[] = (await CharacterRepository.getByUserId(user_id)) as Character[] - if (characters.length >= 4) { - return socket.emit('notification', {message: 'You can only have 4 characters'}); - } + if (characters.length >= 4) { + return socket.emit('notification', { message: 'You can only have 4 characters' }) + } - const character: Character = await CharacterRepository.create(user_id, data.name, 'player') as Character; - characters = [...characters, character]; + const character: Character = (await CharacterRepository.create(user_id, data.name, 'player')) as Character + characters = [...characters, character] - socket.emit('character:create:success'); - socket.emit('character:list', characters); - } catch (error: any) { - return socket.emit('notification', {message: error.errors[0]?.message ?? 'Invalid data'}); - } - }); -} \ No newline at end of file + socket.emit('character:create:success') + socket.emit('character:list', characters) + } catch (error: any) { + return socket.emit('notification', { message: error.errors[0]?.message ?? 'Invalid data' }) + } + }) +} diff --git a/src/events/character/CharacterDelete.ts b/src/events/character/CharacterDelete.ts index a453003..5622f3c 100644 --- a/src/events/character/CharacterDelete.ts +++ b/src/events/character/CharacterDelete.ts @@ -1,30 +1,30 @@ -import {Server} from "socket.io"; -import {TSocket} from "../../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' import { Character, Zone } from '@prisma/client' -import CharacterRepository from "../../repositories/CharacterRepository"; +import CharacterRepository from '../../repositories/CharacterRepository' type TypePayload = { - character_id: number; + character_id: number } type TypeResponse = { - zone: Zone; - characters: Character[]; + zone: Zone + characters: Character[] } export default function (socket: TSocket, io: Server) { - socket.on('character:delete', async (data: TypePayload, callback: (response: TypeResponse) => void) => { - // zod validate - try { - await CharacterRepository.deleteByUserIdAndId(socket.user?.id as number, data.character_id as number); + socket.on('character:delete', async (data: TypePayload, callback: (response: TypeResponse) => void) => { + // zod validate + try { + await CharacterRepository.deleteByUserIdAndId(socket.user?.id as number, data.character_id as number) - const user_id = socket.user?.id as number; - const characters: Character[] = await CharacterRepository.getByUserId(user_id) as Character[]; + const user_id = socket.user?.id as number + const characters: Character[] = (await CharacterRepository.getByUserId(user_id)) as Character[] - socket.emit('character:list', characters); - } catch (error: any) { - console.log(error); - return socket.emit('notification', {message: 'Character delete failed. Please try again.'}); - } - }); -} \ No newline at end of file + socket.emit('character:list', characters) + } catch (error: any) { + console.log(error) + return socket.emit('notification', { message: 'Character delete failed. Please try again.' }) + } + }) +} diff --git a/src/events/character/CharacterList.ts b/src/events/character/CharacterList.ts index b721fd4..17531f0 100644 --- a/src/events/character/CharacterList.ts +++ b/src/events/character/CharacterList.ts @@ -1,17 +1,17 @@ -import { Socket, Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import {Character} from "@prisma/client"; -import CharacterRepository from "../../repositories/CharacterRepository"; +import { Socket, Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' +import { Character } from '@prisma/client' +import CharacterRepository from '../../repositories/CharacterRepository' export default function CharacterList(socket: TSocket, io: Server) { - socket.on('character:list', async (data: any) => { - try { - console.log('character:list requested'); - const user_id = socket.user?.id as number; - const characters: Character[] = await CharacterRepository.getByUserId(user_id) as Character[]; - socket.emit('character:list', characters); - } catch (error: any) { - console.log('character:list error', error); - } - }); -} \ No newline at end of file + socket.on('character:list', async (data: any) => { + try { + console.log('character:list requested') + const user_id = socket.user?.id as number + const characters: Character[] = (await CharacterRepository.getByUserId(user_id)) as Character[] + socket.emit('character:list', characters) + } catch (error: any) { + console.log('character:list error', error) + } + }) +} diff --git a/src/events/character/CharacterMove.ts b/src/events/character/CharacterMove.ts index fa44e39..c44a7f7 100644 --- a/src/events/character/CharacterMove.ts +++ b/src/events/character/CharacterMove.ts @@ -1,33 +1,33 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import CharacterRepository from "../../repositories/CharacterRepository"; -import ZoneManager from "../../managers/ZoneManager"; +import { Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' +import CharacterRepository from '../../repositories/CharacterRepository' +import ZoneManager from '../../managers/ZoneManager' type SocketResponseT = { - position_x: number, - position_y: number, + position_x: number + position_y: number } export default function (socket: TSocket, io: Server) { - socket.on('character:move', async (data: SocketResponseT) => { - try { - console.log('character:move requested', data); + socket.on('character:move', async (data: SocketResponseT) => { + try { + console.log('character:move requested', data) - if (!socket.character) { - console.log('character:move error', 'Character not found'); - return; - } + if (!socket.character) { + console.log('character:move error', 'Character not found') + return + } - socket.character.position_x = data.position_x; - socket.character.position_y = data.position_y; + socket.character.position_x = data.position_x + socket.character.position_y = data.position_y - await CharacterRepository.updatePosition(socket.character.id as number, data.position_x, data.position_y); - ZoneManager.updateCharacterInZone(socket.character.zoneId, socket.character); - console.log(socket.character); + await CharacterRepository.updatePosition(socket.character.id as number, data.position_x, data.position_y) + ZoneManager.updateCharacterInZone(socket.character.zoneId, socket.character) + console.log(socket.character) - io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character); - } catch (error: any) { - console.log('character:move error', error); - } - }); -} \ No newline at end of file + io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character) + } catch (error: any) { + console.log('character:move error', error) + } + }) +} diff --git a/src/events/character/CharacterZoneLeave.ts b/src/events/character/CharacterZoneLeave.ts index 8450db3..6adba2f 100644 --- a/src/events/character/CharacterZoneLeave.ts +++ b/src/events/character/CharacterZoneLeave.ts @@ -1,8 +1,8 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import ZoneRepository from "../../repositories/ZoneRepository"; -import ZoneManager from "../../managers/ZoneManager"; -import {Character, Zone} from "@prisma/client"; +import { Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' +import ZoneRepository from '../../repositories/ZoneRepository' +import ZoneManager from '../../managers/ZoneManager' +import { Character, Zone } from '@prisma/client' /** * Handle character zone leave event @@ -10,39 +10,39 @@ import {Character, Zone} from "@prisma/client"; * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('character:zone:leave', async () => { - console.log(`---Socket ${socket.character?.id} has leaved zone.`); + socket.on('character:zone:leave', async () => { + console.log(`---Socket ${socket.character?.id} has leaved zone.`) - if (!socket.character) { - console.log('Socket leaved zone but had no character set'); - return; - } + if (!socket.character) { + console.log('Socket leaved zone but had no character set') + return + } - if (!socket.character.zoneId) { - console.log(`---Zone id not provided.`); - return; - } + if (!socket.character.zoneId) { + console.log(`---Zone id not provided.`) + return + } - const zone = await ZoneRepository.getById(socket.character.zoneId); + const zone = await ZoneRepository.getById(socket.character.zoneId) - if (!zone) { - console.log(`---Zone not found.`); - return; - } + if (!zone) { + console.log(`---Zone not found.`) + return + } - socket.leave(zone.id.toString()); + socket.leave(zone.id.toString()) - socket.emit('character:zone:unload'); + socket.emit('character:zone:unload') - // let other clients know of new character - io.to(zone.id.toString()).emit('zone:character:leave', socket.character); + // let other clients know of new character + io.to(zone.id.toString()).emit('zone:character:leave', socket.character) - // add character to zone manager - ZoneManager.removeCharacterFromZone(zone.id, socket.character as Character); - }); + // add character to zone manager + ZoneManager.removeCharacterFromZone(zone.id, socket.character as Character) + }) } /** * Resources: * https://stackoverflow.com/questions/6873607/socket-io-rooms-difference-between-broadcast-to-and-sockets-in - */ \ No newline at end of file + */ diff --git a/src/events/character/CharacterZoneRequest.ts b/src/events/character/CharacterZoneRequest.ts index 68c866a..fd11d4f 100644 --- a/src/events/character/CharacterZoneRequest.ts +++ b/src/events/character/CharacterZoneRequest.ts @@ -1,16 +1,16 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import ZoneRepository from "../../repositories/ZoneRepository"; -import ZoneManager from "../../managers/ZoneManager"; -import {Character, Zone} from "@prisma/client"; +import { Server } from 'socket.io' +import { TSocket } from '../../utilities/Types' +import ZoneRepository from '../../repositories/ZoneRepository' +import ZoneManager from '../../managers/ZoneManager' +import { Character, Zone } from '@prisma/client' interface IPayload { - zoneId: number; + zoneId: number } interface IResponse { - zone: Zone; - characters: Character[]; + zone: Zone + characters: Character[] } /** @@ -19,30 +19,30 @@ interface IResponse { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('character:zone:request', async (data: IPayload, callback: (response: IResponse) => void) => { - console.log(`---User ${socket.character?.id} has requested zone.`); + socket.on('character:zone:request', async (data: IPayload, callback: (response: IResponse) => void) => { + console.log(`---User ${socket.character?.id} has requested zone.`) - if (!data.zoneId) { - console.log(`---Zone id not provided.`); - return; - } + if (!data.zoneId) { + console.log(`---Zone id not provided.`) + return + } - const zone = await ZoneRepository.getById(data.zoneId); + const zone = await ZoneRepository.getById(data.zoneId) - if (!zone) { - console.log(`---Zone not found.`); - return; - } + if (!zone) { + console.log(`---Zone not found.`) + return + } - socket.join(zone.id.toString()); + socket.join(zone.id.toString()) - // send over zone and characters to socket - callback({zone, characters: ZoneManager.getCharactersInZone(zone.id)}); + // send over zone and characters to socket + callback({ zone, characters: ZoneManager.getCharactersInZone(zone.id) }) - // let other clients know of new character - io.to(zone.id.toString()).emit('zone:character:join', socket.character); + // let other clients know of new character + io.to(zone.id.toString()).emit('zone:character:join', socket.character) - // add character to zone manager - ZoneManager.addCharacterToZone(zone.id, socket.character as Character); - }); -} \ No newline at end of file + // add character to zone manager + ZoneManager.addCharacterToZone(zone.id, socket.character as Character) + }) +} diff --git a/src/events/gm/object/GmObjectList.ts b/src/events/gm/object/GmObjectList.ts index 6c3a51c..d574848 100644 --- a/src/events/gm/object/GmObjectList.ts +++ b/src/events/gm/object/GmObjectList.ts @@ -1,10 +1,9 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' import { Object } from '@prisma/client' import ObjectRepository from '../../../repositories/ObjectRepository' -interface IPayload { -} +interface IPayload {} /** * Handle game master list object event @@ -12,15 +11,14 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:object:list', async (data: any, callback: (response: Object[]) => void) => { + socket.on('gm:object:list', async (data: any, callback: (response: Object[]) => void) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } - - // get all objects - const objects = await ObjectRepository.getAll(); - callback(objects); - }); -} \ No newline at end of file + // get all objects + const objects = await ObjectRepository.getAll() + callback(objects) + }) +} diff --git a/src/events/gm/object/GmObjectRemove.ts b/src/events/gm/object/GmObjectRemove.ts index 8b5cb69..d67563d 100644 --- a/src/events/gm/object/GmObjectRemove.ts +++ b/src/events/gm/object/GmObjectRemove.ts @@ -1,11 +1,11 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import path from "path"; -import fs from "fs"; -import ObjectRepository from '../../../repositories/ObjectRepository' +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import path from 'path' +import fs from 'fs' +import prisma from '../../../utilities/Prisma' interface IPayload { - object: string; + object: string } /** @@ -14,32 +14,35 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:object:remove', async (data: IPayload, callback: (response: boolean) => void) => { + socket.on('gm:object:remove', async (data: IPayload, callback: (response: boolean) => void) => { + if (socket.character?.role !== 'gm') { + return + } - if (socket.character?.role !== 'gm') { - return; + try { + await prisma.object.delete({ + where: { + id: data.object + } + }) + + // get root path + const public_folder = path.join(process.cwd(), 'public', 'objects') + + // remove the tile from the disk + const finalFilePath = path.join(public_folder, data.object + '.png') + fs.unlink(finalFilePath, (err) => { + if (err) { + console.log(err) + callback(false) + return } - try { - await ObjectRepository.delete(data.object); - - // get root path - const public_folder = path.join(process.cwd(), 'public', 'objects'); - - // remove the tile from the disk - const finalFilePath = path.join(public_folder, data.object + '.png'); - fs.unlink(finalFilePath, (err) => { - if (err) { - console.log(err); - callback(false); - return; - } - - callback(true); - }); - } catch (e) { - console.log(e); - callback(false); - } - }); -} \ No newline at end of file + callback(true) + }) + } catch (e) { + console.log(e) + callback(false) + } + }) +} diff --git a/src/events/gm/object/GmObjectUpdate.ts b/src/events/gm/object/GmObjectUpdate.ts index 3d9da15..73171d8 100644 --- a/src/events/gm/object/GmObjectUpdate.ts +++ b/src/events/gm/object/GmObjectUpdate.ts @@ -1,14 +1,14 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import ObjectRepository from '../../../repositories/ObjectRepository' -import { Object } from '@prisma/client' +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import prisma from '../../../utilities/Prisma' interface IPayload { - id: string; - name: string; - tags: string[]; - origin_x: number; - origin_y: number; + id: string + name: string + tags: string[] + origin_x: number + origin_y: number + isAnimated: boolean } /** @@ -18,18 +18,27 @@ interface IPayload { */ export default function (socket: TSocket, io: Server) { socket.on('gm:object:update', async (data: IPayload, callback: (success: boolean) => void) => { - if (socket.character?.role !== 'gm') { - return; + return } try { - const object = await ObjectRepository.update(data.id, data.name, data.tags, data.origin_x, data.origin_y); - - callback(true); + const object = await prisma.object.update({ + where: { + id: data.id + }, + data: { + name: data.name, + tags: data.tags, + origin_x: data.origin_x, + origin_y: data.origin_y, + isAnimated: data.isAnimated + } + }) + callback(true) } catch (error) { - console.error(error); - callback(false); + console.error(error) + callback(false) } - }); -} \ No newline at end of file + }) +} diff --git a/src/events/gm/object/GmObjectUpload.ts b/src/events/gm/object/GmObjectUpload.ts index 1b7ed04..05e4302 100644 --- a/src/events/gm/object/GmObjectUpload.ts +++ b/src/events/gm/object/GmObjectUpload.ts @@ -1,12 +1,12 @@ -import { Server } from "socket.io"; -import { TSocket } from "../../../utilities/Types"; -import { writeFile } from "node:fs/promises"; -import path from "path"; -import fs from "fs/promises"; -import objectRepository from '../../../repositories/ObjectRepository' +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import { writeFile } from 'node:fs/promises' +import path from 'path' +import fs from 'fs/promises' +import prisma from '../../../utilities/Prisma' interface IObjectData { - [key: string]: Buffer; + [key: string]: Buffer } /** @@ -15,32 +15,41 @@ interface IObjectData { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:object:upload', async (data: IObjectData, callback: (response: boolean) => void) => { - try { - if (socket.character?.role !== 'gm') { - callback(false); - return; - } + socket.on('gm:object:upload', async (data: IObjectData, callback: (response: boolean) => void) => { + try { + if (socket.character?.role !== 'gm') { + callback(false) + return + } - const public_folder = path.join(process.cwd(), 'public', 'objects'); + const public_folder = path.join(process.cwd(), 'public', 'objects') - // Ensure the folder exists - await fs.mkdir(public_folder, { recursive: true }); + // Ensure the folder exists + await fs.mkdir(public_folder, { recursive: true }) - const uploadPromises = Object.entries(data).map(async ([key, objectData]) => { - const object = await objectRepository.create('New object', 0, 0); - const uuid = object.id; - const filename = `${uuid}.png`; - const finalFilePath = path.join(public_folder, filename); - await writeFile(finalFilePath, objectData); - }); + const uploadPromises = Object.entries(data).map(async ([key, objectData]) => { + const object = await prisma.object.create({ + data: { + name: key, + tags: [], + origin_x: 0, + origin_y: 0, + isAnimated: false + } + }) - await Promise.all(uploadPromises); + const uuid = object.id + const filename = `${uuid}.png` + const finalFilePath = path.join(public_folder, filename) + await writeFile(finalFilePath, objectData) + }) - callback(true); - } catch (error) { - console.error('Error uploading tile:', error); - callback(false); - } - }); -} \ No newline at end of file + await Promise.all(uploadPromises) + + callback(true) + } catch (error) { + console.error('Error uploading tile:', error) + callback(false) + } + }) +} diff --git a/src/events/gm/sprite/List.ts b/src/events/gm/sprite/List.ts index 7a5f3e2..5b65f75 100644 --- a/src/events/gm/sprite/List.ts +++ b/src/events/gm/sprite/List.ts @@ -1,10 +1,9 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' import { Sprite } from '@prisma/client' import SpriteRepository from '../../../repositories/SpriteRepository' -interface IPayload { -} +interface IPayload {} /** * Handle game master list sprite event @@ -12,15 +11,14 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:sprite:list', async (data: any, callback: (response: Sprite[]) => void) => { + socket.on('gm:sprite:list', async (data: any, callback: (response: Sprite[]) => void) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } - - // get all sprites - const sprites = await SpriteRepository.getAll(); - callback(sprites); - }); -} \ No newline at end of file + // get all sprites + const sprites = await SpriteRepository.getAll() + callback(sprites) + }) +} diff --git a/src/events/gm/sprite/Remove.ts b/src/events/gm/sprite/Remove.ts index 5151306..b26c7fb 100644 --- a/src/events/gm/sprite/Remove.ts +++ b/src/events/gm/sprite/Remove.ts @@ -1,11 +1,11 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import path from "path"; -import fs from "fs"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import path from 'path' +import fs from 'fs' import SpriteRepository from '../../../repositories/SpriteRepository' interface IPayload { - sprite: string; + sprite: string } /** @@ -14,32 +14,31 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:sprite:remove', async (data: IPayload, callback: (response: boolean) => void) => { + socket.on('gm:sprite:remove', async (data: IPayload, callback: (response: boolean) => void) => { + if (socket.character?.role !== 'gm') { + return + } - if (socket.character?.role !== 'gm') { - return; + try { + await SpriteRepository.delete(data.sprite) + + // get root path + const public_folder = path.join(process.cwd(), 'public', 'sprites') + + // remove the tile from the disk + const finalFilePath = path.join(public_folder, data.sprite + '.png') + fs.unlink(finalFilePath, (err) => { + if (err) { + console.log(err) + callback(false) + return } - try { - await SpriteRepository.delete(data.sprite); - - // get root path - const public_folder = path.join(process.cwd(), 'public', 'sprites'); - - // remove the tile from the disk - const finalFilePath = path.join(public_folder, data.sprite + '.png'); - fs.unlink(finalFilePath, (err) => { - if (err) { - console.log(err); - callback(false); - return; - } - - callback(true); - }); - } catch (e) { - console.log(e); - callback(false); - } - }); -} \ No newline at end of file + callback(true) + }) + } catch (e) { + console.log(e) + callback(false) + } + }) +} diff --git a/src/events/gm/sprite/Update.ts b/src/events/gm/sprite/Update.ts index 13f9314..7bcf9d7 100644 --- a/src/events/gm/sprite/Update.ts +++ b/src/events/gm/sprite/Update.ts @@ -1,13 +1,13 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' import SpriteRepository from '../../../repositories/SpriteRepository' import { Sprite } from '@prisma/client' interface IPayload { - id: string; - name: string; - origin_x: number; - origin_y: number; + id: string + name: string + origin_x: number + origin_y: number } /** @@ -17,18 +17,17 @@ interface IPayload { */ export default function (socket: TSocket, io: Server) { socket.on('gm:sprite:update', async (data: IPayload, callback: (success: boolean) => void) => { - if (socket.character?.role !== 'gm') { - return; + return } try { - const sprite = await SpriteRepository.update(data.id, data.name, data.origin_x, data.origin_y); + const sprite = await SpriteRepository.update(data.id, data.name, data.origin_x, data.origin_y) - callback(true); + callback(true) } catch (error) { - console.error(error); - callback(false); + console.error(error) + callback(false) } - }); -} \ No newline at end of file + }) +} diff --git a/src/events/gm/sprite/Upload.ts b/src/events/gm/sprite/Upload.ts index 8b20d70..2b244d4 100644 --- a/src/events/gm/sprite/Upload.ts +++ b/src/events/gm/sprite/Upload.ts @@ -1,12 +1,12 @@ -import { Server } from "socket.io"; -import { TSocket } from "../../../utilities/Types"; -import { writeFile } from "node:fs/promises"; -import path from "path"; -import fs from "fs/promises"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import { writeFile } from 'node:fs/promises' +import path from 'path' +import fs from 'fs/promises' import spriteRepository from '../../../repositories/SpriteRepository' interface ISpriteData { - [key: string]: Buffer; + [key: string]: Buffer } /** @@ -15,32 +15,32 @@ interface ISpriteData { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:sprite:upload', async (data: ISpriteData, callback: (response: boolean) => void) => { - try { - if (socket.character?.role !== 'gm') { - callback(false); - return; - } + socket.on('gm:sprite:upload', async (data: ISpriteData, callback: (response: boolean) => void) => { + try { + if (socket.character?.role !== 'gm') { + callback(false) + return + } - const public_folder = path.join(process.cwd(), 'public', 'sprites'); + const public_folder = path.join(process.cwd(), 'public', 'sprites') - // Ensure the folder exists - await fs.mkdir(public_folder, { recursive: true }); + // Ensure the folder exists + await fs.mkdir(public_folder, { recursive: true }) - const uploadPromises = Object.entries(data).map(async ([key, spriteData]) => { - const sprite = await spriteRepository.create('New sprite', 0, 0); - const uuid = sprite.id; - const filename = `${uuid}.png`; - const finalFilePath = path.join(public_folder, filename); - await writeFile(finalFilePath, spriteData); - }); + const uploadPromises = Object.entries(data).map(async ([key, spriteData]) => { + const sprite = await spriteRepository.create('New sprite', 0, 0) + const uuid = sprite.id + const filename = `${uuid}.png` + const finalFilePath = path.join(public_folder, filename) + await writeFile(finalFilePath, spriteData) + }) - await Promise.all(uploadPromises); + await Promise.all(uploadPromises) - callback(true); - } catch (error) { - console.error('Error uploading tile:', error); - callback(false); - } - }); -} \ No newline at end of file + callback(true) + } catch (error) { + console.error('Error uploading tile:', error) + callback(false) + } + }) +} diff --git a/src/events/gm/tile/GmTileList.ts b/src/events/gm/tile/GmTileList.ts index c87f54d..155cc0b 100644 --- a/src/events/gm/tile/GmTileList.ts +++ b/src/events/gm/tile/GmTileList.ts @@ -1,10 +1,9 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' import { Tile } from '@prisma/client' import TileRepository from '../../../repositories/TileRepository' -interface IPayload { -} +interface IPayload {} /** * Handle game master list tile event @@ -12,15 +11,14 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:tile:list', async (data: any, callback: (response: Tile[]) => void) => { + socket.on('gm:tile:list', async (data: any, callback: (response: Tile[]) => void) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } - - // get all tiles - const tiles = await TileRepository.getAll(); - callback(tiles); - }); -} \ No newline at end of file + // get all tiles + const tiles = await TileRepository.getAll() + callback(tiles) + }) +} diff --git a/src/events/gm/tile/GmTileRemove.ts b/src/events/gm/tile/GmTileRemove.ts index 3013a72..822fdcd 100644 --- a/src/events/gm/tile/GmTileRemove.ts +++ b/src/events/gm/tile/GmTileRemove.ts @@ -1,11 +1,11 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import path from "path"; -import fs from "fs"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import path from 'path' +import fs from 'fs' import TileRepository from '../../../repositories/TileRepository' interface IPayload { - tile: string; + tile: string } /** @@ -14,32 +14,31 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:tile:remove', async (data: IPayload, callback: (response: boolean) => void) => { + socket.on('gm:tile:remove', async (data: IPayload, callback: (response: boolean) => void) => { + if (socket.character?.role !== 'gm') { + return + } - if (socket.character?.role !== 'gm') { - return; + try { + await TileRepository.delete(data.tile) + + // get root path + const public_folder = path.join(process.cwd(), 'public', 'tiles') + + // remove the tile from the disk + const finalFilePath = path.join(public_folder, data.tile + '.png') + fs.unlink(finalFilePath, (err) => { + if (err) { + console.log(err) + callback(false) + return } - try { - await TileRepository.delete(data.tile); - - // get root path - const public_folder = path.join(process.cwd(), 'public', 'tiles'); - - // remove the tile from the disk - const finalFilePath = path.join(public_folder, data.tile + '.png'); - fs.unlink(finalFilePath, (err) => { - if (err) { - console.log(err); - callback(false); - return; - } - - callback(true); - }); - } catch (e) { - console.log(e); - callback(false); - } - }); -} \ No newline at end of file + callback(true) + }) + } catch (e) { + console.log(e) + callback(false) + } + }) +} diff --git a/src/events/gm/tile/GmTileUpdate.ts b/src/events/gm/tile/GmTileUpdate.ts index 1bc4716..ccf934a 100644 --- a/src/events/gm/tile/GmTileUpdate.ts +++ b/src/events/gm/tile/GmTileUpdate.ts @@ -1,11 +1,11 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' import TileRepository from '../../../repositories/TileRepository' interface IPayload { - id: string; - name: string; - tags: string[]; + id: string + name: string + tags: string[] } /** @@ -15,18 +15,17 @@ interface IPayload { */ export default function (socket: TSocket, io: Server) { socket.on('gm:tile:update', async (data: IPayload, callback: (success: boolean) => void) => { - if (socket.character?.role !== 'gm') { - return; + return } try { - const Tile = await TileRepository.update(data.id, data.name, data.tags); + const Tile = await TileRepository.update(data.id, data.name, data.tags) - callback(true); + callback(true) } catch (error) { - console.error(error); - callback(false); + console.error(error) + callback(false) } - }); -} \ No newline at end of file + }) +} diff --git a/src/events/gm/tile/GmTileUpload.ts b/src/events/gm/tile/GmTileUpload.ts index 0c9cff1..1929eb7 100644 --- a/src/events/gm/tile/GmTileUpload.ts +++ b/src/events/gm/tile/GmTileUpload.ts @@ -1,12 +1,12 @@ -import { Server } from "socket.io"; -import { TSocket } from "../../../utilities/Types"; -import { writeFile } from "node:fs/promises"; -import path from "path"; -import fs from "fs/promises"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import { writeFile } from 'node:fs/promises' +import path from 'path' +import fs from 'fs/promises' import tileRepository from '../../../repositories/TileRepository' interface ITileData { - [key: string]: Buffer; + [key: string]: Buffer } /** @@ -15,32 +15,32 @@ interface ITileData { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:tile:upload', async (data: ITileData, callback: (response: boolean) => void) => { - try { - if (socket.character?.role !== 'gm') { - callback(false); - return; - } + socket.on('gm:tile:upload', async (data: ITileData, callback: (response: boolean) => void) => { + try { + if (socket.character?.role !== 'gm') { + callback(false) + return + } - const public_folder = path.join(process.cwd(), 'public', 'tiles'); + const public_folder = path.join(process.cwd(), 'public', 'tiles') - // Ensure the folder exists - await fs.mkdir(public_folder, { recursive: true }); + // Ensure the folder exists + await fs.mkdir(public_folder, { recursive: true }) - const uploadPromises = Object.entries(data).map(async ([key, tileData]) => { - const tile = await tileRepository.create('New tile'); - const uuid = tile.id; - const filename = `${uuid}.png`; - const finalFilePath = path.join(public_folder, filename); - await writeFile(finalFilePath, tileData); - }); + const uploadPromises = Object.entries(data).map(async ([key, tileData]) => { + const tile = await tileRepository.create('New tile') + const uuid = tile.id + const filename = `${uuid}.png` + const finalFilePath = path.join(public_folder, filename) + await writeFile(finalFilePath, tileData) + }) - await Promise.all(uploadPromises); + await Promise.all(uploadPromises) - callback(true); - } catch (error) { - console.error('Error uploading tile:', error); - callback(false); - } - }); -} \ No newline at end of file + callback(true) + } catch (error) { + console.error('Error uploading tile:', error) + callback(false) + } + }) +} diff --git a/src/events/gm/zone/GmZoneEditorZoneCreate.ts b/src/events/gm/zone/GmZoneEditorZoneCreate.ts index b7b0537..281b91f 100644 --- a/src/events/gm/zone/GmZoneEditorZoneCreate.ts +++ b/src/events/gm/zone/GmZoneEditorZoneCreate.ts @@ -1,13 +1,13 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import ZoneRepository from "../../../repositories/ZoneRepository"; -import ZoneManager from "../../../managers/ZoneManager"; -import {Character, Zone} from "@prisma/client"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import ZoneRepository from '../../../repositories/ZoneRepository' +import ZoneManager from '../../../managers/ZoneManager' +import { Character, Zone } from '@prisma/client' interface IPayload { - name: string; - width: number; - height: number; + name: string + width: number + height: number } /** @@ -16,30 +16,29 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:zone_editor:zone:create', async (data: IPayload, callback: (response: Zone[]) => void) => { + socket.on('gm:zone_editor:zone:create', async (data: IPayload, callback: (response: Zone[]) => void) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } + console.log(`---GM ${socket.character?.id} has created a new zone via zone editor.`) + let zoneList: Zone[] = [] + try { + const zone = await ZoneRepository.create( + data.name, + data.width, + data.height, + Array.from({ length: data.height }, () => Array.from({ length: data.width }, () => 'blank_tile')) + ) - console.log(`---GM ${socket.character?.id} has created a new zone via zone editor.`); - let zoneList: Zone[] = []; - try { - const zone = await ZoneRepository.create( - data.name, - data.width, - data.height, - Array.from({length: data.height}, () => Array.from({length: data.width}, () => 'blank_tile')), - ); - - zoneList = await ZoneRepository.getAll(); - callback(zoneList); - // send over zone and characters to socket - } catch (e) { - console.error(e); - socket.emit('notification', {message: 'Failed to create zone.'}); - callback(zoneList); - } - }); -} \ No newline at end of file + zoneList = await ZoneRepository.getAll() + callback(zoneList) + // send over zone and characters to socket + } catch (e) { + console.error(e) + socket.emit('notification', { message: 'Failed to create zone.' }) + callback(zoneList) + } + }) +} diff --git a/src/events/gm/zone/GmZoneEditorZoneDelete.ts b/src/events/gm/zone/GmZoneEditorZoneDelete.ts index 67c3607..61a1bb9 100644 --- a/src/events/gm/zone/GmZoneEditorZoneDelete.ts +++ b/src/events/gm/zone/GmZoneEditorZoneDelete.ts @@ -1,11 +1,11 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import ZoneRepository from "../../../repositories/ZoneRepository"; -import ZoneManager from "../../../managers/ZoneManager"; -import {Character, Zone} from "@prisma/client"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import ZoneRepository from '../../../repositories/ZoneRepository' +import ZoneManager from '../../../managers/ZoneManager' +import { Character, Zone } from '@prisma/client' interface IPayload { - zoneId: number; + zoneId: number } /** @@ -14,29 +14,28 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:zone_editor:zone:delete', async (data: IPayload, callback: (response: boolean) => void) => { + socket.on('gm:zone_editor:zone:delete', async (data: IPayload, callback: (response: boolean) => void) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } + console.log(`---GM ${socket.character?.id} has deleted a zone via zone editor.`) - console.log(`---GM ${socket.character?.id} has deleted a zone via zone editor.`); + try { + const zone = await ZoneRepository.getById(data.zoneId) - try { - const zone = await ZoneRepository.getById(data.zoneId); + if (!zone) { + console.log(`---Zone not found.`) + return + } - if (!zone) { - console.log(`---Zone not found.`); - return; - } + await ZoneRepository.delete(data.zoneId) - await ZoneRepository.delete(data.zoneId); - - callback(true); - } catch (e) { - console.error(e); - callback(false); - } - }); -} \ No newline at end of file + callback(true) + } catch (e) { + console.error(e) + callback(false) + } + }) +} diff --git a/src/events/gm/zone/GmZoneEditorZoneList.ts b/src/events/gm/zone/GmZoneEditorZoneList.ts index 4911474..56cafe3 100644 --- a/src/events/gm/zone/GmZoneEditorZoneList.ts +++ b/src/events/gm/zone/GmZoneEditorZoneList.ts @@ -1,5 +1,5 @@ -import { Server } from "socket.io"; -import {TSocket} from '../../../utilities/Types' +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' import { Zone } from '@prisma/client' import ZoneRepository from '../../../repositories/ZoneRepository' @@ -11,21 +11,20 @@ interface IPayload {} * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:zone_editor:zone:list', async (data: IPayload, callback: (response: Zone[]) => void) => { + socket.on('gm:zone_editor:zone:list', async (data: IPayload, callback: (response: Zone[]) => void) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } + console.log(`---GM ${socket.character?.id} has requested zone list via zone editor.`) - console.log(`---GM ${socket.character?.id} has requested zone list via zone editor.`); - - try { - const zones = await ZoneRepository.getAll(); - callback(zones); - } catch (e) { - console.error(e); - callback([]); - } - }); -} \ No newline at end of file + try { + const zones = await ZoneRepository.getAll() + callback(zones) + } catch (e) { + console.error(e) + callback([]) + } + }) +} diff --git a/src/events/gm/zone/GmZoneEditorZoneRequest.ts b/src/events/gm/zone/GmZoneEditorZoneRequest.ts index f797095..f50d689 100644 --- a/src/events/gm/zone/GmZoneEditorZoneRequest.ts +++ b/src/events/gm/zone/GmZoneEditorZoneRequest.ts @@ -1,10 +1,10 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import ZoneRepository from "../../../repositories/ZoneRepository"; -import {Zone} from "@prisma/client"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import ZoneRepository from '../../../repositories/ZoneRepository' +import { Zone } from '@prisma/client' interface IPayload { - zoneId: number; + zoneId: number } /** @@ -13,30 +13,29 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:zone_editor:zone:request', async (data: IPayload, callback: (response: Zone) => void) => { + socket.on('gm:zone_editor:zone:request', async (data: IPayload, callback: (response: Zone) => void) => { + if (socket.character?.role !== 'gm') { + return + } - if (socket.character?.role !== 'gm') { - return; - } + console.log(`---GM ${socket.character?.id} has requested zone via zone editor.`) - console.log(`---GM ${socket.character?.id} has requested zone via zone editor.`); + if (!data.zoneId) { + console.log(`---Zone id not provided.`) + return + } - if (!data.zoneId) { - console.log(`---Zone id not provided.`); - return; - } + try { + const zone = await ZoneRepository.getById(data.zoneId) - try { - const zone = await ZoneRepository.getById(data.zoneId); + if (!zone) { + console.log(`---Zone not found.`) + return + } - if (!zone) { - console.log(`---Zone not found.`); - return; - } - - callback(zone); - } catch (e) { - console.error(e); - } - }); -} \ No newline at end of file + callback(zone) + } catch (e) { + console.error(e) + } + }) +} diff --git a/src/events/gm/zone/GmZoneEditorZoneUpdate.ts b/src/events/gm/zone/GmZoneEditorZoneUpdate.ts index d9ab725..660973d 100644 --- a/src/events/gm/zone/GmZoneEditorZoneUpdate.ts +++ b/src/events/gm/zone/GmZoneEditorZoneUpdate.ts @@ -1,17 +1,17 @@ -import { Server } from "socket.io"; -import {TSocket} from "../../../utilities/Types"; -import ZoneRepository from "../../../repositories/ZoneRepository"; -import ZoneManager from "../../../managers/ZoneManager"; +import { Server } from 'socket.io' +import { TSocket } from '../../../utilities/Types' +import ZoneRepository from '../../../repositories/ZoneRepository' +import ZoneManager from '../../../managers/ZoneManager' import { Character, Zone, ZoneEventTile, ZoneObject } from '@prisma/client' interface IPayload { - zoneId: number; - name: string; - width: number; - height: number; - tiles: string[][]; - zoneEventTiles: ZoneEventTile[]; - zoneObjects: ZoneObject[]; + zoneId: number + name: string + width: number + height: number + tiles: string[][] + zoneEventTiles: ZoneEventTile[] + zoneObjects: ZoneObject[] } /** @@ -20,44 +20,35 @@ interface IPayload { * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:zone_editor:zone:update', async (data: IPayload) => { + socket.on('gm:zone_editor:zone:update', async (data: IPayload) => { + if (socket.character?.role !== 'gm') { + console.log(`---Character #${socket.character?.id} is not a game master.`) + return + } - if (socket.character?.role !== 'gm') { - console.log(`---Character #${socket.character?.id} is not a game master.`); - return; - } + console.log(`---GM ${socket.character?.id} has updated zone via zone editor.`) - console.log(`---GM ${socket.character?.id} has updated zone via zone editor.`); + if (!data.zoneId) { + console.log(`---Zone id not provided.`) + return + } - if (!data.zoneId) { - console.log(`---Zone id not provided.`); - return; - } + try { + let zone = await ZoneRepository.getById(data.zoneId) - try { - let zone = await ZoneRepository.getById(data.zoneId); + if (!zone) { + console.log(`---Zone not found.`) + return + } - if (!zone) { - console.log(`---Zone not found.`); - return; - } + await ZoneRepository.update(data.zoneId, data.name, data.width, data.height, data.tiles, data.zoneEventTiles, data.zoneObjects) - await ZoneRepository.update( - data.zoneId, - data.name, - data.width, - data.height, - data.tiles, - data.zoneEventTiles, - data.zoneObjects - ); + zone = await ZoneRepository.getById(data.zoneId) - zone = await ZoneRepository.getById(data.zoneId); - - // send over zone and characters to socket - socket.emit('gm:zone_editor:zone:load', zone); - } catch (error: any) { - console.log(`---Error updating zone: ${error.message}`); - } - }); -} \ No newline at end of file + // send over zone and characters to socket + socket.emit('gm:zone_editor:zone:load', zone) + } catch (error: any) { + console.log(`---Error updating zone: ${error.message}`) + } + }) +} diff --git a/src/managers/CommandManager.ts b/src/managers/CommandManager.ts index 59ebf3b..1507755 100644 --- a/src/managers/CommandManager.ts +++ b/src/managers/CommandManager.ts @@ -1,98 +1,95 @@ -import * as readline from 'readline'; -import * as fs from 'fs'; -import * as path from 'path'; -import { Server } from 'socket.io'; +import * as readline from 'readline' +import * as fs from 'fs' +import * as path from 'path' +import { Server } from 'socket.io' class CommandManager { - private commands: Map = new Map(); - private rl: readline.Interface; - private io: Server | null = null; - private rlClosed: boolean = false; + private commands: Map = new Map() + private rl: readline.Interface + private io: Server | null = null + private rlClosed: boolean = false - constructor() { - this.rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); + constructor() { + this.rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }) - this.rl.on('close', () => { - this.rlClosed = true; - }); + this.rl.on('close', () => { + this.rlClosed = true + }) + } + + public async boot(io: Server) { + this.io = io + await this.loadCommands() + console.log('[✅] Command manager loaded') + this.startPrompt() + } + + private startPrompt() { + if (this.rlClosed) return + + this.rl.question('> ', (command: string) => { + this.processCommand(command) + this.startPrompt() + }) + } + + private async processCommand(command: string): Promise { + const [cmd, ...args] = command.trim().split(' ') + if (this.commands.has(cmd)) { + this.commands.get(cmd)?.(args, this.io as Server) + } else { + this.handleUnknownCommand(cmd) } + } - public async boot(io: Server) { - this.io = io; - await this.loadCommands(); - console.log('[✅] Command manager loaded'); - this.startPrompt(); + private handleUnknownCommand(command: string) { + switch (command) { + case 'exit': + console.log('Goodbye!') + this.rl.close() + break + default: + console.error(`Unknown command: ${command}`) + break } + } - private startPrompt() { - if (this.rlClosed) return; + private async loadCommands() { + const commandsDir = path.resolve(__dirname, 'commands') + try { + const files: string[] = await fs.promises.readdir(commandsDir) - this.rl.question('> ', (command: string) => { - this.processCommand(command); - this.startPrompt(); - }); + for (const file of files) { + await this.loadCommand(commandsDir, file) + } + } catch (error) { + console.error('[❌] Failed to read commands directory:', error) } + } - private async processCommand(command: string): Promise { - const [cmd, ...args] = command.trim().split(' '); - if (this.commands.has(cmd)) { - this.commands.get(cmd)?.(args, this.io as Server); - } else { - this.handleUnknownCommand(cmd); - } + private async loadCommand(commandsDir: string, file: string) { + try { + const ext = path.extname(file) + const commandName = path.basename(file, ext) + const commandPath = path.join(commandsDir, file) + const module = await import(commandPath) + + this.registerCommand(commandName, module.default) + } catch (error) { + console.error('[❌] Failed to load command:', file, error) } + } - private handleUnknownCommand(command: string) { - switch (command) { - case 'exit': - console.log('Goodbye!'); - this.rl.close(); - break; - default: - console.error(`Unknown command: ${command}`); - break; - } - } - - private async loadCommands() { - const commandsDir = path.resolve(__dirname, 'commands'); - try { - const files: string[] = await fs.promises.readdir(commandsDir); - - for (const file of files) { - await this.loadCommand(commandsDir, file); - } - } catch (error) { - console.error('[❌] Failed to read commands directory:', error); - } - } - - private async loadCommand(commandsDir: string, file: string) { - try { - const ext = path.extname(file); - const commandName = path.basename(file, ext); - const commandPath = path.join(commandsDir, file); - const module = await import(commandPath); - - this.registerCommand(commandName, module.default); - } catch (error) { - console.error('[❌] Failed to load command:', file, error); - } - } - - private registerCommand( - name: string, - command: (args: string[], io: Server) => void - ) { - if (this.commands.has(name)) { - console.warn(`Command '${name}' is already registered. Overwriting...`); - } - this.commands.set(name, command); - console.log(`Registered command: ${name}`); + private registerCommand(name: string, command: (args: string[], io: Server) => void) { + if (this.commands.has(name)) { + console.warn(`Command '${name}' is already registered. Overwriting...`) } + this.commands.set(name, command) + console.log(`Registered command: ${name}`) + } } -export default new CommandManager(); +export default new CommandManager() diff --git a/src/managers/UserManager.ts b/src/managers/UserManager.ts index e8ecf4c..4c35935 100644 --- a/src/managers/UserManager.ts +++ b/src/managers/UserManager.ts @@ -1,37 +1,37 @@ -import {User} from "@prisma/client"; +import { User } from '@prisma/client' type TLoggedInUsers = { - users: User[]; + users: User[] } class UserManager { - private loggedInUsers: TLoggedInUsers[] = []; + private loggedInUsers: TLoggedInUsers[] = [] - // Method to initialize user manager - public async boot() { - console.log('[✅] User manager loaded'); - } + // Method to initialize user manager + public async boot() { + console.log('[✅] User manager loaded') + } - // Function that adds user to logged in users - public loginUser(user: User) { - this.loggedInUsers.push({ - users: [user] - }); - } + // Function that adds user to logged in users + public loginUser(user: User) { + this.loggedInUsers.push({ + users: [user] + }) + } - // Function that checks if a user is already logged in - public findUser(user: User) { - return this.loggedInUsers.find((loggedInUser) => { - return loggedInUser.users.includes(user); - }); - } + // Function that checks if a user is already logged in + public findUser(user: User) { + return this.loggedInUsers.find((loggedInUser) => { + return loggedInUser.users.includes(user) + }) + } - // Function that lists all logged in users - public listUsers() { - return this.loggedInUsers.map((loggedInUser) => { - return loggedInUser.users; - }); - } + // Function that lists all logged in users + public listUsers() { + return this.loggedInUsers.map((loggedInUser) => { + return loggedInUser.users + }) + } } -export default new UserManager(); +export default new UserManager() diff --git a/src/managers/ZoneManager.ts b/src/managers/ZoneManager.ts index bb7a12d..bfc1af5 100644 --- a/src/managers/ZoneManager.ts +++ b/src/managers/ZoneManager.ts @@ -1,93 +1,93 @@ -import {Character, Zone} from "@prisma/client"; -import ZoneRepository from "../repositories/ZoneRepository"; -import ZoneService from "../services/ZoneService"; +import { Character, Zone } from '@prisma/client' +import ZoneRepository from '../repositories/ZoneRepository' +import ZoneService from '../services/ZoneService' type TLoadedZone = { - zone: Zone; - characters: Character[]; + zone: Zone + characters: Character[] } class ZoneManager { - private loadedZones: TLoadedZone[] = []; + private loadedZones: TLoadedZone[] = [] - // Method to initialize zone manager - public async boot() { - if (!await ZoneRepository.getById(1)) { - const zoneService = new ZoneService(); - await zoneService.createDemoZone(); - } - - const zones = await ZoneRepository.getAll(); - - for (const zone of zones) { - this.loadZone(zone); - } - - console.log('[✅] Zone manager loaded'); + // Method to initialize zone manager + public async boot() { + if (!(await ZoneRepository.getById(1))) { + const zoneService = new ZoneService() + await zoneService.createDemoZone() } - // Method to handle individual zone loading - public loadZone(zone: Zone) { - this.loadedZones.push({ - zone, - characters: [] - }); - console.log(`[✅] Zone ID ${zone.id} loaded`); + const zones = await ZoneRepository.getAll() + + for (const zone of zones) { + this.loadZone(zone) } - // Method to handle individual zone unloading - public unloadZone(zoneId: number) { - this.loadedZones = this.loadedZones.filter((loadedZone) => { - return loadedZone.zone.id !== zoneId; - }); - console.log(`[❌] Zone ID ${zoneId} unloaded`); - } + console.log('[✅] Zone manager loaded') + } - // Getter for loaded zones - public getLoadedZones(): TLoadedZone[] { - return this.loadedZones; - } + // Method to handle individual zone loading + public loadZone(zone: Zone) { + this.loadedZones.push({ + zone, + characters: [] + }) + console.log(`[✅] Zone ID ${zone.id} loaded`) + } - public addCharacterToZone(zoneId: number, character: Character) { - const loadedZone = this.loadedZones.find((loadedZone) => { - return loadedZone.zone.id === zoneId; - }); - if (loadedZone) { - loadedZone.characters.push(character); - } - } + // Method to handle individual zone unloading + public unloadZone(zoneId: number) { + this.loadedZones = this.loadedZones.filter((loadedZone) => { + return loadedZone.zone.id !== zoneId + }) + console.log(`[❌] Zone ID ${zoneId} unloaded`) + } - public removeCharacterFromZone(zoneId: number, character: Character) { - const loadedZone = this.loadedZones.find((loadedZone) => { - return loadedZone.zone.id === zoneId; - }); - if (loadedZone) { - loadedZone.characters = loadedZone.characters.filter((loadedCharacter) => { - return loadedCharacter.id !== character.id; - }); - } - } + // Getter for loaded zones + public getLoadedZones(): TLoadedZone[] { + return this.loadedZones + } - public updateCharacterInZone(zoneId: number, character: Character) { - const loadedZone = this.loadedZones.find((loadedZone) => { - return loadedZone.zone.id === zoneId; - }); - if (loadedZone) { - const characterIndex = loadedZone.characters.findIndex((loadedCharacter) => { - return loadedCharacter.id === character.id; - }); - if (characterIndex !== -1) { - loadedZone.characters[characterIndex] = character; - } - } + public addCharacterToZone(zoneId: number, character: Character) { + const loadedZone = this.loadedZones.find((loadedZone) => { + return loadedZone.zone.id === zoneId + }) + if (loadedZone) { + loadedZone.characters.push(character) } + } - public getCharactersInZone(zoneId: number): Character[] { - const loadedZone = this.loadedZones.find((loadedZone) => { - return loadedZone.zone.id === zoneId; - }); - return loadedZone ? loadedZone.characters : []; + public removeCharacterFromZone(zoneId: number, character: Character) { + const loadedZone = this.loadedZones.find((loadedZone) => { + return loadedZone.zone.id === zoneId + }) + if (loadedZone) { + loadedZone.characters = loadedZone.characters.filter((loadedCharacter) => { + return loadedCharacter.id !== character.id + }) } + } + + public updateCharacterInZone(zoneId: number, character: Character) { + const loadedZone = this.loadedZones.find((loadedZone) => { + return loadedZone.zone.id === zoneId + }) + if (loadedZone) { + const characterIndex = loadedZone.characters.findIndex((loadedCharacter) => { + return loadedCharacter.id === character.id + }) + if (characterIndex !== -1) { + loadedZone.characters[characterIndex] = character + } + } + } + + public getCharactersInZone(zoneId: number): Character[] { + const loadedZone = this.loadedZones.find((loadedZone) => { + return loadedZone.zone.id === zoneId + }) + return loadedZone ? loadedZone.characters : [] + } } -export default new ZoneManager; +export default new ZoneManager() diff --git a/src/middleware/Authentication.ts b/src/middleware/Authentication.ts index 1c8f7b5..98beaff 100644 --- a/src/middleware/Authentication.ts +++ b/src/middleware/Authentication.ts @@ -1,37 +1,36 @@ // socket io jwt auth middleware -import { verify } from 'jsonwebtoken'; -import { TSocket } from '../utilities/Types'; -import config from "../utilities/Config"; -import UserRepository from "../repositories/UserRepository"; -import {User} from "@prisma/client"; +import { verify } from 'jsonwebtoken' +import { TSocket } from '../utilities/Types' +import config from '../utilities/Config' +import UserRepository from '../repositories/UserRepository' +import { User } from '@prisma/client' -export async function Authentication (socket: TSocket, next: any) -{ - if (!socket.request.headers.cookie) { - console.log('No cookie provided'); - return next(new Error('Authentication error')); - } +export async function Authentication(socket: TSocket, next: any) { + if (!socket.request.headers.cookie) { + console.log('No cookie provided') + return next(new Error('Authentication error')) + } - const cookies = socket.request.headers.cookie.split('; ').reduce((prev: any, current: any) => { - const [name, value] = current.split('='); - prev[name] = value; - return prev; - }, {}); + const cookies = socket.request.headers.cookie.split('; ').reduce((prev: any, current: any) => { + const [name, value] = current.split('=') + prev[name] = value + return prev + }, {}) - const token = cookies['token']; + const token = cookies['token'] - if (token) { - verify(token, config.JWT_SECRET, async (err: any, decoded: any) => { - if (err) { - console.log('err'); - return next(new Error('Authentication error')); - } + if (token) { + verify(token, config.JWT_SECRET, async (err: any, decoded: any) => { + if (err) { + console.log('err') + return next(new Error('Authentication error')) + } - socket.user = await UserRepository.getById(decoded.id) as User; - next(); - }); - } else { - console.log('No token provided'); - next(new Error('Authentication error')); - } -} \ No newline at end of file + socket.user = (await UserRepository.getById(decoded.id)) as User + next() + }) + } else { + console.log('No token provided') + next(new Error('Authentication error')) + } +} diff --git a/src/repositories/CharacterRepository.ts b/src/repositories/CharacterRepository.ts index 2885439..6d93381 100644 --- a/src/repositories/CharacterRepository.ts +++ b/src/repositories/CharacterRepository.ts @@ -1,125 +1,125 @@ -import prisma from '../utilities/Prisma'; // Import the global Prisma instance -import {Character} from '@prisma/client'; +import prisma from '../utilities/Prisma' // Import the global Prisma instance +import { Character } from '@prisma/client' class CharacterRepository { - async getByUserId(userId: number): Promise { - try { - return await prisma.character.findMany({ - where: { - userId, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get character by user ID: ${error.message}`); + async getByUserId(userId: number): Promise { + try { + return await prisma.character.findMany({ + where: { + userId } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get character by user ID: ${error.message}`) } + } - async getByUserAndId(userId: number, characterId: number): Promise { - try { - return await prisma.character.findFirst({ - where: { - userId, - id: characterId, - }, - include: { - zone: true - } - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get character by user ID and character ID: ${error.message}`); + async getByUserAndId(userId: number, characterId: number): Promise { + try { + return await prisma.character.findFirst({ + where: { + userId, + id: characterId + }, + include: { + zone: true } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get character by user ID and character ID: ${error.message}`) } + } - async getById(id: number): Promise { - try { - return await prisma.character.findUnique({ - where: { - id, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get character by ID: ${error.message}`); + async getById(id: number): Promise { + try { + return await prisma.character.findUnique({ + where: { + id } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get character by ID: ${error.message}`) } + } - async create(userId: number, name: string, role: 'player'): Promise { - try { - return await prisma.character.create({ - data: { - userId, - name, - role, - position_x: 0, // @TODO Set default registration values in the database - position_y: 0, // @TODO Set default registration values in the database - rotation: 0, // @TODO Set default registration values in the database - zoneId: 1, // @TODO Set default registration values in the database - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to create character: ${error.message}`); + async create(userId: number, name: string, role: 'player'): Promise { + try { + return await prisma.character.create({ + data: { + userId, + name, + role, + position_x: 0, // @TODO Set default registration values in the database + position_y: 0, // @TODO Set default registration values in the database + rotation: 0, // @TODO Set default registration values in the database + zoneId: 1 // @TODO Set default registration values in the database } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to create character: ${error.message}`) } + } - async updatePosition(id:number, position_x: number, position_y: number): Promise { - try { - return await prisma.character.update({ - where: { - id: id, - }, - data: { - position_x, - position_y, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to update character: ${error.message}`); + async updatePosition(id: number, position_x: number, position_y: number): Promise { + try { + return await prisma.character.update({ + where: { + id: id + }, + data: { + position_x, + position_y } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to update character: ${error.message}`) } + } - async delete(id: number): Promise { - try { - return await prisma.character.delete({ - where: { - id, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to delete character: ${error.message}`); + async delete(id: number): Promise { + try { + return await prisma.character.delete({ + where: { + id } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to delete character: ${error.message}`) } + } - async deleteByUserIdAndId(userId: number, characterId: number): Promise { - try { - return await prisma.character.delete({ - where: { - userId, - id: characterId, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to delete character by user ID and character ID: ${error.message}`); + async deleteByUserIdAndId(userId: number, characterId: number): Promise { + try { + return await prisma.character.delete({ + where: { + userId, + id: characterId } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to delete character by user ID and character ID: ${error.message}`) } + } - async getByName(name: string): Promise { - try { - return await prisma.character.findFirst({ - where: { - name, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get character by name: ${error.message}`); + async getByName(name: string): Promise { + try { + return await prisma.character.findFirst({ + where: { + name } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get character by name: ${error.message}`) } + } } -export default new CharacterRepository; \ No newline at end of file +export default new CharacterRepository() diff --git a/src/repositories/ObjectRepository.ts b/src/repositories/ObjectRepository.ts index ff065b9..44a4435 100644 --- a/src/repositories/ObjectRepository.ts +++ b/src/repositories/ObjectRepository.ts @@ -1,44 +1,16 @@ -import prisma from '../utilities/Prisma'; // Import the global Prisma instance +import prisma from '../utilities/Prisma' // Import the global Prisma instance import { Object } from '@prisma/client' class ObjectRepository { - async getById(id: string): Promise { - return prisma.object.findUnique({ - where: { id }, - }); - } + async getById(id: string): Promise { + return prisma.object.findUnique({ + where: { id } + }) + } - async getAll(): Promise { - return prisma.object.findMany(); - } - - async create(name: string, origin_x: number, origin_y: number): Promise { - return prisma.object.create({ - data: { - name, - origin_x, - origin_y - }, - }); - } - - async update(id: string, name: string, tags: string[], origin_x: number, origin_y: number): Promise { - return prisma.object.update({ - where: { id }, - data: { - name, - tags, - origin_x, - origin_y - }, - }); - } - - async delete(id: string): Promise { - return prisma.object.delete({ - where: { id }, - }); - } + async getAll(): Promise { + return prisma.object.findMany() + } } -export default new ObjectRepository(); \ No newline at end of file +export default new ObjectRepository() diff --git a/src/repositories/SpriteRepository.ts b/src/repositories/SpriteRepository.ts index 6f89172..2a31ff1 100644 --- a/src/repositories/SpriteRepository.ts +++ b/src/repositories/SpriteRepository.ts @@ -1,43 +1,43 @@ -import prisma from '../utilities/Prisma'; // Import the global Prisma instance +import prisma from '../utilities/Prisma' // Import the global Prisma instance import { Sprite } from '@prisma/client' class SpriteRepository { - async getById(id: string): Promise { - return prisma.sprite.findUnique({ - where: { id }, - }); - } + async getById(id: string): Promise { + return prisma.sprite.findUnique({ + where: { id } + }) + } - async getAll(): Promise { - return prisma.sprite.findMany(); - } + async getAll(): Promise { + return prisma.sprite.findMany() + } - async create(name: string, origin_x: number, origin_y: number): Promise { - return prisma.sprite.create({ - data: { - name, - origin_x, - origin_y - }, - }); - } + async create(name: string, origin_x: number, origin_y: number): Promise { + return prisma.sprite.create({ + data: { + name, + origin_x, + origin_y + } + }) + } - async update(id: string, name: string, origin_x: number, origin_y: number): Promise { - return prisma.sprite.update({ - where: { id }, - data: { - name, - origin_x, - origin_y - }, - }); - } + async update(id: string, name: string, origin_x: number, origin_y: number): Promise { + return prisma.sprite.update({ + where: { id }, + data: { + name, + origin_x, + origin_y + } + }) + } - async delete(id: string): Promise { - return prisma.sprite.delete({ - where: { id }, - }); - } + async delete(id: string): Promise { + return prisma.sprite.delete({ + where: { id } + }) + } } -export default new SpriteRepository(); \ No newline at end of file +export default new SpriteRepository() diff --git a/src/repositories/TileRepository.ts b/src/repositories/TileRepository.ts index 53e11f1..cf093c6 100644 --- a/src/repositories/TileRepository.ts +++ b/src/repositories/TileRepository.ts @@ -1,47 +1,47 @@ -import prisma from '../utilities/Prisma'; // Import the global Prisma instance +import prisma from '../utilities/Prisma' // Import the global Prisma instance import { Tile } from '@prisma/client' class TileRepository { - async getById(id: string): Promise { - return prisma.tile.findUnique({ - where: { id }, - }); - } + async getById(id: string): Promise { + return prisma.tile.findUnique({ + where: { id } + }) + } - async getAll(): Promise { - return prisma.tile.findMany(); - } + async getAll(): Promise { + return prisma.tile.findMany() + } - async create(name: string): Promise { - return prisma.tile.create({ - data: { - name, - tags: [] - }, - }); - } + async create(name: string): Promise { + return prisma.tile.create({ + data: { + name, + tags: [] + } + }) + } - async update(id: string, name: string, tags: string[]): Promise { - return prisma.tile.update({ - where: { id }, - data: { - name, - tags - }, - }); - } + async update(id: string, name: string, tags: string[]): Promise { + return prisma.tile.update({ + where: { id }, + data: { + name, + tags + } + }) + } - async delete(id: string): Promise { - try { - await prisma.tile.delete({ - where: { id }, - }); - return true; - } catch (error) { - console.log('Error deleting tile:', error) - return false; - } + async delete(id: string): Promise { + try { + await prisma.tile.delete({ + where: { id } + }) + return true + } catch (error) { + console.log('Error deleting tile:', error) + return false } + } } -export default new TileRepository(); \ No newline at end of file +export default new TileRepository() diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index 8469697..8d9f1ef 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -1,44 +1,44 @@ -import prisma from '../utilities/Prisma'; // Import the global Prisma instance -import { User } from '@prisma/client'; +import prisma from '../utilities/Prisma' // Import the global Prisma instance +import { User } from '@prisma/client' class UserRepository { - async getById(id: number): Promise { - try { - return await prisma.user.findUnique({ - where: { - id, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get user by ID: ${error.message}`); + async getById(id: number): Promise { + try { + return await prisma.user.findUnique({ + where: { + id } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get user by ID: ${error.message}`) } - async getByUsername(username: string): Promise { - try { - return await prisma.user.findUnique({ - where: { - username, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get user by username: ${error.message}`); + } + async getByUsername(username: string): Promise { + try { + return await prisma.user.findUnique({ + where: { + username } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get user by username: ${error.message}`) } - async create(username: string, password: string): Promise { - try { - return await prisma.user.create({ - data: { - username, - password, - }, - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to create user: ${error.message}`); + } + async create(username: string, password: string): Promise { + try { + return await prisma.user.create({ + data: { + username, + password } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to create user: ${error.message}`) } + } } -export default new UserRepository; \ No newline at end of file +export default new UserRepository() diff --git a/src/repositories/ZoneRepository.ts b/src/repositories/ZoneRepository.ts index 2bde86c..4516831 100644 --- a/src/repositories/ZoneRepository.ts +++ b/src/repositories/ZoneRepository.ts @@ -1,120 +1,120 @@ import { Zone, ZoneEventTile, ZoneObject } from '@prisma/client' -import prisma from '../utilities/Prisma'; // Import the global Prisma instance +import prisma from '../utilities/Prisma' // Import the global Prisma instance class ZoneRepository { - async getFirst(): Promise { - try { - return await prisma.zone.findFirst(); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get first zone: ${error.message}`); - } + async getFirst(): Promise { + try { + return await prisma.zone.findFirst() + } catch (error: any) { + // Handle error + throw new Error(`Failed to get first zone: ${error.message}`) } + } - async getAll(): Promise { - try { - return await prisma.zone.findMany(); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get all zone: ${error.message}`); - } + async getAll(): Promise { + try { + return await prisma.zone.findMany() + } catch (error: any) { + // Handle error + throw new Error(`Failed to get all zone: ${error.message}`) } + } - async getById(id: number): Promise { - try { - return await prisma.zone.findUnique({ - where: { - id: id - }, - include: { - zoneEventTiles: { - include: { - zone: true - } - }, - zoneObjects: { - include: { - object: true - } - } - } - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to get zone by id: ${error.message}`); + async getById(id: number): Promise { + try { + return await prisma.zone.findUnique({ + where: { + id: id + }, + include: { + zoneEventTiles: { + include: { + zone: true + } + }, + zoneObjects: { + include: { + object: true + } + } } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to get zone by id: ${error.message}`) } + } - async create(name: string, width: number, height: number, tiles: string[][]): Promise { - try { - return await prisma.zone.create({ - data: { - name: name, - width: width, - height: height, - tiles: tiles - } - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to create zone: ${error.message}`); + async create(name: string, width: number, height: number, tiles: string[][]): Promise { + try { + return await prisma.zone.create({ + data: { + name: name, + width: width, + height: height, + tiles: tiles } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to create zone: ${error.message}`) } + } - async update(id: number, name: string, width: number, height: number, tiles: string[][], zoneEventTiles: ZoneEventTile[], zoneObjects: ZoneObject[]): Promise { - try { - return await prisma.zone.update({ - where: { - id: id - }, - data: { - name, - width, - height, - tiles, - zoneEventTiles: { - deleteMany: { - zoneId: id // Ensure only event tiles related to the zone are deleted - }, - // Save new zone event tiles - create: zoneEventTiles.map(zoneEventTile => ({ - type: zoneEventTile.type, - position_x: zoneEventTile.position_x, - position_y: zoneEventTile.position_y - })) - }, - zoneObjects: { - deleteMany: { - zoneId: id // Ensure only objects related to the zone are deleted - }, - // Save new zone objects - create: zoneObjects.map(zoneObject => ({ - objectId: zoneObject.objectId, - depth: zoneObject.depth, - position_x: zoneObject.position_x, - position_y: zoneObject.position_y - })) - } - } - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to update zone: ${error.message}`); + async update(id: number, name: string, width: number, height: number, tiles: string[][], zoneEventTiles: ZoneEventTile[], zoneObjects: ZoneObject[]): Promise { + try { + return await prisma.zone.update({ + where: { + id: id + }, + data: { + name, + width, + height, + tiles, + zoneEventTiles: { + deleteMany: { + zoneId: id // Ensure only event tiles related to the zone are deleted + }, + // Save new zone event tiles + create: zoneEventTiles.map((zoneEventTile) => ({ + type: zoneEventTile.type, + position_x: zoneEventTile.position_x, + position_y: zoneEventTile.position_y + })) + }, + zoneObjects: { + deleteMany: { + zoneId: id // Ensure only objects related to the zone are deleted + }, + // Save new zone objects + create: zoneObjects.map((zoneObject) => ({ + objectId: zoneObject.objectId, + depth: zoneObject.depth, + position_x: zoneObject.position_x, + position_y: zoneObject.position_y + })) + } } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to update zone: ${error.message}`) } + } - async delete(id: number): Promise { - try { - return await prisma.zone.delete({ - where: { - id: id - } - }); - } catch (error: any) { - // Handle error - throw new Error(`Failed to delete zone: ${error.message}`); + async delete(id: number): Promise { + try { + return await prisma.zone.delete({ + where: { + id: id } + }) + } catch (error: any) { + // Handle error + throw new Error(`Failed to delete zone: ${error.message}`) } + } } -export default new ZoneRepository; \ No newline at end of file +export default new ZoneRepository() diff --git a/src/server.ts b/src/server.ts index b95127e..4573c28 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,104 +1,103 @@ -import fs from "fs"; -import path from "path"; -import express, {Application} from 'express'; -import {createServer as httpServer} from 'http'; -import {addHttpRoutes} from './utilities/Http'; -import cors from 'cors'; -import {Server as SocketServer} from 'socket.io'; -import {TSocket} from "./utilities/Types"; -import config from './utilities/Config'; -import prisma from './utilities/Prisma'; -import ZoneManager from "./managers/ZoneManager"; -import UserManager from "./managers/UserManager"; -import {Authentication} from "./middleware/Authentication"; -import CommandManager from "./managers/CommandManager"; -import {Dirent} from "node:fs"; +import fs from 'fs' +import path from 'path' +import express, { Application } from 'express' +import { createServer as httpServer } from 'http' +import { addHttpRoutes } from './utilities/Http' +import cors from 'cors' +import { Server as SocketServer } from 'socket.io' +import { TSocket } from './utilities/Types' +import config from './utilities/Config' +import prisma from './utilities/Prisma' +import ZoneManager from './managers/ZoneManager' +import UserManager from './managers/UserManager' +import { Authentication } from './middleware/Authentication' +import CommandManager from './managers/CommandManager' +import { Dirent } from 'node:fs' -export class Server -{ - private readonly app: Application; - private readonly http: any; - private readonly io: SocketServer; +export class Server { + private readonly app: Application + private readonly http: any + private readonly io: SocketServer - /** - * Creates an instance of GameServer. - */ - constructor() { - this.app = express(); - this.app.use(cors()); - this.app.use(express.json()); - this.app.use(express.urlencoded({ extended: true })); - this.http = httpServer(this.app) - this.io = new SocketServer(this.http); - this.io.use(Authentication) + /** + * Creates an instance of GameServer. + */ + constructor() { + this.app = express() + this.app.use(cors()) + this.app.use(express.json()) + this.app.use(express.urlencoded({ extended: true })) + this.http = httpServer(this.app) + this.io = new SocketServer(this.http) + this.io.use(Authentication) + } + + /** + * Start the server + */ + public async start() { + // Check prisma connection + try { + await prisma.$connect() + console.log('[✅] Database connected') + } catch (error: any) { + throw new Error(`[❌] Database connection failed: ${error.message}`) } - /** - * Start the server - */ - public async start() { - // Check prisma connection - try { - await prisma.$connect(); - console.log('[✅] Database connected'); - } catch (error: any) { - throw new Error(`[❌] Database connection failed: ${error.message}`); - } - - // Start the server - try { - await this.http.listen(config.PORT, config.HOST); - console.log('[✅] Socket.IO running on port', config.PORT); - } catch (error: any) { - throw new Error(`[❌] Socket.IO failed to start: ${error.message}`); - } - - // Add http API routes - await addHttpRoutes(this.app); - - // Load user manager - await UserManager.boot(); - - // Load zone manager - await ZoneManager.boot(); - - // Load command manager - Disabled for now - // await CommandManager.boot(this.io); - - // Listen for socket connections - this.io.on('connection', this.handleConnection.bind(this)); + // Start the server + try { + await this.http.listen(config.PORT, config.HOST) + console.log('[✅] Socket.IO running on port', config.PORT) + } catch (error: any) { + throw new Error(`[❌] Socket.IO failed to start: ${error.message}`) } - /** - * Handle socket connection - * @param socket - * @private - */ - private async handleConnection(socket: TSocket) { - const eventsPath = path.join(__dirname, 'events'); - try { - await this.loadEventHandlers(eventsPath, socket); - } catch (error: any) { - throw new Error('[❌] Failed to load event handlers: ' + error.message); - } + // Add http API routes + await addHttpRoutes(this.app) + + // Load user manager + await UserManager.boot() + + // Load zone manager + await ZoneManager.boot() + + // Load command manager - Disabled for now + // await CommandManager.boot(this.io); + + // Listen for socket connections + this.io.on('connection', this.handleConnection.bind(this)) + } + + /** + * Handle socket connection + * @param socket + * @private + */ + private async handleConnection(socket: TSocket) { + const eventsPath = path.join(__dirname, 'events') + try { + await this.loadEventHandlers(eventsPath, socket) + } catch (error: any) { + throw new Error('[❌] Failed to load event handlers: ' + error.message) } + } - private async loadEventHandlers(dir: string, socket: TSocket) { - const files: Dirent[] = await fs.promises.readdir(dir, { withFileTypes: true }); + private async loadEventHandlers(dir: string, socket: TSocket) { + const files: Dirent[] = await fs.promises.readdir(dir, { withFileTypes: true }) - for (const file of files) { - const fullPath = path.join(dir, file.name); + for (const file of files) { + const fullPath = path.join(dir, file.name) - if (file.isDirectory()) { - await this.loadEventHandlers(fullPath, socket); - } else if (file.isFile()) { - const module = await import(fullPath); - module.default(socket, this.io); - } - } + if (file.isDirectory()) { + await this.loadEventHandlers(fullPath, socket) + } else if (file.isFile()) { + const module = await import(fullPath) + module.default(socket, this.io) + } } + } } // Start the server -const server = new Server(); -server.start(); \ No newline at end of file +const server = new Server() +server.start() diff --git a/src/services/AssetService.ts b/src/services/AssetService.ts index 24158dc..fab2229 100644 --- a/src/services/AssetService.ts +++ b/src/services/AssetService.ts @@ -1,6 +1,3 @@ +class AssetService {} -class AssetService -{ -} - -export default AssetService; \ No newline at end of file +export default AssetService diff --git a/src/services/CharacterService.ts b/src/services/CharacterService.ts index f166cbc..b62016c 100644 --- a/src/services/CharacterService.ts +++ b/src/services/CharacterService.ts @@ -1,8 +1,5 @@ -import {Character} from "@prisma/client"; +import { Character } from '@prisma/client' -class CharacterService -{ +class CharacterService {} -} - -export default CharacterService; \ No newline at end of file +export default CharacterService diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 437e5f9..26b65fa 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -1,31 +1,30 @@ import bcrypt from 'bcryptjs' import UserRepository from '../repositories/UserRepository' -class UserService -{ - async login(username: string, password: string): Promise { - const user = await UserRepository.getByUsername(username); - if (!user) { - return false; - } - - const passwordMatch = await bcrypt.compare(password, user.password); - if (!passwordMatch) { - return false; - } - - return user; +class UserService { + async login(username: string, password: string): Promise { + const user = await UserRepository.getByUsername(username) + if (!user) { + return false } - async register(username: string, password: string): Promise { - const user = await UserRepository.getByUsername(username); - if (user) { - return false; - } - - const hashedPassword = await bcrypt.hash(password, 10); - return await UserRepository.create(username, hashedPassword) + const passwordMatch = await bcrypt.compare(password, user.password) + if (!passwordMatch) { + return false } + + return user + } + + async register(username: string, password: string): Promise { + const user = await UserRepository.getByUsername(username) + if (user) { + return false + } + + const hashedPassword = await bcrypt.hash(password, 10) + return await UserRepository.create(username, hashedPassword) + } } -export default UserService; \ No newline at end of file +export default UserService diff --git a/src/services/ZoneService.ts b/src/services/ZoneService.ts index 450e5ae..641e67c 100644 --- a/src/services/ZoneService.ts +++ b/src/services/ZoneService.ts @@ -1,25 +1,23 @@ -import {Zone} from "@prisma/client"; -import ZoneRepository from "../repositories/ZoneRepository"; +import { Zone } from '@prisma/client' +import ZoneRepository from '../repositories/ZoneRepository' -class ZoneService -{ - async createDemoZone(): Promise - { - await ZoneRepository.create("Demo Zone", 10, 10, [ - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], - ]) - console.log("Demo zone created."); - return true; - } +class ZoneService { + async createDemoZone(): Promise { + await ZoneRepository.create('Demo Zone', 10, 10, [ + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'], + ['blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile', 'blank_tile'] + ]) + console.log('Demo zone created.') + return true + } } -export default ZoneService; \ No newline at end of file +export default ZoneService diff --git a/src/utilities/Config.ts b/src/utilities/Config.ts index 498e168..b747735 100644 --- a/src/utilities/Config.ts +++ b/src/utilities/Config.ts @@ -1,17 +1,16 @@ -import dotenv from "dotenv"; +import dotenv from 'dotenv' -dotenv.config(); +dotenv.config() -class config -{ - static ENV: string = process.env.ENV || "prod"; - static HOST: string = process.env.HOST || "0.0.0.0"; - static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 6969; - static JWT_SECRET: string = process.env.JWT_SECRET || "secret"; +class config { + static ENV: string = process.env.ENV || 'prod' + static HOST: string = process.env.HOST || '0.0.0.0' + static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 6969 + static JWT_SECRET: string = process.env.JWT_SECRET || 'secret' - static DEFAULT_CHARACTER_ZONE: number = parseInt(process.env.DEFAULT_CHARACTER_ZONE || "1"); - static DEFAULT_CHARACTER_X: number = parseInt(process.env.DEFAULT_CHARACTER_POS_X || "0"); - static DEFAULT_CHARACTER_Y: number = parseInt(process.env.DEFAULT_CHARACTER_POS_Y || "0"); + static DEFAULT_CHARACTER_ZONE: number = parseInt(process.env.DEFAULT_CHARACTER_ZONE || '1') + static DEFAULT_CHARACTER_X: number = parseInt(process.env.DEFAULT_CHARACTER_POS_X || '0') + static DEFAULT_CHARACTER_Y: number = parseInt(process.env.DEFAULT_CHARACTER_POS_Y || '0') } -export default config; \ No newline at end of file +export default config diff --git a/src/utilities/Http.ts b/src/utilities/Http.ts index 6f0fd51..ece09d5 100644 --- a/src/utilities/Http.ts +++ b/src/utilities/Http.ts @@ -2,102 +2,103 @@ * Resources: * https://stackoverflow.com/questions/76131891/what-is-the-best-method-for-socket-io-authentication */ -import {Application, Request, Response} from 'express'; -import UserService from '../services/UserService'; -import jwt from "jsonwebtoken"; -import config from "./Config"; -import {loginAccountSchema, registerAccountSchema} from "./ZodTypes"; -import path from "path"; +import { Application, Request, Response } from 'express' +import UserService from '../services/UserService' +import jwt from 'jsonwebtoken' +import config from './Config' +import { loginAccountSchema, registerAccountSchema } from './ZodTypes' +import path from 'path' import { TAsset } from './Types' import tileRepository from '../repositories/TileRepository' import objectRepository from '../repositories/ObjectRepository' import spriteRepository from '../repositories/SpriteRepository' async function addHttpRoutes(app: Application) { - app.get('/assets', async (req: Request, res: Response) => { - let assets: TAsset[] = []; - const tiles = await tileRepository.getAll(); - tiles.forEach(tile => { - assets.push({ - key: tile.id, - value: '/assets/tiles/' + tile.id + '.png', - group: 'tiles', - type: 'link' - }); - }); + app.get('/assets', async (req: Request, res: Response) => { + let assets: TAsset[] = [] + const tiles = await tileRepository.getAll() + tiles.forEach((tile) => { + assets.push({ + key: tile.id, + value: '/assets/tiles/' + tile.id + '.png', + group: 'tiles', + type: 'link' + }) + }) - const objects = await objectRepository.getAll(); - objects.forEach(object => { - assets.push({ - key: object.id, - value: '/assets/objects/' + object.id + '.png', - group: 'objects', - type: 'link' - }); - }); + const objects = await objectRepository.getAll() + objects.forEach((object) => { + assets.push({ + key: object.id, + value: '/assets/objects/' + object.id + '.png', + group: 'objects', + type: 'link' + }) + }) - res.json(assets); - }); - app.get('/assets/:type/:file', (req: Request, res: Response) => { - const assetName = req.params.file; + res.json(assets) + }) + app.get('/assets/:type/:file', (req: Request, res: Response) => { + const assetName = req.params.file - // if (!isValidAsset(assetName)) { - // return res.status(400).send('Invalid asset name'); - // } + // if (!isValidAsset(assetName)) { + // return res.status(400).send('Invalid asset name'); + // } - const options = { - root: path.join(process.cwd(), 'public', req.params.type), - }; + const options = { + root: path.join(process.cwd(), 'public', req.params.type) + } - res.sendFile(assetName, options, (err) => { - if (err) { - console.error('Error sending file:', err); - res.status(500).send('Error downloading the asset'); - } - }); - }); + res.sendFile(assetName, options, (err) => { + if (err) { + console.error('Error sending file:', err) + res.status(500).send('Error downloading the asset') + } + }) + }) - app.post('/login', async (req: Request, res: Response) => { - const { username, password } = req.body; + app.post('/login', async (req: Request, res: Response) => { + const { username, password } = req.body - try { - loginAccountSchema.parse({ username, password }); - } catch (error: any) { - return res.status(400).json({ message: error.errors[0]?.message }); - } + try { + loginAccountSchema.parse({ username, password }) + } catch (error: any) { + return res.status(400).json({ message: error.errors[0]?.message }) + } - const userService = new UserService(); - const user = await userService.login(username, password); + const userService = new UserService() + const user = await userService.login(username, password) - if (user) { //test - const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '4h' }); - return res.status(200).json({ token }); - } + if (user) { + //test + const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '4h' }) + return res.status(200).json({ token }) + } - return res.status(400).json({ message: 'Failed to login' }); - }); + return res.status(400).json({ message: 'Failed to login' }) + }) - app.post('/register', async (req: Request, res: Response) => { - const { username, password } = req.body; + app.post('/register', async (req: Request, res: Response) => { + const { username, password } = req.body - try { - registerAccountSchema.parse({ username, password }); - } catch (error: any) { - return res.status(400).json({ message: error.errors[0]?.message }); - } + try { + registerAccountSchema.parse({ username, password }) + } catch (error: any) { + return res.status(400).json({ message: error.errors[0]?.message }) + } - const userService = new UserService(); - const user = await userService.register(username, password); + const userService = new UserService() + const user = await userService.register(username, password) - if (user) { - const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '4h' }); - return res.status(200).json({ token }); - } + if (user) { + const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '4h' }) + return res.status(200).json({ token }) + } - return res.status(400).json({ message: 'Failed to register user' }); - }); + return res.status(400).json({ message: 'Failed to register user' }) + }) - console.log('[✅] Web routes added'); + console.log('[✅] Web routes added') } -export { addHttpRoutes }; \ No newline at end of file +export { addHttpRoutes } diff --git a/src/utilities/Prisma.ts b/src/utilities/Prisma.ts index b904402..4590932 100644 --- a/src/utilities/Prisma.ts +++ b/src/utilities/Prisma.ts @@ -1,5 +1,5 @@ -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '@prisma/client' -const prisma = new PrismaClient(); +const prisma = new PrismaClient() -export default prisma; \ No newline at end of file +export default prisma diff --git a/src/utilities/Types.ts b/src/utilities/Types.ts index 33b8a6c..0bb74bf 100644 --- a/src/utilities/Types.ts +++ b/src/utilities/Types.ts @@ -1,33 +1,31 @@ -import { Socket } from 'socket.io'; -import {Character, User} from "@prisma/client"; +import { Socket } from 'socket.io' +import { Character, User } from '@prisma/client' export type TSocket = Socket & { - user?: User - character?: Character - handshake?: { - query?: { - token?: any - } + user?: User + character?: Character + handshake?: { + query?: { + token?: any } - request?: { - headers?: { - cookie?: any - } + } + request?: { + headers?: { + cookie?: any } + } } export type TCharacter = Socket & { - user?: User, - character?: Character + user?: User + character?: Character } -export type TZoneCharacter = Character & { - -} +export type TZoneCharacter = Character & {} export type TAsset = { - key: string - value: string - group: 'tiles' | 'objects' | 'sound' | 'music' | 'ui' | 'font' | 'other' - type: 'base64' | 'link' -} \ No newline at end of file + key: string + value: string + group: 'tiles' | 'objects' | 'sound' | 'music' | 'ui' | 'font' | 'other' + type: 'base64' | 'link' +} diff --git a/src/utilities/ZodTypes.ts b/src/utilities/ZodTypes.ts index f9a8909..6203820 100644 --- a/src/utilities/ZodTypes.ts +++ b/src/utilities/ZodTypes.ts @@ -1,28 +1,37 @@ -import { z } from 'zod'; +import { z } from 'zod' export const loginAccountSchema = z.object({ - username:z.string() - .min(3, { message: 'Name must be at least 3 characters long' }) - .max(255, { message: 'Name must be at most 255 characters long' }) - .regex(/^[A-Za-z][A-Za-z0-9_-]*$/, { message: 'Name must start with a letter and can only contain letters, numbers, underscores, or dashes' }), - password: z.string().min(8, { - message: 'Password must be at least 8 characters long' - }).max(255) -}); + username: z + .string() + .min(3, { message: 'Name must be at least 3 characters long' }) + .max(255, { message: 'Name must be at most 255 characters long' }) + .regex(/^[A-Za-z][A-Za-z0-9_-]*$/, { message: 'Name must start with a letter and can only contain letters, numbers, underscores, or dashes' }), + password: z + .string() + .min(8, { + message: 'Password must be at least 8 characters long' + }) + .max(255) +}) export const registerAccountSchema = z.object({ - username: z.string() - .min(3, { message: 'Name must be at least 3 characters long' }) - .max(255, { message: 'Name must be at most 255 characters long' }) - .regex(/^[A-Za-z][A-Za-z0-9_-]*$/, { message: 'Name must start with a letter and can only contain letters, numbers, underscores, or dashes' }), - password: z.string().min(8, { - message: 'Password must be at least 8 characters long' - }).max(255) -}); + username: z + .string() + .min(3, { message: 'Name must be at least 3 characters long' }) + .max(255, { message: 'Name must be at most 255 characters long' }) + .regex(/^[A-Za-z][A-Za-z0-9_-]*$/, { message: 'Name must start with a letter and can only contain letters, numbers, underscores, or dashes' }), + password: z + .string() + .min(8, { + message: 'Password must be at least 8 characters long' + }) + .max(255) +}) export const ZCharacterCreate = z.object({ - name: z.string() - .min(3, { message: 'Name must be at least 3 characters long' }) - .max(255, { message: 'Name must be at most 255 characters long' }) - .regex(/^[A-Za-z][A-Za-z0-9_-]*$/, { message: 'Name must start with a letter and can only contain letters, numbers, underscores, or dashes' }) -}); \ No newline at end of file + name: z + .string() + .min(3, { message: 'Name must be at least 3 characters long' }) + .max(255, { message: 'Name must be at most 255 characters long' }) + .regex(/^[A-Za-z][A-Za-z0-9_-]*$/, { message: 'Name must start with a letter and can only contain letters, numbers, underscores, or dashes' }) +})