diff --git a/prisma/migrations/20241117163808_added_selectable_field_to_character_types/migration.sql b/prisma/migrations/20241117163808_added_selectable_field_to_character_types/migration.sql new file mode 100644 index 0000000..b3e94cc --- /dev/null +++ b/prisma/migrations/20241117163808_added_selectable_field_to_character_types/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE `CharacterType` ADD COLUMN `isEnabledForCharCreation` BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/schema/game.prisma b/prisma/schema/game.prisma index c3d8571..40ce1fb 100644 --- a/prisma/schema/game.prisma +++ b/prisma/schema/game.prisma @@ -5,3 +5,37 @@ model World { isFogEnabled Boolean @default(false) fogDensity Int @default(0) } + +model Chat { + id Int @id @default(autoincrement()) + characterId Int + character Character @relation(fields: [characterId], references: [id], onDelete: Cascade) + zoneId Int + zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade) + message String + createdAt DateTime @default(now()) +} + +model Sprite { + id String @id @default(uuid()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + spriteActions SpriteAction[] + characterTypes CharacterType[] +} + +model SpriteAction { + id String @id @default(uuid()) + spriteId String + sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade) + action String + sprites Json? + originX Decimal @default(0) + originY Decimal @default(0) + isAnimated Boolean @default(false) + isLooping Boolean @default(false) + frameWidth Int @default(0) + frameHeight Int @default(0) + frameSpeed Int @default(0) +} diff --git a/prisma/schema/schema.prisma b/prisma/schema/schema.prisma index 75b85f9..13d488b 100644 --- a/prisma/schema/schema.prisma +++ b/prisma/schema/schema.prisma @@ -19,13 +19,3 @@ datasource db { provider = "mysql" url = env("DATABASE_URL") } - -model Chat { - id Int @id @default(autoincrement()) - characterId Int - character Character @relation(fields: [characterId], references: [id], onDelete: Cascade) - zoneId Int - zone Zone @relation(fields: [zoneId], references: [id], onDelete: Cascade) - message String - createdAt DateTime @default(now()) -} diff --git a/prisma/schema/sprite.prisma b/prisma/schema/sprite.prisma deleted file mode 100644 index c9a85c5..0000000 --- a/prisma/schema/sprite.prisma +++ /dev/null @@ -1,23 +0,0 @@ -model Sprite { - id String @id @default(uuid()) - name String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - spriteActions SpriteAction[] - characterTypes CharacterType[] -} - -model SpriteAction { - id String @id @default(uuid()) - spriteId String - sprite Sprite @relation(fields: [spriteId], references: [id], onDelete: Cascade) - action String - sprites Json? - originX Decimal @default(0) - originY Decimal @default(0) - isAnimated Boolean @default(false) - isLooping Boolean @default(false) - frameWidth Int @default(0) - frameHeight Int @default(0) - frameSpeed Int @default(0) -} diff --git a/prisma/schema/user.prisma b/prisma/schema/user.prisma index 7c1f967..c67bdbd 100644 --- a/prisma/schema/user.prisma +++ b/prisma/schema/user.prisma @@ -1,11 +1,11 @@ model User { - id Int @id @default(autoincrement()) - username String @unique - email String @unique - password String - online Boolean @default(false) - characters Character[] - passwordResetTokens PasswordResetToken[] + id Int @id @default(autoincrement()) + username String @unique + email String @unique + password String + online Boolean @default(false) + characters Character[] + passwordResetTokens PasswordResetToken[] } model PasswordResetToken { @@ -30,15 +30,16 @@ enum CharacterRace { } model CharacterType { - id Int @id @default(autoincrement()) - name String - gender CharacterGender - race CharacterRace - characters Character[] - spriteId String? - sprite Sprite? @relation(fields: [spriteId], references: [id], onDelete: Cascade) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + name String + gender CharacterGender + race CharacterRace + isEnabledForCharCreation Boolean @default(false) + characters Character[] + spriteId String? + sprite Sprite? @relation(fields: [spriteId], references: [id], onDelete: Cascade) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Character { @@ -71,4 +72,4 @@ model CharacterItem { itemId String item Item @relation(fields: [itemId], references: [id], onDelete: Cascade) quantity Int -} \ No newline at end of file +} diff --git a/src/socketEvents/chat/gameMaster/alertCommand.ts b/src/socketEvents/chat/gameMaster/alertCommand.ts index 5456f31..1030d63 100644 --- a/src/socketEvents/chat/gameMaster/alertCommand.ts +++ b/src/socketEvents/chat/gameMaster/alertCommand.ts @@ -28,26 +28,23 @@ export default class AlertCommandEvent { const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!) if (!character) { gameLogger.error('chat:alert_command error', 'Character not found') - callback(false) - return + return callback(false) } // Check if the user is the GM if (character.role !== 'gm') { gameLogger.info(`User ${character.id} tried to set time but is not a game master.`) - callback(false) - return + return callback(false) } const args = getArgs('alert', data.message) if (!args) { - callback(false) - return + return callback(false) } this.io.emit('notification', { title: 'Message from GM', message: args.join(' ') }) - callback(true) + return callback(true) } catch (error: any) { gameLogger.error('chat:alert_command error', error.message) callback(false) diff --git a/src/socketEvents/chat/gameMaster/setTimeCommand.ts b/src/socketEvents/chat/gameMaster/setTimeCommand.ts index 51e5a42..64e4379 100644 --- a/src/socketEvents/chat/gameMaster/setTimeCommand.ts +++ b/src/socketEvents/chat/gameMaster/setTimeCommand.ts @@ -29,14 +29,12 @@ export default class SetTimeCommand { const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!) if (!character) { gameLogger.error('chat:alert_command error', 'Character not found') - callback(false) return } // Check if the user is the GM if (character.role !== 'gm') { gameLogger.info(`User ${character.id} tried to set time but is not a game master.`) - callback(false) return } @@ -44,20 +42,16 @@ export default class SetTimeCommand { const args = getArgs('time', data.message) if (!args) { - callback(false) return } const time = args[0] // 24h time, e.g. 17:34 if (!time) { - callback(false) return } await DateManager.setTime(time) - - callback(true) } catch (error: any) { gameLogger.error('command error', error.message) callback(false) diff --git a/src/socketEvents/chat/gameMaster/teleportCommand.ts b/src/socketEvents/chat/gameMaster/teleportCommand.ts index 5992842..e5e0a49 100644 --- a/src/socketEvents/chat/gameMaster/teleportCommand.ts +++ b/src/socketEvents/chat/gameMaster/teleportCommand.ts @@ -26,7 +26,6 @@ export default class TeleportCommandEvent { const zoneCharacter = ZoneManager.getCharacter(this.socket.characterId!) if (!zoneCharacter) { gameLogger.error('chat:message error', 'Character not found') - callback(false) return } @@ -35,7 +34,6 @@ export default class TeleportCommandEvent { // Check if the user is the GM if (character.role !== 'gm') { gameLogger.info(`User ${character.id} tried to set time but is not a game master.`) - callback(false) return } @@ -86,8 +84,6 @@ export default class TeleportCommandEvent { this.socket.emit('notification', { title: 'Server message', message: `You have been teleported to ${zone.name}` }) gameMasterLogger.info('teleport', `Character ${character.id} teleported to zone ${zone.id}`) - - callback(true) } catch (error: any) { gameMasterLogger.error(`Error in teleport command: ${error.message}`) this.socket.emit('notification', { title: 'Server message', message: 'An error occurred while teleporting' }) diff --git a/src/socketEvents/chat/gameMaster/toggleFogCommand.ts b/src/socketEvents/chat/gameMaster/toggleFogCommand.ts index d8f4302..b1ef920 100644 --- a/src/socketEvents/chat/gameMaster/toggleFogCommand.ts +++ b/src/socketEvents/chat/gameMaster/toggleFogCommand.ts @@ -29,20 +29,16 @@ export default class ToggleFogCommand { const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!) if (!character) { gameLogger.error('chat:alert_command error', 'Character not found') - callback(false) return } // Check if the user is the GM if (character.role !== 'gm') { gameLogger.info(`User ${character.id} tried to set time but is not a game master.`) - callback(false) return } await WeatherManager.toggleFog() - - callback(true) } catch (error: any) { gameLogger.error('command error', error.message) callback(false) diff --git a/src/socketEvents/chat/gameMaster/toggleRainCommand.ts b/src/socketEvents/chat/gameMaster/toggleRainCommand.ts index 9b74ebf..7950525 100644 --- a/src/socketEvents/chat/gameMaster/toggleRainCommand.ts +++ b/src/socketEvents/chat/gameMaster/toggleRainCommand.ts @@ -29,20 +29,16 @@ export default class ToggleRainCommand { const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!) if (!character) { gameLogger.error('chat:alert_command error', 'Character not found') - callback(false) return } // Check if the user is the GM if (character.role !== 'gm') { gameLogger.info(`User ${character.id} tried to set time but is not a game master.`) - callback(false) return } await WeatherManager.toggleRain() - - callback(true) } catch (error: any) { gameLogger.error('command error', error.message) callback(false) diff --git a/src/socketEvents/gameMaster/assetManager/characterType/create.ts b/src/socketEvents/gameMaster/assetManager/characterType/create.ts index 46cd6a5..71e08e1 100644 --- a/src/socketEvents/gameMaster/assetManager/characterType/create.ts +++ b/src/socketEvents/gameMaster/assetManager/characterType/create.ts @@ -11,10 +11,10 @@ export default class CharacterTypeCreateEvent { ) {} public listen(): void { - this.socket.on('gm:characterType:create', this.handleCharacterTypeCreate.bind(this)) + this.socket.on('gm:characterType:create', this.handleEvent.bind(this)) } - private async handleCharacterTypeCreate(data: undefined, callback: (response: boolean, characterType?: any) => void): Promise { + private async handleEvent(data: undefined, callback: (response: boolean, characterType?: any) => void): Promise { try { const character = await characterRepository.getById(this.socket.characterId as number) if (!character) return callback(false) diff --git a/src/socketEvents/gameMaster/assetManager/characterType/remove.ts b/src/socketEvents/gameMaster/assetManager/characterType/delete.ts similarity index 86% rename from src/socketEvents/gameMaster/assetManager/characterType/remove.ts rename to src/socketEvents/gameMaster/assetManager/characterType/delete.ts index c4fc976..46b043b 100644 --- a/src/socketEvents/gameMaster/assetManager/characterType/remove.ts +++ b/src/socketEvents/gameMaster/assetManager/characterType/delete.ts @@ -10,17 +10,17 @@ interface IPayload { object: string } -export default class ObjectRemoveEvent { +export default class CharacterTypeDeleteEvent { constructor( private readonly io: Server, private readonly socket: TSocket ) {} public listen(): void { - this.socket.on('gm:object:remove', this.handleObjectRemove.bind(this)) + this.socket.on('gm:characterType:remove', this.handleEvent.bind(this)) } - private async handleObjectRemove(data: IPayload, callback: (response: boolean) => void): Promise { + private async handleEvent(data: IPayload, callback: (response: boolean) => void): Promise { const character = await characterRepository.getById(this.socket.characterId as number) if (!character) return callback(false) diff --git a/src/socketEvents/gameMaster/assetManager/characterType/list.ts b/src/socketEvents/gameMaster/assetManager/characterType/list.ts index 53df172..b3624f6 100644 --- a/src/socketEvents/gameMaster/assetManager/characterType/list.ts +++ b/src/socketEvents/gameMaster/assetManager/characterType/list.ts @@ -14,10 +14,10 @@ export default class CharacterTypeListEvent { ) {} public listen(): void { - this.socket.on('gm:characterType:list', this.handleCharacterTypeList.bind(this)) + this.socket.on('gm:characterType:list', this.handleEvent.bind(this)) } - private async handleCharacterTypeList(data: IPayload, callback: (response: CharacterType[]) => void): Promise { + private async handleEvent(data: IPayload, callback: (response: CharacterType[]) => void): Promise { const character = await characterRepository.getById(this.socket.characterId as number) if (!character) { gameMasterLogger.error('gm:characterType:list error', 'Character not found') diff --git a/src/socketEvents/gameMaster/assetManager/characterType/update.ts b/src/socketEvents/gameMaster/assetManager/characterType/update.ts index 2c7c27b..7a5bf09 100644 --- a/src/socketEvents/gameMaster/assetManager/characterType/update.ts +++ b/src/socketEvents/gameMaster/assetManager/characterType/update.ts @@ -2,27 +2,25 @@ import { Server } from 'socket.io' import { TSocket } from '../../../../utilities/types' import prisma from '../../../../utilities/prisma' import characterRepository from '../../../../repositories/characterRepository' +import { CharacterGender, CharacterRace } from '@prisma/client' type Payload = { - id: string + id: number name: string - tags: string[] - originX: number - originY: number - isAnimated: boolean - frameSpeed: number - frameWidth: number - frameHeight: number + gender: CharacterGender + race: CharacterRace + isEnabledForCharCreation: boolean + spriteId: string } -export default class ObjectUpdateEvent { +export default class CharacterTypeUpdateEvent { constructor( private readonly io: Server, private readonly socket: TSocket ) {} public listen(): void { - this.socket.on('gm:object:update', this.handleObjectUpdate.bind(this)) + this.socket.on('gm:characterType:update', this.handleObjectUpdate.bind(this)) } private async handleObjectUpdate(data: Payload, callback: (success: boolean) => void): Promise { @@ -34,21 +32,17 @@ export default class ObjectUpdateEvent { } try { - await prisma.object.update({ - where: { - id: data.id - }, + await prisma.characterType.update({ + where: { id: data.id }, data: { name: data.name, - tags: data.tags, - originX: data.originX, - originY: data.originY, - isAnimated: data.isAnimated, - frameSpeed: data.frameSpeed, - frameWidth: data.frameWidth, - frameHeight: data.frameHeight + gender: data.gender, + race: data.race, + isEnabledForCharCreation: data.isEnabledForCharCreation, + spriteId: data.spriteId } }) + callback(true) } catch (error) { console.error(error)