From 93cb7b78873098111e3f7528ad552a71d8c76e36 Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Mon, 3 Jun 2024 20:40:01 +0200 Subject: [PATCH] Added better security for character loading, worked on zone joining and moving logic --- src/app/UserManager.ts | 2 +- src/app/ZoneManager.ts | 25 +++++++++++++++++++++ src/app/events/CharacterConnect.ts | 5 +++-- src/app/events/CharacterList.ts | 11 ++++++--- src/app/events/CharacterMove.ts | 19 ++++++++++++++++ src/app/events/CharacterZoneLoad.ts | 20 ++++++++++------- src/app/repositories/CharacterRepository.ts | 14 ++++++++++++ 7 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 src/app/events/CharacterMove.ts diff --git a/src/app/UserManager.ts b/src/app/UserManager.ts index a12c2e4..e8ecf4c 100644 --- a/src/app/UserManager.ts +++ b/src/app/UserManager.ts @@ -13,7 +13,7 @@ class UserManager { } // Function that adds user to logged in users - public addUser(user: User) { + public loginUser(user: User) { this.loggedInUsers.push({ users: [user] }); diff --git a/src/app/ZoneManager.ts b/src/app/ZoneManager.ts index 8dee26d..764e51d 100644 --- a/src/app/ZoneManager.ts +++ b/src/app/ZoneManager.ts @@ -59,6 +59,31 @@ class ZoneManager { } } + public removeCharacterFromZone(zoneId: number, characterId: number) { + const loadedZone = this.loadedZones.find((loadedZone) => { + return loadedZone.zone.id === zoneId; + }); + if (loadedZone) { + loadedZone.characters = loadedZone.characters.filter((character) => { + return character.id !== characterId; + }); + } + } + + 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; diff --git a/src/app/events/CharacterConnect.ts b/src/app/events/CharacterConnect.ts index 0bd2923..556754c 100644 --- a/src/app/events/CharacterConnect.ts +++ b/src/app/events/CharacterConnect.ts @@ -1,7 +1,7 @@ import { Socket, Server } from "socket.io"; import {TSocket} from "../utilities/Types"; import CharacterRepository from "../repositories/CharacterRepository"; -import {Character} from "@prisma/client"; +import {Character, User} from "@prisma/client"; type SocketResponseT = { character_id: number @@ -9,8 +9,9 @@ type SocketResponseT = { 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.getById(data.character_id) as Character; + 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/app/events/CharacterList.ts b/src/app/events/CharacterList.ts index e5a6a9a..cf8bc5e 100644 --- a/src/app/events/CharacterList.ts +++ b/src/app/events/CharacterList.ts @@ -5,8 +5,13 @@ import CharacterRepository from "../repositories/CharacterRepository"; export default function CharacterList(socket: TSocket, io: Server) { socket.on('character:list', async (data: any) => { - const user_id = socket.user?.id as number; - const characters: Character[] = await CharacterRepository.getByUserId(user_id) as Character[]; - socket.emit('character:list', characters); + 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 diff --git a/src/app/events/CharacterMove.ts b/src/app/events/CharacterMove.ts new file mode 100644 index 0000000..b5e7239 --- /dev/null +++ b/src/app/events/CharacterMove.ts @@ -0,0 +1,19 @@ +import { Socket, Server } from "socket.io"; +import {TSocket} from "../utilities/Types"; +import CharacterRepository from "../repositories/CharacterRepository"; +import {Character} from "@prisma/client"; + +type SocketResponseT = { + character_id: number +} + +export default function (socket: TSocket, io: Server) { + socket.on('character:move', async (data: SocketResponseT) => { + try { + socket.character = await CharacterRepository.getById(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 diff --git a/src/app/events/CharacterZoneLoad.ts b/src/app/events/CharacterZoneLoad.ts index 7440339..de08be4 100644 --- a/src/app/events/CharacterZoneLoad.ts +++ b/src/app/events/CharacterZoneLoad.ts @@ -1,7 +1,8 @@ -import { Socket, Server } from "socket.io"; +import { Server } from "socket.io"; +import {TSocket} from "../utilities/Types"; import ZoneRepository from "../repositories/ZoneRepository"; import ZoneManager from "../ZoneManager"; -import {Zone} from "@prisma/client"; +import {Character, Zone} from "@prisma/client"; interface IZoneLoad { zoneId?: number; @@ -14,9 +15,9 @@ interface IZoneLoad { * @param socket * @param io */ -export default function (socket: Socket, io: Server) { +export default function (socket: TSocket, io: Server) { socket.on('character:zone:load', async (data: IZoneLoad) => { - console.log(`---User ${socket.id} has requested zone.`); + console.log(`---User ${socket.character?.id} has requested zone.`); const zone = await ZoneRepository.getById(1); @@ -27,15 +28,18 @@ export default function (socket: Socket, io: Server) { socket.join(zone.name); - const socketConnectionsInRoom = await io.in(zone.name).fetchSockets(); - const characters = socketConnectionsInRoom.filter(socket => socket.id !== socket.id); + ZoneManager.addCharacterToZone(zone.id, socket.character as Character); - // update to match with model Character + // const socketConnectionsInRoom = await io.in(zone.name).fetchSockets(); + // const characters = socketConnectionsInRoom.filter(socket => socket.id !== socket.id); + + // let other clients know of new character + socket.to(zone.name).emit('character:zone:character_join', socket.character); // send over zone and characters io.in(zone.name).to(socket.id).emit('character:zone:load', { zone: zone, - characters: characters, + characters: ZoneManager.getCharactersInZone(zone.id), }); }); } \ No newline at end of file diff --git a/src/app/repositories/CharacterRepository.ts b/src/app/repositories/CharacterRepository.ts index 8fea578..7eb2fba 100644 --- a/src/app/repositories/CharacterRepository.ts +++ b/src/app/repositories/CharacterRepository.ts @@ -16,6 +16,20 @@ class CharacterRepository { } } + async getByUserAndId(userId: number, characterId: number): Promise { + try { + return await prisma.character.findFirst({ + where: { + userId, + id: characterId, + }, + }); + } 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({