forked from noxious/server
Renamed zone > map
This commit is contained in:
parent
887da447e0
commit
11041fec83
@ -1,10 +1,26 @@
|
|||||||
import { Migration } from '@mikro-orm/migrations';
|
import { Migration } from '@mikro-orm/migrations';
|
||||||
|
|
||||||
export class Migration20250101224501 extends Migration {
|
export class Migration20250102162954 extends Migration {
|
||||||
|
|
||||||
override async up(): Promise<void> {
|
override async up(): Promise<void> {
|
||||||
|
this.addSql(`create table \`map\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`width\` int not null default 10, \`height\` int not null default 10, \`tiles\` json 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;`);
|
||||||
|
|
||||||
|
this.addSql(`create table \`map_effect\` (\`id\` varchar(255) not null, \`map_id\` varchar(255) not null, \`effect\` varchar(255) not null, \`strength\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
|
this.addSql(`alter table \`map_effect\` add index \`map_effect_map_id_index\`(\`map_id\`);`);
|
||||||
|
|
||||||
|
this.addSql(`create table \`map_event_tile\` (\`id\` varchar(255) not null, \`map_id\` varchar(255) not null, \`type\` enum('BLOCK', 'TELEPORT', 'NPC', 'ITEM') not null, \`position_x\` int not null, \`position_y\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
|
this.addSql(`alter table \`map_event_tile\` add index \`map_event_tile_map_id_index\`(\`map_id\`);`);
|
||||||
|
|
||||||
|
this.addSql(`create table \`map_event_tile_teleport\` (\`id\` varchar(255) not null, \`map_event_tile_id\` varchar(255) not null, \`to_map_id\` varchar(255) not null, \`to_rotation\` int not null, \`to_position_x\` int not null, \`to_position_y\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
|
this.addSql(`alter table \`map_event_tile_teleport\` add unique \`map_event_tile_teleport_map_event_tile_id_unique\`(\`map_event_tile_id\`);`);
|
||||||
|
this.addSql(`alter table \`map_event_tile_teleport\` add index \`map_event_tile_teleport_to_map_id_index\`(\`to_map_id\`);`);
|
||||||
|
|
||||||
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;`);
|
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;`);
|
||||||
|
|
||||||
|
this.addSql(`create table \`placed_map_object\` (\`id\` varchar(255) not null, \`map_id\` varchar(255) not null, \`map_object_id\` varchar(255) not null, \`depth\` int not null default 0, \`is_rotated\` tinyint(1) not null default false, \`position_x\` int not null default 0, \`position_y\` int not null default 0, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
|
this.addSql(`alter table \`placed_map_object\` add index \`placed_map_object_map_id_index\`(\`map_id\`);`);
|
||||||
|
this.addSql(`alter table \`placed_map_object\` add index \`placed_map_object_map_object_id_index\`(\`map_object_id\`);`);
|
||||||
|
|
||||||
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 \`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) null, \`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) null, \`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;`);
|
||||||
@ -29,20 +45,16 @@ export class Migration20250101224501 extends Migration {
|
|||||||
this.addSql(`alter table \`password_reset_token\` add index \`password_reset_token_user_id_index\`(\`user_id\`);`);
|
this.addSql(`alter table \`password_reset_token\` add index \`password_reset_token_user_id_index\`(\`user_id\`);`);
|
||||||
this.addSql(`alter table \`password_reset_token\` add unique \`password_reset_token_token_unique\`(\`token\`);`);
|
this.addSql(`alter table \`password_reset_token\` add unique \`password_reset_token_token_unique\`(\`token\`);`);
|
||||||
|
|
||||||
this.addSql(`create table \`world\` (\`date\` datetime not null, \`is_rain_enabled\` tinyint(1) not null default false, \`rain_percentage\` int not null default 0, \`is_fog_enabled\` tinyint(1) not null default false, \`fog_density\` int not null default 0, primary key (\`date\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`create table \`character\` (\`id\` varchar(255) not null, \`user_id\` varchar(255) not null, \`name\` varchar(255) not null, \`online\` tinyint(1) not null default false, \`role\` varchar(255) not null default 'player', \`map_id\` varchar(255) not null, \`position_x\` int not null default 0, \`position_y\` int not null default 0, \`rotation\` int not null default 0, \`character_type_id\` varchar(255) null, \`character_hair_id\` varchar(255) null, \`alignment\` int not null default 50, \`hitpoints\` int not null default 100, \`mana\` int not null default 100, \`level\` int not null default 1, \`experience\` int not null default 0, \`strength\` int not null default 10, \`dexterity\` int not null default 10, \`intelligence\` int not null default 10, \`wisdom\` int not null default 10, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
|
|
||||||
this.addSql(`create table \`zone\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`width\` int not null default 10, \`height\` int not null default 10, \`tiles\` json 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;`);
|
|
||||||
|
|
||||||
this.addSql(`create table \`character\` (\`id\` varchar(255) not null, \`user_id\` varchar(255) not null, \`name\` varchar(255) not null, \`online\` tinyint(1) not null default false, \`role\` varchar(255) not null default 'player', \`zone_id\` varchar(255) not null, \`position_x\` int not null default 0, \`position_y\` int not null default 0, \`rotation\` int not null default 0, \`character_type_id\` varchar(255) null, \`character_hair_id\` varchar(255) null, \`alignment\` int not null default 50, \`hitpoints\` int not null default 100, \`mana\` int not null default 100, \`level\` int not null default 1, \`experience\` int not null default 0, \`strength\` int not null default 10, \`dexterity\` int not null default 10, \`intelligence\` int not null default 10, \`wisdom\` int not null default 10, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
|
||||||
this.addSql(`alter table \`character\` add index \`character_user_id_index\`(\`user_id\`);`);
|
this.addSql(`alter table \`character\` add index \`character_user_id_index\`(\`user_id\`);`);
|
||||||
this.addSql(`alter table \`character\` add unique \`character_name_unique\`(\`name\`);`);
|
this.addSql(`alter table \`character\` add unique \`character_name_unique\`(\`name\`);`);
|
||||||
this.addSql(`alter table \`character\` add index \`character_zone_id_index\`(\`zone_id\`);`);
|
this.addSql(`alter table \`character\` add index \`character_map_id_index\`(\`map_id\`);`);
|
||||||
this.addSql(`alter table \`character\` add index \`character_character_type_id_index\`(\`character_type_id\`);`);
|
this.addSql(`alter table \`character\` add index \`character_character_type_id_index\`(\`character_type_id\`);`);
|
||||||
this.addSql(`alter table \`character\` add index \`character_character_hair_id_index\`(\`character_hair_id\`);`);
|
this.addSql(`alter table \`character\` add index \`character_character_hair_id_index\`(\`character_hair_id\`);`);
|
||||||
|
|
||||||
this.addSql(`create table \`chat\` (\`id\` varchar(255) not null, \`character_id\` varchar(255) not null, \`zone_id\` varchar(255) not null, \`message\` varchar(255) not null, \`created_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`create table \`chat\` (\`id\` varchar(255) not null, \`character_id\` varchar(255) not null, \`map_id\` varchar(255) not null, \`message\` varchar(255) not null, \`created_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
this.addSql(`alter table \`chat\` add index \`chat_character_id_index\`(\`character_id\`);`);
|
this.addSql(`alter table \`chat\` add index \`chat_character_id_index\`(\`character_id\`);`);
|
||||||
this.addSql(`alter table \`chat\` add index \`chat_zone_id_index\`(\`zone_id\`);`);
|
this.addSql(`alter table \`chat\` add index \`chat_map_id_index\`(\`map_id\`);`);
|
||||||
|
|
||||||
this.addSql(`create table \`character_item\` (\`id\` varchar(255) not null, \`character_id\` varchar(255) not null, \`item_id\` varchar(255) not null, \`quantity\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`create table \`character_item\` (\`id\` varchar(255) not null, \`character_id\` varchar(255) not null, \`item_id\` varchar(255) not null, \`quantity\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
this.addSql(`alter table \`character_item\` add index \`character_item_character_id_index\`(\`character_id\`);`);
|
this.addSql(`alter table \`character_item\` add index \`character_item_character_id_index\`(\`character_id\`);`);
|
||||||
@ -52,19 +64,17 @@ export class Migration20250101224501 extends Migration {
|
|||||||
this.addSql(`alter table \`character_equipment\` add index \`character_equipment_character_id_index\`(\`character_id\`);`);
|
this.addSql(`alter table \`character_equipment\` add index \`character_equipment_character_id_index\`(\`character_id\`);`);
|
||||||
this.addSql(`alter table \`character_equipment\` add index \`character_equipment_character_item_id_index\`(\`character_item_id\`);`);
|
this.addSql(`alter table \`character_equipment\` add index \`character_equipment_character_item_id_index\`(\`character_item_id\`);`);
|
||||||
|
|
||||||
this.addSql(`create table \`zone_effect\` (\`id\` varchar(255) not null, \`zone_id\` varchar(255) not null, \`effect\` varchar(255) not null, \`strength\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`create table \`world\` (\`date\` datetime not null, \`is_rain_enabled\` tinyint(1) not null default false, \`rain_percentage\` int not null default 0, \`is_fog_enabled\` tinyint(1) not null default false, \`fog_density\` int not null default 0, primary key (\`date\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||||
this.addSql(`alter table \`zone_effect\` add index \`zone_effect_zone_id_index\`(\`zone_id\`);`);
|
|
||||||
|
|
||||||
this.addSql(`create table \`zone_event_tile\` (\`id\` varchar(255) not null, \`zone_id\` varchar(255) not null, \`type\` enum('BLOCK', 'TELEPORT', 'NPC', 'ITEM') not null, \`position_x\` int not null, \`position_y\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`alter table \`map_effect\` add constraint \`map_effect_map_id_foreign\` foreign key (\`map_id\`) references \`map\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`zone_event_tile\` add index \`zone_event_tile_zone_id_index\`(\`zone_id\`);`);
|
|
||||||
|
|
||||||
this.addSql(`create table \`zone_event_tile_teleport\` (\`id\` varchar(255) not null, \`zone_event_tile_id\` varchar(255) not null, \`to_zone_id\` varchar(255) not null, \`to_rotation\` int not null, \`to_position_x\` int not null, \`to_position_y\` int not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`alter table \`map_event_tile\` add constraint \`map_event_tile_map_id_foreign\` foreign key (\`map_id\`) references \`map\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`zone_event_tile_teleport\` add unique \`zone_event_tile_teleport_zone_event_tile_id_unique\`(\`zone_event_tile_id\`);`);
|
|
||||||
this.addSql(`alter table \`zone_event_tile_teleport\` add index \`zone_event_tile_teleport_to_zone_id_index\`(\`to_zone_id\`);`);
|
|
||||||
|
|
||||||
this.addSql(`create table \`zone_object\` (\`id\` varchar(255) not null, \`zone_id\` varchar(255) not null, \`map_object_id\` varchar(255) not null, \`depth\` int not null default 0, \`is_rotated\` tinyint(1) not null default false, \`position_x\` int not null default 0, \`position_y\` int not null default 0, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
this.addSql(`alter table \`map_event_tile_teleport\` add constraint \`map_event_tile_teleport_map_event_tile_id_foreign\` foreign key (\`map_event_tile_id\`) references \`map_event_tile\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`zone_object\` add index \`zone_object_zone_id_index\`(\`zone_id\`);`);
|
this.addSql(`alter table \`map_event_tile_teleport\` add constraint \`map_event_tile_teleport_to_map_id_foreign\` foreign key (\`to_map_id\`) references \`map\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`zone_object\` add index \`zone_object_map_object_id_index\`(\`map_object_id\`);`);
|
|
||||||
|
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 on delete set null;`);
|
||||||
|
|
||||||
@ -77,28 +87,18 @@ export class Migration20250101224501 extends Migration {
|
|||||||
this.addSql(`alter table \`password_reset_token\` add constraint \`password_reset_token_user_id_foreign\` foreign key (\`user_id\`) references \`user\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`password_reset_token\` add constraint \`password_reset_token_user_id_foreign\` foreign key (\`user_id\`) references \`user\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
|
|
||||||
this.addSql(`alter table \`character\` add constraint \`character_user_id_foreign\` foreign key (\`user_id\`) references \`user\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`character\` add constraint \`character_user_id_foreign\` foreign key (\`user_id\`) references \`user\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`character\` add constraint \`character_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade;`);
|
this.addSql(`alter table \`character\` add constraint \`character_map_id_foreign\` foreign key (\`map_id\`) references \`map\` (\`id\`) on update cascade;`);
|
||||||
this.addSql(`alter table \`character\` add constraint \`character_character_type_id_foreign\` foreign key (\`character_type_id\`) references \`character_type\` (\`id\`) on update cascade on delete set null;`);
|
this.addSql(`alter table \`character\` add constraint \`character_character_type_id_foreign\` foreign key (\`character_type_id\`) references \`character_type\` (\`id\`) on update cascade on delete set null;`);
|
||||||
this.addSql(`alter table \`character\` add constraint \`character_character_hair_id_foreign\` foreign key (\`character_hair_id\`) references \`character_hair\` (\`id\`) on update cascade on delete set null;`);
|
this.addSql(`alter table \`character\` add constraint \`character_character_hair_id_foreign\` foreign key (\`character_hair_id\`) references \`character_hair\` (\`id\`) on update cascade on delete set null;`);
|
||||||
|
|
||||||
this.addSql(`alter table \`chat\` add constraint \`chat_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`chat\` add constraint \`chat_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`chat\` add constraint \`chat_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`chat\` add constraint \`chat_map_id_foreign\` foreign key (\`map_id\`) references \`map\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
|
|
||||||
this.addSql(`alter table \`character_item\` add constraint \`character_item_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`character_item\` add constraint \`character_item_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`character_item\` add constraint \`character_item_item_id_foreign\` foreign key (\`item_id\`) references \`item\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`character_item\` add constraint \`character_item_item_id_foreign\` foreign key (\`item_id\`) references \`item\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
|
|
||||||
this.addSql(`alter table \`character_equipment\` add constraint \`character_equipment_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`character_equipment\` add constraint \`character_equipment_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
this.addSql(`alter table \`character_equipment\` add constraint \`character_equipment_character_item_id_foreign\` foreign key (\`character_item_id\`) references \`character_item\` (\`id\`) on update cascade on delete cascade;`);
|
this.addSql(`alter table \`character_equipment\` add constraint \`character_equipment_character_item_id_foreign\` foreign key (\`character_item_id\`) references \`character_item\` (\`id\`) on update cascade on delete cascade;`);
|
||||||
|
|
||||||
this.addSql(`alter table \`zone_effect\` add constraint \`zone_effect_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade on delete cascade;`);
|
|
||||||
|
|
||||||
this.addSql(`alter table \`zone_event_tile\` add constraint \`zone_event_tile_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade on delete cascade;`);
|
|
||||||
|
|
||||||
this.addSql(`alter table \`zone_event_tile_teleport\` add constraint \`zone_event_tile_teleport_zone_event_tile_id_foreign\` foreign key (\`zone_event_tile_id\`) references \`zone_event_tile\` (\`id\`) on update cascade on delete cascade;`);
|
|
||||||
this.addSql(`alter table \`zone_event_tile_teleport\` add constraint \`zone_event_tile_teleport_to_zone_id_foreign\` foreign key (\`to_zone_id\`) references \`zone\` (\`id\`) on update cascade on delete cascade;`);
|
|
||||||
|
|
||||||
this.addSql(`alter table \`zone_object\` add constraint \`zone_object_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade on delete cascade;`);
|
|
||||||
this.addSql(`alter table \`zone_object\` add constraint \`zone_object_map_object_id_foreign\` foreign key (\`map_object_id\`) references \`map_object\` (\`id\`) on update cascade on delete cascade;`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
11
package-lock.json
generated
11
package-lock.json
generated
@ -3179,15 +3179,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-set-tostringtag": {
|
"node_modules/es-set-tostringtag": {
|
||||||
"version": "2.0.3",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
"integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-intrinsic": "^1.2.4",
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
"has-tostringtag": "^1.0.2",
|
"has-tostringtag": "^1.0.2",
|
||||||
"hasown": "^2.0.1"
|
"hasown": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
|
@ -55,7 +55,7 @@ export enum CharacterEquipmentSlotType {
|
|||||||
RING = 'RING'
|
RING = 'RING'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ZoneEventTileType {
|
export enum MapEventTileType {
|
||||||
BLOCK = 'BLOCK',
|
BLOCK = 'BLOCK',
|
||||||
TELEPORT = 'TELEPORT',
|
TELEPORT = 'TELEPORT',
|
||||||
NPC = 'NPC',
|
NPC = 'NPC',
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Server, Socket } from 'socket.io'
|
import { Server, Socket } from 'socket.io'
|
||||||
|
|
||||||
import { Character } from '#entities/character'
|
import { Character } from '#entities/character'
|
||||||
import { ZoneEventTile } from '#entities/zoneEventTile'
|
import { MapEventTile } from '#entities/mapEventTile'
|
||||||
import { ZoneEventTileTeleport } from '#entities/zoneEventTileTeleport'
|
import { MapEventTileTeleport } from '#entities/mapEventTileTeleport'
|
||||||
|
|
||||||
export type UUID = `${string}-${string}-${string}-${string}-${string}`
|
export type UUID = `${string}-${string}-${string}-${string}-${string}`
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ export type ExtendedCharacter = Character & {
|
|||||||
resetMovement?: boolean
|
resetMovement?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ZoneEventTileWithTeleport = ZoneEventTile & {
|
export type MapEventTileWithTeleport = MapEventTile & {
|
||||||
teleport: ZoneEventTileTeleport
|
teleport: MapEventTileTeleport
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AssetData = {
|
export type AssetData = {
|
||||||
|
@ -14,11 +14,11 @@ import { Sprite } from '#entities/sprite'
|
|||||||
import { SpriteAction } from '#entities/spriteAction'
|
import { SpriteAction } from '#entities/spriteAction'
|
||||||
import { Tile } from '#entities/tile'
|
import { Tile } from '#entities/tile'
|
||||||
import { User } from '#entities/user'
|
import { User } from '#entities/user'
|
||||||
import { Zone } from '#entities/zone'
|
import { Map } from '#entities/map'
|
||||||
import { ZoneEffect } from '#entities/zoneEffect'
|
import { MapEffect } from '#entities/mapEffect'
|
||||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
// @TODO : Replace this with seeding
|
// @TODO : Replace this with seeding
|
||||||
// https://mikro-orm.io/docs/seeding
|
// https://mikro-orm.io/docs/seeding
|
||||||
@ -32,8 +32,8 @@ export default class InitCommand extends BaseCommand {
|
|||||||
await this.createCharacterHair()
|
await this.createCharacterHair()
|
||||||
// await this.createCharacterEquipment()
|
// await this.createCharacterEquipment()
|
||||||
|
|
||||||
// Zone
|
// Map
|
||||||
await this.createZone()
|
await this.createMap()
|
||||||
|
|
||||||
// User
|
// User
|
||||||
await this.createUser()
|
await this.createUser()
|
||||||
@ -224,17 +224,17 @@ export default class InitCommand extends BaseCommand {
|
|||||||
await equipmentSprite.save()
|
await equipmentSprite.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createZone(): Promise<void> {
|
private async createMap(): Promise<void> {
|
||||||
const zone = new Zone()
|
const map = new Map()
|
||||||
await zone
|
await map
|
||||||
.setName('New zone')
|
.setName('New map')
|
||||||
.setWidth(100)
|
.setWidth(100)
|
||||||
.setHeight(100)
|
.setHeight(100)
|
||||||
.setTiles(Array.from({ length: 100 }, () => Array.from({ length: 100 }, () => 'a2fd8d6f-5042-437a-9c1e-c66b91ecc35b')))
|
.setTiles(Array.from({ length: 100 }, () => Array.from({ length: 100 }, () => 'a2fd8d6f-5042-437a-9c1e-c66b91ecc35b')))
|
||||||
.save()
|
.save()
|
||||||
|
|
||||||
const effect = new ZoneEffect()
|
const effect = new MapEffect()
|
||||||
await effect.setEffect('light').setStrength(100).setZone(zone).save()
|
await effect.setEffect('light').setStrength(100).setMap(map).save()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createUser(): Promise<void> {
|
private async createUser(): Promise<void> {
|
||||||
@ -247,7 +247,7 @@ export default class InitCommand extends BaseCommand {
|
|||||||
.setUser(user)
|
.setUser(user)
|
||||||
.setName('root')
|
.setName('root')
|
||||||
.setRole('gm')
|
.setRole('gm')
|
||||||
.setZone((await ZoneRepository.getFirst())!)
|
.setMap((await MapRepository.getFirst())!)
|
||||||
.setCharacterType((await CharacterTypeRepository.getFirst()) ?? undefined)
|
.setCharacterType((await CharacterTypeRepository.getFirst()) ?? undefined)
|
||||||
.setCharacterHair((await CharacterHairRepository.getFirst()) ?? undefined)
|
.setCharacterHair((await CharacterHairRepository.getFirst()) ?? undefined)
|
||||||
.save()
|
.save()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Server } from 'socket.io'
|
import { Server } from 'socket.io'
|
||||||
|
|
||||||
import { BaseCommand } from '#application/base/baseCommand'
|
import { BaseCommand } from '#application/base/baseCommand'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
|
|
||||||
type CommandInput = string[]
|
type CommandInput = string[]
|
||||||
|
|
||||||
export default class ListZonesCommand extends BaseCommand {
|
export default class ListMapsCommand extends BaseCommand {
|
||||||
public execute(input: CommandInput): void {
|
public execute(input: CommandInput): void {
|
||||||
console.log(ZoneManager.getLoadedZones())
|
console.log(MapManager.getLoadedMaps())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ import { CharacterItem } from './characterItem'
|
|||||||
import { CharacterType } from './characterType'
|
import { CharacterType } from './characterType'
|
||||||
import { Chat } from './chat'
|
import { Chat } from './chat'
|
||||||
import { User } from './user'
|
import { User } from './user'
|
||||||
import { Zone } from './zone'
|
import { Map } from './map'
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
@ -35,7 +35,7 @@ export class Character extends BaseEntity {
|
|||||||
|
|
||||||
// Position
|
// Position
|
||||||
@ManyToOne()
|
@ManyToOne()
|
||||||
zone!: Zone // @TODO: Update to spawn point when current zone is not found
|
map!: Map // @TODO: Update to spawn point when current map is not found
|
||||||
|
|
||||||
@Property()
|
@Property()
|
||||||
positionX = 0
|
positionX = 0
|
||||||
@ -142,13 +142,13 @@ export class Character extends BaseEntity {
|
|||||||
return this.chats
|
return this.chats
|
||||||
}
|
}
|
||||||
|
|
||||||
setZone(zone: Zone) {
|
setMap(map: Map) {
|
||||||
this.zone = zone
|
this.map = map
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZone() {
|
getMap() {
|
||||||
return this.zone
|
return this.map
|
||||||
}
|
}
|
||||||
|
|
||||||
setPositionX(positionX: number) {
|
setPositionX(positionX: number) {
|
||||||
|
@ -3,7 +3,7 @@ import { randomUUID } from 'node:crypto'
|
|||||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||||
|
|
||||||
import { Character } from './character'
|
import { Character } from './character'
|
||||||
import { Zone } from './zone'
|
import { Map } from './map'
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
@ -17,7 +17,7 @@ export class Chat extends BaseEntity {
|
|||||||
character!: Character
|
character!: Character
|
||||||
|
|
||||||
@ManyToOne({ deleteRule: 'cascade' })
|
@ManyToOne({ deleteRule: 'cascade' })
|
||||||
zone!: Zone
|
map!: Map
|
||||||
|
|
||||||
@Property()
|
@Property()
|
||||||
message!: string
|
message!: string
|
||||||
@ -43,13 +43,13 @@ export class Chat extends BaseEntity {
|
|||||||
return this.character
|
return this.character
|
||||||
}
|
}
|
||||||
|
|
||||||
setZone(zone: Zone) {
|
setMap(map: Map) {
|
||||||
this.zone = zone
|
this.map = map
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZone() {
|
getMap() {
|
||||||
return this.zone
|
return this.map
|
||||||
}
|
}
|
||||||
|
|
||||||
setMessage(message: string) {
|
setMessage(message: string) {
|
||||||
|
@ -4,16 +4,16 @@ import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/
|
|||||||
|
|
||||||
import { Character } from './character'
|
import { Character } from './character'
|
||||||
import { Chat } from './chat'
|
import { Chat } from './chat'
|
||||||
import { ZoneEffect } from './zoneEffect'
|
import { MapEffect } from './mapEffect'
|
||||||
import { ZoneEventTile } from './zoneEventTile'
|
import { MapEventTile } from './mapEventTile'
|
||||||
import { ZoneEventTileTeleport } from './zoneEventTileTeleport'
|
import { MapEventTileTeleport } from './mapEventTileTeleport'
|
||||||
import { ZoneObject } from './zoneObject'
|
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
|
import { placedMapObject } from '#entities/placedMapObject'
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Zone extends BaseEntity {
|
export class Map extends BaseEntity {
|
||||||
@PrimaryKey()
|
@PrimaryKey()
|
||||||
id = randomUUID()
|
id = randomUUID()
|
||||||
|
|
||||||
@ -38,22 +38,22 @@ export class Zone extends BaseEntity {
|
|||||||
@Property()
|
@Property()
|
||||||
updatedAt = new Date()
|
updatedAt = new Date()
|
||||||
|
|
||||||
@OneToMany(() => ZoneEffect, (effect) => effect.zone)
|
@OneToMany(() => MapEffect, (effect) => effect.map)
|
||||||
zoneEffects = new Collection<ZoneEffect>(this)
|
mapEffects = new Collection<MapEffect>(this)
|
||||||
|
|
||||||
@OneToMany(() => ZoneEventTile, (tile) => tile.zone)
|
@OneToMany(() => MapEventTile, (tile) => tile.map)
|
||||||
zoneEventTiles = new Collection<ZoneEventTile>(this)
|
mapEventTiles = new Collection<MapEventTile>(this)
|
||||||
|
|
||||||
@OneToMany(() => ZoneEventTileTeleport, (teleport) => teleport.toZone)
|
@OneToMany(() => MapEventTileTeleport, (teleport) => teleport.toMap)
|
||||||
zoneEventTileTeleports = new Collection<ZoneEventTileTeleport>(this)
|
mapEventTileTeleports = new Collection<MapEventTileTeleport>(this)
|
||||||
|
|
||||||
@OneToMany(() => ZoneObject, (object) => object.zone)
|
@OneToMany(() => placedMapObject, (object) => object.map)
|
||||||
zoneObjects = new Collection<ZoneObject>(this)
|
placedMapObjects = new Collection<placedMapObject>(this)
|
||||||
|
|
||||||
@OneToMany(() => Character, (character) => character.zone)
|
@OneToMany(() => Character, (character) => character.map)
|
||||||
characters = new Collection<Character>(this)
|
characters = new Collection<Character>(this)
|
||||||
|
|
||||||
@OneToMany(() => Chat, (chat) => chat.zone)
|
@OneToMany(() => Chat, (chat) => chat.map)
|
||||||
chats = new Collection<Chat>(this)
|
chats = new Collection<Chat>(this)
|
||||||
|
|
||||||
setId(id: UUID) {
|
setId(id: UUID) {
|
||||||
@ -128,40 +128,40 @@ export class Zone extends BaseEntity {
|
|||||||
return this.updatedAt
|
return this.updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
setZoneEffects(zoneEffects: Collection<ZoneEffect>) {
|
setMapEffects(mapEffects: Collection<MapEffect>) {
|
||||||
this.zoneEffects = zoneEffects
|
this.mapEffects = mapEffects
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZoneEffects() {
|
getMapEffects() {
|
||||||
return this.zoneEffects
|
return this.mapEffects
|
||||||
}
|
}
|
||||||
|
|
||||||
setZoneEventTiles(zoneEventTiles: Collection<ZoneEventTile>) {
|
setMapEventTiles(mapEventTiles: Collection<MapEventTile>) {
|
||||||
this.zoneEventTiles = zoneEventTiles
|
this.mapEventTiles = mapEventTiles
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZoneEventTiles() {
|
getMapEventTiles() {
|
||||||
return this.zoneEventTiles
|
return this.mapEventTiles
|
||||||
}
|
}
|
||||||
|
|
||||||
setZoneEventTileTeleports(zoneEventTileTeleports: Collection<ZoneEventTileTeleport>) {
|
setMapEventTileTeleports(mapEventTileTeleports: Collection<MapEventTileTeleport>) {
|
||||||
this.zoneEventTileTeleports = zoneEventTileTeleports
|
this.mapEventTileTeleports = mapEventTileTeleports
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZoneEventTileTeleports() {
|
getMapEventTileTeleports() {
|
||||||
return this.zoneEventTileTeleports
|
return this.mapEventTileTeleports
|
||||||
}
|
}
|
||||||
|
|
||||||
setZoneObjects(zoneObjects: Collection<ZoneObject>) {
|
setPlacedMapObjects(placedMapObjects: Collection<placedMapObject>) {
|
||||||
this.zoneObjects = zoneObjects
|
this.placedMapObjects = placedMapObjects
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZoneObjects() {
|
getPlacedMapObjects() {
|
||||||
return this.zoneObjects
|
return this.placedMapObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
setCharacters(characters: Collection<Character>) {
|
setCharacters(characters: Collection<Character>) {
|
@ -2,18 +2,18 @@ import { randomUUID } from 'node:crypto'
|
|||||||
|
|
||||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||||
|
|
||||||
import { Zone } from './zone'
|
import { Map } from './map'
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ZoneEffect extends BaseEntity {
|
export class MapEffect extends BaseEntity {
|
||||||
@PrimaryKey()
|
@PrimaryKey()
|
||||||
id = randomUUID()
|
id = randomUUID()
|
||||||
|
|
||||||
@ManyToOne({ deleteRule: 'cascade' })
|
@ManyToOne({ deleteRule: 'cascade' })
|
||||||
zone!: Zone
|
map!: Map
|
||||||
|
|
||||||
@Property()
|
@Property()
|
||||||
effect!: string
|
effect!: string
|
||||||
@ -30,13 +30,13 @@ export class ZoneEffect extends BaseEntity {
|
|||||||
return this.id
|
return this.id
|
||||||
}
|
}
|
||||||
|
|
||||||
setZone(zone: Zone) {
|
setMap(map: Map) {
|
||||||
this.zone = zone
|
this.map = map
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZone() {
|
getMap() {
|
||||||
return this.zone
|
return this.map
|
||||||
}
|
}
|
||||||
|
|
||||||
setEffect(effect: string) {
|
setEffect(effect: string) {
|
@ -2,23 +2,23 @@ import { randomUUID } from 'node:crypto'
|
|||||||
|
|
||||||
import { Entity, Enum, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
import { Entity, Enum, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||||
|
|
||||||
import { Zone } from './zone'
|
import { Map } from './map'
|
||||||
import { ZoneEventTileTeleport } from './zoneEventTileTeleport'
|
import { MapEventTileTeleport } from './mapEventTileTeleport'
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { ZoneEventTileType } from '#application/enums'
|
import { MapEventTileType } from '#application/enums'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ZoneEventTile extends BaseEntity {
|
export class MapEventTile extends BaseEntity {
|
||||||
@PrimaryKey()
|
@PrimaryKey()
|
||||||
id = randomUUID()
|
id = randomUUID()
|
||||||
|
|
||||||
@ManyToOne({ deleteRule: 'cascade' })
|
@ManyToOne({ deleteRule: 'cascade' })
|
||||||
zone!: Zone
|
map!: Map
|
||||||
|
|
||||||
@Enum(() => ZoneEventTileType)
|
@Enum(() => MapEventTileType)
|
||||||
type!: ZoneEventTileType
|
type!: MapEventTileType
|
||||||
|
|
||||||
@Property()
|
@Property()
|
||||||
positionX!: number
|
positionX!: number
|
||||||
@ -26,8 +26,8 @@ export class ZoneEventTile extends BaseEntity {
|
|||||||
@Property()
|
@Property()
|
||||||
positionY!: number
|
positionY!: number
|
||||||
|
|
||||||
@OneToOne(() => ZoneEventTileTeleport, (teleport) => teleport.zoneEventTile)
|
@OneToOne(() => MapEventTileTeleport, (teleport) => teleport.mapEventTile)
|
||||||
teleport?: ZoneEventTileTeleport
|
teleport?: MapEventTileTeleport
|
||||||
|
|
||||||
setId(id: UUID) {
|
setId(id: UUID) {
|
||||||
this.id = id
|
this.id = id
|
||||||
@ -38,16 +38,16 @@ export class ZoneEventTile extends BaseEntity {
|
|||||||
return this.id
|
return this.id
|
||||||
}
|
}
|
||||||
|
|
||||||
setZone(zone: Zone) {
|
setMap(map: Map) {
|
||||||
this.zone = zone
|
this.map = map
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZone() {
|
getMap() {
|
||||||
return this.zone
|
return this.map
|
||||||
}
|
}
|
||||||
|
|
||||||
setType(type: ZoneEventTileType) {
|
setType(type: MapEventTileType) {
|
||||||
this.type = type
|
this.type = type
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ export class ZoneEventTile extends BaseEntity {
|
|||||||
return this.positionY
|
return this.positionY
|
||||||
}
|
}
|
||||||
|
|
||||||
setTeleport(teleport: ZoneEventTileTeleport) {
|
setTeleport(teleport: MapEventTileTeleport) {
|
||||||
this.teleport = teleport
|
this.teleport = teleport
|
||||||
return this
|
return this
|
||||||
}
|
}
|
@ -2,22 +2,22 @@ import { randomUUID } from 'node:crypto'
|
|||||||
|
|
||||||
import { Entity, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
import { Entity, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||||
|
|
||||||
import { Zone } from './zone'
|
import { Map } from './map'
|
||||||
import { ZoneEventTile } from './zoneEventTile'
|
import { MapEventTile } from './mapEventTile'
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ZoneEventTileTeleport extends BaseEntity {
|
export class MapEventTileTeleport extends BaseEntity {
|
||||||
@PrimaryKey()
|
@PrimaryKey()
|
||||||
id = randomUUID()
|
id = randomUUID()
|
||||||
|
|
||||||
@OneToOne({ deleteRule: 'cascade' })
|
@OneToOne({ deleteRule: 'cascade' })
|
||||||
zoneEventTile!: ZoneEventTile
|
mapEventTile!: MapEventTile
|
||||||
|
|
||||||
@ManyToOne({ deleteRule: 'cascade' })
|
@ManyToOne({ deleteRule: 'cascade' })
|
||||||
toZone!: Zone
|
toMap!: Map
|
||||||
|
|
||||||
@Property()
|
@Property()
|
||||||
toRotation!: number
|
toRotation!: number
|
||||||
@ -37,22 +37,22 @@ export class ZoneEventTileTeleport extends BaseEntity {
|
|||||||
return this.id
|
return this.id
|
||||||
}
|
}
|
||||||
|
|
||||||
setZoneEventTile(zoneEventTile: ZoneEventTile) {
|
setMapEventTile(mapEventTile: MapEventTile) {
|
||||||
this.zoneEventTile = zoneEventTile
|
this.mapEventTile = mapEventTile
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZoneEventTile() {
|
getMapEventTile() {
|
||||||
return this.zoneEventTile
|
return this.mapEventTile
|
||||||
}
|
}
|
||||||
|
|
||||||
setToZone(toZone: Zone) {
|
setToMap(toMap: Map) {
|
||||||
this.toZone = toZone
|
this.toMap = toMap
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getToZone() {
|
getToMap() {
|
||||||
return this.toZone
|
return this.toMap
|
||||||
}
|
}
|
||||||
|
|
||||||
setToRotation(toRotation: number) {
|
setToRotation(toRotation: number) {
|
@ -1,8 +1,6 @@
|
|||||||
import { randomUUID } from 'node:crypto'
|
import { randomUUID } from 'node:crypto'
|
||||||
|
|
||||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||||
|
|
||||||
import { ZoneObject } from './zoneObject'
|
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
|
@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto'
|
|||||||
|
|
||||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||||
|
|
||||||
import { Zone } from './zone'
|
import { Map } from './map'
|
||||||
|
|
||||||
import { BaseEntity } from '#application/base/baseEntity'
|
import { BaseEntity } from '#application/base/baseEntity'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
@ -10,12 +10,12 @@ import { MapObject } from '#entities/mapObject'
|
|||||||
|
|
||||||
//@TODO : Rename mapObject
|
//@TODO : Rename mapObject
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ZoneObject extends BaseEntity {
|
export class placedMapObject extends BaseEntity {
|
||||||
@PrimaryKey()
|
@PrimaryKey()
|
||||||
id = randomUUID()
|
id = randomUUID()
|
||||||
|
|
||||||
@ManyToOne({ deleteRule: 'cascade' })
|
@ManyToOne({ deleteRule: 'cascade' })
|
||||||
zone!: Zone
|
map!: Map
|
||||||
|
|
||||||
@ManyToOne({ deleteRule: 'cascade' })
|
@ManyToOne({ deleteRule: 'cascade' })
|
||||||
mapObject!: MapObject
|
mapObject!: MapObject
|
||||||
@ -41,13 +41,13 @@ export class ZoneObject extends BaseEntity {
|
|||||||
return this.id
|
return this.id
|
||||||
}
|
}
|
||||||
|
|
||||||
setZone(zone: Zone) {
|
setMap(map: Map) {
|
||||||
this.zone = zone
|
this.map = map
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getZone() {
|
getMap() {
|
||||||
return this.zone
|
return this.map
|
||||||
}
|
}
|
||||||
|
|
||||||
setMapObject(mapObject: MapObject) {
|
setMapObject(mapObject: MapObject) {
|
@ -1,6 +1,6 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||||
import CharacterRepository from '#repositories/characterRepository'
|
import CharacterRepository from '#repositories/characterRepository'
|
||||||
import TeleportService from '#services/teleportService'
|
import TeleportService from '#services/teleportService'
|
||||||
@ -61,7 +61,7 @@ export default class CharacterConnectEvent extends BaseEvent {
|
|||||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||||
|
|
||||||
await TeleportService.teleportCharacter(character.id, {
|
await TeleportService.teleportCharacter(character.id, {
|
||||||
targetZoneId: character.zone.id,
|
targetMapId: character.map.id,
|
||||||
targetX: character.positionX,
|
targetX: character.positionX,
|
||||||
targetY: character.positionY,
|
targetY: character.positionY,
|
||||||
rotation: character.rotation,
|
rotation: character.rotation,
|
||||||
@ -75,6 +75,6 @@ export default class CharacterConnectEvent extends BaseEvent {
|
|||||||
|
|
||||||
private async checkForActiveCharacters(): Promise<boolean> {
|
private async checkForActiveCharacters(): Promise<boolean> {
|
||||||
const characters = await CharacterRepository.getByUserId(this.socket.userId!)
|
const characters = await CharacterRepository.getByUserId(this.socket.userId!)
|
||||||
return characters?.some((char) => ZoneManager.getCharacterById(char.id)) ?? false
|
return characters?.some((char) => MapManager.getCharacterById(char.id)) ?? false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { ZCharacterCreate } from '#application/zodTypes'
|
|||||||
import { Character } from '#entities/character'
|
import { Character } from '#entities/character'
|
||||||
import CharacterRepository from '#repositories/characterRepository'
|
import CharacterRepository from '#repositories/characterRepository'
|
||||||
import UserRepository from '#repositories/userRepository'
|
import UserRepository from '#repositories/userRepository'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
export default class CharacterCreateEvent extends BaseEvent {
|
export default class CharacterCreateEvent extends BaseEvent {
|
||||||
public listen(): void {
|
public listen(): void {
|
||||||
@ -37,10 +37,10 @@ export default class CharacterCreateEvent extends BaseEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: Change to default location
|
// @TODO: Change to default location
|
||||||
const zone = await ZoneRepository.getFirst()
|
const map = await MapRepository.getFirst()
|
||||||
|
|
||||||
const newCharacter = new Character()
|
const newCharacter = new Character()
|
||||||
await newCharacter.setName(data.name).setUser(user).setZone(zone!).save()
|
await newCharacter.setName(data.name).setUser(user).setMap(map!).save()
|
||||||
|
|
||||||
if (!newCharacter) {
|
if (!newCharacter) {
|
||||||
return this.socket.emit('notification', { message: 'Failed to create character. Please try again (later).' })
|
return this.socket.emit('notification', { message: 'Failed to create character. Please try again (later).' })
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
import { Character } from '#entities/character'
|
import { Character } from '#entities/character'
|
||||||
import { Zone } from '#entities/zone'
|
import { Map } from '#entities/map'
|
||||||
import CharacterRepository from '#repositories/characterRepository'
|
import CharacterRepository from '#repositories/characterRepository'
|
||||||
|
|
||||||
type TypePayload = {
|
type TypePayload = {
|
||||||
@ -9,7 +9,7 @@ type TypePayload = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TypeResponse = {
|
type TypeResponse = {
|
||||||
zone: Zone
|
map: Map
|
||||||
characters: Character[]
|
characters: Character[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
import ChatService from '#services/chatService'
|
import ChatService from '#services/chatService'
|
||||||
import TeleportService from '#services/teleportService'
|
import TeleportService from '#services/teleportService'
|
||||||
|
|
||||||
@ -16,13 +16,13 @@ export default class TeleportCommandEvent extends BaseEvent {
|
|||||||
|
|
||||||
private async handleEvent(data: TypePayload, callback: (response: boolean) => void) {
|
private async handleEvent(data: TypePayload, callback: (response: boolean) => void) {
|
||||||
try {
|
try {
|
||||||
const zoneCharacter = ZoneManager.getCharacterById(this.socket.characterId!)
|
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||||
if (!zoneCharacter) {
|
if (!mapCharacter) {
|
||||||
this.logger.error('chat:message error', 'Character not found')
|
this.logger.error('chat:message error', 'Character not found')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const character = zoneCharacter.character
|
const character = mapCharacter.character
|
||||||
|
|
||||||
if (character.role !== 'gm') {
|
if (character.role !== 'gm') {
|
||||||
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||||
@ -36,16 +36,16 @@ export default class TeleportCommandEvent extends BaseEvent {
|
|||||||
if (!args || args.length === 0 || args.length > 3) {
|
if (!args || args.length === 0 || args.length > 3) {
|
||||||
this.socket.emit('notification', {
|
this.socket.emit('notification', {
|
||||||
title: 'Server message',
|
title: 'Server message',
|
||||||
message: 'Usage: /teleport <zoneId> [x] [y]'
|
message: 'Usage: /teleport <mapId> [x] [y]'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const zoneId = args[0] as UUID
|
const mapId = args[0] as UUID
|
||||||
const targetX = args[1] ? parseInt(args[1], 10) : 0
|
const targetX = args[1] ? parseInt(args[1], 10) : 0
|
||||||
const targetY = args[2] ? parseInt(args[2], 10) : 0
|
const targetY = args[2] ? parseInt(args[2], 10) : 0
|
||||||
|
|
||||||
if (!zoneId || isNaN(targetX) || isNaN(targetY)) {
|
if (!mapId || isNaN(targetX) || isNaN(targetY)) {
|
||||||
this.socket.emit('notification', {
|
this.socket.emit('notification', {
|
||||||
title: 'Server message',
|
title: 'Server message',
|
||||||
message: 'Invalid parameters. X and Y coordinates must be numbers.'
|
message: 'Invalid parameters. X and Y coordinates must be numbers.'
|
||||||
@ -53,16 +53,16 @@ export default class TeleportCommandEvent extends BaseEvent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const zone = await ZoneRepository.getById(zoneId)
|
const map = await MapRepository.getById(mapId)
|
||||||
if (!zone) {
|
if (!map) {
|
||||||
this.socket.emit('notification', {
|
this.socket.emit('notification', {
|
||||||
title: 'Server message',
|
title: 'Server message',
|
||||||
message: 'Zone not found'
|
message: 'Map not found'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.zone.id === zone.id && targetX === character.positionX && targetY === character.positionY) {
|
if (character.map.id === map.id && targetX === character.positionX && targetY === character.positionY) {
|
||||||
this.socket.emit('notification', {
|
this.socket.emit('notification', {
|
||||||
title: 'Server message',
|
title: 'Server message',
|
||||||
message: 'You are already at that location'
|
message: 'You are already at that location'
|
||||||
@ -71,7 +71,7 @@ export default class TeleportCommandEvent extends BaseEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const success = await TeleportService.teleportCharacter(character.id, {
|
const success = await TeleportService.teleportCharacter(character.id, {
|
||||||
targetZoneId: zone.id,
|
targetMapId: map.id,
|
||||||
targetX,
|
targetX,
|
||||||
targetY,
|
targetY,
|
||||||
rotation: character.rotation
|
rotation: character.rotation
|
||||||
@ -86,9 +86,9 @@ export default class TeleportCommandEvent extends BaseEvent {
|
|||||||
|
|
||||||
this.socket.emit('notification', {
|
this.socket.emit('notification', {
|
||||||
title: 'Server message',
|
title: 'Server message',
|
||||||
message: `Teleported to ${zone.name} (${targetX}, ${targetY})`
|
message: `Teleported to ${map.name} (${targetX}, ${targetY})`
|
||||||
})
|
})
|
||||||
this.logger.info('teleport', `Character ${character.id} teleported to zone ${zone.id} at position (${targetX}, ${targetY})`)
|
this.logger.info('teleport', `Character ${character.id} teleported to map ${map.id} at position (${targetX}, ${targetY})`)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error(`Error in teleport command: ${error.message}`)
|
this.logger.error(`Error in teleport command: ${error.message}`)
|
||||||
this.socket.emit('notification', {
|
this.socket.emit('notification', {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
import ChatService from '#services/chatService'
|
import ChatService from '#services/chatService'
|
||||||
|
|
||||||
type TypePayload = {
|
type TypePayload = {
|
||||||
@ -18,21 +18,21 @@ export default class ChatMessageEvent extends BaseEvent {
|
|||||||
return callback(false)
|
return callback(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const zoneCharacter = ZoneManager.getCharacterById(this.socket.characterId!)
|
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||||
if (!zoneCharacter) {
|
if (!mapCharacter) {
|
||||||
this.logger.error('chat:message error', 'Character not found')
|
this.logger.error('chat:message error', 'Character not found')
|
||||||
return callback(false)
|
return callback(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const character = zoneCharacter.character
|
const character = mapCharacter.character
|
||||||
|
|
||||||
const zone = await ZoneRepository.getById(character.zone.id)
|
const map = await MapRepository.getById(character.map.id)
|
||||||
if (!zone) {
|
if (!map) {
|
||||||
this.logger.error('chat:message error', 'Zone not found')
|
this.logger.error('chat:message error', 'Map not found')
|
||||||
return callback(false)
|
return callback(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await ChatService.sendZoneMessage(character.getId(), zone.getId(), data.message)) {
|
if (await ChatService.sendMapMessage(character.getId(), map.getId(), data.message)) {
|
||||||
return callback(true)
|
return callback(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
|
|
||||||
export default class DisconnectEvent extends BaseEvent {
|
export default class DisconnectEvent extends BaseEvent {
|
||||||
public listen(): void {
|
public listen(): void {
|
||||||
@ -15,13 +15,13 @@ export default class DisconnectEvent extends BaseEvent {
|
|||||||
|
|
||||||
this.io.emit('user:disconnect', this.socket.userId)
|
this.io.emit('user:disconnect', this.socket.userId)
|
||||||
|
|
||||||
const zoneCharacter = ZoneManager.getCharacterById(this.socket.characterId!)
|
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||||
if (!zoneCharacter) {
|
if (!mapCharacter) {
|
||||||
this.logger.info('User disconnected but had no character set')
|
this.logger.info('User disconnected but had no character set')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await zoneCharacter.disconnect(this.socket, this.io)
|
await mapCharacter.disconnect(this.socket, this.io)
|
||||||
this.logger.info('User disconnected along with their character')
|
this.logger.info('User disconnected along with their character')
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error('disconnect error: ' + error.message)
|
this.logger.error('disconnect error: ' + error.message)
|
||||||
|
@ -1,32 +1,18 @@
|
|||||||
import { Object } from '@prisma/client'
|
|
||||||
import { Server } from 'socket.io'
|
|
||||||
|
|
||||||
import { TSocket } from '#application/types'
|
|
||||||
import characterRepository from '#repositories/characterRepository'
|
|
||||||
import ObjectRepository from '#repositories/objectRepository'
|
import ObjectRepository from '#repositories/objectRepository'
|
||||||
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
|
|
||||||
interface IPayload {}
|
interface IPayload {}
|
||||||
|
|
||||||
export default class ObjectListEvent {
|
export default class ObjectListEvent extends BaseEvent{
|
||||||
constructor(
|
|
||||||
private readonly io: Server,
|
|
||||||
private readonly socket: TSocket
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public listen(): void {
|
public listen(): void {
|
||||||
this.socket.on('gm:object:list', this.handleEvent.bind(this))
|
this.socket.on('gm:object:list', this.handleEvent.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleEvent(data: IPayload, callback: (response: Object[]) => void): Promise<void> {
|
private async handleEvent(data: IPayload, callback: (response: Object[]) => void): Promise<void> {
|
||||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
if (!(await this.isCharacterGM())) return
|
||||||
if (!character) return callback([])
|
|
||||||
|
|
||||||
if (character.role !== 'gm') {
|
|
||||||
return callback([])
|
|
||||||
}
|
|
||||||
|
|
||||||
// get all objects
|
// get all objects
|
||||||
const objects = await ObjectRepository.getAll()
|
const objects = await ObjectRepository.getAll()
|
||||||
callback(objects)
|
return callback(objects)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
import fs from 'fs/promises'
|
import fs from 'fs/promises'
|
||||||
|
|
||||||
import { Server } from 'socket.io'
|
|
||||||
|
|
||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import Storage from '#application/storage'
|
import Storage from '#application/storage'
|
||||||
|
import { Sprite } from '#entities/sprite'
|
||||||
|
|
||||||
export default class SpriteCreateEvent extends BaseEvent {
|
export default class SpriteCreateEvent extends BaseEvent {
|
||||||
constructor(
|
|
||||||
private readonly io: Server,
|
|
||||||
private readonly socket: TSocket
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public listen(): void {
|
public listen(): void {
|
||||||
this.socket.on('gm:sprite:create', this.handleEvent.bind(this))
|
this.socket.on('gm:sprite:create', this.handleEvent.bind(this))
|
||||||
}
|
}
|
||||||
@ -24,21 +18,19 @@ export default class SpriteCreateEvent extends BaseEvent {
|
|||||||
// Ensure the folder exists
|
// Ensure the folder exists
|
||||||
await fs.mkdir(public_folder, { recursive: true })
|
await fs.mkdir(public_folder, { recursive: true })
|
||||||
|
|
||||||
const sprite = await prisma.sprite.create({
|
const sprite = new Sprite()
|
||||||
data: {
|
await sprite.setName('New sprite').save()
|
||||||
name: 'New sprite'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const uuid = sprite.id
|
const uuid = sprite.id
|
||||||
|
|
||||||
// Create folder with uuid
|
// Create folder with uuid
|
||||||
const sprite_folder = Storage.getPublicPath('sprites', uuid)
|
const sprite_folder = Storage.getPublicPath('sprites', uuid)
|
||||||
await fs.mkdir(sprite_folder, { recursive: true })
|
await fs.mkdir(sprite_folder, { recursive: true })
|
||||||
|
|
||||||
callback(true)
|
return callback(true)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating sprite:', error)
|
console.error('Error creating sprite:', error)
|
||||||
callback(false)
|
return callback(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
import { Zone } from '#entities/zone'
|
import { Map } from '#entities/map'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
type Payload = {
|
type Payload = {
|
||||||
name: string
|
name: string
|
||||||
@ -8,30 +8,30 @@ type Payload = {
|
|||||||
height: number
|
height: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ZoneCreateEvent extends BaseEvent {
|
export default class MapCreateEvent extends BaseEvent {
|
||||||
public listen(): void {
|
public listen(): void {
|
||||||
this.socket.on('gm:zone_editor:zone:create', this.handleEvent.bind(this))
|
this.socket.on('gm:map_editor:map:create', this.handleEvent.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleEvent(data: Payload, callback: (response: Zone[]) => void): Promise<void> {
|
private async handleEvent(data: Payload, callback: (response: Map[]) => void): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (!(await this.isCharacterGM())) return
|
if (!(await this.isCharacterGM())) return
|
||||||
|
|
||||||
this.logger.info(`User ${(await this.getCharacter())!.getId()} has created a new zone via zone editor.`)
|
this.logger.info(`User ${(await this.getCharacter())!.getId()} has created a new map via map editor.`)
|
||||||
|
|
||||||
const zone = new Zone()
|
const map = new Map()
|
||||||
await zone
|
await map
|
||||||
.setName(data.name)
|
.setName(data.name)
|
||||||
.setWidth(data.width)
|
.setWidth(data.width)
|
||||||
.setHeight(data.height)
|
.setHeight(data.height)
|
||||||
.setTiles(Array.from({ length: data.height }, () => Array.from({ length: data.width }, () => 'blank_tile')))
|
.setTiles(Array.from({ length: data.height }, () => Array.from({ length: data.width }, () => 'blank_tile')))
|
||||||
.save()
|
.save()
|
||||||
|
|
||||||
const zoneList = await ZoneRepository.getAll()
|
const mapList = await MapRepository.getAll()
|
||||||
return callback(zoneList)
|
return callback(mapList)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error('gm:zone_editor:zone:create error', error.message)
|
this.logger.error('gm:map_editor:map:create error', error.message)
|
||||||
this.socket.emit('notification', { message: 'Failed to create zone.' })
|
this.socket.emit('notification', { message: 'Failed to create map.' })
|
||||||
return callback([])
|
return callback([])
|
||||||
}
|
}
|
||||||
}
|
}
|
29
src/events/gameMaster/mapEditor/delete.ts
Normal file
29
src/events/gameMaster/mapEditor/delete.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
|
type Payload = {
|
||||||
|
mapId: UUID
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MapDeleteEvent extends BaseEvent {
|
||||||
|
public listen(): void {
|
||||||
|
this.socket.on('gm:map_editor:map:delete', this.handleEvent.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleEvent(data: Payload, callback: (response: boolean) => void): Promise<void> {
|
||||||
|
if (!(await this.isCharacterGM())) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.logger.info(`Deleting map ${data.mapId}`)
|
||||||
|
|
||||||
|
await (await MapRepository.getById(data.mapId))?.delete()
|
||||||
|
|
||||||
|
this.logger.info(`Map ${data.mapId} deleted successfully.`)
|
||||||
|
return callback(true)
|
||||||
|
} catch (error: unknown) {
|
||||||
|
this.logger.error('gm:map_editor:map:delete error', error)
|
||||||
|
return callback(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
src/events/gameMaster/mapEditor/list.ts
Normal file
25
src/events/gameMaster/mapEditor/list.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
|
import { Map } from '#entities/map'
|
||||||
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
|
interface IPayload {}
|
||||||
|
|
||||||
|
export default class MapListEvent extends BaseEvent {
|
||||||
|
public listen(): void {
|
||||||
|
this.socket.on('gm:map_editor:map:list', this.handleEvent.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleEvent(data: IPayload, callback: (response: Map[]) => void): Promise<void> {
|
||||||
|
try {
|
||||||
|
if (!(await this.isCharacterGM())) return
|
||||||
|
|
||||||
|
this.logger.info(`User ${(await this.getCharacter())!.getId()} has created a new map via map editor.`)
|
||||||
|
|
||||||
|
const maps = await MapRepository.getAll()
|
||||||
|
return callback(maps)
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error('gm:map_editor:map:list error', error.message)
|
||||||
|
return callback([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
src/events/gameMaster/mapEditor/request.ts
Normal file
39
src/events/gameMaster/mapEditor/request.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import { Map } from '#entities/map'
|
||||||
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
|
interface IPayload {
|
||||||
|
mapId: UUID
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MapRequestEvent extends BaseEvent {
|
||||||
|
public listen(): void {
|
||||||
|
this.socket.on('gm:map_editor:map:request', this.handleEvent.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleEvent(data: IPayload, callback: (response: Map | null) => void): Promise<void> {
|
||||||
|
try {
|
||||||
|
if (!(await this.isCharacterGM())) return
|
||||||
|
|
||||||
|
this.logger.info(`User ${(await this.getCharacter())!.getId()} has requested map via map editor.`)
|
||||||
|
|
||||||
|
if (!data.mapId) {
|
||||||
|
this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request map but did not provide a map id.`)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = await MapRepository.getById(data.mapId)
|
||||||
|
|
||||||
|
if (!map) {
|
||||||
|
this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request map ${data.mapId} but it does not exist.`)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(map)
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error('gm:map_editor:map:request error', error.message)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
132
src/events/gameMaster/mapEditor/update.ts
Normal file
132
src/events/gameMaster/mapEditor/update.ts
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
|
import { MapEventTileType } from '#application/enums'
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import { Map } from '#entities/map'
|
||||||
|
import { MapEffect } from '#entities/mapEffect'
|
||||||
|
import { MapEventTile } from '#entities/mapEventTile'
|
||||||
|
import { MapEventTileTeleport } from '#entities/mapEventTileTeleport'
|
||||||
|
import { MapObject } from '#entities/mapObject'
|
||||||
|
import mapManager from '#managers/mapManager'
|
||||||
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
|
interface IPayload {
|
||||||
|
mapId: UUID
|
||||||
|
name: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
tiles: string[][]
|
||||||
|
pvp: boolean
|
||||||
|
mapEventTiles: {
|
||||||
|
type: MapEventTileType
|
||||||
|
positionX: number
|
||||||
|
positionY: number
|
||||||
|
teleport?: {
|
||||||
|
toMapId: UUID
|
||||||
|
toPositionX: number
|
||||||
|
toPositionY: number
|
||||||
|
toRotation: number
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
mapEffects: {
|
||||||
|
effect: string
|
||||||
|
strength: number
|
||||||
|
}[]
|
||||||
|
mapObjects: MapObject[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MapUpdateEvent extends BaseEvent {
|
||||||
|
public listen(): void {
|
||||||
|
this.socket.on('gm:map_editor:map:update', this.handleEvent.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleEvent(data: IPayload, callback: (response: Map | null) => void): Promise<void> {
|
||||||
|
try {
|
||||||
|
if (!(await this.isCharacterGM())) return
|
||||||
|
|
||||||
|
const character = await this.getCharacter()
|
||||||
|
this.logger.info(`User ${character!.getId()} has updated map via map editor.`)
|
||||||
|
|
||||||
|
if (!data.mapId) {
|
||||||
|
this.logger.info(`User ${character!.getId()} tried to update map but did not provide a map id.`)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
let map = await MapRepository.getById(data.mapId)
|
||||||
|
|
||||||
|
if (!map) {
|
||||||
|
this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist.`)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation logic remains the same
|
||||||
|
if (data.tiles.length > data.height) {
|
||||||
|
data.tiles = data.tiles.slice(0, data.height)
|
||||||
|
}
|
||||||
|
for (let i = 0; i < data.tiles.length; i++) {
|
||||||
|
if (data.tiles[i].length > data.width) {
|
||||||
|
data.tiles[i] = data.tiles[i].slice(0, data.width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.mapEventTiles = data.mapEventTiles.filter((tile) => tile.positionX >= 0 && tile.positionX < data.width && tile.positionY >= 0 && tile.positionY < data.height)
|
||||||
|
|
||||||
|
data.mapObjects = data.mapObjects.filter((obj) => obj.positionX >= 0 && obj.positionX < data.width && obj.positionY >= 0 && obj.positionY < data.height)
|
||||||
|
|
||||||
|
// Clear existing collections
|
||||||
|
map.mapEventTiles.removeAll()
|
||||||
|
map.mapObjects.removeAll()
|
||||||
|
map.mapEffects.removeAll()
|
||||||
|
|
||||||
|
// Create and add new map event tiles
|
||||||
|
for (const tile of data.mapEventTiles) {
|
||||||
|
const mapEventTile = new MapEventTile().setType(tile.type).setPositionX(tile.positionX).setPositionY(tile.positionY).setMap(map)
|
||||||
|
|
||||||
|
if (tile.teleport) {
|
||||||
|
const teleport = new MapEventTileTeleport()
|
||||||
|
.setToMap((await MapRepository.getById(tile.teleport.toMapId))!)
|
||||||
|
.setToPositionX(tile.teleport.toPositionX)
|
||||||
|
.setToPositionY(tile.teleport.toPositionY)
|
||||||
|
.setToRotation(tile.teleport.toRotation)
|
||||||
|
|
||||||
|
mapEventTile.setTeleport(teleport)
|
||||||
|
}
|
||||||
|
|
||||||
|
map.mapEventTiles.add(mapEventTile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and add new map objects
|
||||||
|
for (const object of data.mapObjects) {
|
||||||
|
const mapObject = new MapObject().setMapObject(object.mapObject).setDepth(object.depth).setIsRotated(object.isRotated).setPositionX(object.positionX).setPositionY(object.positionY).setMap(map)
|
||||||
|
|
||||||
|
map.mapObjects.add(mapObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and add new map effects
|
||||||
|
for (const effect of data.mapEffects) {
|
||||||
|
const mapEffect = new MapEffect().setEffect(effect.effect).setStrength(effect.strength).setMap(map)
|
||||||
|
|
||||||
|
map.mapEffects.add(mapEffect)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update map properties
|
||||||
|
await map.setName(data.name).setWidth(data.width).setHeight(data.height).setTiles(data.tiles).setPvp(data.pvp).setUpdatedAt(new Date()).update()
|
||||||
|
|
||||||
|
// Reload map from database to get fresh data
|
||||||
|
map = await MapRepository.getById(data.mapId)
|
||||||
|
|
||||||
|
if (!map) {
|
||||||
|
this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist after update.`)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload map for players
|
||||||
|
mapManager.unloadMap(data.mapId)
|
||||||
|
await mapManager.loadMap(map)
|
||||||
|
|
||||||
|
return callback(map)
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`gm:map_editor:map:update error: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
return callback(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
|
||||||
|
|
||||||
type Payload = {
|
|
||||||
zoneId: UUID
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ZoneDeleteEvent extends BaseEvent {
|
|
||||||
public listen(): void {
|
|
||||||
this.socket.on('gm:zone_editor:zone:delete', this.handleEvent.bind(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleEvent(data: Payload, callback: (response: boolean) => void): Promise<void> {
|
|
||||||
if (!(await this.isCharacterGM())) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.logger.info(`Deleting zone ${data.zoneId}`)
|
|
||||||
|
|
||||||
await (await ZoneRepository.getById(data.zoneId))?.delete()
|
|
||||||
|
|
||||||
this.logger.info(`Zone ${data.zoneId} deleted successfully.`)
|
|
||||||
return callback(true)
|
|
||||||
} catch (error: unknown) {
|
|
||||||
this.logger.error('gm:zone_editor:zone:delete error', error)
|
|
||||||
return callback(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
|
||||||
import { Zone } from '#entities/zone'
|
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
|
||||||
|
|
||||||
interface IPayload {}
|
|
||||||
|
|
||||||
export default class ZoneListEvent extends BaseEvent {
|
|
||||||
public listen(): void {
|
|
||||||
this.socket.on('gm:zone_editor:zone:list', this.handleEvent.bind(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleEvent(data: IPayload, callback: (response: Zone[]) => void): Promise<void> {
|
|
||||||
try {
|
|
||||||
if (!(await this.isCharacterGM())) return
|
|
||||||
|
|
||||||
this.logger.info(`User ${(await this.getCharacter())!.getId()} has created a new zone via zone editor.`)
|
|
||||||
|
|
||||||
const zones = await ZoneRepository.getAll()
|
|
||||||
return callback(zones)
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error('gm:zone_editor:zone:list error', error.message)
|
|
||||||
return callback([])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import { Zone } from '#entities/zone'
|
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
|
||||||
|
|
||||||
interface IPayload {
|
|
||||||
zoneId: UUID
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ZoneRequestEvent extends BaseEvent {
|
|
||||||
public listen(): void {
|
|
||||||
this.socket.on('gm:zone_editor:zone:request', this.handleEvent.bind(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleEvent(data: IPayload, callback: (response: Zone | null) => void): Promise<void> {
|
|
||||||
try {
|
|
||||||
if (!(await this.isCharacterGM())) return
|
|
||||||
|
|
||||||
this.logger.info(`User ${(await this.getCharacter())!.getId()} has requested zone via zone editor.`)
|
|
||||||
|
|
||||||
if (!data.zoneId) {
|
|
||||||
this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request zone but did not provide a zone id.`)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
const zone = await ZoneRepository.getById(data.zoneId)
|
|
||||||
|
|
||||||
if (!zone) {
|
|
||||||
this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request zone ${data.zoneId} but it does not exist.`)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(zone)
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error('gm:zone_editor:zone:request error', error.message)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
|
||||||
import { ZoneEventTileType } from '#application/enums'
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import { Zone } from '#entities/zone'
|
|
||||||
import { ZoneEffect } from '#entities/zoneEffect'
|
|
||||||
import { ZoneEventTile } from '#entities/zoneEventTile'
|
|
||||||
import { ZoneEventTileTeleport } from '#entities/zoneEventTileTeleport'
|
|
||||||
import { ZoneObject } from '#entities/zoneObject'
|
|
||||||
import zoneManager from '#managers/zoneManager'
|
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
|
||||||
|
|
||||||
interface IPayload {
|
|
||||||
zoneId: UUID
|
|
||||||
name: string
|
|
||||||
width: number
|
|
||||||
height: number
|
|
||||||
tiles: string[][]
|
|
||||||
pvp: boolean
|
|
||||||
zoneEventTiles: {
|
|
||||||
type: ZoneEventTileType
|
|
||||||
positionX: number
|
|
||||||
positionY: number
|
|
||||||
teleport?: {
|
|
||||||
toZoneId: UUID
|
|
||||||
toPositionX: number
|
|
||||||
toPositionY: number
|
|
||||||
toRotation: number
|
|
||||||
}
|
|
||||||
}[]
|
|
||||||
zoneEffects: {
|
|
||||||
effect: string
|
|
||||||
strength: number
|
|
||||||
}[]
|
|
||||||
zoneObjects: ZoneObject[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ZoneUpdateEvent extends BaseEvent {
|
|
||||||
public listen(): void {
|
|
||||||
this.socket.on('gm:zone_editor:zone:update', this.handleEvent.bind(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleEvent(data: IPayload, callback: (response: Zone | null) => void): Promise<void> {
|
|
||||||
try {
|
|
||||||
if (!(await this.isCharacterGM())) return
|
|
||||||
|
|
||||||
const character = await this.getCharacter()
|
|
||||||
this.logger.info(`User ${character!.getId()} has updated zone via zone editor.`)
|
|
||||||
|
|
||||||
if (!data.zoneId) {
|
|
||||||
this.logger.info(`User ${character!.getId()} tried to update zone but did not provide a zone id.`)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
let zone = await ZoneRepository.getById(data.zoneId)
|
|
||||||
|
|
||||||
if (!zone) {
|
|
||||||
this.logger.info(`User ${character!.getId()} tried to update zone ${data.zoneId} but it does not exist.`)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validation logic remains the same
|
|
||||||
if (data.tiles.length > data.height) {
|
|
||||||
data.tiles = data.tiles.slice(0, data.height)
|
|
||||||
}
|
|
||||||
for (let i = 0; i < data.tiles.length; i++) {
|
|
||||||
if (data.tiles[i].length > data.width) {
|
|
||||||
data.tiles[i] = data.tiles[i].slice(0, data.width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.zoneEventTiles = data.zoneEventTiles.filter((tile) => tile.positionX >= 0 && tile.positionX < data.width && tile.positionY >= 0 && tile.positionY < data.height)
|
|
||||||
|
|
||||||
data.zoneObjects = data.zoneObjects.filter((obj) => obj.positionX >= 0 && obj.positionX < data.width && obj.positionY >= 0 && obj.positionY < data.height)
|
|
||||||
|
|
||||||
// Clear existing collections
|
|
||||||
zone.zoneEventTiles.removeAll()
|
|
||||||
zone.zoneObjects.removeAll()
|
|
||||||
zone.zoneEffects.removeAll()
|
|
||||||
|
|
||||||
// Create and add new zone event tiles
|
|
||||||
for (const tile of data.zoneEventTiles) {
|
|
||||||
const zoneEventTile = new ZoneEventTile().setType(tile.type).setPositionX(tile.positionX).setPositionY(tile.positionY).setZone(zone)
|
|
||||||
|
|
||||||
if (tile.teleport) {
|
|
||||||
const teleport = new ZoneEventTileTeleport()
|
|
||||||
.setToZone((await ZoneRepository.getById(tile.teleport.toZoneId))!)
|
|
||||||
.setToPositionX(tile.teleport.toPositionX)
|
|
||||||
.setToPositionY(tile.teleport.toPositionY)
|
|
||||||
.setToRotation(tile.teleport.toRotation)
|
|
||||||
|
|
||||||
zoneEventTile.setTeleport(teleport)
|
|
||||||
}
|
|
||||||
|
|
||||||
zone.zoneEventTiles.add(zoneEventTile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and add new zone objects
|
|
||||||
for (const object of data.zoneObjects) {
|
|
||||||
const zoneObject = new ZoneObject().setMapObject(object.mapObject).setDepth(object.depth).setIsRotated(object.isRotated).setPositionX(object.positionX).setPositionY(object.positionY).setZone(zone)
|
|
||||||
|
|
||||||
zone.zoneObjects.add(zoneObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and add new zone effects
|
|
||||||
for (const effect of data.zoneEffects) {
|
|
||||||
const zoneEffect = new ZoneEffect().setEffect(effect.effect).setStrength(effect.strength).setZone(zone)
|
|
||||||
|
|
||||||
zone.zoneEffects.add(zoneEffect)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update zone properties
|
|
||||||
await zone.setName(data.name).setWidth(data.width).setHeight(data.height).setTiles(data.tiles).setPvp(data.pvp).setUpdatedAt(new Date()).update()
|
|
||||||
|
|
||||||
// Reload zone from database to get fresh data
|
|
||||||
zone = await ZoneRepository.getById(data.zoneId)
|
|
||||||
|
|
||||||
if (!zone) {
|
|
||||||
this.logger.info(`User ${character!.getId()} tried to update zone ${data.zoneId} but it does not exist after update.`)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload zone for players
|
|
||||||
zoneManager.unloadZone(data.zoneId)
|
|
||||||
await zoneManager.loadZone(zone)
|
|
||||||
|
|
||||||
return callback(zone)
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`gm:zone_editor:zone:update error: ${error instanceof Error ? error.message : String(error)}`)
|
|
||||||
return callback(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
104
src/events/map/characterMove.ts
Normal file
104
src/events/map/characterMove.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { BaseEvent } from '#application/base/baseEvent'
|
||||||
|
import { MapEventTileWithTeleport } from '#application/types'
|
||||||
|
import MapManager from '#managers/mapManager'
|
||||||
|
import MapCharacter from '#models/mapCharacter'
|
||||||
|
import mapEventTileRepository from '#repositories/mapEventTileRepository'
|
||||||
|
import CharacterService from '#services/characterService'
|
||||||
|
import MapEventTileService from '#services/mapEventTileService'
|
||||||
|
|
||||||
|
export default class CharacterMove extends BaseEvent {
|
||||||
|
private readonly characterService = CharacterService
|
||||||
|
private readonly mapEventTileService = MapEventTileService
|
||||||
|
|
||||||
|
public listen(): void {
|
||||||
|
this.socket.on('map:character:move', this.handleEvent.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleEvent({ positionX, positionY }: { positionX: number; positionY: number }): Promise<void> {
|
||||||
|
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||||
|
if (!mapCharacter?.character) {
|
||||||
|
this.logger.error('map:character:move error: Character not found or not initialized')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already moving, cancel current movement and wait for it to fully stop
|
||||||
|
if (mapCharacter.isMoving) {
|
||||||
|
mapCharacter.isMoving = false
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = await this.characterService.calculatePath(mapCharacter.character, positionX, positionY)
|
||||||
|
if (!path) {
|
||||||
|
this.io.in(mapCharacter.character.map.id).emit('map:character:moveError', 'No valid path found')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start new movement
|
||||||
|
mapCharacter.isMoving = true
|
||||||
|
mapCharacter.currentPath = path // Add this property to MapCharacter class
|
||||||
|
await this.moveAlongPath(mapCharacter, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async moveAlongPath(mapCharacter: MapCharacter, path: Array<{ x: number; y: number }>): Promise<void> {
|
||||||
|
const { character } = mapCharacter
|
||||||
|
|
||||||
|
for (let i = 0; i < path.length - 1; i++) {
|
||||||
|
if (!mapCharacter.isMoving || mapCharacter.currentPath !== path) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const [start, end] = [path[i], path[i + 1]]
|
||||||
|
character.rotation = CharacterService.calculateRotation(start.x, start.y, end.x, end.y)
|
||||||
|
|
||||||
|
const mapEventTile = await mapEventTileRepository.getEventTileByMapIdAndPosition(character.map.id, Math.floor(end.x), Math.floor(end.y))
|
||||||
|
|
||||||
|
if (mapEventTile?.type === 'BLOCK') break
|
||||||
|
if (mapEventTile?.type === 'TELEPORT' && mapEventTile.teleport) {
|
||||||
|
await this.handleMapEventTile(mapEventTile as MapEventTileWithTeleport)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position first
|
||||||
|
character.positionX = end.x
|
||||||
|
character.positionY = end.y
|
||||||
|
|
||||||
|
// Then emit with the same properties
|
||||||
|
this.io.in(character.map.id).emit('map:character:move', {
|
||||||
|
characterId: character.id,
|
||||||
|
positionX: character.positionX,
|
||||||
|
positionY: character.positionY,
|
||||||
|
rotation: character.rotation,
|
||||||
|
isMoving: true
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.characterService.applyMovementDelay()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapCharacter.isMoving && mapCharacter.currentPath === path) {
|
||||||
|
this.finalizeMovement(mapCharacter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleMapEventTile(mapEventTile: MapEventTileWithTeleport): Promise<void> {
|
||||||
|
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||||
|
if (!mapCharacter) {
|
||||||
|
this.logger.error('map:character:move error: Character not found')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapEventTile.teleport) {
|
||||||
|
await this.mapEventTileService.handleTeleport(this.io, this.socket, mapCharacter.character, mapEventTile.teleport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private finalizeMovement(mapCharacter: MapCharacter): void {
|
||||||
|
mapCharacter.isMoving = false
|
||||||
|
this.io.in(mapCharacter.character.map.id).emit('map:character:move', {
|
||||||
|
characterId: mapCharacter.character.id,
|
||||||
|
positionX: mapCharacter.character.positionX,
|
||||||
|
positionY: mapCharacter.character.positionY,
|
||||||
|
rotation: mapCharacter.character.rotation,
|
||||||
|
isMoving: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -1,104 +0,0 @@
|
|||||||
import { BaseEvent } from '#application/base/baseEvent'
|
|
||||||
import { ZoneEventTileWithTeleport } from '#application/types'
|
|
||||||
import ZoneManager from '#managers/zoneManager'
|
|
||||||
import ZoneCharacter from '#models/zoneCharacter'
|
|
||||||
import zoneEventTileRepository from '#repositories/zoneEventTileRepository'
|
|
||||||
import CharacterService from '#services/characterService'
|
|
||||||
import ZoneEventTileService from '#services/zoneEventTileService'
|
|
||||||
|
|
||||||
export default class CharacterMove extends BaseEvent {
|
|
||||||
private readonly characterService = CharacterService
|
|
||||||
private readonly zoneEventTileService = ZoneEventTileService
|
|
||||||
|
|
||||||
public listen(): void {
|
|
||||||
this.socket.on('zone:character:move', this.handleEvent.bind(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleEvent({ positionX, positionY }: { positionX: number; positionY: number }): Promise<void> {
|
|
||||||
const zoneCharacter = ZoneManager.getCharacterById(this.socket.characterId!)
|
|
||||||
if (!zoneCharacter?.character) {
|
|
||||||
this.logger.error('zone:character:move error: Character not found or not initialized')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If already moving, cancel current movement and wait for it to fully stop
|
|
||||||
if (zoneCharacter.isMoving) {
|
|
||||||
zoneCharacter.isMoving = false
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
||||||
}
|
|
||||||
|
|
||||||
const path = await this.characterService.calculatePath(zoneCharacter.character, positionX, positionY)
|
|
||||||
if (!path) {
|
|
||||||
this.io.in(zoneCharacter.character.zone.id).emit('zone:character:moveError', 'No valid path found')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start new movement
|
|
||||||
zoneCharacter.isMoving = true
|
|
||||||
zoneCharacter.currentPath = path // Add this property to ZoneCharacter class
|
|
||||||
await this.moveAlongPath(zoneCharacter, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
private async moveAlongPath(zoneCharacter: ZoneCharacter, path: Array<{ x: number; y: number }>): Promise<void> {
|
|
||||||
const { character } = zoneCharacter
|
|
||||||
|
|
||||||
for (let i = 0; i < path.length - 1; i++) {
|
|
||||||
if (!zoneCharacter.isMoving || zoneCharacter.currentPath !== path) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const [start, end] = [path[i], path[i + 1]]
|
|
||||||
character.rotation = CharacterService.calculateRotation(start.x, start.y, end.x, 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) {
|
|
||||||
await this.handleZoneEventTile(zoneEventTile as ZoneEventTileWithTeleport)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update position first
|
|
||||||
character.positionX = end.x
|
|
||||||
character.positionY = end.y
|
|
||||||
|
|
||||||
// Then emit with the same properties
|
|
||||||
this.io.in(character.zone.id).emit('zone:character:move', {
|
|
||||||
characterId: character.id,
|
|
||||||
positionX: character.positionX,
|
|
||||||
positionY: character.positionY,
|
|
||||||
rotation: character.rotation,
|
|
||||||
isMoving: true
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.characterService.applyMovementDelay()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zoneCharacter.isMoving && zoneCharacter.currentPath === path) {
|
|
||||||
this.finalizeMovement(zoneCharacter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleZoneEventTile(zoneEventTile: ZoneEventTileWithTeleport): Promise<void> {
|
|
||||||
const zoneCharacter = ZoneManager.getCharacterById(this.socket.characterId!)
|
|
||||||
if (!zoneCharacter) {
|
|
||||||
this.logger.error('zone:character:move error: Character not found')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zoneEventTile.teleport) {
|
|
||||||
await this.zoneEventTileService.handleTeleport(this.io, this.socket, zoneCharacter.character, zoneEventTile.teleport)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private finalizeMovement(zoneCharacter: ZoneCharacter): void {
|
|
||||||
zoneCharacter.isMoving = false
|
|
||||||
this.io.in(zoneCharacter.character.zone.id).emit('zone:character:move', {
|
|
||||||
characterId: zoneCharacter.character.id,
|
|
||||||
positionX: zoneCharacter.character.positionX,
|
|
||||||
positionY: zoneCharacter.character.positionY,
|
|
||||||
rotation: zoneCharacter.character.rotation,
|
|
||||||
isMoving: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ import Storage from '#application/storage'
|
|||||||
import { AssetData, UUID } from '#application/types'
|
import { AssetData, UUID } from '#application/types'
|
||||||
import SpriteRepository from '#repositories/spriteRepository'
|
import SpriteRepository from '#repositories/spriteRepository'
|
||||||
import TileRepository from '#repositories/tileRepository'
|
import TileRepository from '#repositories/tileRepository'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
export class AssetsController extends BaseController {
|
export class AssetsController extends BaseController {
|
||||||
/**
|
/**
|
||||||
@ -28,24 +28,24 @@ export class AssetsController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List tiles by zone
|
* List tiles by map
|
||||||
* @param req
|
* @param req
|
||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
public async listTilesByZone(req: Request, res: Response) {
|
public async listTilesByMap(req: Request, res: Response) {
|
||||||
const zoneId = req.params.zoneId as UUID
|
const mapId = req.params.mapId as UUID
|
||||||
|
|
||||||
if (!zoneId) {
|
if (!mapId) {
|
||||||
return this.sendError(res, 'Invalid zone ID', 400)
|
return this.sendError(res, 'Invalid map ID', 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
const zone = await ZoneRepository.getById(zoneId)
|
const map = await MapRepository.getById(mapId)
|
||||||
if (!zone) {
|
if (!map) {
|
||||||
return this.sendError(res, 'Zone not found', 404)
|
return this.sendError(res, 'Map not found', 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
const assets: AssetData[] = []
|
const assets: AssetData[] = []
|
||||||
const tiles = await TileRepository.getByZoneId(zoneId)
|
const tiles = await TileRepository.getByMapId(mapId)
|
||||||
|
|
||||||
for (const tile of tiles) {
|
for (const tile of tiles) {
|
||||||
assets.push({ key: tile.getId(), data: '/assets/tiles/' + tile.getId() + '.png', group: 'tiles', updatedAt: tile.getUpdatedAt() } as AssetData)
|
assets.push({ key: tile.getId(), data: '/assets/tiles/' + tile.getId() + '.png', group: 'tiles', updatedAt: tile.getUpdatedAt() } as AssetData)
|
||||||
|
@ -33,7 +33,7 @@ class HttpManager {
|
|||||||
|
|
||||||
// Assets routes
|
// Assets routes
|
||||||
app.get('/assets/list_tiles', (req, res) => this.assetsController.listTiles(req, res))
|
app.get('/assets/list_tiles', (req, res) => this.assetsController.listTiles(req, res))
|
||||||
app.get('/assets/list_tiles/:zoneId', (req, res) => this.assetsController.listTilesByZone(req, res))
|
app.get('/assets/list_tiles/:mapId', (req, res) => this.assetsController.listTilesByMap(req, res))
|
||||||
app.get('/assets/list_sprite_actions/:spriteId', (req, res) => this.assetsController.listSpriteActions(req, res))
|
app.get('/assets/list_sprite_actions/:spriteId', (req, res) => this.assetsController.listSpriteActions(req, res))
|
||||||
app.get('/assets/:type/:spriteId?/:file', (req, res) => this.assetsController.downloadAsset(req, res))
|
app.get('/assets/:type/:spriteId?/:file', (req, res) => this.assetsController.downloadAsset(req, res))
|
||||||
}
|
}
|
||||||
|
50
src/managers/mapManager.ts
Normal file
50
src/managers/mapManager.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import Logger, { LoggerType } from '#application/logger'
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import { Map } from '#entities/map'
|
||||||
|
import LoadedMap from '#models/loadedMap'
|
||||||
|
import MapCharacter from '#models/mapCharacter'
|
||||||
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
|
class MapManager {
|
||||||
|
private readonly maps: Record<UUID, LoadedMap> = {}
|
||||||
|
private logger = Logger.type(LoggerType.GAME)
|
||||||
|
|
||||||
|
public async boot(): Promise<void> {
|
||||||
|
const maps = await MapRepository.getAll()
|
||||||
|
await Promise.all(maps.map((map) => this.loadMap(map)))
|
||||||
|
|
||||||
|
this.logger.info(`Map manager loaded with ${Object.keys(this.maps).length} maps`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async loadMap(map: Map): Promise<void> {
|
||||||
|
this.maps[map.id] = new LoadedMap(map)
|
||||||
|
this.logger.info(`Map ID ${map.id} loaded`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public unloadMap(mapId: UUID): void {
|
||||||
|
delete this.maps[mapId]
|
||||||
|
this.logger.info(`Map ID ${mapId} unloaded`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLoadedMaps(): LoadedMap[] {
|
||||||
|
return Object.values(this.maps)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMapById(mapId: UUID): LoadedMap | undefined {
|
||||||
|
return this.maps[mapId]
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCharacterById(characterId: UUID): MapCharacter | undefined {
|
||||||
|
for (const map of Object.values(this.maps)) {
|
||||||
|
const character = map.getCharactersInMap().find((char) => char.character.id === characterId)
|
||||||
|
if (character) return character
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeCharacter(characterId: UUID): void {
|
||||||
|
Object.values(this.maps).forEach((map) => map.removeCharacter(characterId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new MapManager()
|
@ -1,51 +0,0 @@
|
|||||||
import Logger, { LoggerType } from '#application/logger'
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import { Zone } from '#entities/zone'
|
|
||||||
import LoadedZone from '#models/loadedZone'
|
|
||||||
import ZoneCharacter from '#models/zoneCharacter'
|
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
|
||||||
|
|
||||||
class ZoneManager {
|
|
||||||
private readonly zones = new Map<UUID, LoadedZone>()
|
|
||||||
private logger = Logger.type(LoggerType.GAME)
|
|
||||||
|
|
||||||
public async boot(): Promise<void> {
|
|
||||||
const zones = await ZoneRepository.getAll()
|
|
||||||
await Promise.all(zones.map((zone) => this.loadZone(zone)))
|
|
||||||
|
|
||||||
this.logger.info(`Zone manager loaded with ${this.zones.size} zones`)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async loadZone(zone: Zone): Promise<void> {
|
|
||||||
const loadedZone = new LoadedZone(zone)
|
|
||||||
this.zones.set(zone.id, loadedZone)
|
|
||||||
this.logger.info(`Zone ID ${zone.id} loaded`)
|
|
||||||
}
|
|
||||||
|
|
||||||
public unloadZone(zoneId: UUID): void {
|
|
||||||
this.zones.delete(zoneId)
|
|
||||||
this.logger.info(`Zone ID ${zoneId} unloaded`)
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLoadedZones(): LoadedZone[] {
|
|
||||||
return Array.from(this.zones.values())
|
|
||||||
}
|
|
||||||
|
|
||||||
public getZoneById(zoneId: UUID): LoadedZone | undefined {
|
|
||||||
return this.zones.get(zoneId)
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCharacterById(characterId: UUID): ZoneCharacter | undefined {
|
|
||||||
for (const zone of this.zones.values()) {
|
|
||||||
const character = zone.getCharactersInZone().find((char) => char.character.id === characterId)
|
|
||||||
if (character) return character
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeCharacter(characterId: UUID): void {
|
|
||||||
this.zones.forEach((zone) => zone.removeCharacter(characterId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new ZoneManager()
|
|
58
src/models/loadedMap.ts
Normal file
58
src/models/loadedMap.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import MapCharacter from './mapCharacter'
|
||||||
|
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import { Character } from '#entities/character'
|
||||||
|
import { Map } from '#entities/map'
|
||||||
|
import mapEventTileRepository from '#repositories/mapEventTileRepository'
|
||||||
|
|
||||||
|
class LoadedMap {
|
||||||
|
private readonly map: Map
|
||||||
|
private characters: MapCharacter[] = []
|
||||||
|
|
||||||
|
constructor(map: Map) {
|
||||||
|
this.map = map
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMap(): Map {
|
||||||
|
return this.map
|
||||||
|
}
|
||||||
|
|
||||||
|
public addCharacter(character: Character) {
|
||||||
|
const mapCharacter = new MapCharacter(character)
|
||||||
|
this.characters.push(mapCharacter)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async removeCharacter(id: UUID) {
|
||||||
|
const mapCharacter = this.getCharacterById(id)
|
||||||
|
if (mapCharacter) {
|
||||||
|
await mapCharacter.savePosition()
|
||||||
|
this.characters = this.characters.filter((c) => c.character.id !== id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCharacterById(id: UUID): MapCharacter | undefined {
|
||||||
|
return this.characters.find((c) => c.character.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCharactersInMap(): MapCharacter[] {
|
||||||
|
console.log(this.characters)
|
||||||
|
return this.characters
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getGrid(): Promise<number[][]> {
|
||||||
|
let grid: number[][] = Array.from({ length: this.map.height }, () => Array.from({ length: this.map.width }, () => 0))
|
||||||
|
|
||||||
|
const eventTiles = await mapEventTileRepository.getAll(this.map.id)
|
||||||
|
|
||||||
|
// Set the grid values based on the event tiles, these are strings
|
||||||
|
eventTiles.forEach((eventTile) => {
|
||||||
|
if (eventTile.type === 'BLOCK') {
|
||||||
|
grid[eventTile.positionY][eventTile.positionX] = 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return grid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoadedMap
|
@ -1,58 +0,0 @@
|
|||||||
import ZoneCharacter from './zoneCharacter'
|
|
||||||
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import { Character } from '#entities/character'
|
|
||||||
import { Zone } from '#entities/zone'
|
|
||||||
import zoneEventTileRepository from '#repositories/zoneEventTileRepository'
|
|
||||||
|
|
||||||
class LoadedZone {
|
|
||||||
private readonly zone: Zone
|
|
||||||
private characters: ZoneCharacter[] = []
|
|
||||||
|
|
||||||
constructor(zone: Zone) {
|
|
||||||
this.zone = zone
|
|
||||||
}
|
|
||||||
|
|
||||||
public getZone(): Zone {
|
|
||||||
return this.zone
|
|
||||||
}
|
|
||||||
|
|
||||||
public addCharacter(character: Character) {
|
|
||||||
const zoneCharacter = new ZoneCharacter(character)
|
|
||||||
this.characters.push(zoneCharacter)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async removeCharacter(id: UUID) {
|
|
||||||
const zoneCharacter = this.getCharacterById(id)
|
|
||||||
if (zoneCharacter) {
|
|
||||||
await zoneCharacter.savePosition()
|
|
||||||
this.characters = this.characters.filter((c) => c.character.id !== id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCharacterById(id: UUID): ZoneCharacter | undefined {
|
|
||||||
return this.characters.find((c) => c.character.id === id)
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCharactersInZone(): ZoneCharacter[] {
|
|
||||||
console.log(this.characters)
|
|
||||||
return this.characters
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getGrid(): Promise<number[][]> {
|
|
||||||
let grid: number[][] = Array.from({ length: this.zone.height }, () => Array.from({ length: this.zone.width }, () => 0))
|
|
||||||
|
|
||||||
const eventTiles = await zoneEventTileRepository.getAll(this.zone.id)
|
|
||||||
|
|
||||||
// Set the grid values based on the event tiles, these are strings
|
|
||||||
eventTiles.forEach((eventTile) => {
|
|
||||||
if (eventTile.type === 'BLOCK') {
|
|
||||||
grid[eventTile.positionY][eventTile.positionX] = 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return grid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LoadedZone
|
|
@ -3,10 +3,10 @@ import { Server } from 'socket.io'
|
|||||||
import { TSocket } from '#application/types'
|
import { TSocket } from '#application/types'
|
||||||
import { Character } from '#entities/character'
|
import { Character } from '#entities/character'
|
||||||
import SocketManager from '#managers/socketManager'
|
import SocketManager from '#managers/socketManager'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
import TeleportService from '#services/teleportService'
|
import TeleportService from '#services/teleportService'
|
||||||
|
|
||||||
class ZoneCharacter {
|
class MapCharacter {
|
||||||
public readonly character: Character
|
public readonly character: Character
|
||||||
public isMoving: boolean = false
|
public isMoving: boolean = false
|
||||||
public currentPath: Array<{ x: number; y: number }> | null = null
|
public currentPath: Array<{ x: number; y: number }> | null = null
|
||||||
@ -16,12 +16,12 @@ class ZoneCharacter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async savePosition() {
|
public async savePosition() {
|
||||||
await this.character.setPositionX(this.character.positionX).setPositionY(this.character.positionY).setRotation(this.character.rotation).setZone(this.character.zone).update()
|
await this.character.setPositionX(this.character.positionX).setPositionY(this.character.positionY).setRotation(this.character.rotation).setMap(this.character.map).update()
|
||||||
}
|
}
|
||||||
|
|
||||||
public async teleport(zoneId: number, targetX: number, targetY: number): Promise<void> {
|
public async teleport(mapId: number, targetX: number, targetY: number): Promise<void> {
|
||||||
await TeleportService.teleportCharacter(this.character.id, {
|
await TeleportService.teleportCharacter(this.character.id, {
|
||||||
targetZoneId: zoneId,
|
targetMapId: mapId,
|
||||||
targetX,
|
targetX,
|
||||||
targetY
|
targetY
|
||||||
})
|
})
|
||||||
@ -34,13 +34,13 @@ class ZoneCharacter {
|
|||||||
this.currentPath = null
|
this.currentPath = null
|
||||||
await this.savePosition()
|
await this.savePosition()
|
||||||
|
|
||||||
// Leave zone and remove from manager
|
// Leave map and remove from manager
|
||||||
if (this.character.zone) {
|
if (this.character.map) {
|
||||||
socket.leave(this.character.zone.id)
|
socket.leave(this.character.map.id)
|
||||||
ZoneManager.removeCharacter(this.character.id)
|
MapManager.removeCharacter(this.character.id)
|
||||||
|
|
||||||
// Notify zone players
|
// Notify map players
|
||||||
io.in(this.character.zone.id).emit('zone:character:leave', this.character.id)
|
io.in(this.character.map.id).emit('map:character:leave', this.character.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all players
|
// Notify all players
|
||||||
@ -51,4 +51,4 @@ class ZoneCharacter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ZoneCharacter
|
export default MapCharacter
|
@ -35,12 +35,12 @@ class ChatRepository extends BaseRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByZoneId(zoneId: UUID): Promise<Chat[]> {
|
async getByMapId(mapId: UUID): Promise<Chat[]> {
|
||||||
try {
|
try {
|
||||||
const repository = this.em.getRepository(Chat)
|
const repository = this.em.getRepository(Chat)
|
||||||
return await repository.find({ zone: zoneId })
|
return await repository.find({ map: mapId })
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error(`Failed to get chats by zone ID: ${error instanceof Error ? error.message : String(error)}`)
|
this.logger.error(`Failed to get chats by map ID: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
src/repositories/mapEventTileRepository.ts
Normal file
33
src/repositories/mapEventTileRepository.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { BaseRepository } from '#application/base/baseRepository'
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import { MapEventTile } from '#entities/mapEventTile'
|
||||||
|
|
||||||
|
class MapEventTileRepository extends BaseRepository {
|
||||||
|
async getAll(id: UUID): Promise<MapEventTile[]> {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(MapEventTile)
|
||||||
|
return await repository.find({
|
||||||
|
map: id
|
||||||
|
})
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get map event tiles: ${error.message}`)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getEventTileByMapIdAndPosition(mapId: UUID, positionX: number, positionY: number) {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(MapEventTile)
|
||||||
|
return await repository.findOne({
|
||||||
|
map: mapId,
|
||||||
|
positionX: positionX,
|
||||||
|
positionY: positionY
|
||||||
|
})
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get map event tile: ${error.message}`)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new MapEventTileRepository()
|
73
src/repositories/mapRepository.ts
Normal file
73
src/repositories/mapRepository.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { BaseRepository } from '#application/base/baseRepository'
|
||||||
|
import { UUID } from '#application/types'
|
||||||
|
import { Map } from '#entities/map'
|
||||||
|
import { MapEventTile } from '#entities/mapEventTile'
|
||||||
|
import { MapObject } from '#entities/mapObject'
|
||||||
|
|
||||||
|
class MapRepository extends BaseRepository {
|
||||||
|
async getFirst(): Promise<Map | null> {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(Map)
|
||||||
|
return await repository.findOne({ id: { $exists: true } })
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get first map: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<Map[]> {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(Map)
|
||||||
|
return await repository.findAll()
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get all map: ${error.message}`)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getById(id: UUID) {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(Map)
|
||||||
|
return await repository.findOne({ id })
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get map by id: ${error.message}`)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getEventTiles(id: UUID): Promise<MapEventTile[]> {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(MapEventTile)
|
||||||
|
return await repository.find({ map: id })
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get map event tiles: ${error.message}`)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFirstEventTile(mapId: UUID, positionX: number, positionY: number): Promise<MapEventTile | null> {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(MapEventTile)
|
||||||
|
return await repository.findOne({
|
||||||
|
map: mapId,
|
||||||
|
positionX: positionX,
|
||||||
|
positionY: positionY
|
||||||
|
})
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get map event tile: ${error.message}`)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMapObjects(id: UUID): Promise<MapObject[]> {
|
||||||
|
try {
|
||||||
|
const repository = this.em.getRepository(MapObject)
|
||||||
|
return await repository.find({ map: id })
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`Failed to get map objects: ${error.message}`)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new MapRepository()
|
@ -4,8 +4,8 @@ import { BaseRepository } from '#application/base/baseRepository'
|
|||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
import { unduplicateArray } from '#application/utilities'
|
import { unduplicateArray } from '#application/utilities'
|
||||||
import { Tile } from '#entities/tile'
|
import { Tile } from '#entities/tile'
|
||||||
import { Zone } from '#entities/zone'
|
import { Map } from '#entities/map'
|
||||||
import ZoneService from '#services/zoneService'
|
import MapService from '#services/mapService'
|
||||||
|
|
||||||
class TileRepository extends BaseRepository {
|
class TileRepository extends BaseRepository {
|
||||||
async getById(id: UUID) {
|
async getById(id: UUID) {
|
||||||
@ -37,18 +37,18 @@ class TileRepository extends BaseRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByZoneId(zoneId: UUID) {
|
async getByMapId(mapId: UUID) {
|
||||||
try {
|
try {
|
||||||
const repository = this.em.getRepository(Zone)
|
const repository = this.em.getRepository(Map)
|
||||||
const tileRepository = this.em.getRepository(Tile)
|
const tileRepository = this.em.getRepository(Tile)
|
||||||
|
|
||||||
const zone = await repository.findOne({ id: zoneId })
|
const map = await repository.findOne({ id: mapId })
|
||||||
if (!zone) return []
|
if (!map) return []
|
||||||
|
|
||||||
const zoneTileArray = unduplicateArray(ZoneService.flattenZoneArray(JSON.parse(JSON.stringify(zone.tiles))))
|
const mapTileArray = unduplicateArray(MapService.flattenMapArray(JSON.parse(JSON.stringify(map.tiles))))
|
||||||
|
|
||||||
return await tileRepository.find({
|
return await tileRepository.find({
|
||||||
id: zoneTileArray
|
id: mapTileArray
|
||||||
})
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return []
|
return []
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import { BaseRepository } from '#application/base/baseRepository'
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import { ZoneEventTile } from '#entities/zoneEventTile'
|
|
||||||
|
|
||||||
class ZoneEventTileRepository extends BaseRepository {
|
|
||||||
async getAll(id: UUID): Promise<ZoneEventTile[]> {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(ZoneEventTile)
|
|
||||||
return await repository.find({
|
|
||||||
zone: id
|
|
||||||
})
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get zone event tiles: ${error.message}`)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getEventTileByZoneIdAndPosition(zoneId: UUID, positionX: number, positionY: number) {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(ZoneEventTile)
|
|
||||||
return await repository.findOne({
|
|
||||||
zone: zoneId,
|
|
||||||
positionX: positionX,
|
|
||||||
positionY: positionY
|
|
||||||
})
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get zone event tile: ${error.message}`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new ZoneEventTileRepository()
|
|
@ -1,73 +0,0 @@
|
|||||||
import { BaseRepository } from '#application/base/baseRepository'
|
|
||||||
import { UUID } from '#application/types'
|
|
||||||
import { Zone } from '#entities/zone'
|
|
||||||
import { ZoneEventTile } from '#entities/zoneEventTile'
|
|
||||||
import { ZoneObject } from '#entities/zoneObject'
|
|
||||||
|
|
||||||
class ZoneRepository extends BaseRepository {
|
|
||||||
async getFirst(): Promise<Zone | null> {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(Zone)
|
|
||||||
return await repository.findOne({ id: { $exists: true } })
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get first zone: ${error instanceof Error ? error.message : String(error)}`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAll(): Promise<Zone[]> {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(Zone)
|
|
||||||
return await repository.findAll()
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get all zone: ${error.message}`)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getById(id: UUID) {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(Zone)
|
|
||||||
return await repository.findOne({ id })
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get zone by id: ${error.message}`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getEventTiles(id: UUID): Promise<ZoneEventTile[]> {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(ZoneEventTile)
|
|
||||||
return await repository.find({ zone: id })
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get zone event tiles: ${error.message}`)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFirstEventTile(zoneId: UUID, positionX: number, positionY: number): Promise<ZoneEventTile | null> {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(ZoneEventTile)
|
|
||||||
return await repository.findOne({
|
|
||||||
zone: zoneId,
|
|
||||||
positionX: positionX,
|
|
||||||
positionY: positionY
|
|
||||||
})
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get zone event tile: ${error.message}`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getZoneObjects(id: UUID): Promise<ZoneObject[]> {
|
|
||||||
try {
|
|
||||||
const repository = this.em.getRepository(ZoneObject)
|
|
||||||
return await repository.find({ zone: id })
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error(`Failed to get zone objects: ${error.message}`)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new ZoneRepository()
|
|
@ -13,7 +13,7 @@ import QueueManager from '#managers/queueManager'
|
|||||||
import SocketManager from '#managers/socketManager'
|
import SocketManager from '#managers/socketManager'
|
||||||
import UserManager from '#managers/userManager'
|
import UserManager from '#managers/userManager'
|
||||||
import WeatherManager from '#managers/weatherManager'
|
import WeatherManager from '#managers/weatherManager'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
|
|
||||||
export class Server {
|
export class Server {
|
||||||
private readonly app: Application
|
private readonly app: Application
|
||||||
@ -45,7 +45,7 @@ export class Server {
|
|||||||
UserManager.boot(),
|
UserManager.boot(),
|
||||||
// DateManager.boot(),
|
// DateManager.boot(),
|
||||||
// WeatherManager.boot(),
|
// WeatherManager.boot(),
|
||||||
ZoneManager.boot(),
|
MapManager.boot(),
|
||||||
ConsoleManager.boot()
|
ConsoleManager.boot()
|
||||||
])
|
])
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { BaseService } from '#application/base/baseService'
|
import { BaseService } from '#application/base/baseService'
|
||||||
import config from '#application/config'
|
import config from '#application/config'
|
||||||
import { Character } from '#entities/character'
|
import { Character } from '#entities/character'
|
||||||
import { Zone } from '#entities/zone'
|
import { Map } from '#entities/map'
|
||||||
import SocketManager from '#managers/socketManager'
|
import SocketManager from '#managers/socketManager'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
import CharacterRepository from '#repositories/characterRepository'
|
import CharacterRepository from '#repositories/characterRepository'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
type Position = { x: number; y: number }
|
type Position = { x: number; y: number }
|
||||||
export type Node = Position & { parent?: Node; g: number; h: number; f: number }
|
export type Node = Position & { parent?: Node; g: number; h: number; f: number }
|
||||||
@ -24,11 +24,11 @@ class CharacterService extends BaseService {
|
|||||||
]
|
]
|
||||||
|
|
||||||
public async calculatePath(character: Character, targetX: number, targetY: number): Promise<Position[] | null> {
|
public async calculatePath(character: Character, targetX: number, targetY: number): Promise<Position[] | null> {
|
||||||
const zone = ZoneManager.getZoneById(character.zone.id)
|
const map = MapManager.getMapById(character.map.id)
|
||||||
const grid = await zone?.getGrid()
|
const grid = await map?.getGrid()
|
||||||
|
|
||||||
if (!grid?.length) {
|
if (!grid?.length) {
|
||||||
this.logger.error('zone:character:move error: Grid not found or empty')
|
this.logger.error('map:character:move error: Grid not found or empty')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,22 +6,22 @@ import { Chat } from '#entities/chat'
|
|||||||
import SocketManager from '#managers/socketManager'
|
import SocketManager from '#managers/socketManager'
|
||||||
import CharacterRepository from '#repositories/characterRepository'
|
import CharacterRepository from '#repositories/characterRepository'
|
||||||
import ChatRepository from '#repositories/chatRepository'
|
import ChatRepository from '#repositories/chatRepository'
|
||||||
import ZoneRepository from '#repositories/zoneRepository'
|
import MapRepository from '#repositories/mapRepository'
|
||||||
|
|
||||||
class ChatService extends BaseService {
|
class ChatService extends BaseService {
|
||||||
async sendZoneMessage(characterId: UUID, zoneId: UUID, message: string): Promise<boolean> {
|
async sendMapMessage(characterId: UUID, mapId: UUID, message: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const character = await CharacterRepository.getById(characterId)
|
const character = await CharacterRepository.getById(characterId)
|
||||||
if (!character) return false
|
if (!character) return false
|
||||||
|
|
||||||
const zone = await ZoneRepository.getById(zoneId)
|
const map = await MapRepository.getById(mapId)
|
||||||
if (!zone) return false
|
if (!map) return false
|
||||||
|
|
||||||
const chat = new Chat()
|
const chat = new Chat()
|
||||||
await chat.setCharacter(character).setZone(zone).setMessage(message).save()
|
await chat.setCharacter(character).setMap(map).setMessage(message).save()
|
||||||
|
|
||||||
const io = SocketManager.getIO()
|
const io = SocketManager.getIO()
|
||||||
io.to(zoneId).emit('chat:message', chat)
|
io.to(mapId).emit('chat:message', chat)
|
||||||
return true
|
return true
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error(`Failed to save chat message: ${error instanceof Error ? error.message : String(error)}`)
|
this.logger.error(`Failed to save chat message: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
49
src/services/mapEventTileService.ts
Normal file
49
src/services/mapEventTileService.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { Server } from 'socket.io'
|
||||||
|
|
||||||
|
import { BaseService } from '#application/base/baseService'
|
||||||
|
import { ExtendedCharacter, TSocket } from '#application/types'
|
||||||
|
import { MapEventTileTeleport } from '#entities/mapEventTileTeleport'
|
||||||
|
import MapManager from '#managers/mapManager'
|
||||||
|
|
||||||
|
class MapEventTileService extends BaseService {
|
||||||
|
public async handleTeleport(io: Server, socket: TSocket, character: ExtendedCharacter, teleport: MapEventTileTeleport): Promise<void> {
|
||||||
|
if (teleport.toMap.id === character.map.id) return
|
||||||
|
|
||||||
|
const loadedMap = MapManager.getMapById(teleport.toMap.id)
|
||||||
|
if (!loadedMap) {
|
||||||
|
this.logger.error('map:character:join error: Loaded map not found')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = loadedMap.getMap()
|
||||||
|
|
||||||
|
const oldMapId = character.map.id
|
||||||
|
const newMapId = teleport.toMap.id
|
||||||
|
|
||||||
|
character.isMoving = false
|
||||||
|
// Update local character object
|
||||||
|
character.setMap(teleport.toMap).setRotation(teleport.toRotation).setPositionX(teleport.toPositionX).setPositionY(teleport.toPositionY)
|
||||||
|
|
||||||
|
await character.save()
|
||||||
|
|
||||||
|
// Remove and add character to new map
|
||||||
|
await loadedMap.removeCharacter(character.id)
|
||||||
|
loadedMap.addCharacter(character)
|
||||||
|
|
||||||
|
// Emit events
|
||||||
|
io.to(oldMapId).emit('map:character:leave', character.id)
|
||||||
|
io.to(newMapId).emit('map:character:join', character)
|
||||||
|
|
||||||
|
// Update socket rooms
|
||||||
|
socket.leave(oldMapId)
|
||||||
|
socket.join(newMapId)
|
||||||
|
|
||||||
|
// Send teleport information to the client
|
||||||
|
socket.emit('map:character:teleport', {
|
||||||
|
map,
|
||||||
|
characters: loadedMap.getCharactersInMap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new MapEventTileService()
|
@ -1,7 +1,7 @@
|
|||||||
import { BaseService } from '#application/base/baseService'
|
import { BaseService } from '#application/base/baseService'
|
||||||
|
|
||||||
class ZoneService extends BaseService {
|
class MapService extends BaseService {
|
||||||
public flattenZoneArray(tiles: string[][]) {
|
public flattenMapArray(tiles: string[][]) {
|
||||||
const normalArray = []
|
const normalArray = []
|
||||||
|
|
||||||
for (const row of tiles) {
|
for (const row of tiles) {
|
||||||
@ -12,4 +12,4 @@ class ZoneService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new ZoneService()
|
export default new MapService()
|
@ -2,11 +2,11 @@ import Logger, { LoggerType } from '#application/logger'
|
|||||||
import { UUID } from '#application/types'
|
import { UUID } from '#application/types'
|
||||||
import { Character } from '#entities/character'
|
import { Character } from '#entities/character'
|
||||||
import SocketManager from '#managers/socketManager'
|
import SocketManager from '#managers/socketManager'
|
||||||
import ZoneManager from '#managers/zoneManager'
|
import MapManager from '#managers/mapManager'
|
||||||
import ZoneCharacter from '#models/zoneCharacter'
|
import MapCharacter from '#models/mapCharacter'
|
||||||
|
|
||||||
interface TeleportOptions {
|
interface TeleportOptions {
|
||||||
targetZoneId: UUID
|
targetMapId: UUID
|
||||||
targetX: number
|
targetX: number
|
||||||
targetY: number
|
targetY: number
|
||||||
rotation?: number
|
rotation?: number
|
||||||
@ -18,13 +18,13 @@ class TeleportService {
|
|||||||
private readonly logger = Logger.type(LoggerType.GAME)
|
private readonly logger = Logger.type(LoggerType.GAME)
|
||||||
|
|
||||||
public async teleportCharacter(characterId: UUID, options: TeleportOptions): Promise<boolean> {
|
public async teleportCharacter(characterId: UUID, options: TeleportOptions): Promise<boolean> {
|
||||||
const { targetZoneId, targetX, targetY, rotation = 0, isInitialJoin = false, character } = options
|
const { targetMapId, targetX, targetY, rotation = 0, isInitialJoin = false, character } = options
|
||||||
|
|
||||||
const socket = SocketManager.getSocketByCharacterId(characterId)
|
const socket = SocketManager.getSocketByCharacterId(characterId)
|
||||||
const targetZone = ZoneManager.getZoneById(targetZoneId)
|
const targetMap = MapManager.getMapById(targetMapId)
|
||||||
|
|
||||||
if (!socket || !targetZone) {
|
if (!socket || !targetMap) {
|
||||||
this.logger.error(`Teleport failed - Missing socket or target zone for character ${characterId}`)
|
this.logger.error(`Teleport failed - Missing socket or target map for character ${characterId}`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,40 +33,40 @@ class TeleportService {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingCharacter = !isInitialJoin && ZoneManager.getCharacterById(characterId)
|
const existingCharacter = !isInitialJoin && MapManager.getCharacterById(characterId)
|
||||||
const zoneCharacter = isInitialJoin
|
const mapCharacter = isInitialJoin
|
||||||
? new ZoneCharacter(character!)
|
? new MapCharacter(character!)
|
||||||
: existingCharacter ||
|
: existingCharacter ||
|
||||||
(() => {
|
(() => {
|
||||||
this.logger.error(`Teleport failed - Character ${characterId} not found in ZoneManager`)
|
this.logger.error(`Teleport failed - Character ${characterId} not found in MapManager`)
|
||||||
return null
|
return null
|
||||||
})()
|
})()
|
||||||
|
|
||||||
if (!zoneCharacter) return false
|
if (!mapCharacter) return false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentZoneId = zoneCharacter.character.zone?.id
|
const currentMapId = mapCharacter.character.map?.id
|
||||||
const io = SocketManager.getIO()
|
const io = SocketManager.getIO()
|
||||||
|
|
||||||
// Handle current zone cleanup
|
// Handle current map cleanup
|
||||||
if (currentZoneId) {
|
if (currentMapId) {
|
||||||
socket.leave(currentZoneId)
|
socket.leave(currentMapId)
|
||||||
ZoneManager.removeCharacter(characterId)
|
MapManager.removeCharacter(characterId)
|
||||||
io.in(currentZoneId).emit('zone:character:leave', characterId)
|
io.in(currentMapId).emit('map:character:leave', characterId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update character position and zone
|
// Update character position and map
|
||||||
await zoneCharacter.character.setPositionX(targetX).setPositionY(targetY).setRotation(rotation).setZone(targetZone.getZone()).update()
|
await mapCharacter.character.setPositionX(targetX).setPositionY(targetY).setRotation(rotation).setMap(targetMap.getMap()).update()
|
||||||
|
|
||||||
// Join new zone
|
// Join new map
|
||||||
socket.join(targetZoneId)
|
socket.join(targetMapId)
|
||||||
targetZone.addCharacter(zoneCharacter.character)
|
targetMap.addCharacter(mapCharacter.character)
|
||||||
|
|
||||||
// Notify clients
|
// Notify clients
|
||||||
io.in(targetZoneId).emit('zone:character:join', zoneCharacter)
|
io.in(targetMapId).emit('map:character:join', mapCharacter)
|
||||||
socket.emit('zone:character:teleport', {
|
socket.emit('map:character:teleport', {
|
||||||
zone: targetZone.getZone(),
|
map: targetMap.getMap(),
|
||||||
characters: targetZone.getCharactersInZone()
|
characters: targetMap.getCharactersInMap()
|
||||||
})
|
})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
import { Server } from 'socket.io'
|
|
||||||
|
|
||||||
import { BaseService } from '#application/base/baseService'
|
|
||||||
import { ExtendedCharacter, TSocket } from '#application/types'
|
|
||||||
import { ZoneEventTileTeleport } from '#entities/zoneEventTileTeleport'
|
|
||||||
import ZoneManager from '#managers/zoneManager'
|
|
||||||
|
|
||||||
class ZoneEventTileService extends BaseService {
|
|
||||||
public async handleTeleport(io: Server, socket: TSocket, character: ExtendedCharacter, teleport: ZoneEventTileTeleport): Promise<void> {
|
|
||||||
if (teleport.toZone.id === character.zone.id) return
|
|
||||||
|
|
||||||
const loadedZone = ZoneManager.getZoneById(teleport.toZone.id)
|
|
||||||
if (!loadedZone) {
|
|
||||||
this.logger.error('zone:character:join error: Loaded zone not found')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const zone = loadedZone.getZone()
|
|
||||||
|
|
||||||
const oldZoneId = character.zone.id
|
|
||||||
const newZoneId = teleport.toZone.id
|
|
||||||
|
|
||||||
character.isMoving = false
|
|
||||||
// Update local character object
|
|
||||||
character.setZone(teleport.toZone).setRotation(teleport.toRotation).setPositionX(teleport.toPositionX).setPositionY(teleport.toPositionY)
|
|
||||||
|
|
||||||
await character.save()
|
|
||||||
|
|
||||||
// Remove and add character to new zone
|
|
||||||
await loadedZone.removeCharacter(character.id)
|
|
||||||
loadedZone.addCharacter(character)
|
|
||||||
|
|
||||||
// Emit events
|
|
||||||
io.to(oldZoneId).emit('zone:character:leave', character.id)
|
|
||||||
io.to(newZoneId).emit('zone:character:join', character)
|
|
||||||
|
|
||||||
// Update socket rooms
|
|
||||||
socket.leave(oldZoneId)
|
|
||||||
socket.join(newZoneId)
|
|
||||||
|
|
||||||
// Send teleport information to the client
|
|
||||||
socket.emit('zone:character:teleport', {
|
|
||||||
zone,
|
|
||||||
characters: loadedZone.getCharactersInZone()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new ZoneEventTileService()
|
|
Loading…
x
Reference in New Issue
Block a user