From 4a963b4359598fa946f24aa1ac299168f088ae1e Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Thu, 26 Dec 2024 16:45:00 +0100 Subject: [PATCH] Improved entities, ran formatting, utilise getters and setters --- ...26031358.ts => Migration20241226153149.ts} | 2 +- src/entities/character.ts | 8 +++--- src/entities/sprite.ts | 27 +++++++++---------- src/http/auth.ts | 2 +- src/repositories/characterHairRepository.ts | 15 +++-------- src/repositories/characterRepository.ts | 13 +++------ src/repositories/characterTypeRepository.ts | 6 ++--- src/repositories/chatRepository.ts | 19 +++++++------ src/repositories/spriteRepository.ts | 4 +-- src/repositories/userRepository.ts | 6 ++--- src/repositories/zoneRepository.ts | 27 +++++++++---------- src/server.ts | 2 +- src/services/chatService.ts | 5 +--- src/services/userService.ts | 9 ++----- src/services/zoneEventTileService.ts | 6 +---- src/socketEvents/character/list.ts | 2 +- src/socketEvents/zone/characterJoin.ts | 4 +-- src/socketEvents/zone/characterMove.ts | 8 +++--- 18 files changed, 68 insertions(+), 97 deletions(-) rename migrations/{Migration20241226031358.ts => Migration20241226153149.ts} (99%) diff --git a/migrations/Migration20241226031358.ts b/migrations/Migration20241226153149.ts similarity index 99% rename from migrations/Migration20241226031358.ts rename to migrations/Migration20241226153149.ts index 79f19be..2c7bbed 100644 --- a/migrations/Migration20241226031358.ts +++ b/migrations/Migration20241226153149.ts @@ -1,6 +1,6 @@ import { Migration } from '@mikro-orm/migrations'; -export class Migration20241226031358 extends Migration { +export class Migration20241226153149 extends Migration { override async up(): Promise { this.addSql(`create table \`map_object\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`tags\` json null, \`origin_x\` int not null default 0, \`origin_y\` int not null default 0, \`is_animated\` tinyint(1) not null default false, \`frame_rate\` int not null default 0, \`frame_width\` int not null default 0, \`frame_height\` int not null default 0, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); diff --git a/src/entities/character.ts b/src/entities/character.ts index 65e0c11..e0e878e 100644 --- a/src/entities/character.ts +++ b/src/entities/character.ts @@ -42,17 +42,17 @@ export class Character extends BaseEntity { rotation = 0 // Customization - @ManyToOne(() => CharacterType, { nullable: true }) + @ManyToOne() characterType?: CharacterType - @ManyToOne(() => CharacterHair, { nullable: true }) + @ManyToOne() characterHair?: CharacterHair // Inventory - @OneToMany(() => CharacterItem, (item) => item.character) + @OneToMany({ mappedBy: 'character' }) items = new Collection(this) - @OneToMany(() => CharacterEquipment, (equipment) => equipment.character) + @OneToMany({ mappedBy: 'character' }) equipment = new Collection(this) // Stats diff --git a/src/entities/sprite.ts b/src/entities/sprite.ts index b53f24c..c9aa758 100644 --- a/src/entities/sprite.ts +++ b/src/entities/sprite.ts @@ -2,9 +2,6 @@ import { randomUUID } from 'node:crypto' import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core' import { BaseEntity } from '#application/bases/baseEntity' import { SpriteAction } from './spriteAction' -import { CharacterType } from './characterType' -import { CharacterHair } from './characterHair' -import { Item } from './item' import { UUID } from '#application/types' @Entity() @@ -15,24 +12,15 @@ export class Sprite extends BaseEntity { @Property() name!: string + @OneToMany(() => SpriteAction, (action) => action.sprite) + spriteActions = new Collection(this) + @Property() createdAt = new Date() @Property() updatedAt = new Date() - @OneToMany(() => SpriteAction, (action) => action.sprite) - spriteActions = new Collection(this) - - @OneToMany(() => CharacterType, (type) => type.sprite) - characterTypes = new Collection(this) - - @OneToMany(() => CharacterHair, (hair) => hair.sprite) - characterHairs = new Collection(this) - - @OneToMany(() => Item, (item) => item.sprite) - items = new Collection(this) - setId(id: UUID) { this.id = id return this @@ -51,6 +39,15 @@ export class Sprite extends BaseEntity { return this.name } + setSpriteActions(spriteActions: Collection) { + this.spriteActions = spriteActions + return this + } + + getSpriteActions() { + return this.spriteActions + } + setCreatedAt(createdAt: Date) { this.createdAt = createdAt return this diff --git a/src/http/auth.ts b/src/http/auth.ts index 2b120fb..c1f3420 100644 --- a/src/http/auth.ts +++ b/src/http/auth.ts @@ -20,7 +20,7 @@ router.post('/login', async (req: Request, res: Response) => { const user = await userService.login(username, password) if (user && typeof user !== 'boolean') { - const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '4h' }) + const token = jwt.sign({ id: user.getId() }, config.JWT_SECRET, { expiresIn: '4h' }) return res.status(200).json({ token }) } diff --git a/src/repositories/characterHairRepository.ts b/src/repositories/characterHairRepository.ts index 9f422bc..0e73253 100644 --- a/src/repositories/characterHairRepository.ts +++ b/src/repositories/characterHairRepository.ts @@ -6,7 +6,7 @@ class CharacterHairRepository extends BaseRepository { async getFirst() { try { const repository = this.em.getRepository(CharacterHair) - return await repository.findOne({ id: { $exists: true } }) + return await repository.findOne({ id: { $exists: true } }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get first character hair: ${error instanceof Error ? error.message : String(error)}`) return null @@ -16,7 +16,7 @@ class CharacterHairRepository extends BaseRepository { async getAll() { try { const repository = this.em.getRepository(CharacterHair) - return await repository.findAll() + return await repository.findAll({ populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get all character hair: ${error instanceof Error ? error.message : String(error)}`) return null @@ -26,9 +26,7 @@ class CharacterHairRepository extends BaseRepository { async getAllSelectable() { try { const repository = this.em.getRepository(CharacterHair) - return await repository.find({ - isSelectable: true - }) + return await repository.find({ isSelectable: true }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get selectable character hair: ${error instanceof Error ? error.message : String(error)}`) return null @@ -38,12 +36,7 @@ class CharacterHairRepository extends BaseRepository { async getById(id: number) { try { const repository = this.em.getRepository(CharacterHair) - return await repository.findOne( - { id }, - { - populate: ['sprite.spriteActions'] - } - ) + return await repository.findOne({ id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get character hair by ID: ${error instanceof Error ? error.message : String(error)}`) return null diff --git a/src/repositories/characterRepository.ts b/src/repositories/characterRepository.ts index b59a947..6827ff2 100644 --- a/src/repositories/characterRepository.ts +++ b/src/repositories/characterRepository.ts @@ -6,9 +6,7 @@ class CharacterRepository extends BaseRepository { async getByUserId(userId: number): Promise { try { const repository = this.em.getRepository(Character) - return await repository.find({ - user: userId - }) + return await repository.find({ user: userId }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get character by user ID: ${error instanceof Error ? error.message : String(error)}`) return [] @@ -18,10 +16,7 @@ class CharacterRepository extends BaseRepository { async getByUserAndId(userId: number, characterId: number): Promise { try { const repository = this.em.getRepository(Character) - return await repository.findOne({ - user: userId, - id: characterId - }) + return await repository.findOne({ user: userId, id: characterId }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get character by user ID and character ID: ${error instanceof Error ? error.message : String(error)}`) return null @@ -31,7 +26,7 @@ class CharacterRepository extends BaseRepository { async getById(id: number): Promise { try { const repository = this.em.getRepository(Character) - return await repository.findOne({ id }) + return await repository.findOne({ id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get character by ID: ${error instanceof Error ? error.message : String(error)}`) return null @@ -41,7 +36,7 @@ class CharacterRepository extends BaseRepository { async getByName(name: string): Promise { try { const repository = this.em.getRepository(Character) - return await repository.findOne({ name }) + return await repository.findOne({ name }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get character by name: ${error instanceof Error ? error.message : String(error)}`) return null diff --git a/src/repositories/characterTypeRepository.ts b/src/repositories/characterTypeRepository.ts index fe0cd28..afb2717 100644 --- a/src/repositories/characterTypeRepository.ts +++ b/src/repositories/characterTypeRepository.ts @@ -6,7 +6,7 @@ class CharacterTypeRepository extends BaseRepository { async getFirst() { try { const repository = this.em.getRepository(CharacterType) - return await repository.findOne({ id: { $exists: true } }) + return await repository.findOne({ id: { $exists: true } }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get first character type: ${error instanceof Error ? error.message : String(error)}`) return null @@ -16,7 +16,7 @@ class CharacterTypeRepository extends BaseRepository { async getAll() { try { const repository = this.em.getRepository(CharacterType) - return await repository.findAll() + return await repository.findAll({ populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get all character types: ${error instanceof Error ? error.message : String(error)}`) return null @@ -26,7 +26,7 @@ class CharacterTypeRepository extends BaseRepository { async getById(id: number) { try { const repository = this.em.getRepository(CharacterType) - return await repository.findOne({ id }) + return await repository.findOne({ id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get character type by ID: ${error instanceof Error ? error.message : String(error)}`) return null diff --git a/src/repositories/chatRepository.ts b/src/repositories/chatRepository.ts index dba603e..c94f4be 100644 --- a/src/repositories/chatRepository.ts +++ b/src/repositories/chatRepository.ts @@ -6,9 +6,12 @@ class ChatRepository extends BaseRepository { async getById(id: number): Promise { try { const repository = this.em.getRepository(Chat) - return await repository.find({ - id - }) + return await repository.find( + { + id + }, + { populate: ['*'] } + ) } catch (error: any) { appLogger.error(`Failed to get chat by ID: ${error instanceof Error ? error.message : String(error)}`) return [] @@ -18,7 +21,7 @@ class ChatRepository extends BaseRepository { async getAll(): Promise { try { const repository = this.em.getRepository(Chat) - return await repository.findAll() + return await repository.findAll({ populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get all chats: ${error instanceof Error ? error.message : String(error)}`) return [] @@ -28,9 +31,7 @@ class ChatRepository extends BaseRepository { async getByCharacterId(characterId: number): Promise { try { const repository = this.em.getRepository(Chat) - return await repository.find({ - character: characterId - }) + return await repository.find({ character: characterId }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get chats by character ID: ${error instanceof Error ? error.message : String(error)}`) return [] @@ -40,9 +41,7 @@ class ChatRepository extends BaseRepository { async getByZoneId(zoneId: number): Promise { try { const repository = this.em.getRepository(Chat) - return await repository.find({ - zone: zoneId - }) + return await repository.find({ zone: zoneId }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get chats by zone ID: ${error instanceof Error ? error.message : String(error)}`) return [] diff --git a/src/repositories/spriteRepository.ts b/src/repositories/spriteRepository.ts index bc458a0..4b3309c 100644 --- a/src/repositories/spriteRepository.ts +++ b/src/repositories/spriteRepository.ts @@ -6,7 +6,7 @@ class SpriteRepository extends BaseRepository { async getById(id: FilterValue<`${string}-${string}-${string}-${string}-${string}`>) { try { const repository = this.em.getRepository(Sprite) - return await repository.findOne({ id }) + return await repository.findOne({ id }, { populate: ['*'] }) } catch (error: any) { return null } @@ -15,7 +15,7 @@ class SpriteRepository extends BaseRepository { async getAll(): Promise { try { const repository = this.em.getRepository(Sprite) - return await repository.findAll() + return await repository.findAll({ populate: ['*'] }) } catch (error: any) { return null } diff --git a/src/repositories/userRepository.ts b/src/repositories/userRepository.ts index e2d2d12..ae3d27b 100644 --- a/src/repositories/userRepository.ts +++ b/src/repositories/userRepository.ts @@ -6,7 +6,7 @@ class UserRepository extends BaseRepository { async getById(id: number) { try { const repository = this.em.getRepository(User) - return await repository.findOne({ id }) + return await repository.findOne({ id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get user by ID: ${error instanceof Error ? error.message : String(error)}`) return null @@ -16,7 +16,7 @@ class UserRepository extends BaseRepository { async getByUsername(username: string) { try { const repository = this.em.getRepository(User) - return await repository.findOne({ username }) + return await repository.findOne({ username }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get user by username: ${error instanceof Error ? error.message : String(error)}`) return null @@ -26,7 +26,7 @@ class UserRepository extends BaseRepository { async getByEmail(email: string) { try { const repository = this.em.getRepository(User) - return await repository.findOne({ email }) + return await repository.findOne({ email }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get user by email: ${error instanceof Error ? error.message : String(error)}`) return null diff --git a/src/repositories/zoneRepository.ts b/src/repositories/zoneRepository.ts index 5c01225..5a9da3c 100644 --- a/src/repositories/zoneRepository.ts +++ b/src/repositories/zoneRepository.ts @@ -8,7 +8,7 @@ class ZoneRepository extends BaseRepository { async getFirst(): Promise { try { const repository = this.em.getRepository(Zone) - return await repository.findOne({ id: { $exists: true } }) + return await repository.findOne({ id: { $exists: true } }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get first zone: ${error instanceof Error ? error.message : String(error)}`) return null @@ -18,7 +18,7 @@ class ZoneRepository extends BaseRepository { async getAll(): Promise { try { const repository = this.em.getRepository(Zone) - return await repository.findAll() + return await repository.findAll({ populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get all zone: ${error.message}`) return [] @@ -28,7 +28,7 @@ class ZoneRepository extends BaseRepository { async getById(id: number) { try { const repository = this.em.getRepository(Zone) - return await repository.findOne({ id }) + return await repository.findOne({ id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get zone by id: ${error.message}`) return null @@ -38,9 +38,7 @@ class ZoneRepository extends BaseRepository { async getEventTiles(id: number): Promise { try { const repository = this.em.getRepository(ZoneEventTile) - return await repository.find({ - zone: id - }) + return await repository.find({ zone: id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get zone event tiles: ${error.message}`) return [] @@ -50,11 +48,14 @@ class ZoneRepository extends BaseRepository { async getFirstEventTile(zoneId: number, positionX: number, positionY: number): Promise { try { const repository = this.em.getRepository(ZoneEventTile) - return await repository.findOne({ - zone: zoneId, - positionX: positionX, - positionY: positionY - }) + return await repository.findOne( + { + zone: zoneId, + positionX: positionX, + positionY: positionY + }, + { populate: ['*'] } + ) } catch (error: any) { appLogger.error(`Failed to get zone event tile: ${error.message}`) return null @@ -64,9 +65,7 @@ class ZoneRepository extends BaseRepository { async getZoneObjects(id: number): Promise { try { const repository = this.em.getRepository(ZoneObject) - return await repository.find({ - zone: id - }) + return await repository.find({ zone: id }, { populate: ['*'] }) } catch (error: any) { appLogger.error(`Failed to get zone objects: ${error.message}`) return [] diff --git a/src/server.ts b/src/server.ts index bd448aa..4d54149 100644 --- a/src/server.ts +++ b/src/server.ts @@ -74,7 +74,7 @@ export class Server { await UserManager.boot() // Load date manager - await DateManager.boot(this.io) + // await DateManager.boot(this.io) // Load weather manager await WeatherManager.boot(this.io) diff --git a/src/services/chatService.ts b/src/services/chatService.ts index 34dee1d..49f422b 100644 --- a/src/services/chatService.ts +++ b/src/services/chatService.ts @@ -17,10 +17,7 @@ class ChatService { const newChat = new Chat() - newChat - .setCharacter(character) - .setZone(zone) - .setMessage(message) + newChat.setCharacter(character).setZone(zone).setMessage(message) await newChat.save() diff --git a/src/services/userService.ts b/src/services/userService.ts index 3a7c1f6..f0828ca 100644 --- a/src/services/userService.ts +++ b/src/services/userService.ts @@ -48,10 +48,7 @@ class UserService { const hashedPassword = await bcrypt.hash(password, 10) const newUser = new User() - newUser - .setUsername(username) - .setEmail(email) - .setPassword(hashedPassword) + newUser.setUsername(username).setEmail(email).setPassword(hashedPassword) await newUser.save() return newUser @@ -82,9 +79,7 @@ class UserService { // Create new token using MikroORM const passwordResetToken = new PasswordResetToken() - passwordResetToken - .setUser(user) - .setToken(token) + passwordResetToken.setUser(user).setToken(token) await passwordResetToken.save() const transporter = NodeMailer.createTransport({ diff --git a/src/services/zoneEventTileService.ts b/src/services/zoneEventTileService.ts index 4dcc9e7..a0c9fb2 100644 --- a/src/services/zoneEventTileService.ts +++ b/src/services/zoneEventTileService.ts @@ -21,11 +21,7 @@ export class ZoneEventTileService { character.isMoving = false // Update local character object - character - .setZone(teleport.toZone) - .setRotation(teleport.toRotation) - .setPositionX(teleport.toPositionX) - .setPositionY(teleport.toPositionY) + character.setZone(teleport.toZone).setRotation(teleport.toRotation).setPositionX(teleport.toPositionX).setPositionY(teleport.toPositionY) await character.save() diff --git a/src/socketEvents/character/list.ts b/src/socketEvents/character/list.ts index 92d0a6a..9179c54 100644 --- a/src/socketEvents/character/list.ts +++ b/src/socketEvents/character/list.ts @@ -16,7 +16,7 @@ export default class CharacterListEvent { private async handleCharacterList(data: any): Promise { try { - const characters: Character[] = (await CharacterRepository.getByUserId(this.socket.userId!)) as Character[] + const characters: Character[] = await CharacterRepository.getByUserId(this.socket.userId!) this.socket.emit('character:list', characters) } catch (error: any) { gameLogger.error('character:list error', error.message) diff --git a/src/socketEvents/zone/characterJoin.ts b/src/socketEvents/zone/characterJoin.ts index a3787e2..27b3872 100644 --- a/src/socketEvents/zone/characterJoin.ts +++ b/src/socketEvents/zone/characterJoin.ts @@ -1,12 +1,12 @@ import { Server } from 'socket.io' import { TSocket } from '#application/types' import ZoneRepository from '#repositories/zoneRepository' -import { Zone } from '@prisma/client' import { gameLogger } from '#application/logger' import CharacterRepository from '#repositories/characterRepository' import ZoneManager from '#managers/zoneManager' import zoneCharacter from '#models/zoneCharacter' import zoneManager from '#managers/zoneManager' +import { Zone } from '#entities/zone' interface IResponse { zone: Zone @@ -39,7 +39,7 @@ export default class CharacterJoinEvent { /** * @TODO: If zone is not found, spawn back to the start */ - const zone = await ZoneRepository.getById(character.zoneId) + const zone = await ZoneRepository.getById(character.zone!.id) if (!zone) { gameLogger.error('zone:character:join error', 'Zone not found') return diff --git a/src/socketEvents/zone/characterMove.ts b/src/socketEvents/zone/characterMove.ts index f6f159d..67813e9 100644 --- a/src/socketEvents/zone/characterMove.ts +++ b/src/socketEvents/zone/characterMove.ts @@ -36,7 +36,7 @@ export default class CharacterMove { const path = await this.characterService.calculatePath(zoneCharacter.character, positionX, positionY) if (!path) { - this.io.in(zoneCharacter.character.zoneId.toString()).emit('character:moveError', 'No valid path found') + this.io.in(zoneCharacter.character.zone!.id.toString()).emit('character:moveError', 'No valid path found') return } @@ -58,7 +58,7 @@ export default class CharacterMove { const [start, end] = [path[i], path[i + 1]] character.rotation = Rotation.calculate(start.x, start.y, end.x, end.y) - const zoneEventTile = await zoneEventTileRepository.getEventTileByZoneIdAndPosition(character.zoneId, Math.floor(end.x), Math.floor(end.y)) + const zoneEventTile = await zoneEventTileRepository.getEventTileByZoneIdAndPosition(character.zone!.id, Math.floor(end.x), Math.floor(end.y)) if (zoneEventTile?.type === 'BLOCK') break if (zoneEventTile?.type === 'TELEPORT' && zoneEventTile.teleport) { @@ -67,7 +67,7 @@ export default class CharacterMove { } this.characterService.updatePosition(character, end) - this.io.in(character.zoneId.toString()).emit('character:move', zoneCharacter) + this.io.in(character.zone!.id.toString()).emit('character:move', zoneCharacter) await this.characterService.applyMovementDelay() } @@ -91,6 +91,6 @@ export default class CharacterMove { private finalizeMovement(zoneCharacter: ZoneCharacter): void { zoneCharacter.isMoving = false - this.io.in(zoneCharacter.character.zoneId.toString()).emit('character:move', zoneCharacter) + this.io.in(zoneCharacter.character.zone!.id.toString()).emit('character:move', zoneCharacter) } }