From 1017013032dc4be7740ce0c3704565bf3b6efb25 Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Sat, 23 Nov 2024 16:48:07 +0100 Subject: [PATCH] Moved service logic from repo to service, minor improvements, working hair customisation proof of concept --- src/models/zoneCharacter.ts | 2 +- src/repositories/characterHairRepository.ts | 7 ++ src/repositories/characterRepository.ts | 62 ++++++-------- .../{character => }/characterService.ts | 80 ++++++++++++------- .../character/characterScreen/list_hair.ts | 0 .../charactersScreen/character_hair_list.ts | 22 +++++ src/socketEvents/character/connect.ts | 8 +- src/socketEvents/character/create.ts | 2 +- src/socketEvents/character/delete.ts | 4 +- src/socketEvents/zone/characterMove.ts | 2 +- 10 files changed, 118 insertions(+), 71 deletions(-) rename src/services/{character => }/characterService.ts (68%) delete mode 100644 src/socketEvents/character/characterScreen/list_hair.ts create mode 100644 src/socketEvents/character/charactersScreen/character_hair_list.ts diff --git a/src/models/zoneCharacter.ts b/src/models/zoneCharacter.ts index 690e439..a6912ef 100644 --- a/src/models/zoneCharacter.ts +++ b/src/models/zoneCharacter.ts @@ -1,5 +1,5 @@ import { Character } from '@prisma/client' -import { CharacterService } from '../services/character/characterService' +import { CharacterService } from '../services/characterService' class ZoneCharacter { public readonly character: Character diff --git a/src/repositories/characterHairRepository.ts b/src/repositories/characterHairRepository.ts index e4eeaa2..dd47bb9 100644 --- a/src/repositories/characterHairRepository.ts +++ b/src/repositories/characterHairRepository.ts @@ -5,6 +5,13 @@ class CharacterHairRepository { async getAll(): Promise { return prisma.characterHair.findMany() } + async getIsEnabledForCharCreationHair(): Promise { + return prisma.characterHair.findMany({ + where: { + isEnabledForCharCreation: true + } + }) + } } export default new CharacterHairRepository() diff --git a/src/repositories/characterRepository.ts b/src/repositories/characterRepository.ts index 500b167..712cbdd 100644 --- a/src/repositories/characterRepository.ts +++ b/src/repositories/characterRepository.ts @@ -1,9 +1,8 @@ import prisma from '../utilities/prisma' // Import the global Prisma instance -import { Character } from '@prisma/client' import { appLogger } from '../utilities/logger' class CharacterRepository { - async getByUserId(userId: number): Promise { + async getByUserId(userId: number) { try { return await prisma.character.findMany({ where: { @@ -15,6 +14,11 @@ class CharacterRepository { include: { sprite: true } + }, + hair: { + include: { + sprite: true + } } } }) @@ -25,7 +29,7 @@ class CharacterRepository { } } - async getByUserAndId(userId: number, characterId: number): Promise { + async getByUserAndId(userId: number, characterId: number) { try { return await prisma.character.findFirst({ where: { @@ -38,6 +42,11 @@ class CharacterRepository { include: { sprite: true } + }, + hair: { + include: { + sprite: true + } } } }) @@ -48,7 +57,7 @@ class CharacterRepository { } } - async getById(id: number): Promise { + async getById(id: number) { try { return await prisma.character.findUnique({ where: { @@ -60,6 +69,11 @@ class CharacterRepository { include: { sprite: true } + }, + hair: { + include: { + sprite: true + } } } }) @@ -70,40 +84,7 @@ class CharacterRepository { } } - async updatePosition(id: number, positionX: number, positionY: number): Promise { - try { - return await prisma.character.update({ - where: { - id: id - }, - data: { - positionX, - positionY - } - }) - } catch (error: any) { - // Handle error - appLogger.error(`Failed to update character: ${error instanceof Error ? error.message : String(error)}`) - return null - } - } - - async deleteByUserIdAndId(userId: number, characterId: number): Promise { - try { - return await prisma.character.delete({ - where: { - userId, - id: characterId - } - }) - } catch (error: any) { - // Handle error - appLogger.error(`Failed to delete character by user ID and character ID: ${error instanceof Error ? error.message : String(error)}`) - return null - } - } - - async getByName(name: string): Promise { + async getByName(name: string) { try { return await prisma.character.findFirst({ where: { @@ -115,6 +96,11 @@ class CharacterRepository { include: { sprite: true } + }, + hair: { + include: { + sprite: true + } } } }) diff --git a/src/services/character/characterService.ts b/src/services/characterService.ts similarity index 68% rename from src/services/character/characterService.ts rename to src/services/characterService.ts index 75bd05c..eef016e 100644 --- a/src/services/character/characterService.ts +++ b/src/services/characterService.ts @@ -1,9 +1,9 @@ -import { AStar } from '../../utilities/character/aStar' -import ZoneManager from '../../managers/zoneManager' -import prisma from '../../utilities/prisma' -import Rotation from '../../utilities/character/rotation' -import { gameLogger } from '../../utilities/logger' -import { Character, CharacterGender, CharacterRace } from '@prisma/client' +import { AStar } from '../utilities/character/aStar' +import ZoneManager from '../managers/zoneManager' +import prisma from '../utilities/prisma' +import Rotation from '../utilities/character/rotation' +import { appLogger, gameLogger } from '../utilities/logger' +import { Character } from '@prisma/client' interface Position { x: number @@ -13,6 +13,52 @@ interface Position { export class CharacterService { private readonly MOVEMENT_DELAY_MS = 250 + async create(name: string, userId: number) { + return prisma.character.create({ + data: { + name, + userId + // characterTypeId: 1 // @TODO set to chosen character type + } + }) + } + + async updateHair(characterId: number, hairId: number | null) { + await prisma.character.update({ + where: { id: characterId }, + data: { + hairId + } + }) + } + + async deleteByUserIdAndId(userId: number, characterId: number): Promise { + try { + return await prisma.character.delete({ + where: { + userId, + id: characterId + } + }) + } catch (error: any) { + // Handle error + appLogger.error(`Failed to delete character by user ID and character ID: ${error instanceof Error ? error.message : String(error)}`) + return null + } + } + + async updateCharacterPosition(id: number, positionX: number, positionY: number, rotation: number, zoneId: number) { + await prisma.character.update({ + where: { id }, + data: { + positionX, + positionY, + rotation, + zoneId + } + }) + } + public updatePosition(character: Character, position: Position, newZoneId?: number): void { if (!this.isValidPosition(position)) { gameLogger.error(`Invalid position coordinates: ${position.x}, ${position.y}`) @@ -55,26 +101,4 @@ export class CharacterService { private isValidPosition(position: Position): boolean { return Number.isFinite(position.x) && Number.isFinite(position.y) && position.x >= 0 && position.y >= 0 } - - async create(name: string, userId: number) { - return prisma.character.create({ - data: { - name, - userId - // characterTypeId: 1 // @TODO set to chosen character type - } - }) - } - - async updateCharacterPosition(id: number, positionX: number, positionY: number, rotation: number, zoneId: number) { - await prisma.character.update({ - where: { id }, - data: { - positionX, - positionY, - rotation, - zoneId - } - }) - } } diff --git a/src/socketEvents/character/characterScreen/list_hair.ts b/src/socketEvents/character/characterScreen/list_hair.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/socketEvents/character/charactersScreen/character_hair_list.ts b/src/socketEvents/character/charactersScreen/character_hair_list.ts new file mode 100644 index 0000000..2796997 --- /dev/null +++ b/src/socketEvents/character/charactersScreen/character_hair_list.ts @@ -0,0 +1,22 @@ +import { Server } from 'socket.io' +import { CharacterHair } from '@prisma/client' +import { TSocket } from '../../../utilities/types' +import characterHairRepository from '../../../repositories/characterHairRepository' + +interface IPayload {} + +export default class characterHairListEvent { + constructor( + private readonly io: Server, + private readonly socket: TSocket + ) {} + + public listen(): void { + this.socket.on('character:hair:list', this.handleEvent.bind(this)) + } + + private async handleEvent(data: IPayload, callback: (response: CharacterHair[]) => void): Promise { + const items = await characterHairRepository.getIsEnabledForCharCreationHair() + callback(items) + } +} diff --git a/src/socketEvents/character/connect.ts b/src/socketEvents/character/connect.ts index fb66a4a..54874bf 100644 --- a/src/socketEvents/character/connect.ts +++ b/src/socketEvents/character/connect.ts @@ -3,9 +3,11 @@ import { TSocket } from '../../utilities/types' import CharacterRepository from '../../repositories/characterRepository' import { gameLogger } from '../../utilities/logger' import ZoneManager from '../../managers/zoneManager' +import { CharacterService } from '../../services/characterService' interface CharacterConnectPayload { characterId: number + hairId?: number } export default class CharacterConnectEvent { @@ -18,7 +20,7 @@ export default class CharacterConnectEvent { this.socket.on('character:connect', this.handleCharacterConnect.bind(this)) } - private async handleCharacterConnect({ characterId }: CharacterConnectPayload): Promise { + private async handleCharacterConnect({ characterId, hairId }: CharacterConnectPayload): Promise { if (!this.socket.userId) { this.emitError('User not authenticated') return @@ -30,6 +32,10 @@ export default class CharacterConnectEvent { return } + // Update hair + const characterService = new CharacterService() + await characterService.updateHair(characterId, hairId ?? null) + const character = await this.connectCharacter(characterId) if (!character) { this.emitError('Character not found or does not belong to this user') diff --git a/src/socketEvents/character/create.ts b/src/socketEvents/character/create.ts index dbb1afe..2a886c2 100644 --- a/src/socketEvents/character/create.ts +++ b/src/socketEvents/character/create.ts @@ -2,7 +2,7 @@ import { Server } from 'socket.io' import { TSocket } from '../../utilities/types' import { Character } from '@prisma/client' import CharacterRepository from '../../repositories/characterRepository' -import { CharacterService } from '../../services/character/characterService' +import { CharacterService } from '../../services/characterService' import { ZCharacterCreate } from '../../utilities/zodTypes' import { gameLogger } from '../../utilities/logger' import { ZodError } from 'zod' diff --git a/src/socketEvents/character/delete.ts b/src/socketEvents/character/delete.ts index 100a9c2..5104cb2 100644 --- a/src/socketEvents/character/delete.ts +++ b/src/socketEvents/character/delete.ts @@ -2,6 +2,7 @@ import { Server } from 'socket.io' import { TSocket } from '../../utilities/types' import { Character, Zone } from '@prisma/client' import CharacterRepository from '../../repositories/characterRepository' +import { CharacterService } from '../../services/characterService' type TypePayload = { characterId: number @@ -24,7 +25,8 @@ export default class CharacterDeleteEvent { private async handleCharacterDelete(data: TypePayload, callback: (response: TypeResponse) => void): Promise { try { - await CharacterRepository.deleteByUserIdAndId(this.socket.userId!, data.characterId!) + const characterService = new CharacterService() + await characterService.deleteByUserIdAndId(this.socket.userId!, data.characterId!) const characters: Character[] = (await CharacterRepository.getByUserId(this.socket.userId!)) as Character[] diff --git a/src/socketEvents/zone/characterMove.ts b/src/socketEvents/zone/characterMove.ts index c62ce80..14395bf 100644 --- a/src/socketEvents/zone/characterMove.ts +++ b/src/socketEvents/zone/characterMove.ts @@ -1,6 +1,6 @@ import { Server } from 'socket.io' import { TSocket, ZoneEventTileWithTeleport } from '../../utilities/types' -import { CharacterService } from '../../services/character/characterService' +import { CharacterService } from '../../services/characterService' import { ZoneEventTileService } from '../../services/zoneEventTileService' import Rotation from '../../utilities/character/rotation' import { gameLogger } from '../../utilities/logger'