diff --git a/package-lock.json b/package-lock.json index f2928f1..1fa040b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2141,9 +2141,9 @@ } }, "node_modules/pino": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.5.0.tgz", - "integrity": "sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", + "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", diff --git a/src/socketEvents/gameMaster/assetManager/sprite/copy.ts b/src/socketEvents/gameMaster/assetManager/sprite/copy.ts new file mode 100644 index 0000000..2d38725 --- /dev/null +++ b/src/socketEvents/gameMaster/assetManager/sprite/copy.ts @@ -0,0 +1,77 @@ +import { Server } from 'socket.io' +import { TSocket } from '../../../../utilities/types' +import prisma from '../../../../utilities/prisma' +import CharacterRepository from '../../../../repositories/characterRepository' +import { gameMasterLogger } from '../../../../utilities/logger' +import type { Prisma } from '@prisma/client' + +interface CopyPayload { + id: string +} + +export default class SpriteCopyEvent { + constructor( + private readonly io: Server, + private readonly socket: TSocket + ) {} + + public listen(): void { + this.socket.on('gm:sprite:copy', this.handleSpriteCopy.bind(this)) + } + + private async handleSpriteCopy(payload: CopyPayload, callback: (success: boolean) => void): Promise { + try { + if (!(await this.validateGameMasterAccess())) { + return callback(false) + } + + const sourceSprite = await prisma.sprite.findUnique({ + where: { id: payload.id }, + include: { + spriteActions: true + } + }) + + if (!sourceSprite) { + throw new Error('Source sprite not found') + } + + const newSprite = await prisma.sprite.create({ + data: { + name: `${sourceSprite.name} (Copy)`, + spriteActions: { + create: sourceSprite.spriteActions.map(action => ({ + action: action.action, + sprites: action.sprites as Prisma.InputJsonValue, + originX: action.originX, + originY: action.originY, + isAnimated: action.isAnimated, + isLooping: action.isLooping, + frameWidth: action.frameWidth, + frameHeight: action.frameHeight, + frameRate: action.frameRate + })) + } + } + }) + + callback(true) + } catch (error) { + this.handleError(error, payload.id, callback) + } + } + + private async validateGameMasterAccess(): Promise { + const character = await CharacterRepository.getById(this.socket.characterId!) + return character?.role === 'gm' + } + + private handleError(error: unknown, spriteId: string, callback: (success: boolean) => void): void { + gameMasterLogger.error(`Error copying sprite ${spriteId}: ${this.getErrorMessage(error)}`) + callback(false) + } + + private getErrorMessage(error: unknown): string { + return error instanceof Error ? error.message : String(error) + } +} \ No newline at end of file