From 0efa9fb1d5308a7d64f5fec5eee62b9ce393aa25 Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Tue, 18 Feb 2025 17:09:15 +0100 Subject: [PATCH] #245 : Enhanced asset CRUD logic --- package-lock.json | 6 +++--- src/application/base/baseEvent.ts | 2 +- src/entities/base/characterHair.ts | 14 +++++++++++++- src/entities/base/item.ts | 4 ++-- src/events/character/connect.ts | 4 ++-- .../assetManager/characterHair/create.ts | 12 +++++++++++- .../gameMaster/assetManager/item/create.ts | 5 ++++- src/events/gameMaster/mapEditor/update.ts | 2 +- src/migrations/.snapshot-game.json | 17 +++++++++++++---- ...0217134639.ts => Migration20250218160822.ts} | 10 +++++----- 10 files changed, 55 insertions(+), 21 deletions(-) rename src/migrations/{Migration20250217134639.ts => Migration20250218160822.ts} (96%) diff --git a/package-lock.json b/package-lock.json index 683c634..ed6e753 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3316,9 +3316,9 @@ "license": "MIT" }, "node_modules/long": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.0.tgz", - "integrity": "sha512-5vvY5yF1zF/kXk+L94FRiTDa1Znom46UjPCH6/XbSvS8zBKMFBHTJk8KDMqJ+2J6QezQFi7k1k8v21ClJYHPaw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", "license": "Apache-2.0" }, "node_modules/lru-cache": { diff --git a/src/application/base/baseEvent.ts b/src/application/base/baseEvent.ts index 986b149..dc0efaa 100644 --- a/src/application/base/baseEvent.ts +++ b/src/application/base/baseEvent.ts @@ -45,7 +45,7 @@ export abstract class BaseEvent { return character?.getRole() === 'gm' } - protected emitError(message: string): void { + protected sendNotificationAndLog(message: string): void { this.socket.emit(SocketEvent.NOTIFICATION, { title: 'Server message', message }) this.logger.error('Base event error', `Player ${this.socket.userId}: ${message}`) } diff --git a/src/entities/base/characterHair.ts b/src/entities/base/characterHair.ts index b257cae..51f801f 100644 --- a/src/entities/base/characterHair.ts +++ b/src/entities/base/characterHair.ts @@ -16,11 +16,14 @@ export class BaseCharacterHair extends BaseEntity { @Property() gender: CharacterGender = CharacterGender.MALE + @Property() + color: string = '#000000' + @Property() isSelectable = false @ManyToOne() - sprite?: Sprite + sprite!: Sprite @Property() createdAt = new Date() @@ -55,6 +58,15 @@ export class BaseCharacterHair extends BaseEntity { return this.gender } + setColor(color: string) { + this.color = color + return this + } + + getColor() { + return this.color + } + setIsSelectable(isSelectable: boolean) { this.isSelectable = isSelectable return this diff --git a/src/entities/base/item.ts b/src/entities/base/item.ts index 8e837b7..01b2808 100644 --- a/src/entities/base/item.ts +++ b/src/entities/base/item.ts @@ -25,8 +25,8 @@ export class BaseItem extends BaseEntity { @Enum(() => ItemRarity) rarity: ItemRarity = ItemRarity.COMMON - @ManyToOne(() => Sprite) - sprite?: Sprite + @ManyToOne() + sprite!: Sprite @Property() createdAt = new Date() diff --git a/src/events/character/connect.ts b/src/events/character/connect.ts index 49c984e..9ebabff 100644 --- a/src/events/character/connect.ts +++ b/src/events/character/connect.ts @@ -22,14 +22,14 @@ export default class CharacterConnectEvent extends BaseEvent { private async handleEvent(data: CharacterConnectPayload, callback: (response: any) => void): Promise { try { if (await this.checkForActiveCharacters()) { - this.emitError('You are already connected to another character') + this.sendNotificationAndLog('You are already connected to another character') return } const character = await this.characterRepository.getByUserAndId(this.socket.userId, data.characterId) if (!character) { - this.emitError('Character not found or does not belong to this user') + this.sendNotificationAndLog('Character not found or does not belong to this user') return } diff --git a/src/events/gameMaster/assetManager/characterHair/create.ts b/src/events/gameMaster/assetManager/characterHair/create.ts index 6952ea4..6d186a8 100644 --- a/src/events/gameMaster/assetManager/characterHair/create.ts +++ b/src/events/gameMaster/assetManager/characterHair/create.ts @@ -1,6 +1,7 @@ import { BaseEvent } from '@/application/base/baseEvent' import { SocketEvent } from '@/application/enums' import { CharacterHair } from '@/entities/characterHair' +import SpriteRepository from "@/repositories/spriteRepository"; export default class CharacterHairCreateEvent extends BaseEvent { public listen(): void { @@ -11,8 +12,17 @@ export default class CharacterHairCreateEvent extends BaseEvent { try { if (!(await this.isCharacterGM())) return + // Get first sprite + const spriteRepository = new SpriteRepository() + const firstSprite = await spriteRepository.getFirst() + + if (!firstSprite) { + this.sendNotificationAndLog('No sprites found') + return callback(false) + } + const newCharacterHair = new CharacterHair() - await newCharacterHair.setName('New hair').save() + await newCharacterHair.setName('New hair').setSprite(firstSprite).save() return callback(true) } catch (error) { diff --git a/src/events/gameMaster/assetManager/item/create.ts b/src/events/gameMaster/assetManager/item/create.ts index 3bad4d5..cd7cd83 100644 --- a/src/events/gameMaster/assetManager/item/create.ts +++ b/src/events/gameMaster/assetManager/item/create.ts @@ -14,7 +14,10 @@ export default class ItemCreateEvent extends BaseEvent { const spriteRepository = new SpriteRepository() const sprite = await spriteRepository.getFirst() - if (!sprite) return callback(false) + if (!sprite) { + this.sendNotificationAndLog('No sprites found') + return callback(false) + } const newItem = new Item() await newItem.setName('New Item').setItemType(ItemType.WEAPON).setStackable(false).setRarity(ItemRarity.COMMON).setSprite(sprite).save() diff --git a/src/events/gameMaster/mapEditor/update.ts b/src/events/gameMaster/mapEditor/update.ts index 8989745..72c99b2 100644 --- a/src/events/gameMaster/mapEditor/update.ts +++ b/src/events/gameMaster/mapEditor/update.ts @@ -130,7 +130,7 @@ export default class MapUpdateEvent extends BaseEvent { return callback(await map.mapEditorObject()) } catch (error: any) { - this.emitError(`gm:map:update error: ${error instanceof Error ? error.message + error.stack : String(error)}`) + this.sendNotificationAndLog(`gm:map:update error: ${error instanceof Error ? error.message + error.stack : String(error)}`) return callback(null) } } diff --git a/src/migrations/.snapshot-game.json b/src/migrations/.snapshot-game.json index 672ae91..498b9b4 100644 --- a/src/migrations/.snapshot-game.json +++ b/src/migrations/.snapshot-game.json @@ -863,7 +863,7 @@ "unsigned": false, "autoincrement": false, "primary": false, - "nullable": true, + "nullable": false, "length": 255, "mappedType": "string" }, @@ -923,7 +923,6 @@ "id" ], "referencedTableName": "sprite", - "deleteRule": "set null", "updateRule": "cascade" } }, @@ -1096,6 +1095,17 @@ "default": "'MALE'", "mappedType": "string" }, + "color": { + "name": "color", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "default": "'#000000'", + "mappedType": "string" + }, "is_selectable": { "name": "is_selectable", "type": "tinyint(1)", @@ -1113,7 +1123,7 @@ "unsigned": false, "autoincrement": false, "primary": false, - "nullable": true, + "nullable": false, "length": 255, "mappedType": "string" }, @@ -1173,7 +1183,6 @@ "id" ], "referencedTableName": "sprite", - "deleteRule": "set null", "updateRule": "cascade" } }, diff --git a/src/migrations/Migration20250217134639.ts b/src/migrations/Migration20250218160822.ts similarity index 96% rename from src/migrations/Migration20250217134639.ts rename to src/migrations/Migration20250218160822.ts index 38a652e..daec3a8 100644 --- a/src/migrations/Migration20250217134639.ts +++ b/src/migrations/Migration20250218160822.ts @@ -1,6 +1,6 @@ import { Migration } from '@mikro-orm/migrations'; -export class Migration20250217134639 extends Migration { +export class Migration20250218160822 extends Migration { override async up(): Promise { this.addSql(`create table \`map\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null default '', \`width\` int not null default 10, \`height\` int not null default 10, \`tiles\` json not null, \`pvp\` tinyint(1) not null default false, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); @@ -24,13 +24,13 @@ export class Migration20250217134639 extends Migration { this.addSql(`create table \`sprite\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); - this.addSql(`create table \`item\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`description\` varchar(255) not null default '', \`item_type\` enum('WEAPON', 'HELMET', 'CHEST', 'LEGS', 'BOOTS', 'GLOVES', 'RING', 'NECKLACE') not null, \`stackable\` tinyint(1) not null default false, \`rarity\` enum('COMMON', 'UNCOMMON', 'RARE', 'EPIC', 'LEGENDARY') not null default 'COMMON', \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); + this.addSql(`create table \`item\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`description\` varchar(255) not null default '', \`item_type\` enum('WEAPON', 'HELMET', 'CHEST', 'LEGS', 'BOOTS', 'GLOVES', 'RING', 'NECKLACE') not null, \`stackable\` tinyint(1) not null default false, \`rarity\` enum('COMMON', 'UNCOMMON', 'RARE', 'EPIC', 'LEGENDARY') not null default 'COMMON', \`sprite_id\` varchar(255) not null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); this.addSql(`alter table \`item\` add index \`item_sprite_id_index\`(\`sprite_id\`);`); this.addSql(`create table \`character_type\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` enum('MALE', 'FEMALE') not null, \`race\` enum('HUMAN', 'ELF', 'DWARF', 'ORC', 'GOBLIN') not null, \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); this.addSql(`alter table \`character_type\` add index \`character_type_sprite_id_index\`(\`sprite_id\`);`); - this.addSql(`create table \`character_hair\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` varchar(255) not null default 'MALE', \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); + this.addSql(`create table \`character_hair\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` varchar(255) not null default 'MALE', \`color\` varchar(255) not null default '#000000', \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) not null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); this.addSql(`alter table \`character_hair\` add index \`character_hair_sprite_id_index\`(\`sprite_id\`);`); this.addSql(`create table \`sprite_action\` (\`id\` varchar(255) not null, \`sprite_id\` varchar(255) not null, \`action\` varchar(255) not null, \`sprites\` json null, \`origin_x\` numeric(5,2) not null default 0, \`origin_y\` numeric(5,2) not null default 0, \`frame_width\` int not null default 0, \`frame_height\` int not null default 0, \`frame_rate\` int not null default 0, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`); @@ -78,11 +78,11 @@ export class Migration20250217134639 extends Migration { this.addSql(`alter table \`placed_map_object\` add constraint \`placed_map_object_map_id_foreign\` foreign key (\`map_id\`) references \`map\` (\`id\`) on update cascade on delete cascade;`); this.addSql(`alter table \`placed_map_object\` add constraint \`placed_map_object_map_object_id_foreign\` foreign key (\`map_object_id\`) references \`map_object\` (\`id\`) on update cascade on delete cascade;`); - this.addSql(`alter table \`item\` add constraint \`item_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`); + this.addSql(`alter table \`item\` add constraint \`item_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade;`); this.addSql(`alter table \`character_type\` add constraint \`character_type_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`); - this.addSql(`alter table \`character_hair\` add constraint \`character_hair_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`); + this.addSql(`alter table \`character_hair\` add constraint \`character_hair_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade;`); this.addSql(`alter table \`sprite_action\` add constraint \`sprite_action_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete cascade;`);