diff --git a/prisma/migrations/20240706203202_init/migration.sql b/prisma/migrations/20240707014015_init/migration.sql similarity index 99% rename from prisma/migrations/20240706203202_init/migration.sql rename to prisma/migrations/20240707014015_init/migration.sql index fe8bc5a..d168782 100644 --- a/prisma/migrations/20240706203202_init/migration.sql +++ b/prisma/migrations/20240707014015_init/migration.sql @@ -76,7 +76,6 @@ CREATE TABLE `Zone` ( `width` INTEGER NOT NULL, `height` INTEGER NOT NULL, `tiles` JSON NOT NULL, - `walls` JSON NOT NULL, `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updatedAt` DATETIME(3) NOT NULL, diff --git a/src/app/events/gm/zone/GmZoneEditorZoneCreate.ts b/src/app/events/gm/zone/GmZoneEditorZoneCreate.ts new file mode 100644 index 0000000..1e720de --- /dev/null +++ b/src/app/events/gm/zone/GmZoneEditorZoneCreate.ts @@ -0,0 +1,44 @@ +import { Server } from "socket.io"; +import {TSocket} from "../../../utilities/Types"; +import ZoneRepository from "../../../repositories/ZoneRepository"; +import ZoneManager from "../../../ZoneManager"; +import {Character, Zone} from "@prisma/client"; + +interface IPayload { + name: string; + width: number; + height: number; +} + +/** + * Handle game master zone create event + * @param socket + * @param io + */ +export default function (socket: TSocket, io: Server) { + socket.on('gm:zone_editor:zone:create', async (data: IPayload, callback: (response: boolean) => void) => { + + 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.`); + + try { + const zone = await ZoneRepository.create( + data.name, + data.width, + data.height, + Array.from({length: data.height}, () => Array.from({length: data.width}, () => 'blank_tile')), + ); + + // send over zone and characters to socket + socket.emit('gm:zone_editor:zone:load', zone); + callback(true); + } catch (e) { + console.error(e); + callback(false); + } + }); +} \ No newline at end of file diff --git a/src/app/events/gm/zone/GmZoneEditorZoneDelete.ts b/src/app/events/gm/zone/GmZoneEditorZoneDelete.ts new file mode 100644 index 0000000..91456b7 --- /dev/null +++ b/src/app/events/gm/zone/GmZoneEditorZoneDelete.ts @@ -0,0 +1,42 @@ +import { Server } from "socket.io"; +import {TSocket} from "../../../utilities/Types"; +import ZoneRepository from "../../../repositories/ZoneRepository"; +import ZoneManager from "../../../ZoneManager"; +import {Character, Zone} from "@prisma/client"; + +interface IPayload { + zoneId: number; +} + +/** + * Handle game master zone delete event + * @param socket + * @param io + */ +export default function (socket: TSocket, io: Server) { + 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; + } + + console.log(`---GM ${socket.character?.id} has deleted a zone via zone editor.`); + + try { + const zone = await ZoneRepository.getById(data.zoneId); + + if (!zone) { + console.log(`---Zone not found.`); + return; + } + + await ZoneRepository.delete(data.zoneId); + + callback(true); + } catch (e) { + console.error(e); + callback(false); + } + }); +} \ No newline at end of file diff --git a/src/app/events/gm/zone/GmZoneEditorZoneList.ts b/src/app/events/gm/zone/GmZoneEditorZoneList.ts new file mode 100644 index 0000000..e88c5c7 --- /dev/null +++ b/src/app/events/gm/zone/GmZoneEditorZoneList.ts @@ -0,0 +1,32 @@ +import { Server } from "socket.io"; +import {TSocket} from '../../../utilities/Types' +import { Zone } from '@prisma/client' +import ZoneRepository from '../../../repositories/ZoneRepository' + +interface IPayload { +} + +/** + * Handle game master list zones event + * @param socket + * @param io + */ +export default function (socket: TSocket, io: Server) { + socket.on('gm:zone_editor:zone:list', async (data: any, callback: (response: Zone[]) => void) => { + + 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.`); + + try { + const zones = await ZoneRepository.getAll(); + callback(zones); + } catch (e) { + console.error(e); + callback([]); + } + }); +} \ No newline at end of file diff --git a/src/app/events/gm/GmZoneEditorZoneRequest.ts b/src/app/events/gm/zone/GmZoneEditorZoneRequest.ts similarity index 84% rename from src/app/events/gm/GmZoneEditorZoneRequest.ts rename to src/app/events/gm/zone/GmZoneEditorZoneRequest.ts index ea5735d..bd3eb16 100644 --- a/src/app/events/gm/GmZoneEditorZoneRequest.ts +++ b/src/app/events/gm/zone/GmZoneEditorZoneRequest.ts @@ -1,7 +1,7 @@ import { Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import ZoneRepository from "../../repositories/ZoneRepository"; -import ZoneManager from "../../ZoneManager"; +import {TSocket} from "../../../utilities/Types"; +import ZoneRepository from "../../../repositories/ZoneRepository"; +import ZoneManager from "../../../ZoneManager"; import {Character, Zone} from "@prisma/client"; interface IPayload { diff --git a/src/app/events/gm/GmZoneEditorZoneSave.ts b/src/app/events/gm/zone/GmZoneEditorZoneUpdate.ts similarity index 72% rename from src/app/events/gm/GmZoneEditorZoneSave.ts rename to src/app/events/gm/zone/GmZoneEditorZoneUpdate.ts index e9515a5..354570a 100644 --- a/src/app/events/gm/GmZoneEditorZoneSave.ts +++ b/src/app/events/gm/zone/GmZoneEditorZoneUpdate.ts @@ -1,7 +1,7 @@ import { Server } from "socket.io"; -import {TSocket} from "../../utilities/Types"; -import ZoneRepository from "../../repositories/ZoneRepository"; -import ZoneManager from "../../ZoneManager"; +import {TSocket} from "../../../utilities/Types"; +import ZoneRepository from "../../../repositories/ZoneRepository"; +import ZoneManager from "../../../ZoneManager"; import {Character, Zone} from "@prisma/client"; interface IPayload { @@ -9,24 +9,23 @@ interface IPayload { name: string; width: number; height: number; - tiles: number[][]; - walls: number[][]; + tiles: string[][]; } /** - * Handle game master zone save event + * Handle game master zone update event * @param socket * @param io */ export default function (socket: TSocket, io: Server) { - socket.on('gm:zone_editor:zone:save', 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; } - console.log(`---GM ${socket.character?.id} has saved zone via zone editor.`); + console.log(`---GM ${socket.character?.id} has updated zone via zone editor.`); console.log(data); @@ -48,7 +47,6 @@ export default function (socket: TSocket, io: Server) { data.width, data.height, data.tiles, - data.walls ); zone = await ZoneRepository.getById(data.zoneId); diff --git a/src/app/repositories/ZoneRepository.ts b/src/app/repositories/ZoneRepository.ts index 35857db..6e9d1bd 100644 --- a/src/app/repositories/ZoneRepository.ts +++ b/src/app/repositories/ZoneRepository.ts @@ -33,7 +33,7 @@ class ZoneRepository { } } - async create(name: string, width: number, height: number, tiles: number[][], walls: number[][]): Promise { + async create(name: string, width: number, height: number, tiles: string[][]): Promise { try { return await prisma.zone.create({ data: { @@ -41,7 +41,6 @@ class ZoneRepository { width: width, height: height, tiles: tiles, - walls: walls, } }); } catch (error: any) { @@ -50,7 +49,7 @@ class ZoneRepository { } } - async update(id: number, name: string, width: number, height: number, tiles: number[][], walls: number[][]): Promise { + async update(id: number, name: string, width: number, height: number, tiles: string[][]): Promise { try { return await prisma.zone.update({ where: { @@ -61,7 +60,6 @@ class ZoneRepository { width: width, height: height, tiles: tiles, - walls: walls, } }); } catch (error: any) { @@ -69,6 +67,19 @@ class ZoneRepository { 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}`); + } + } } export default new ZoneRepository; \ No newline at end of file diff --git a/src/app/services/ZoneService.ts b/src/app/services/ZoneService.ts index f036041..450e5ae 100644 --- a/src/app/services/ZoneService.ts +++ b/src/app/services/ZoneService.ts @@ -6,27 +6,16 @@ class ZoneService async createDemoZone(): Promise { await ZoneRepository.create("Demo Zone", 10, 10, [ - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - ], [ - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ['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; diff --git a/src/app/utilities/Http.ts b/src/app/utilities/Http.ts index a857a97..5c52b97 100644 --- a/src/app/utilities/Http.ts +++ b/src/app/utilities/Http.ts @@ -94,6 +94,11 @@ function listTiles(): string[] { // get root path const folder = path.join(process.cwd(), 'public', 'tiles'); + // if folder does not exist, create it + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder); + } + // list the files in the folder let tiles: string[] = []; @@ -107,8 +112,6 @@ function listTiles(): string[] { console.log(err); } - console.log(tiles); - return tiles; } @@ -116,6 +119,11 @@ function listObjects(): string[] { // get root path const folder = path.join(process.cwd(), 'public', 'objects'); + // if folder does not exist, create it + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder); + } + // list the files in the folder let objects: string[] = []; @@ -129,7 +137,5 @@ function listObjects(): string[] { console.log(err); } - console.log(objects); - return objects; } \ No newline at end of file