Compare commits
71 Commits
feature/#2
...
feature/ma
Author | SHA1 | Date | |
---|---|---|---|
5680b324b4 | |||
9771f45e6d | |||
b3ac6d34b8 | |||
b115181756 | |||
bf4789b9a8 | |||
f004f059f6 | |||
e6adb959ba | |||
85161ab4f6 | |||
8f4d4fc482 | |||
a0584c2bb9 | |||
7f4a784915 | |||
71fdbd89a4 | |||
5c34ed7286 | |||
edb7836e55 | |||
112559055c | |||
1546deb811 | |||
d7ac70662a | |||
dae0d365d5 | |||
020f2bd3c5 | |||
189fd39377 | |||
0ba79c2299 | |||
74f5214ca3 | |||
410d5cb7a8 | |||
41e65fc3e9 | |||
4b6935c44a | |||
4232042a06 | |||
3869eefaaf | |||
a4437fadce | |||
458293a5fc | |||
849ef07297 | |||
39ec4daa06 | |||
010454914b | |||
f47023dc81 | |||
4397552a86 | |||
7b90fa5c13 | |||
7dabed7ff6 | |||
d91a70be09 | |||
514ed87818 | |||
24586855cb | |||
be9ee97385 | |||
a05cd97430 | |||
cc1dbe5179 | |||
d7982493e1 | |||
57b21f1499 | |||
33afef5466 | |||
813ddbd8b1 | |||
4a55f47c06 | |||
097773995f | |||
04e4170c2d | |||
46cfb61cf5 | |||
db7121a4fa | |||
1dd0e73c4a | |||
747d05a92a | |||
48784a437f | |||
6b12d8e7b1 | |||
50c2b249f4 | |||
82aaf8a015 | |||
0e0854d365 | |||
b2e0ac47e7 | |||
f2d0e87e26 | |||
9bdafd5026 | |||
ae269be196 | |||
21f4c5328f | |||
47ec425acf | |||
1f0db75806 | |||
9a448542d3 | |||
067976c54a | |||
0b4420f956 | |||
e843213b0a | |||
4d50edd5dd | |||
0cadbc33b9 |
@ -3,7 +3,7 @@ ENV=development
|
||||
HOST="0.0.0.0"
|
||||
PORT=4000
|
||||
JWT_SECRET="secret"
|
||||
CLIENT_URL="http://192.168.3.4:5173"
|
||||
CLIENT_URL="http://localhost:5173"
|
||||
|
||||
# Database configuration
|
||||
REDIS_URL="redis://@127.0.0.1:6379/4"
|
||||
|
@ -3,6 +3,6 @@
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 300,
|
||||
"printWidth": 200,
|
||||
"trailingComma": "none"
|
||||
}
|
12
README.md
12
README.md
@ -2,12 +2,22 @@
|
||||
|
||||
This is the server for the Noxious game.
|
||||
|
||||
## Projects requirements
|
||||
|
||||
- NodeJS 20.x or higher
|
||||
- MySQL 8.x or higher
|
||||
- Redis 7.x or higher
|
||||
|
||||
## Installation
|
||||
|
||||
1. Clone the repository
|
||||
2. Install dependencies with `npm install`
|
||||
3. Copy the `.env.example` file to `.env` and fill in the required variables
|
||||
4. Run the server with `npm run dev`
|
||||
4. Extract assets.zip to the `public` folder
|
||||
5. After MySQL and Redis are running, run `npx mikro-orm migration:up` to create the database schema
|
||||
6. Run the server with `npm run dev`
|
||||
7. Write `init` in the console to import default data and restart the server
|
||||
8. Write `tiles` in the console to fix tile sizes
|
||||
|
||||
## Commands
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20250103003053 extends Migration {
|
||||
export class Migration20250123193515 extends Migration {
|
||||
|
||||
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;`);
|
||||
@ -17,19 +17,19 @@ export class Migration20250103003053 extends Migration {
|
||||
|
||||
this.addSql(`create table \`map_object\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`tags\` json null, \`origin_x\` numeric(10,2) not null default 0, \`origin_y\` numeric(10,2) 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(`create table \`placed_map_object\` (\`id\` varchar(255) not null, \`map_id\` varchar(255) not null, \`map_object_id\` varchar(255) not null, \`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 \`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) not null default '', \`item_type\` enum('WEAPON', 'HELMET', 'CHEST', 'LEGS', 'BOOTS', 'GLOVES', 'RING', 'NECKLACE') not null, \`stackable\` tinyint(1) not null default false, \`rarity\` enum('COMMON', 'UNCOMMON', 'RARE', 'EPIC', 'LEGENDARY') not null default 'COMMON', \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`item\` add index \`item_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`character_type\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` enum('MALE', 'FEMALE') not null, \`race\` enum('HUMAN', 'ELF', 'DWARF', 'ORC', 'GOBLIN') not null, \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`character_type\` add index \`character_type_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`character_hair\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` varchar(255) not null default 'MALE', \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`create table \`character_hair\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` varchar(255) not null default 'MALE', \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`character_hair\` add index \`character_hair_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`sprite_action\` (\`id\` varchar(255) not null, \`sprite_id\` varchar(255) not null, \`action\` varchar(255) not null, \`sprites\` json null, \`origin_x\` int not null default 0, \`origin_y\` int not null default 0, \`is_animated\` tinyint(1) not null default false, \`is_looping\` tinyint(1) not null default false, \`frame_width\` int not null default 0, \`frame_height\` int not null default 0, \`frame_rate\` int not null default 0, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
104
migrations/Migration20250127005232.ts
Normal file
104
migrations/Migration20250127005232.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20250127005232 extends Migration {
|
||||
|
||||
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\` numeric(10,2) not null default 0, \`origin_y\` numeric(10,2) not null default 0, \`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, \`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 \`item\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`description\` varchar(255) not null default '', \`item_type\` enum('WEAPON', 'HELMET', 'CHEST', 'LEGS', 'BOOTS', 'GLOVES', 'RING', 'NECKLACE') not null, \`stackable\` tinyint(1) not null default false, \`rarity\` enum('COMMON', 'UNCOMMON', 'RARE', 'EPIC', 'LEGENDARY') not null default 'COMMON', \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`item\` add index \`item_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`character_type\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` enum('MALE', 'FEMALE') not null, \`race\` enum('HUMAN', 'ELF', 'DWARF', 'ORC', 'GOBLIN') not null, \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`character_type\` add index \`character_type_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`character_hair\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`gender\` varchar(255) not null default 'MALE', \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`character_hair\` add index \`character_hair_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`sprite_action\` (\`id\` varchar(255) not null, \`sprite_id\` varchar(255) not null, \`action\` varchar(255) not null, \`sprites\` json null, \`origin_x\` int not null default 0, \`origin_y\` int not null default 0, \`frame_width\` int not null default 0, \`frame_height\` int not null default 0, \`frame_rate\` int not null default 0, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`sprite_action\` add index \`sprite_action_sprite_id_index\`(\`sprite_id\`);`);
|
||||
|
||||
this.addSql(`create table \`tile\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`tags\` json null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
|
||||
this.addSql(`create table \`user\` (\`id\` varchar(255) not null, \`username\` varchar(255) not null, \`email\` varchar(255) not null, \`password\` varchar(255) not null, \`online\` tinyint(1) not null default false, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
this.addSql(`alter table \`user\` add unique \`user_username_unique\`(\`username\`);`);
|
||||
this.addSql(`alter table \`user\` add unique \`user_email_unique\`(\`email\`);`);
|
||||
|
||||
this.addSql(`create table \`password_reset_token\` (\`id\` varchar(255) not null, \`user_id\` varchar(255) not null, \`token\` varchar(255) not null, \`created_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
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(`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(`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 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_hair_id_index\`(\`character_hair_id\`);`);
|
||||
|
||||
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_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(`alter table \`character_item\` add index \`character_item_character_id_index\`(\`character_id\`);`);
|
||||
this.addSql(`alter table \`character_item\` add index \`character_item_item_id_index\`(\`item_id\`);`);
|
||||
|
||||
this.addSql(`create table \`character_equipment\` (\`id\` varchar(255) not null, \`slot\` enum('HEAD', 'BODY', 'ARMS', 'LEGS', 'NECK', 'RING') not null, \`character_id\` varchar(255) not null, \`character_item_id\` varchar(255) not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
|
||||
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(`create table \`world\` (\`date\` datetime not null, \`rain_percentage\` int not null default 0, \`fog_density\` int not null default 0, primary key (\`date\`)) 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 \`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 \`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 \`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 \`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 \`character_type\` add constraint \`character_type_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`);
|
||||
|
||||
this.addSql(`alter table \`character_hair\` add constraint \`character_hair_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`);
|
||||
|
||||
this.addSql(`alter table \`sprite_action\` add constraint \`sprite_action_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`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_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_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_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_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_item_id_foreign\` foreign key (\`character_item_id\`) references \`character_item\` (\`id\`) on update cascade on delete cascade;`);
|
||||
}
|
||||
|
||||
}
|
@ -8,16 +8,15 @@ import serverConfig from './src/application/config'
|
||||
export default defineConfig({
|
||||
extensions: [Migrator],
|
||||
metadataProvider: TsMorphMetadataProvider,
|
||||
entities: ['./src/entities/**/*.js'],
|
||||
entitiesTs: ['./src/entities/**/*.ts'],
|
||||
entities: ['./src/entities/*.js'],
|
||||
entitiesTs: ['./src/entities/*.ts'],
|
||||
driver: MySqlDriver,
|
||||
host: serverConfig.DB_HOST,
|
||||
port: serverConfig.DB_PORT,
|
||||
user: serverConfig.DB_USER,
|
||||
password: serverConfig.DB_PASS,
|
||||
dbName: serverConfig.DB_NAME,
|
||||
debug: serverConfig.ENV !== 'production',
|
||||
// allowGlobalContext: true,
|
||||
debug: false,
|
||||
driverOptions: {
|
||||
allowPublicKeyRetrieval: true
|
||||
},
|
||||
|
622
package-lock.json
generated
622
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,6 @@
|
||||
import { Request, Response } from 'express'
|
||||
import fs from 'fs'
|
||||
|
||||
import { Response } from 'express'
|
||||
|
||||
import Logger, { LoggerType } from '#application/logger'
|
||||
|
||||
@ -19,4 +21,18 @@ export abstract class BaseController {
|
||||
message
|
||||
})
|
||||
}
|
||||
|
||||
protected sendFile(res: Response, filePath: string) {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
this.logger.error(`File not found: ${filePath}`)
|
||||
return this.sendError(res, 'Asset not found', 404)
|
||||
}
|
||||
|
||||
res.sendFile(filePath, (error) => {
|
||||
if (error) {
|
||||
this.logger.error('Error sending file:' + error)
|
||||
this.sendError(res, 'Error downloading the asset', 500)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -5,23 +5,32 @@ import Logger, { LoggerType } from '#application/logger'
|
||||
|
||||
export abstract class BaseEntity {
|
||||
protected readonly logger = Logger.type(LoggerType.ENTITY)
|
||||
protected entityManager?: EntityManager
|
||||
|
||||
private getEntityManager(): EntityManager {
|
||||
return Database.getEntityManager()
|
||||
if (!this.entityManager) {
|
||||
this.entityManager = Database.getORM().em.fork()
|
||||
}
|
||||
return this.entityManager
|
||||
}
|
||||
|
||||
public setEntityManager(entityManager: EntityManager) {
|
||||
this.entityManager = entityManager
|
||||
return this
|
||||
}
|
||||
|
||||
async save(): Promise<this> {
|
||||
return this.execute('persist', 'save entity')
|
||||
}
|
||||
|
||||
async update(): Promise<this> {
|
||||
return this.execute('merge', 'update entity')
|
||||
}
|
||||
|
||||
async delete(): Promise<this> {
|
||||
return this.execute('remove', 'remove entity')
|
||||
}
|
||||
|
||||
async update(): Promise<this> {
|
||||
return this.execute('merge', 'update entity')
|
||||
}
|
||||
|
||||
private async execute(method: 'persist' | 'merge' | 'remove', actionDescription: string): Promise<this> {
|
||||
try {
|
||||
const em = this.getEntityManager()
|
||||
|
@ -14,7 +14,8 @@ export abstract class BaseEvent {
|
||||
) {}
|
||||
|
||||
protected async getCharacter(): Promise<Character | null> {
|
||||
return CharacterRepository.getById(this.socket.characterId!)
|
||||
const characterRepository = new CharacterRepository()
|
||||
return characterRepository.getById(this.socket.characterId!)
|
||||
}
|
||||
|
||||
protected async isCharacterGM(): Promise<boolean> {
|
||||
|
@ -6,8 +6,12 @@ import Logger, { LoggerType } from '#application/logger'
|
||||
|
||||
export abstract class BaseRepository {
|
||||
protected readonly logger = Logger.type(LoggerType.REPOSITORY)
|
||||
private entityManager?: EntityManager
|
||||
|
||||
protected get em(): EntityManager {
|
||||
return Database.getEntityManager()
|
||||
getEntityManager(): EntityManager {
|
||||
if (!this.entityManager) {
|
||||
this.entityManager = Database.getORM().em.fork()
|
||||
}
|
||||
return this.entityManager
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ export class LogReader {
|
||||
})
|
||||
|
||||
stream.on('data', (data) => {
|
||||
process.stdout.write('\r' + `[${filename}]\n${data}`)
|
||||
process.stdout.write('\n> ')
|
||||
console.log(`[${filename}]`)
|
||||
console.log(data.toString()) //
|
||||
})
|
||||
|
||||
currentPosition = newPosition
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { EntityManager } from '@mikro-orm/core'
|
||||
import { MikroORM } from '@mikro-orm/mysql'
|
||||
|
||||
import Logger, { LoggerType } from './logger'
|
||||
@ -10,7 +9,7 @@ class Database {
|
||||
|
||||
public static async initialize(): Promise<void> {
|
||||
try {
|
||||
Database.orm = await MikroORM.init(config)
|
||||
this.orm = await MikroORM.init(config)
|
||||
this.logger.info('Database connection initialized')
|
||||
} catch (error) {
|
||||
this.logger.error(`MikroORM connection failed: ${error}`)
|
||||
@ -18,8 +17,8 @@ class Database {
|
||||
}
|
||||
}
|
||||
|
||||
public static getEntityManager(): EntityManager {
|
||||
return Database.orm.em.fork()
|
||||
public static getORM(): MikroORM {
|
||||
return this.orm
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ export type AssetData = {
|
||||
updatedAt: Date
|
||||
originX?: number
|
||||
originY?: number
|
||||
isAnimated?: boolean
|
||||
frameRate?: number
|
||||
frameWidth?: number
|
||||
frameHeight?: number
|
||||
@ -46,8 +45,11 @@ export type AssetData = {
|
||||
|
||||
export type WorldSettings = {
|
||||
date: Date
|
||||
isRainEnabled: boolean
|
||||
isFogEnabled: boolean
|
||||
weatherState: WeatherState
|
||||
}
|
||||
|
||||
export type WeatherState = {
|
||||
rainPercentage: number
|
||||
fogDensity: number
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,13 @@ import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { CharacterHair } from '#entities/characterHair'
|
||||
import { CharacterType } from '#entities/characterType'
|
||||
import { Map } from '#entities/map'
|
||||
import { MapEffect } from '#entities/mapEffect'
|
||||
import { MapObject } from '#entities/mapObject'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
import { SpriteAction } from '#entities/spriteAction'
|
||||
import { Tile } from '#entities/tile'
|
||||
import { User } from '#entities/user'
|
||||
import { Map } from '#entities/map'
|
||||
import { MapEffect } from '#entities/mapEffect'
|
||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
@ -24,6 +24,10 @@ import MapRepository from '#repositories/mapRepository'
|
||||
// https://mikro-orm.io/docs/seeding
|
||||
|
||||
export default class InitCommand extends BaseCommand {
|
||||
private readonly mapRepository = new MapRepository()
|
||||
private readonly characterTypeRepository = new CharacterTypeRepository()
|
||||
private readonly characterHairRepository = new CharacterHairRepository()
|
||||
|
||||
public async execute(): Promise<void> {
|
||||
// Assets
|
||||
await this.importTiles()
|
||||
@ -85,8 +89,6 @@ export default class InitCommand extends BaseCommand {
|
||||
])
|
||||
.setOriginX(0)
|
||||
.setOriginY(0)
|
||||
.setIsAnimated(false)
|
||||
.setIsLooping(false)
|
||||
.setFrameWidth(64)
|
||||
.setFrameHeight(94)
|
||||
.setFrameRate(0)
|
||||
@ -101,8 +103,6 @@ export default class InitCommand extends BaseCommand {
|
||||
])
|
||||
.setOriginX(0)
|
||||
.setOriginY(0)
|
||||
.setIsAnimated(false)
|
||||
.setIsLooping(false)
|
||||
.setFrameWidth(64)
|
||||
.setFrameHeight(94)
|
||||
.setFrameRate(0)
|
||||
@ -120,8 +120,6 @@ export default class InitCommand extends BaseCommand {
|
||||
])
|
||||
.setOriginX(0)
|
||||
.setOriginY(0)
|
||||
.setIsAnimated(true)
|
||||
.setIsLooping(false)
|
||||
.setFrameWidth(64)
|
||||
.setFrameHeight(94)
|
||||
.setFrameRate(7)
|
||||
@ -139,8 +137,6 @@ export default class InitCommand extends BaseCommand {
|
||||
])
|
||||
.setOriginX(0)
|
||||
.setOriginY(0)
|
||||
.setIsAnimated(true)
|
||||
.setIsLooping(false)
|
||||
.setFrameWidth(64)
|
||||
.setFrameHeight(94)
|
||||
.setFrameRate(7)
|
||||
@ -148,7 +144,14 @@ export default class InitCommand extends BaseCommand {
|
||||
.save()
|
||||
|
||||
const characterType = new CharacterType()
|
||||
await characterType.setId('75b70c78-17f0-44c0-a4fa-15043cb95be0').setName('New character type').setGender(CharacterGender.MALE).setRace(CharacterRace.HUMAN).setIsSelectable(true).setSprite(characterSprite).save()
|
||||
await characterType
|
||||
.setId('75b70c78-17f0-44c0-a4fa-15043cb95be0')
|
||||
.setName('New character type')
|
||||
.setGender(CharacterGender.MALE)
|
||||
.setRace(CharacterRace.HUMAN)
|
||||
.setIsSelectable(true)
|
||||
.setSprite(characterSprite)
|
||||
.save()
|
||||
}
|
||||
|
||||
private async createCharacterHair(): Promise<void> {
|
||||
@ -164,8 +167,6 @@ export default class InitCommand extends BaseCommand {
|
||||
])
|
||||
.setOriginX(0.5)
|
||||
.setOriginY(5.34)
|
||||
.setIsAnimated(false)
|
||||
.setIsLooping(false)
|
||||
.setFrameWidth(64)
|
||||
.setFrameHeight(18)
|
||||
.setFrameRate(0)
|
||||
@ -180,8 +181,6 @@ export default class InitCommand extends BaseCommand {
|
||||
])
|
||||
.setOriginX(0.5)
|
||||
.setOriginY(4.34)
|
||||
.setIsAnimated(false)
|
||||
.setIsLooping(false)
|
||||
.setFrameWidth(64)
|
||||
.setFrameHeight(22)
|
||||
.setFrameRate(0)
|
||||
@ -205,8 +204,6 @@ export default class InitCommand extends BaseCommand {
|
||||
sprites: ['data:image/png;base64,...'],
|
||||
originX: 0,
|
||||
originY: 0,
|
||||
isAnimated: false,
|
||||
isLooping: false,
|
||||
frameWidth: 64,
|
||||
frameHeight: 94,
|
||||
frameRate: 0
|
||||
@ -247,9 +244,9 @@ export default class InitCommand extends BaseCommand {
|
||||
.setUser(user)
|
||||
.setName('root')
|
||||
.setRole('gm')
|
||||
.setMap((await MapRepository.getFirst())!)
|
||||
.setCharacterType((await CharacterTypeRepository.getFirst()) ?? undefined)
|
||||
.setCharacterHair((await CharacterHairRepository.getFirst()) ?? undefined)
|
||||
.setMap((await this.mapRepository.getFirst())!)
|
||||
.setCharacterType(await this.characterTypeRepository.getFirst())
|
||||
.setCharacterHair(await this.characterHairRepository.getFirst())
|
||||
.save()
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
import { BaseCommand } from '#application/base/baseCommand'
|
||||
import MapManager from '#managers/mapManager'
|
||||
|
||||
|
@ -16,13 +16,17 @@ interface AvatarOptions {
|
||||
}
|
||||
|
||||
export class AvatarController extends BaseController {
|
||||
private readonly characterTypeRepository = new CharacterTypeRepository()
|
||||
private readonly characterHairRepository = new CharacterHairRepository()
|
||||
private readonly characterRepository = new CharacterRepository()
|
||||
|
||||
/**
|
||||
* Get avatar by character
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async getByName(req: Request, res: Response) {
|
||||
const character = await CharacterRepository.getByName(req.params.characterName)
|
||||
const character = await this.characterRepository.getByName(req.params.characterName)
|
||||
if (!character?.characterType) {
|
||||
return this.sendError(res, 'Character or character type not found', 404)
|
||||
}
|
||||
@ -53,7 +57,7 @@ export class AvatarController extends BaseController {
|
||||
*/
|
||||
private async generateAvatar(res: Response, options: AvatarOptions) {
|
||||
try {
|
||||
const characterType = await CharacterTypeRepository.getById(options.characterTypeId)
|
||||
const characterType = await this.characterTypeRepository.getById(options.characterTypeId)
|
||||
if (!characterType?.sprite?.id) {
|
||||
return this.sendError(res, 'Character type not found', 404)
|
||||
}
|
||||
@ -70,7 +74,7 @@ export class AvatarController extends BaseController {
|
||||
})
|
||||
|
||||
if (options.characterHairId) {
|
||||
const characterHair = await CharacterHairRepository.getById(options.characterHairId)
|
||||
const characterHair = await this.characterHairRepository.getById(options.characterHairId)
|
||||
if (characterHair?.sprite?.id) {
|
||||
const hairSpritePath = Storage.getPublicPath('sprites', characterHair.sprite.id, 'front.png')
|
||||
if (fs.existsSync(hairSpritePath)) {
|
119
src/controllers/cache.ts
Normal file
119
src/controllers/cache.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import { Request, Response } from 'express'
|
||||
|
||||
import { BaseController } from '#application/base/baseController'
|
||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||
import MapObjectRepository from '#repositories/mapObjectRepository'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
import TileRepository from '#repositories/tileRepository'
|
||||
|
||||
export class CacheController extends BaseController {
|
||||
/**
|
||||
* Serve a list of tiles and send as JSON
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async tiles(req: Request, res: Response) {
|
||||
const items: any[] = []
|
||||
|
||||
const tileRepository = new TileRepository()
|
||||
const tiles = await tileRepository.getAll()
|
||||
|
||||
for (const tile of tiles) {
|
||||
items.push(await tile.cache())
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a list of maps and send as JSON
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async maps(req: Request, res: Response) {
|
||||
const items: any[] = []
|
||||
|
||||
const mapRepository = new MapRepository()
|
||||
const maps = await mapRepository.getAll()
|
||||
|
||||
for (const map of maps) {
|
||||
items.push(await map.cache())
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a list of map objects and send as JSON
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async mapObjects(req: Request, res: Response) {
|
||||
const items: any[] = []
|
||||
|
||||
const mapObjectRepository = new MapObjectRepository()
|
||||
const mapObjects = await mapObjectRepository.getAll()
|
||||
|
||||
for (const mapObject of mapObjects) {
|
||||
items.push(await mapObject.cache())
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a list of character hairs and send as JSON
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async characterHair(req: Request, res: Response) {
|
||||
const items: any[] = []
|
||||
|
||||
const characterHairRepository = new CharacterHairRepository()
|
||||
const characterHairs = await characterHairRepository.getAll()
|
||||
|
||||
for (const characterHair of characterHairs) {
|
||||
items.push(await characterHair.cache())
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a list of character types and send as JSON
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async characterTypes(req: Request, res: Response) {
|
||||
const items: any[] = []
|
||||
|
||||
const characterTypeRepository = new CharacterTypeRepository()
|
||||
const characterTypes = await characterTypeRepository.getAll()
|
||||
|
||||
for (const characterType of characterTypes) {
|
||||
items.push(await characterType.cache())
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a list of sprites and send as JSON
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async sprites(req: Request, res: Response) {
|
||||
const items: any[] = []
|
||||
|
||||
const spriteRepository = new SpriteRepository()
|
||||
const sprites = await spriteRepository.getAll()
|
||||
|
||||
for (const sprite of sprites) {
|
||||
items.push(await sprite.cache())
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, items)
|
||||
}
|
||||
}
|
19
src/controllers/textures.ts
Normal file
19
src/controllers/textures.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Request, Response } from 'express'
|
||||
|
||||
import { BaseController } from '#application/base/baseController'
|
||||
import Storage from '#application/storage'
|
||||
|
||||
export class TexturesController extends BaseController {
|
||||
/**
|
||||
* Download texture
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async download(req: Request, res: Response) {
|
||||
const { type, spriteId, file } = req.params
|
||||
|
||||
const texture = type === 'sprites' && spriteId ? Storage.getPublicPath(type, spriteId, file) : Storage.getPublicPath(type, file)
|
||||
|
||||
this.sendFile(res, texture)
|
||||
}
|
||||
}
|
295
src/entities/base/character.ts
Normal file
295
src/entities/base/character.ts
Normal file
@ -0,0 +1,295 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { CharacterEquipment } from '#entities/characterEquipment'
|
||||
import { CharacterHair } from '#entities/characterHair'
|
||||
import { CharacterItem } from '#entities/characterItem'
|
||||
import { CharacterType } from '#entities/characterType'
|
||||
import { Chat } from '#entities/chat'
|
||||
import { Map } from '#entities/map'
|
||||
import { User } from '#entities/user'
|
||||
|
||||
export class BaseCharacter extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
user!: User
|
||||
|
||||
@Property({ unique: true })
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
online = false
|
||||
|
||||
@Property()
|
||||
role = 'player'
|
||||
|
||||
@OneToMany(() => Chat, (chat) => chat.character)
|
||||
chats = new Collection<Chat>(this)
|
||||
|
||||
// Position - @TODO: Update to spawn point when current map is not found
|
||||
@ManyToOne()
|
||||
map!: Map
|
||||
|
||||
@Property()
|
||||
positionX = 0
|
||||
|
||||
@Property()
|
||||
positionY = 0
|
||||
|
||||
@Property()
|
||||
rotation = 0
|
||||
|
||||
// Customization
|
||||
@ManyToOne({ deleteRule: 'set null' })
|
||||
characterType: CharacterType | null = null
|
||||
|
||||
@ManyToOne({ deleteRule: 'set null' })
|
||||
characterHair: CharacterHair | null = null
|
||||
|
||||
// Inventory
|
||||
@OneToMany({ mappedBy: 'character' })
|
||||
items = new Collection<CharacterItem>(this)
|
||||
|
||||
@OneToMany({ mappedBy: 'character' })
|
||||
equipment = new Collection<CharacterEquipment>(this)
|
||||
|
||||
// Stats
|
||||
@Property()
|
||||
alignment = 50
|
||||
|
||||
@Property()
|
||||
hitpoints = 100
|
||||
|
||||
@Property()
|
||||
mana = 100
|
||||
|
||||
@Property()
|
||||
level = 1
|
||||
|
||||
@Property()
|
||||
experience = 0
|
||||
|
||||
@Property()
|
||||
strength = 10
|
||||
|
||||
@Property()
|
||||
dexterity = 10
|
||||
|
||||
@Property()
|
||||
intelligence = 10
|
||||
|
||||
@Property()
|
||||
wisdom = 10
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setUser(user: User) {
|
||||
this.user = user
|
||||
return this
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.user
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setOnline(online: boolean) {
|
||||
this.online = online
|
||||
return this
|
||||
}
|
||||
|
||||
getOnline() {
|
||||
return this.online
|
||||
}
|
||||
|
||||
setRole(role: string) {
|
||||
this.role = role
|
||||
return this
|
||||
}
|
||||
|
||||
getRole() {
|
||||
return this.role
|
||||
}
|
||||
|
||||
setChats(chats: Collection<Chat>) {
|
||||
this.chats = chats
|
||||
return this
|
||||
}
|
||||
|
||||
getChats() {
|
||||
return this.chats
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setPositionX(positionX: number) {
|
||||
this.positionX = positionX
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionX() {
|
||||
return this.positionX
|
||||
}
|
||||
|
||||
setPositionY(positionY: number) {
|
||||
this.positionY = positionY
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionY() {
|
||||
return this.positionY
|
||||
}
|
||||
|
||||
setRotation(rotation: number) {
|
||||
this.rotation = rotation
|
||||
return this
|
||||
}
|
||||
|
||||
getRotation() {
|
||||
return this.rotation
|
||||
}
|
||||
|
||||
setCharacterType(characterType: CharacterType | null) {
|
||||
this.characterType = characterType
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacterType() {
|
||||
return this.characterType
|
||||
}
|
||||
|
||||
setCharacterHair(characterHair: CharacterHair | null) {
|
||||
this.characterHair = characterHair
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacterHair() {
|
||||
return this.characterHair
|
||||
}
|
||||
|
||||
setItems(items: Collection<CharacterItem>) {
|
||||
this.items = items
|
||||
return this
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.items
|
||||
}
|
||||
|
||||
setEquipment(equipment: Collection<CharacterEquipment>) {
|
||||
this.equipment = equipment
|
||||
return this
|
||||
}
|
||||
|
||||
getEquipment() {
|
||||
return this.equipment
|
||||
}
|
||||
|
||||
setAlignment(alignment: number) {
|
||||
this.alignment = alignment
|
||||
return this
|
||||
}
|
||||
|
||||
getAlignment() {
|
||||
return this.alignment
|
||||
}
|
||||
|
||||
setHitpoints(hitpoints: number) {
|
||||
this.hitpoints = hitpoints
|
||||
return this
|
||||
}
|
||||
|
||||
getHitpoints() {
|
||||
return this.hitpoints
|
||||
}
|
||||
|
||||
setMana(mana: number) {
|
||||
this.mana = mana
|
||||
return this
|
||||
}
|
||||
|
||||
getMana() {
|
||||
return this.mana
|
||||
}
|
||||
|
||||
setLevel(level: number) {
|
||||
this.level = level
|
||||
return this
|
||||
}
|
||||
|
||||
getLevel() {
|
||||
return this.level
|
||||
}
|
||||
|
||||
setExperience(experience: number) {
|
||||
this.experience = experience
|
||||
return this
|
||||
}
|
||||
|
||||
getExperience() {
|
||||
return this.experience
|
||||
}
|
||||
|
||||
setStrength(strength: number) {
|
||||
this.strength = strength
|
||||
return this
|
||||
}
|
||||
|
||||
getStrength() {
|
||||
return this.strength
|
||||
}
|
||||
|
||||
setDexterity(dexterity: number) {
|
||||
this.dexterity = dexterity
|
||||
return this
|
||||
}
|
||||
|
||||
getDexterity() {
|
||||
return this.dexterity
|
||||
}
|
||||
|
||||
setIntelligence(intelligence: number) {
|
||||
this.intelligence = intelligence
|
||||
return this
|
||||
}
|
||||
|
||||
getIntelligence() {
|
||||
return this.intelligence
|
||||
}
|
||||
|
||||
setWisdom(wisdom: number) {
|
||||
this.wisdom = wisdom
|
||||
return this
|
||||
}
|
||||
|
||||
getWisdom() {
|
||||
return this.wisdom
|
||||
}
|
||||
}
|
59
src/entities/base/characterEquipment.ts
Normal file
59
src/entities/base/characterEquipment.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Enum, ManyToOne, PrimaryKey } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { CharacterEquipmentSlotType } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { CharacterItem } from '#entities/characterItem'
|
||||
|
||||
export class BaseCharacterEquipment extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Enum(() => CharacterEquipmentSlotType)
|
||||
slot!: CharacterEquipmentSlotType
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
character!: Character
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
characterItem!: CharacterItem
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setSlot(slot: CharacterEquipmentSlotType) {
|
||||
this.slot = slot
|
||||
return this
|
||||
}
|
||||
|
||||
getSlot() {
|
||||
return this.slot
|
||||
}
|
||||
|
||||
setCharacter(character: Character) {
|
||||
this.character = character
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacter() {
|
||||
return this.character
|
||||
}
|
||||
|
||||
setCharacterItem(characterItem: CharacterItem) {
|
||||
this.characterItem = characterItem
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacterItem() {
|
||||
return this.characterItem
|
||||
}
|
||||
}
|
95
src/entities/base/characterHair.ts
Normal file
95
src/entities/base/characterHair.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { CharacterGender } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
|
||||
export class BaseCharacterHair extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
gender: CharacterGender = CharacterGender.MALE
|
||||
|
||||
@Property()
|
||||
isSelectable = false
|
||||
|
||||
@ManyToOne()
|
||||
sprite?: Sprite
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setGender(gender: CharacterGender) {
|
||||
this.gender = gender
|
||||
return this
|
||||
}
|
||||
|
||||
getGender() {
|
||||
return this.gender
|
||||
}
|
||||
|
||||
setIsSelectable(isSelectable: boolean) {
|
||||
this.isSelectable = isSelectable
|
||||
return this
|
||||
}
|
||||
|
||||
getIsSelectable() {
|
||||
return this.isSelectable
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
59
src/entities/base/characterItem.ts
Normal file
59
src/entities/base/characterItem.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { CharacterEquipment } from '#entities/characterEquipment'
|
||||
import { Item } from '#entities/item'
|
||||
|
||||
export class BaseCharacterItem extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
character!: Character
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
item!: Item
|
||||
|
||||
@Property()
|
||||
quantity!: number
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setCharacter(character: Character) {
|
||||
this.character = character
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacter() {
|
||||
return this.character
|
||||
}
|
||||
|
||||
setItem(item: Item) {
|
||||
this.item = item
|
||||
return this
|
||||
}
|
||||
|
||||
getItem() {
|
||||
return this.item
|
||||
}
|
||||
|
||||
setQuantity(quantity: number) {
|
||||
this.quantity = quantity
|
||||
return this
|
||||
}
|
||||
|
||||
getQuantity() {
|
||||
return this.quantity
|
||||
}
|
||||
}
|
107
src/entities/base/characterType.ts
Normal file
107
src/entities/base/characterType.ts
Normal file
@ -0,0 +1,107 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { CharacterGender, CharacterRace } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
|
||||
export class BaseCharacterType extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Enum(() => CharacterGender)
|
||||
gender!: CharacterGender
|
||||
|
||||
@Enum(() => CharacterRace)
|
||||
race!: CharacterRace
|
||||
|
||||
@Property()
|
||||
isSelectable = false
|
||||
|
||||
@ManyToOne()
|
||||
sprite?: Sprite
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setGender(gender: CharacterGender) {
|
||||
this.gender = gender
|
||||
return this
|
||||
}
|
||||
|
||||
getGender() {
|
||||
return this.gender
|
||||
}
|
||||
|
||||
setRace(race: CharacterRace) {
|
||||
this.race = race
|
||||
return this
|
||||
}
|
||||
|
||||
getRace() {
|
||||
return this.race
|
||||
}
|
||||
|
||||
setIsSelectable(isSelectable: boolean) {
|
||||
this.isSelectable = isSelectable
|
||||
return this
|
||||
}
|
||||
|
||||
getIsSelectable() {
|
||||
return this.isSelectable
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
70
src/entities/base/chat.ts
Normal file
70
src/entities/base/chat.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { Map } from '#entities/map'
|
||||
|
||||
export class BaseChat extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
character!: Character
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@Property()
|
||||
message!: string
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setCharacter(character: Character) {
|
||||
this.character = character
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacter() {
|
||||
return this.character
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setMessage(message: string) {
|
||||
this.message = message
|
||||
return this
|
||||
}
|
||||
|
||||
getMessage() {
|
||||
return this.message
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
}
|
119
src/entities/base/item.ts
Normal file
119
src/entities/base/item.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { ItemType, ItemRarity } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { CharacterItem } from '#entities/characterItem'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
|
||||
export class BaseItem extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
description: string = ''
|
||||
|
||||
@Enum(() => ItemType)
|
||||
itemType!: ItemType
|
||||
|
||||
@Property()
|
||||
stackable = false
|
||||
|
||||
@Enum(() => ItemRarity)
|
||||
rarity: ItemRarity = ItemRarity.COMMON
|
||||
|
||||
@ManyToOne(() => Sprite)
|
||||
sprite?: Sprite
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setDescription(description: string) {
|
||||
this.description = description
|
||||
return this
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return this.description
|
||||
}
|
||||
|
||||
setItemType(itemType: ItemType) {
|
||||
this.itemType = itemType
|
||||
return this
|
||||
}
|
||||
|
||||
getItemType() {
|
||||
return this.itemType
|
||||
}
|
||||
|
||||
setStackable(stackable: boolean) {
|
||||
this.stackable = stackable
|
||||
return this
|
||||
}
|
||||
|
||||
getStackable() {
|
||||
return this.stackable
|
||||
}
|
||||
|
||||
setRarity(rarity: ItemRarity) {
|
||||
this.rarity = rarity
|
||||
return this
|
||||
}
|
||||
|
||||
getRarity() {
|
||||
return this.rarity
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
143
src/entities/base/map.ts
Normal file
143
src/entities/base/map.ts
Normal file
@ -0,0 +1,143 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { MapEffect } from '#entities/mapEffect'
|
||||
import { MapEventTile } from '#entities/mapEventTile'
|
||||
import { PlacedMapObject } from '#entities/placedMapObject'
|
||||
|
||||
export class BaseMap extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
width = 10
|
||||
|
||||
@Property()
|
||||
height = 10
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
tiles?: any
|
||||
|
||||
@Property()
|
||||
pvp = false
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
@OneToMany(() => MapEffect, (effect) => effect.map, { orphanRemoval: true })
|
||||
mapEffects = new Collection<MapEffect>(this)
|
||||
|
||||
@OneToMany(() => MapEventTile, (tile) => tile.map, { orphanRemoval: true })
|
||||
mapEventTiles = new Collection<MapEventTile>(this)
|
||||
|
||||
@OneToMany(() => PlacedMapObject, (placedMapObject) => placedMapObject.map, { orphanRemoval: true })
|
||||
placedMapObjects = new Collection<PlacedMapObject>(this)
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setWidth(width: number) {
|
||||
this.width = width
|
||||
return this
|
||||
}
|
||||
|
||||
getWidth() {
|
||||
return this.width
|
||||
}
|
||||
|
||||
setHeight(height: number) {
|
||||
this.height = height
|
||||
return this
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
return this.height
|
||||
}
|
||||
|
||||
setTiles(tiles: any) {
|
||||
this.tiles = tiles
|
||||
return this
|
||||
}
|
||||
|
||||
getTiles() {
|
||||
return this.tiles
|
||||
}
|
||||
|
||||
setPvp(pvp: boolean) {
|
||||
this.pvp = pvp
|
||||
return this
|
||||
}
|
||||
|
||||
getPvp() {
|
||||
return this.pvp
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
|
||||
setMapEffects(mapEffects: Collection<MapEffect>) {
|
||||
this.mapEffects = mapEffects
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEffects() {
|
||||
return this.mapEffects
|
||||
}
|
||||
|
||||
setMapEventTiles(mapEventTiles: Collection<MapEventTile>) {
|
||||
this.mapEventTiles = mapEventTiles
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEventTiles() {
|
||||
return this.mapEventTiles
|
||||
}
|
||||
|
||||
setPlacedMapObjects(placedMapObjects: Collection<PlacedMapObject>) {
|
||||
this.placedMapObjects = placedMapObjects
|
||||
return this
|
||||
}
|
||||
|
||||
getPlacedMapObjects() {
|
||||
return this.placedMapObjects
|
||||
}
|
||||
}
|
57
src/entities/base/mapEffect.ts
Normal file
57
src/entities/base/mapEffect.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Map } from '#entities/map'
|
||||
|
||||
export class BaseMapEffect extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@Property()
|
||||
effect!: string
|
||||
|
||||
@Property()
|
||||
strength!: number
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setEffect(effect: string) {
|
||||
this.effect = effect
|
||||
return this
|
||||
}
|
||||
|
||||
getEffect() {
|
||||
return this.effect
|
||||
}
|
||||
|
||||
setStrength(strength: number) {
|
||||
this.strength = strength
|
||||
return this
|
||||
}
|
||||
|
||||
getStrength() {
|
||||
return this.strength
|
||||
}
|
||||
}
|
83
src/entities/base/mapEventTile.ts
Normal file
83
src/entities/base/mapEventTile.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, Enum, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { MapEventTileType } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { Map } from '#entities/map'
|
||||
import { MapEventTileTeleport } from '#entities/mapEventTileTeleport'
|
||||
|
||||
export class BaseMapEventTile extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@Enum(() => MapEventTileType)
|
||||
type!: MapEventTileType
|
||||
|
||||
@Property()
|
||||
positionX!: number
|
||||
|
||||
@Property()
|
||||
positionY!: number
|
||||
|
||||
@OneToOne(() => MapEventTileTeleport, (teleport) => teleport.mapEventTile, { eager: true })
|
||||
teleport?: MapEventTileTeleport
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setType(type: MapEventTileType) {
|
||||
this.type = type
|
||||
return this
|
||||
}
|
||||
|
||||
getType() {
|
||||
return this.type
|
||||
}
|
||||
|
||||
setPositionX(positionX: number) {
|
||||
this.positionX = positionX
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionX() {
|
||||
return this.positionX
|
||||
}
|
||||
|
||||
setPositionY(positionY: number) {
|
||||
this.positionY = positionY
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionY() {
|
||||
return this.positionY
|
||||
}
|
||||
|
||||
setTeleport(teleport: MapEventTileTeleport) {
|
||||
this.teleport = teleport
|
||||
return this
|
||||
}
|
||||
|
||||
getTeleport() {
|
||||
return this.teleport
|
||||
}
|
||||
}
|
82
src/entities/base/mapEventTileTeleport.ts
Normal file
82
src/entities/base/mapEventTileTeleport.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Map } from '#entities/map'
|
||||
import { MapEventTile } from '#entities/mapEventTile'
|
||||
|
||||
export class BaseMapEventTileTeleport extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@OneToOne({ deleteRule: 'cascade' })
|
||||
mapEventTile!: MapEventTile
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade', eager: true })
|
||||
toMap!: Map
|
||||
|
||||
@Property()
|
||||
toRotation!: number
|
||||
|
||||
@Property()
|
||||
toPositionX!: number
|
||||
|
||||
@Property()
|
||||
toPositionY!: number
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMapEventTile(mapEventTile: MapEventTile) {
|
||||
this.mapEventTile = mapEventTile
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEventTile() {
|
||||
return this.mapEventTile
|
||||
}
|
||||
|
||||
setToMap(toMap: Map) {
|
||||
this.toMap = toMap
|
||||
return this
|
||||
}
|
||||
|
||||
getToMap() {
|
||||
return this.toMap
|
||||
}
|
||||
|
||||
setToRotation(toRotation: number) {
|
||||
this.toRotation = toRotation
|
||||
return this
|
||||
}
|
||||
|
||||
getToRotation() {
|
||||
return this.toRotation
|
||||
}
|
||||
|
||||
setToPositionX(toPositionX: number) {
|
||||
this.toPositionX = toPositionX
|
||||
return this
|
||||
}
|
||||
|
||||
getToPositionX() {
|
||||
return this.toPositionX
|
||||
}
|
||||
|
||||
setToPositionY(toPositionY: number) {
|
||||
this.toPositionY = toPositionY
|
||||
return this
|
||||
}
|
||||
|
||||
getToPositionY() {
|
||||
return this.toPositionY
|
||||
}
|
||||
}
|
128
src/entities/base/mapObject.ts
Normal file
128
src/entities/base/mapObject.ts
Normal file
@ -0,0 +1,128 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
|
||||
export class BaseMapObject extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
tags?: any
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 2 })
|
||||
originX = 0
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 2 })
|
||||
originY = 0
|
||||
|
||||
@Property()
|
||||
frameRate = 0
|
||||
|
||||
@Property()
|
||||
frameWidth = 0
|
||||
|
||||
@Property()
|
||||
frameHeight = 0
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setTags(tags: any) {
|
||||
this.tags = tags
|
||||
return this
|
||||
}
|
||||
|
||||
getTags() {
|
||||
return this.tags
|
||||
}
|
||||
|
||||
setOriginX(originX: number) {
|
||||
this.originX = originX
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginX() {
|
||||
return this.originX
|
||||
}
|
||||
|
||||
setOriginY(originY: number) {
|
||||
this.originY = originY
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginY() {
|
||||
return this.originY
|
||||
}
|
||||
|
||||
setFrameRate(frameRate: number) {
|
||||
this.frameRate = frameRate
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameRate() {
|
||||
return this.frameRate
|
||||
}
|
||||
|
||||
setFrameWidth(frameWidth: number) {
|
||||
this.frameWidth = frameWidth
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameWidth() {
|
||||
return this.frameWidth
|
||||
}
|
||||
|
||||
setFrameHeight(frameHeight: number) {
|
||||
this.frameHeight = frameHeight
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameHeight() {
|
||||
return this.frameHeight
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
57
src/entities/base/passwordResetToken.ts
Normal file
57
src/entities/base/passwordResetToken.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { User } from '#entities/user'
|
||||
|
||||
export class BasePasswordResetToken extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
user!: User
|
||||
|
||||
@Property({ unique: true })
|
||||
token!: string
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setUser(user: User) {
|
||||
this.user = user
|
||||
return this
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.user
|
||||
}
|
||||
|
||||
setToken(token: string) {
|
||||
this.token = token
|
||||
return this
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this.token
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
}
|
84
src/entities/base/placedMapObject.ts
Normal file
84
src/entities/base/placedMapObject.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Map } from '#entities/map'
|
||||
import { MapObject } from '#entities/mapObject'
|
||||
|
||||
//@TODO : Rename mapObject
|
||||
|
||||
export class BasePlacedMapObject extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade', eager: true })
|
||||
mapObject!: MapObject
|
||||
|
||||
@Property()
|
||||
isRotated = false
|
||||
|
||||
@Property()
|
||||
positionX = 0
|
||||
|
||||
@Property()
|
||||
positionY = 0
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setMapObject(mapObject: MapObject) {
|
||||
this.mapObject = mapObject
|
||||
return this
|
||||
}
|
||||
|
||||
getMapObject() {
|
||||
return this.mapObject
|
||||
}
|
||||
|
||||
setIsRotated(isRotated: boolean) {
|
||||
this.isRotated = isRotated
|
||||
return this
|
||||
}
|
||||
|
||||
getIsRotated() {
|
||||
return this.isRotated
|
||||
}
|
||||
|
||||
setPositionX(positionX: number) {
|
||||
this.positionX = positionX
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionX() {
|
||||
return this.positionX
|
||||
}
|
||||
|
||||
setPositionY(positionY: number) {
|
||||
this.positionY = positionY
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionY() {
|
||||
return this.positionY
|
||||
}
|
||||
}
|
69
src/entities/base/sprite.ts
Normal file
69
src/entities/base/sprite.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { SpriteAction } from '#entities/spriteAction'
|
||||
|
||||
export class BaseSprite extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@OneToMany(() => SpriteAction, (action) => action.sprite)
|
||||
spriteActions = new Collection<SpriteAction>(this)
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setSpriteActions(spriteActions: Collection<SpriteAction>) {
|
||||
this.spriteActions = spriteActions
|
||||
return this
|
||||
}
|
||||
|
||||
getSpriteActions() {
|
||||
return this.spriteActions
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
117
src/entities/base/spriteAction.ts
Normal file
117
src/entities/base/spriteAction.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
|
||||
export class BaseSpriteAction extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
sprite!: Sprite
|
||||
|
||||
@Property()
|
||||
action!: string
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
sprites?: string[]
|
||||
|
||||
@Property()
|
||||
originX = 0
|
||||
|
||||
@Property()
|
||||
originY = 0
|
||||
|
||||
@Property()
|
||||
frameWidth = 0
|
||||
|
||||
@Property()
|
||||
frameHeight = 0
|
||||
|
||||
@Property()
|
||||
frameRate = 0
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setAction(action: string) {
|
||||
this.action = action
|
||||
return this
|
||||
}
|
||||
|
||||
getAction() {
|
||||
return this.action
|
||||
}
|
||||
|
||||
setSprites(sprites: string[]) {
|
||||
this.sprites = sprites
|
||||
return this
|
||||
}
|
||||
|
||||
getSprites() {
|
||||
return this.sprites
|
||||
}
|
||||
|
||||
setOriginX(originX: number) {
|
||||
this.originX = originX
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginX() {
|
||||
return this.originX
|
||||
}
|
||||
|
||||
setOriginY(originY: number) {
|
||||
this.originY = originY
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginY() {
|
||||
return this.originY
|
||||
}
|
||||
|
||||
setFrameWidth(frameWidth: number) {
|
||||
this.frameWidth = frameWidth
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameWidth() {
|
||||
return this.frameWidth
|
||||
}
|
||||
|
||||
setFrameHeight(frameHeight: number) {
|
||||
this.frameHeight = frameHeight
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameHeight() {
|
||||
return this.frameHeight
|
||||
}
|
||||
|
||||
setFrameRate(frameRate: number) {
|
||||
this.frameRate = frameRate
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameRate() {
|
||||
return this.frameRate
|
||||
}
|
||||
}
|
68
src/entities/base/tile.ts
Normal file
68
src/entities/base/tile.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
|
||||
export class BaseTile extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
tags?: any
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setTags(tags: any) {
|
||||
this.tags = tags
|
||||
return this
|
||||
}
|
||||
|
||||
getTags() {
|
||||
return this.tags
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
96
src/entities/base/user.ts
Normal file
96
src/entities/base/user.ts
Normal file
@ -0,0 +1,96 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { PasswordResetToken } from '#entities/passwordResetToken'
|
||||
|
||||
export class BaseUser extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property({ unique: true })
|
||||
username!: string
|
||||
|
||||
@Property({ unique: true })
|
||||
email!: string
|
||||
|
||||
@Property()
|
||||
password!: string
|
||||
|
||||
@Property()
|
||||
online = false
|
||||
|
||||
@OneToMany(() => Character, (character) => character.user)
|
||||
characters = new Collection<Character>(this)
|
||||
|
||||
@OneToMany(() => PasswordResetToken, (token) => token.user)
|
||||
passwordResetTokens = new Collection<PasswordResetToken>(this)
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setUsername(username: string) {
|
||||
this.username = username
|
||||
return this
|
||||
}
|
||||
|
||||
getUsername() {
|
||||
return this.username
|
||||
}
|
||||
|
||||
setEmail(email: string) {
|
||||
this.email = email
|
||||
return this
|
||||
}
|
||||
|
||||
getEmail() {
|
||||
return this.email
|
||||
}
|
||||
|
||||
setPassword(password: string) {
|
||||
this.password = bcrypt.hashSync(password, 10)
|
||||
return this
|
||||
}
|
||||
|
||||
getPassword() {
|
||||
return this.password
|
||||
}
|
||||
|
||||
setOnline(online: boolean) {
|
||||
this.online = online
|
||||
return this
|
||||
}
|
||||
|
||||
getOnline() {
|
||||
return this.online
|
||||
}
|
||||
|
||||
setCharacters(characters: Collection<Character>) {
|
||||
this.characters = characters
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacters() {
|
||||
return this.characters
|
||||
}
|
||||
|
||||
setPasswordResetTokens(passwordResetTokens: Collection<PasswordResetToken>) {
|
||||
this.passwordResetTokens = passwordResetTokens
|
||||
return this
|
||||
}
|
||||
|
||||
getPasswordResetTokens() {
|
||||
return this.passwordResetTokens
|
||||
return this
|
||||
}
|
||||
}
|
41
src/entities/base/world.ts
Normal file
41
src/entities/base/world.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
|
||||
export class BaseWorld extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
date = new Date()
|
||||
|
||||
@Property()
|
||||
rainPercentage = 0
|
||||
|
||||
@Property()
|
||||
fogDensity = 0
|
||||
|
||||
setDate(date: Date) {
|
||||
this.date = date
|
||||
return this
|
||||
}
|
||||
|
||||
getDate() {
|
||||
return this.date
|
||||
}
|
||||
|
||||
setRainPercentage(rainPercentage: number) {
|
||||
this.rainPercentage = rainPercentage
|
||||
return this
|
||||
}
|
||||
|
||||
getRainPercentage() {
|
||||
return this.rainPercentage
|
||||
}
|
||||
|
||||
setFogDensity(fogDensity: number) {
|
||||
this.fogDensity = fogDensity
|
||||
return this
|
||||
}
|
||||
|
||||
getFogDensity() {
|
||||
return this.fogDensity
|
||||
}
|
||||
}
|
@ -1,297 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { CharacterEquipment } from './characterEquipment'
|
||||
import { CharacterHair } from './characterHair'
|
||||
import { CharacterItem } from './characterItem'
|
||||
import { CharacterType } from './characterType'
|
||||
import { Chat } from './chat'
|
||||
import { User } from './user'
|
||||
import { Map } from './map'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseCharacter } from '#entities/base/character'
|
||||
|
||||
@Entity()
|
||||
export class Character extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
user!: User
|
||||
|
||||
@Property({ unique: true })
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
online = false
|
||||
|
||||
@Property()
|
||||
role = 'player'
|
||||
|
||||
@OneToMany(() => Chat, (chat) => chat.character)
|
||||
chats = new Collection<Chat>(this)
|
||||
|
||||
// Position
|
||||
@ManyToOne()
|
||||
map!: Map // @TODO: Update to spawn point when current map is not found
|
||||
|
||||
@Property()
|
||||
positionX = 0
|
||||
|
||||
@Property()
|
||||
positionY = 0
|
||||
|
||||
@Property()
|
||||
rotation = 0
|
||||
|
||||
// Customization
|
||||
@ManyToOne({ deleteRule: 'set null' })
|
||||
characterType?: CharacterType | null | undefined
|
||||
|
||||
@ManyToOne({ deleteRule: 'set null' })
|
||||
characterHair?: CharacterHair | null | undefined
|
||||
|
||||
// Inventory
|
||||
@OneToMany({ mappedBy: 'character' })
|
||||
items = new Collection<CharacterItem>(this)
|
||||
|
||||
@OneToMany({ mappedBy: 'character' })
|
||||
equipment = new Collection<CharacterEquipment>(this)
|
||||
|
||||
// Stats
|
||||
@Property()
|
||||
alignment = 50
|
||||
|
||||
@Property()
|
||||
hitpoints = 100
|
||||
|
||||
@Property()
|
||||
mana = 100
|
||||
|
||||
@Property()
|
||||
level = 1
|
||||
|
||||
@Property()
|
||||
experience = 0
|
||||
|
||||
@Property()
|
||||
strength = 10
|
||||
|
||||
@Property()
|
||||
dexterity = 10
|
||||
|
||||
@Property()
|
||||
intelligence = 10
|
||||
|
||||
@Property()
|
||||
wisdom = 10
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setUser(user: User) {
|
||||
this.user = user
|
||||
return this
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.user
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setOnline(online: boolean) {
|
||||
this.online = online
|
||||
return this
|
||||
}
|
||||
|
||||
getOnline() {
|
||||
return this.online
|
||||
}
|
||||
|
||||
setRole(role: string) {
|
||||
this.role = role
|
||||
return this
|
||||
}
|
||||
|
||||
getRole() {
|
||||
return this.role
|
||||
}
|
||||
|
||||
setChats(chats: Collection<Chat>) {
|
||||
this.chats = chats
|
||||
return this
|
||||
}
|
||||
|
||||
getChats() {
|
||||
return this.chats
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setPositionX(positionX: number) {
|
||||
this.positionX = positionX
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionX() {
|
||||
return this.positionX
|
||||
}
|
||||
|
||||
setPositionY(positionY: number) {
|
||||
this.positionY = positionY
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionY() {
|
||||
return this.positionY
|
||||
}
|
||||
|
||||
setRotation(rotation: number) {
|
||||
this.rotation = rotation
|
||||
return this
|
||||
}
|
||||
|
||||
getRotation() {
|
||||
return this.rotation
|
||||
}
|
||||
|
||||
setCharacterType(characterType: CharacterType | null | undefined) {
|
||||
this.characterType = characterType
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacterType() {
|
||||
return this.characterType
|
||||
}
|
||||
|
||||
setCharacterHair(characterHair: CharacterHair | null | undefined) {
|
||||
this.characterHair = characterHair
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacterHair() {
|
||||
return this.characterHair
|
||||
}
|
||||
|
||||
setItems(items: Collection<CharacterItem>) {
|
||||
this.items = items
|
||||
return this
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.items
|
||||
}
|
||||
|
||||
setEquipment(equipment: Collection<CharacterEquipment>) {
|
||||
this.equipment = equipment
|
||||
return this
|
||||
}
|
||||
|
||||
getEquipment() {
|
||||
return this.equipment
|
||||
}
|
||||
|
||||
setAlignment(alignment: number) {
|
||||
this.alignment = alignment
|
||||
return this
|
||||
}
|
||||
|
||||
getAlignment() {
|
||||
return this.alignment
|
||||
}
|
||||
|
||||
setHitpoints(hitpoints: number) {
|
||||
this.hitpoints = hitpoints
|
||||
return this
|
||||
}
|
||||
|
||||
getHitpoints() {
|
||||
return this.hitpoints
|
||||
}
|
||||
|
||||
setMana(mana: number) {
|
||||
this.mana = mana
|
||||
return this
|
||||
}
|
||||
|
||||
getMana() {
|
||||
return this.mana
|
||||
}
|
||||
|
||||
setLevel(level: number) {
|
||||
this.level = level
|
||||
return this
|
||||
}
|
||||
|
||||
getLevel() {
|
||||
return this.level
|
||||
}
|
||||
|
||||
setExperience(experience: number) {
|
||||
this.experience = experience
|
||||
return this
|
||||
}
|
||||
|
||||
getExperience() {
|
||||
return this.experience
|
||||
}
|
||||
|
||||
setStrength(strength: number) {
|
||||
this.strength = strength
|
||||
return this
|
||||
}
|
||||
|
||||
getStrength() {
|
||||
return this.strength
|
||||
}
|
||||
|
||||
setDexterity(dexterity: number) {
|
||||
this.dexterity = dexterity
|
||||
return this
|
||||
}
|
||||
|
||||
getDexterity() {
|
||||
return this.dexterity
|
||||
}
|
||||
|
||||
setIntelligence(intelligence: number) {
|
||||
this.intelligence = intelligence
|
||||
return this
|
||||
}
|
||||
|
||||
getIntelligence() {
|
||||
return this.intelligence
|
||||
}
|
||||
|
||||
setWisdom(wisdom: number) {
|
||||
this.wisdom = wisdom
|
||||
return this
|
||||
}
|
||||
|
||||
getWisdom() {
|
||||
return this.wisdom
|
||||
}
|
||||
}
|
||||
export class Character extends BaseCharacter {}
|
||||
|
@ -1,61 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, Enum, ManyToOne, PrimaryKey } from '@mikro-orm/core'
|
||||
|
||||
import { Character } from './character'
|
||||
import { CharacterItem } from './characterItem'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { CharacterEquipmentSlotType } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseCharacterEquipment } from '#entities/base/characterEquipment'
|
||||
|
||||
@Entity()
|
||||
export class CharacterEquipment extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Enum(() => CharacterEquipmentSlotType)
|
||||
slot!: CharacterEquipmentSlotType
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
character!: Character
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
characterItem!: CharacterItem
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setSlot(slot: CharacterEquipmentSlotType) {
|
||||
this.slot = slot
|
||||
return this
|
||||
}
|
||||
|
||||
getSlot() {
|
||||
return this.slot
|
||||
}
|
||||
|
||||
setCharacter(character: Character) {
|
||||
this.character = character
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacter() {
|
||||
return this.character
|
||||
}
|
||||
|
||||
setCharacterItem(characterItem: CharacterItem) {
|
||||
this.characterItem = characterItem
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacterItem() {
|
||||
return this.characterItem
|
||||
}
|
||||
}
|
||||
export class CharacterEquipment extends BaseCharacterEquipment {}
|
||||
|
@ -1,73 +1,15 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Character } from './character'
|
||||
import { Sprite } from './sprite'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { CharacterGender } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseCharacterHair } from '#entities/base/characterHair'
|
||||
|
||||
@Entity()
|
||||
export class CharacterHair extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
gender: CharacterGender = CharacterGender.MALE
|
||||
|
||||
@Property()
|
||||
isSelectable = false
|
||||
|
||||
@ManyToOne({ nullable: true })
|
||||
sprite?: Sprite
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setGender(gender: CharacterGender) {
|
||||
this.gender = gender
|
||||
return this
|
||||
}
|
||||
|
||||
getGender() {
|
||||
return this.gender
|
||||
}
|
||||
|
||||
setIsSelectable(isSelectable: boolean) {
|
||||
this.isSelectable = isSelectable
|
||||
return this
|
||||
}
|
||||
|
||||
getIsSelectable() {
|
||||
return this.isSelectable
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
export class CharacterHair extends BaseCharacterHair {
|
||||
public async cache() {
|
||||
try {
|
||||
return this
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Character } from './character'
|
||||
import { CharacterEquipment } from './characterEquipment'
|
||||
import { Item } from './item'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseCharacterItem } from '#entities/base/characterItem'
|
||||
|
||||
@Entity()
|
||||
export class CharacterItem extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
character!: Character
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
item!: Item
|
||||
|
||||
@Property()
|
||||
quantity!: number
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setCharacter(character: Character) {
|
||||
this.character = character
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacter() {
|
||||
return this.character
|
||||
}
|
||||
|
||||
setItem(item: Item) {
|
||||
this.item = item
|
||||
return this
|
||||
}
|
||||
|
||||
getItem() {
|
||||
return this.item
|
||||
}
|
||||
|
||||
setQuantity(quantity: number) {
|
||||
this.quantity = quantity
|
||||
return this
|
||||
}
|
||||
|
||||
getQuantity() {
|
||||
return this.quantity
|
||||
}
|
||||
}
|
||||
export class CharacterItem extends BaseCharacterItem {}
|
||||
|
@ -1,109 +1,15 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Character } from './character'
|
||||
import { Sprite } from './sprite'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { CharacterGender, CharacterRace } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseCharacterType } from '#entities/base/characterType'
|
||||
|
||||
@Entity()
|
||||
export class CharacterType extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Enum(() => CharacterGender)
|
||||
gender!: CharacterGender
|
||||
|
||||
@Enum(() => CharacterRace)
|
||||
race!: CharacterRace
|
||||
|
||||
@Property()
|
||||
isSelectable = false
|
||||
|
||||
@ManyToOne({ nullable: true })
|
||||
sprite?: Sprite
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setGender(gender: CharacterGender) {
|
||||
this.gender = gender
|
||||
return this
|
||||
}
|
||||
|
||||
getGender() {
|
||||
return this.gender
|
||||
}
|
||||
|
||||
setRace(race: CharacterRace) {
|
||||
this.race = race
|
||||
return this
|
||||
}
|
||||
|
||||
getRace() {
|
||||
return this.race
|
||||
}
|
||||
|
||||
setIsSelectable(isSelectable: boolean) {
|
||||
this.isSelectable = isSelectable
|
||||
return this
|
||||
}
|
||||
|
||||
getIsSelectable() {
|
||||
return this.isSelectable
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
export class CharacterType extends BaseCharacterType {
|
||||
public async cache() {
|
||||
try {
|
||||
return this
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,72 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Character } from './character'
|
||||
import { Map } from './map'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseChat } from '#entities/base/chat'
|
||||
|
||||
@Entity()
|
||||
export class Chat extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
character!: Character
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@Property()
|
||||
message!: string
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setCharacter(character: Character) {
|
||||
this.character = character
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacter() {
|
||||
return this.character
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setMessage(message: string) {
|
||||
this.message = message
|
||||
return this
|
||||
}
|
||||
|
||||
getMessage() {
|
||||
return this.message
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
}
|
||||
export class Chat extends BaseChat {}
|
||||
|
@ -1,121 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { CharacterItem } from './characterItem'
|
||||
import { Sprite } from './sprite'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { ItemType, ItemRarity } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseItem } from '#entities/base/item'
|
||||
|
||||
@Entity()
|
||||
export class Item extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
description?: string
|
||||
|
||||
@Enum(() => ItemType)
|
||||
itemType!: ItemType
|
||||
|
||||
@Property()
|
||||
stackable = false
|
||||
|
||||
@Enum(() => ItemRarity)
|
||||
rarity: ItemRarity = ItemRarity.COMMON
|
||||
|
||||
@ManyToOne(() => Sprite, { nullable: true })
|
||||
sprite?: Sprite
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setDescription(description: string) {
|
||||
this.description = description
|
||||
return this
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return this.description
|
||||
}
|
||||
|
||||
setItemType(itemType: ItemType) {
|
||||
this.itemType = itemType
|
||||
return this
|
||||
}
|
||||
|
||||
getItemType() {
|
||||
return this.itemType
|
||||
}
|
||||
|
||||
setStackable(stackable: boolean) {
|
||||
this.stackable = stackable
|
||||
return this
|
||||
}
|
||||
|
||||
getStackable() {
|
||||
return this.stackable
|
||||
}
|
||||
|
||||
setRarity(rarity: ItemRarity) {
|
||||
this.rarity = rarity
|
||||
return this
|
||||
}
|
||||
|
||||
getRarity() {
|
||||
return this.rarity
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
}
|
||||
export class Item extends BaseItem {}
|
||||
|
@ -1,184 +1,39 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
import { BaseMap } from '#entities/base/map'
|
||||
|
||||
import { Character } from './character'
|
||||
import { Chat } from './chat'
|
||||
import { MapEffect } from './mapEffect'
|
||||
import { MapEventTile } from './mapEventTile'
|
||||
import { MapEventTileTeleport } from './mapEventTileTeleport'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { PlacedMapObject } from '#entities/placedMapObject'
|
||||
export type MapCacheT = ReturnType<Map['cache']> | {}
|
||||
|
||||
@Entity()
|
||||
export class Map extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
export class Map extends BaseMap {
|
||||
public async cache() {
|
||||
try {
|
||||
await this.getPlacedMapObjects().load()
|
||||
await this.getMapEffects().load()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property()
|
||||
width = 10
|
||||
|
||||
@Property()
|
||||
height = 10
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
tiles?: any
|
||||
|
||||
@Property()
|
||||
pvp = false
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
@OneToMany(() => MapEffect, (effect) => effect.map)
|
||||
mapEffects = new Collection<MapEffect>(this)
|
||||
|
||||
@OneToMany(() => MapEventTile, (tile) => tile.map)
|
||||
mapEventTiles = new Collection<MapEventTile>(this)
|
||||
|
||||
@OneToMany(() => MapEventTileTeleport, (teleport) => teleport.toMap)
|
||||
mapEventTileTeleports = new Collection<MapEventTileTeleport>(this)
|
||||
|
||||
@OneToMany(() => PlacedMapObject, (object) => object.map)
|
||||
placedMapObjects = new Collection<PlacedMapObject>(this)
|
||||
|
||||
@OneToMany(() => Character, (character) => character.map)
|
||||
characters = new Collection<Character>(this)
|
||||
|
||||
@OneToMany(() => Chat, (chat) => chat.map)
|
||||
chats = new Collection<Chat>(this)
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setWidth(width: number) {
|
||||
this.width = width
|
||||
return this
|
||||
}
|
||||
|
||||
getWidth() {
|
||||
return this.width
|
||||
}
|
||||
|
||||
setHeight(height: number) {
|
||||
this.height = height
|
||||
return this
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
return this.height
|
||||
}
|
||||
|
||||
setTiles(tiles: any) {
|
||||
this.tiles = tiles
|
||||
return this
|
||||
}
|
||||
|
||||
getTiles() {
|
||||
return this.tiles
|
||||
}
|
||||
|
||||
setPvp(pvp: boolean) {
|
||||
this.pvp = pvp
|
||||
return this
|
||||
}
|
||||
|
||||
getPvp() {
|
||||
return this.pvp
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
}
|
||||
|
||||
setMapEffects(mapEffects: Collection<MapEffect>) {
|
||||
this.mapEffects = mapEffects
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEffects() {
|
||||
return this.mapEffects
|
||||
}
|
||||
|
||||
setMapEventTiles(mapEventTiles: Collection<MapEventTile>) {
|
||||
this.mapEventTiles = mapEventTiles
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEventTiles() {
|
||||
return this.mapEventTiles
|
||||
}
|
||||
|
||||
setMapEventTileTeleports(mapEventTileTeleports: Collection<MapEventTileTeleport>) {
|
||||
this.mapEventTileTeleports = mapEventTileTeleports
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEventTileTeleports() {
|
||||
return this.mapEventTileTeleports
|
||||
}
|
||||
|
||||
setPlacedMapObjects(placedMapObjects: Collection<PlacedMapObject>) {
|
||||
this.placedMapObjects = placedMapObjects
|
||||
return this
|
||||
}
|
||||
|
||||
getPlacedMapObjects() {
|
||||
return this.placedMapObjects
|
||||
}
|
||||
|
||||
setCharacters(characters: Collection<Character>) {
|
||||
this.characters = characters
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacters() {
|
||||
return this.characters
|
||||
}
|
||||
|
||||
setChats(chats: Collection<Chat>) {
|
||||
this.chats = chats
|
||||
return this
|
||||
}
|
||||
|
||||
getChats() {
|
||||
return this.chats
|
||||
return {
|
||||
id: this.getId(),
|
||||
name: this.getName(),
|
||||
width: this.getWidth(),
|
||||
height: this.getHeight(),
|
||||
tiles: this.getTiles(),
|
||||
pvp: this.getPvp(),
|
||||
updatedAt: this.getUpdatedAt(),
|
||||
placedMapObjects: this.getPlacedMapObjects().map((placedMapObject) => ({
|
||||
id: placedMapObject.getId(),
|
||||
mapObject: placedMapObject.getMapObject().getId(),
|
||||
isRotated: placedMapObject.getIsRotated(),
|
||||
positionX: placedMapObject.getPositionX(),
|
||||
positionY: placedMapObject.getPositionY()
|
||||
})),
|
||||
mapEffects: this.getMapEffects().map((mapEffect) => ({
|
||||
effect: mapEffect.getEffect(),
|
||||
strength: mapEffect.getStrength()
|
||||
}))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Map } from './map'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseMapEffect } from '#entities/base/mapEffect'
|
||||
|
||||
@Entity()
|
||||
export class MapEffect extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@Property()
|
||||
effect!: string
|
||||
|
||||
@Property()
|
||||
strength!: number
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setEffect(effect: string) {
|
||||
this.effect = effect
|
||||
return this
|
||||
}
|
||||
|
||||
getEffect() {
|
||||
return this.effect
|
||||
}
|
||||
|
||||
setStrength(strength: number) {
|
||||
this.strength = strength
|
||||
return this
|
||||
}
|
||||
|
||||
getStrength() {
|
||||
return this.strength
|
||||
}
|
||||
}
|
||||
export class MapEffect extends BaseMapEffect {}
|
||||
|
@ -1,85 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, Enum, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Map } from './map'
|
||||
import { MapEventTileTeleport } from './mapEventTileTeleport'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { MapEventTileType } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseMapEventTile } from '#entities/base/mapEventTile'
|
||||
|
||||
@Entity()
|
||||
export class MapEventTile extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@Enum(() => MapEventTileType)
|
||||
type!: MapEventTileType
|
||||
|
||||
@Property()
|
||||
positionX!: number
|
||||
|
||||
@Property()
|
||||
positionY!: number
|
||||
|
||||
@OneToOne(() => MapEventTileTeleport, (teleport) => teleport.mapEventTile)
|
||||
teleport?: MapEventTileTeleport
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setType(type: MapEventTileType) {
|
||||
this.type = type
|
||||
return this
|
||||
}
|
||||
|
||||
getType() {
|
||||
return this.type
|
||||
}
|
||||
|
||||
setPositionX(positionX: number) {
|
||||
this.positionX = positionX
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionX() {
|
||||
return this.positionX
|
||||
}
|
||||
|
||||
setPositionY(positionY: number) {
|
||||
this.positionY = positionY
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionY() {
|
||||
return this.positionY
|
||||
}
|
||||
|
||||
setTeleport(teleport: MapEventTileTeleport) {
|
||||
this.teleport = teleport
|
||||
return this
|
||||
}
|
||||
|
||||
getTeleport() {
|
||||
return this.teleport
|
||||
}
|
||||
}
|
||||
export class MapEventTile extends BaseMapEventTile {}
|
||||
|
@ -1,84 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, ManyToOne, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Map } from './map'
|
||||
import { MapEventTile } from './mapEventTile'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseMapEventTileTeleport } from '#entities/base/mapEventTileTeleport'
|
||||
|
||||
@Entity()
|
||||
export class MapEventTileTeleport extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@OneToOne({ deleteRule: 'cascade' })
|
||||
mapEventTile!: MapEventTile
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
toMap!: Map
|
||||
|
||||
@Property()
|
||||
toRotation!: number
|
||||
|
||||
@Property()
|
||||
toPositionX!: number
|
||||
|
||||
@Property()
|
||||
toPositionY!: number
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMapEventTile(mapEventTile: MapEventTile) {
|
||||
this.mapEventTile = mapEventTile
|
||||
return this
|
||||
}
|
||||
|
||||
getMapEventTile() {
|
||||
return this.mapEventTile
|
||||
}
|
||||
|
||||
setToMap(toMap: Map) {
|
||||
this.toMap = toMap
|
||||
return this
|
||||
}
|
||||
|
||||
getToMap() {
|
||||
return this.toMap
|
||||
}
|
||||
|
||||
setToRotation(toRotation: number) {
|
||||
this.toRotation = toRotation
|
||||
return this
|
||||
}
|
||||
|
||||
getToRotation() {
|
||||
return this.toRotation
|
||||
}
|
||||
|
||||
setToPositionX(toPositionX: number) {
|
||||
this.toPositionX = toPositionX
|
||||
return this
|
||||
}
|
||||
|
||||
getToPositionX() {
|
||||
return this.toPositionX
|
||||
}
|
||||
|
||||
setToPositionY(toPositionY: number) {
|
||||
this.toPositionY = toPositionY
|
||||
return this
|
||||
}
|
||||
|
||||
getToPositionY() {
|
||||
return this.toPositionY
|
||||
}
|
||||
}
|
||||
export class MapEventTileTeleport extends BaseMapEventTileTeleport {}
|
||||
|
@ -1,141 +1,15 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseMapObject } from '#entities/base/mapObject'
|
||||
|
||||
@Entity()
|
||||
export class MapObject extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
tags?: any
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 2 })
|
||||
originX = 0
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 2 })
|
||||
originY = 0
|
||||
|
||||
@Property()
|
||||
isAnimated = false
|
||||
|
||||
@Property()
|
||||
frameRate = 0
|
||||
|
||||
@Property()
|
||||
frameWidth = 0
|
||||
|
||||
@Property()
|
||||
frameHeight = 0
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setTags(tags: any) {
|
||||
this.tags = tags
|
||||
return this
|
||||
}
|
||||
|
||||
getTags() {
|
||||
return this.tags
|
||||
}
|
||||
|
||||
setOriginX(originX: number) {
|
||||
this.originX = originX
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginX() {
|
||||
return this.originX
|
||||
}
|
||||
|
||||
setOriginY(originY: number) {
|
||||
this.originY = originY
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginY() {
|
||||
return this.originY
|
||||
}
|
||||
|
||||
setIsAnimated(isAnimated: boolean) {
|
||||
this.isAnimated = isAnimated
|
||||
return this
|
||||
}
|
||||
|
||||
getIsAnimated() {
|
||||
return this.isAnimated
|
||||
}
|
||||
|
||||
setFrameRate(frameRate: number) {
|
||||
this.frameRate = frameRate
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameRate() {
|
||||
return this.frameRate
|
||||
}
|
||||
|
||||
setFrameWidth(frameWidth: number) {
|
||||
this.frameWidth = frameWidth
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameWidth() {
|
||||
return this.frameWidth
|
||||
}
|
||||
|
||||
setFrameHeight(frameHeight: number) {
|
||||
this.frameHeight = frameHeight
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameHeight() {
|
||||
return this.frameHeight
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
export class MapObject extends BaseMapObject {
|
||||
public async cache() {
|
||||
try {
|
||||
return this
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { User } from './user'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BasePasswordResetToken } from '#entities/base/passwordResetToken'
|
||||
|
||||
@Entity()
|
||||
export class PasswordResetToken extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
user!: User
|
||||
|
||||
@Property({ unique: true })
|
||||
token!: string
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setUser(user: User) {
|
||||
this.user = user
|
||||
return this
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.user
|
||||
}
|
||||
|
||||
setToken(token: string) {
|
||||
this.token = token
|
||||
return this
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this.token
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
}
|
||||
export class PasswordResetToken extends BasePasswordResetToken {}
|
||||
|
@ -1,97 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
import { BasePlacedMapObject } from '#entities/base/placedMapObject'
|
||||
|
||||
import { Map } from './map'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { MapObject } from '#entities/mapObject'
|
||||
|
||||
//@TODO : Rename mapObject
|
||||
@Entity()
|
||||
export class PlacedMapObject extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
map!: Map
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
mapObject!: MapObject
|
||||
|
||||
@Property()
|
||||
depth = 0
|
||||
|
||||
@Property()
|
||||
isRotated = false
|
||||
|
||||
@Property()
|
||||
positionX = 0
|
||||
|
||||
@Property()
|
||||
positionY = 0
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setMap(map: Map) {
|
||||
this.map = map
|
||||
return this
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
}
|
||||
|
||||
setMapObject(mapObject: MapObject) {
|
||||
this.mapObject = mapObject
|
||||
return this
|
||||
}
|
||||
|
||||
getMapObject() {
|
||||
return this.mapObject
|
||||
}
|
||||
|
||||
setDepth(depth: number) {
|
||||
this.depth = depth
|
||||
return this
|
||||
}
|
||||
|
||||
getDepth() {
|
||||
return this.depth
|
||||
}
|
||||
|
||||
setIsRotated(isRotated: boolean) {
|
||||
this.isRotated = isRotated
|
||||
return this
|
||||
}
|
||||
|
||||
getIsRotated() {
|
||||
return this.isRotated
|
||||
}
|
||||
|
||||
setPositionX(positionX: number) {
|
||||
this.positionX = positionX
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionX() {
|
||||
return this.positionX
|
||||
}
|
||||
|
||||
setPositionY(positionY: number) {
|
||||
this.positionY = positionY
|
||||
return this
|
||||
}
|
||||
|
||||
getPositionY() {
|
||||
return this.positionY
|
||||
}
|
||||
}
|
||||
export class PlacedMapObject extends BasePlacedMapObject {}
|
||||
|
@ -1,71 +1,32 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { SpriteAction } from './spriteAction'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseSprite } from '#entities/base/sprite'
|
||||
|
||||
@Entity()
|
||||
export class Sprite extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
export class Sprite extends BaseSprite {
|
||||
public async cache() {
|
||||
await this.getSpriteActions().load()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@OneToMany(() => SpriteAction, (action) => action.sprite)
|
||||
spriteActions = new Collection<SpriteAction>(this)
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setSpriteActions(spriteActions: Collection<SpriteAction>) {
|
||||
this.spriteActions = spriteActions
|
||||
return this
|
||||
}
|
||||
|
||||
getSpriteActions() {
|
||||
return this.spriteActions
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
try {
|
||||
return {
|
||||
id: this.getId(),
|
||||
name: this.getName(),
|
||||
createdAt: this.getCreatedAt(),
|
||||
updatedAt: this.getUpdatedAt(),
|
||||
spriteActions: this.getSpriteActions().map((spriteAction) => ({
|
||||
id: spriteAction.getId(),
|
||||
action: spriteAction.getAction(),
|
||||
originX: spriteAction.getOriginX(),
|
||||
originY: spriteAction.getOriginY(),
|
||||
frameWidth: spriteAction.getFrameWidth(),
|
||||
frameHeight: spriteAction.getFrameHeight(),
|
||||
frameRate: spriteAction.getFrameRate(),
|
||||
frameCount: spriteAction.getSprites()?.length
|
||||
}))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,143 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { Sprite } from './sprite'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseSpriteAction } from '#entities/base/spriteAction'
|
||||
|
||||
@Entity()
|
||||
export class SpriteAction extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@ManyToOne({ deleteRule: 'cascade' })
|
||||
sprite!: Sprite
|
||||
|
||||
@Property()
|
||||
action!: string
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
sprites?: string[]
|
||||
|
||||
@Property()
|
||||
originX = 0
|
||||
|
||||
@Property()
|
||||
originY = 0
|
||||
|
||||
@Property()
|
||||
isAnimated = false
|
||||
|
||||
@Property()
|
||||
isLooping = false
|
||||
|
||||
@Property()
|
||||
frameWidth = 0
|
||||
|
||||
@Property()
|
||||
frameHeight = 0
|
||||
|
||||
@Property()
|
||||
frameRate = 0
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setSprite(sprite: Sprite) {
|
||||
this.sprite = sprite
|
||||
return this
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return this.sprite
|
||||
}
|
||||
|
||||
setAction(action: string) {
|
||||
this.action = action
|
||||
return this
|
||||
}
|
||||
|
||||
getAction() {
|
||||
return this.action
|
||||
}
|
||||
|
||||
setSprites(sprites: string[]) {
|
||||
this.sprites = sprites
|
||||
return this
|
||||
}
|
||||
|
||||
getSprites() {
|
||||
return this.sprites
|
||||
}
|
||||
|
||||
setOriginX(originX: number) {
|
||||
this.originX = originX
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginX() {
|
||||
return this.originX
|
||||
}
|
||||
|
||||
setOriginY(originY: number) {
|
||||
this.originY = originY
|
||||
return this
|
||||
}
|
||||
|
||||
getOriginY() {
|
||||
return this.originY
|
||||
}
|
||||
|
||||
setIsAnimated(isAnimated: boolean) {
|
||||
this.isAnimated = isAnimated
|
||||
return this
|
||||
}
|
||||
|
||||
getIsAnimated() {
|
||||
return this.isAnimated
|
||||
}
|
||||
|
||||
setIsLooping(isLooping: boolean) {
|
||||
this.isLooping = isLooping
|
||||
return this
|
||||
}
|
||||
|
||||
getIsLooping() {
|
||||
return this.isLooping
|
||||
}
|
||||
|
||||
setFrameWidth(frameWidth: number) {
|
||||
this.frameWidth = frameWidth
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameWidth() {
|
||||
return this.frameWidth
|
||||
}
|
||||
|
||||
setFrameHeight(frameHeight: number) {
|
||||
this.frameHeight = frameHeight
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameHeight() {
|
||||
return this.frameHeight
|
||||
}
|
||||
|
||||
setFrameRate(frameRate: number) {
|
||||
this.frameRate = frameRate
|
||||
return this
|
||||
}
|
||||
|
||||
getFrameRate() {
|
||||
return this.frameRate
|
||||
}
|
||||
}
|
||||
export class SpriteAction extends BaseSpriteAction {}
|
||||
|
@ -1,69 +1,15 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseTile } from '#entities/base/tile'
|
||||
|
||||
@Entity()
|
||||
export class Tile extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property()
|
||||
name!: string
|
||||
|
||||
@Property({ type: 'json', nullable: true })
|
||||
tags?: any
|
||||
|
||||
@Property()
|
||||
createdAt = new Date()
|
||||
|
||||
@Property()
|
||||
updatedAt = new Date()
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name
|
||||
}
|
||||
|
||||
setTags(tags: any) {
|
||||
this.tags = tags
|
||||
return this
|
||||
}
|
||||
|
||||
getTags() {
|
||||
return this.tags
|
||||
}
|
||||
|
||||
setCreatedAt(createdAt: Date) {
|
||||
this.createdAt = createdAt
|
||||
return this
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
return this.createdAt
|
||||
}
|
||||
|
||||
setUpdatedAt(updatedAt: Date) {
|
||||
this.updatedAt = updatedAt
|
||||
return this
|
||||
}
|
||||
|
||||
getUpdatedAt() {
|
||||
return this.updatedAt
|
||||
export class Tile extends BaseTile {
|
||||
public async cache() {
|
||||
try {
|
||||
return this
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,98 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
import { Character } from './character'
|
||||
import { PasswordResetToken } from './passwordResetToken'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseUser } from '#entities/base/user'
|
||||
|
||||
@Entity()
|
||||
export class User extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
id = randomUUID()
|
||||
|
||||
@Property({ unique: true })
|
||||
username!: string
|
||||
|
||||
@Property({ unique: true })
|
||||
email!: string
|
||||
|
||||
@Property()
|
||||
password!: string
|
||||
|
||||
@Property()
|
||||
online = false
|
||||
|
||||
@OneToMany(() => Character, (character) => character.user)
|
||||
characters = new Collection<Character>(this)
|
||||
|
||||
@OneToMany(() => PasswordResetToken, (token) => token.user)
|
||||
passwordResetTokens = new Collection<PasswordResetToken>(this)
|
||||
|
||||
setId(id: UUID) {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.id
|
||||
}
|
||||
|
||||
setUsername(username: string) {
|
||||
this.username = username
|
||||
return this
|
||||
}
|
||||
|
||||
getUsername() {
|
||||
return this.username
|
||||
}
|
||||
|
||||
setEmail(email: string) {
|
||||
this.email = email
|
||||
return this
|
||||
}
|
||||
|
||||
getEmail() {
|
||||
return this.email
|
||||
}
|
||||
|
||||
setPassword(password: string) {
|
||||
this.password = bcrypt.hashSync(password, 10)
|
||||
return this
|
||||
}
|
||||
|
||||
getPassword() {
|
||||
return this.password
|
||||
}
|
||||
|
||||
setOnline(online: boolean) {
|
||||
this.online = online
|
||||
return this
|
||||
}
|
||||
|
||||
getOnline() {
|
||||
return this.online
|
||||
}
|
||||
|
||||
setCharacters(characters: Collection<Character>) {
|
||||
this.characters = characters
|
||||
return this
|
||||
}
|
||||
|
||||
getCharacters() {
|
||||
return this.characters
|
||||
}
|
||||
|
||||
setPasswordResetTokens(passwordResetTokens: Collection<PasswordResetToken>) {
|
||||
this.passwordResetTokens = passwordResetTokens
|
||||
return this
|
||||
}
|
||||
|
||||
getPasswordResetTokens() {
|
||||
return this.passwordResetTokens
|
||||
return this
|
||||
}
|
||||
}
|
||||
export class User extends BaseUser {}
|
||||
|
@ -1,66 +1,6 @@
|
||||
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
|
||||
import { Entity } from '@mikro-orm/core'
|
||||
|
||||
import { BaseEntity } from '#application/base/baseEntity'
|
||||
import { BaseWorld } from '#entities/base/world'
|
||||
|
||||
@Entity()
|
||||
export class World extends BaseEntity {
|
||||
@PrimaryKey()
|
||||
date = new Date()
|
||||
|
||||
@Property()
|
||||
isRainEnabled = false
|
||||
|
||||
@Property()
|
||||
rainPercentage = 0
|
||||
|
||||
@Property()
|
||||
isFogEnabled = false
|
||||
|
||||
@Property()
|
||||
fogDensity = 0
|
||||
|
||||
setDate(date: Date) {
|
||||
this.date = date
|
||||
return this
|
||||
}
|
||||
|
||||
getDate() {
|
||||
return this.date
|
||||
}
|
||||
|
||||
setIsRainEnabled(isRainEnabled: boolean) {
|
||||
this.isRainEnabled = isRainEnabled
|
||||
return this
|
||||
}
|
||||
|
||||
getIsRainEnabled() {
|
||||
return this.isRainEnabled
|
||||
}
|
||||
|
||||
setRainPercentage(rainPercentage: number) {
|
||||
this.rainPercentage = rainPercentage
|
||||
return this
|
||||
}
|
||||
|
||||
getRainPercentage() {
|
||||
return this.rainPercentage
|
||||
}
|
||||
|
||||
setIsFogEnabled(isFogEnabled: boolean) {
|
||||
this.isFogEnabled = isFogEnabled
|
||||
return this
|
||||
}
|
||||
|
||||
getIsFogEnabled() {
|
||||
return this.isFogEnabled
|
||||
}
|
||||
|
||||
setFogDensity(fogDensity: number) {
|
||||
this.fogDensity = fogDensity
|
||||
return this
|
||||
}
|
||||
|
||||
getFogDensity() {
|
||||
return this.fogDensity
|
||||
}
|
||||
}
|
||||
export class World extends BaseWorld {}
|
||||
|
@ -1,23 +0,0 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import Database from '#application/database'
|
||||
import { CharacterHair } from '#entities/characterHair'
|
||||
import characterHairRepository from '#repositories/characterHairRepository'
|
||||
|
||||
interface IPayload {}
|
||||
|
||||
export default class characterHairListEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('character:hair:list', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: CharacterHair[]) => void): Promise<void> {
|
||||
try {
|
||||
const items: CharacterHair[] = await characterHairRepository.getAllSelectable()
|
||||
await Database.getEntityManager().populate(items, ['sprite'])
|
||||
return callback(items)
|
||||
} catch (error) {
|
||||
this.logger.error('character:hair:list error', error)
|
||||
return callback([])
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,9 @@ interface CharacterConnectPayload {
|
||||
}
|
||||
|
||||
export default class CharacterConnectEvent extends BaseEvent {
|
||||
private readonly characterHairRepository = new CharacterHairRepository()
|
||||
private readonly characterRepository = new CharacterRepository()
|
||||
|
||||
public listen(): void {
|
||||
this.socket.on('character:connect', this.handleEvent.bind(this))
|
||||
}
|
||||
@ -22,7 +25,7 @@ export default class CharacterConnectEvent extends BaseEvent {
|
||||
return
|
||||
}
|
||||
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, data.characterId)
|
||||
const character = await this.characterRepository.getByUserAndId(this.socket.userId!, data.characterId)
|
||||
|
||||
if (!character) {
|
||||
this.emitError('Character not found or does not belong to this user')
|
||||
@ -34,8 +37,8 @@ export default class CharacterConnectEvent extends BaseEvent {
|
||||
|
||||
// Set character hair
|
||||
if (data.characterHairId !== undefined && data.characterHairId !== null) {
|
||||
const characterHair = await CharacterHairRepository.getById(data.characterHairId)
|
||||
await character.setCharacterHair(characterHair).update()
|
||||
const characterHair = await this.characterHairRepository.getById(data.characterHairId)
|
||||
await character.setCharacterHair(characterHair).save()
|
||||
}
|
||||
|
||||
// Emit character connect event
|
||||
@ -58,7 +61,7 @@ export default class CharacterConnectEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async checkForActiveCharacters(): Promise<boolean> {
|
||||
const characters = await CharacterRepository.getByUserId(this.socket.userId!)
|
||||
const characters = await this.characterRepository.getByUserId(this.socket.userId!)
|
||||
return characters?.some((char) => MapManager.getCharacterById(char.id)) ?? false
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { ZCharacterCreate } from '#application/zodTypes'
|
||||
import { Character } from '#entities/character'
|
||||
import CharacterRepository from '#repositories/characterRepository'
|
||||
import UserRepository from '#repositories/userRepository'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
import UserRepository from '#repositories/userRepository'
|
||||
|
||||
export default class CharacterCreateEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
@ -17,27 +17,31 @@ export default class CharacterCreateEvent extends BaseEvent {
|
||||
try {
|
||||
data = ZCharacterCreate.parse(data)
|
||||
|
||||
const user = await UserRepository.getById(this.socket.userId!)
|
||||
const userRepository = new UserRepository()
|
||||
const characterRepository = new CharacterRepository()
|
||||
const mapRepository = new MapRepository()
|
||||
|
||||
const user = await userRepository.getById(this.socket.userId!)
|
||||
|
||||
if (!user) {
|
||||
return this.socket.emit('notification', { message: 'User not found' })
|
||||
}
|
||||
|
||||
// Check if character name already exists
|
||||
const characterExists = await CharacterRepository.getByName(data.name)
|
||||
const characterExists = await characterRepository.getByName(data.name)
|
||||
|
||||
if (characterExists) {
|
||||
return this.socket.emit('notification', { message: 'Character name already exists' })
|
||||
}
|
||||
|
||||
let characters: Character[] = await CharacterRepository.getByUserId(user.getId())
|
||||
let characters: Character[] = await characterRepository.getByUserId(user.getId())
|
||||
|
||||
if (characters.length >= 4) {
|
||||
return this.socket.emit('notification', { message: 'You can only have 4 characters' })
|
||||
}
|
||||
|
||||
// @TODO: Change to default location
|
||||
const map = await MapRepository.getFirst()
|
||||
const map = await mapRepository.getFirst()
|
||||
|
||||
const newCharacter = new Character()
|
||||
await newCharacter.setName(data.name).setUser(user).setMap(map!).save()
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { UUID } from '#application/types'
|
||||
import { Character } from '#entities/character'
|
||||
import { Map } from '#entities/map'
|
||||
import CharacterRepository from '#repositories/characterRepository'
|
||||
|
||||
type TypePayload = {
|
||||
@ -19,8 +18,9 @@ export default class CharacterDeleteEvent extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: TypePayload, callback: (response: TypeResponse) => void): Promise<any> {
|
||||
try {
|
||||
await (await CharacterRepository.getByUserAndId(this.socket.userId!, data.characterId))?.delete()
|
||||
const characters: Character[] = await CharacterRepository.getByUserId(this.socket.userId!)
|
||||
const characterRepository = new CharacterRepository()
|
||||
await (await characterRepository.getByUserAndId(this.socket.userId!, data.characterId))?.delete()
|
||||
const characters: Character[] = await characterRepository.getByUserId(this.socket.userId!)
|
||||
|
||||
this.socket.emit('character:list', characters)
|
||||
} catch (error: any) {
|
||||
|
@ -9,7 +9,9 @@ export default class CharacterListEvent extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: any): Promise<void> {
|
||||
try {
|
||||
let characters: Character[] = await CharacterRepository.getByUserId(this.socket.userId!, ['characterType', 'characterHair'])
|
||||
const characterRepository = new CharacterRepository()
|
||||
let characters: Character[] = await characterRepository.getByUserId(this.socket.userId!)
|
||||
|
||||
this.socket.emit('character:list', characters)
|
||||
} catch (error: any) {
|
||||
this.logger.error('character:list error', error.message)
|
||||
|
@ -13,22 +13,11 @@ export default class AlertCommandEvent extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
if (!ChatService.isCommand(data.message, 'alert')) {
|
||||
return
|
||||
}
|
||||
// Check if command is alert
|
||||
if (!ChatService.isCommand(data.message, 'alert')) return
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
this.logger.error('chat:alert_command error', 'Character not found')
|
||||
return callback(false)
|
||||
}
|
||||
|
||||
// Check if the user is the GM
|
||||
if (character.role !== 'gm') {
|
||||
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||
return callback(false)
|
||||
}
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const args = ChatService.getArgs('alert', data.message)
|
||||
|
||||
|
@ -14,22 +14,11 @@ export default class SetTimeCommand extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
if (!ChatService.isCommand(data.message, 'time')) {
|
||||
return
|
||||
}
|
||||
// Check if command is time
|
||||
if (!ChatService.isCommand(data.message, 'time')) return
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
this.logger.error('chat:alert_command error', 'Character not found')
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the user is the GM
|
||||
if (character.role !== 'gm') {
|
||||
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||
return
|
||||
}
|
||||
// Check if character exists and is GM
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
// Get arguments
|
||||
const args = ChatService.getArgs('time', data.message)
|
||||
|
@ -16,21 +16,15 @@ export default class TeleportCommandEvent extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: TypePayload, callback: (response: boolean) => void) {
|
||||
try {
|
||||
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||
if (!mapCharacter) {
|
||||
this.logger.error('chat:message error', 'Character not found')
|
||||
return
|
||||
}
|
||||
|
||||
const character = mapCharacter.character
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if command is teleport
|
||||
if (!ChatService.isCommand(data.message, 'teleport')) return
|
||||
|
||||
// Check if character exists and is GM
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const character = await this.getCharacter()
|
||||
if (!character) return
|
||||
|
||||
const args = ChatService.getArgs('teleport', data.message)
|
||||
|
||||
if (!args || args.length === 0 || args.length > 3) {
|
||||
@ -53,7 +47,8 @@ export default class TeleportCommandEvent extends BaseEvent {
|
||||
return
|
||||
}
|
||||
|
||||
const map = await MapRepository.getById(mapId)
|
||||
const mapRepository = new MapRepository()
|
||||
const map = await mapRepository.getById(mapId)
|
||||
if (!map) {
|
||||
this.socket.emit('notification', {
|
||||
title: 'Server message',
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import WeatherManager from '#managers/weatherManager'
|
||||
import CharacterRepository from '#repositories/characterRepository'
|
||||
import ChatService from '#services/chatService'
|
||||
|
||||
type TypePayload = {
|
||||
@ -14,24 +13,16 @@ export default class ToggleFogCommand extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
if (!ChatService.isCommand(data.message, 'fog')) {
|
||||
return
|
||||
}
|
||||
// Check if command is fog
|
||||
if (!ChatService.isCommand(data.message, 'fog')) return
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
this.logger.error('chat:alert_command error', 'Character not found')
|
||||
return
|
||||
}
|
||||
// Check if character exists and is GM
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
// Check if the user is the GM
|
||||
if (character.role !== 'gm') {
|
||||
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||
return
|
||||
}
|
||||
const args = ChatService.getArgs('fog', data.message)
|
||||
|
||||
await WeatherManager.toggleFog()
|
||||
await WeatherManager.setFogValue(args![0] ? Number(args![0]) : null);
|
||||
callback(true)
|
||||
} catch (error: any) {
|
||||
this.logger.error('command error', error.message)
|
||||
callback(false)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import WeatherManager from '#managers/weatherManager'
|
||||
import CharacterRepository from '#repositories/characterRepository'
|
||||
import ChatService from '#services/chatService'
|
||||
|
||||
type TypePayload = {
|
||||
@ -14,24 +13,16 @@ export default class ToggleRainCommand extends BaseEvent {
|
||||
|
||||
private async handleEvent(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
if (!ChatService.isCommand(data.message, 'rain')) {
|
||||
return
|
||||
}
|
||||
// Check if command is rain
|
||||
if (!ChatService.isCommand(data.message, 'rain')) return
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
this.logger.error('chat:alert_command error', 'Character not found')
|
||||
return
|
||||
}
|
||||
// Check if character exists and is GM
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
// Check if the user is the GM
|
||||
if (character.role !== 'gm') {
|
||||
this.logger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||
return
|
||||
}
|
||||
let args = ChatService.getArgs('rain', data.message)
|
||||
|
||||
await WeatherManager.toggleRain()
|
||||
await WeatherManager.setRainValue(args![0] ? Number(args![0]) : null);
|
||||
callback(true)
|
||||
} catch (error: any) {
|
||||
this.logger.error('command error', error.message)
|
||||
callback(false)
|
||||
|
@ -26,7 +26,8 @@ export default class ChatMessageEvent extends BaseEvent {
|
||||
|
||||
const character = mapCharacter.character
|
||||
|
||||
const map = await MapRepository.getById(character.map.id)
|
||||
const mapRepository = new MapRepository()
|
||||
const map = await mapRepository.getById(character.map.id)
|
||||
if (!map) {
|
||||
this.logger.error('chat:message error', 'Map not found')
|
||||
return callback(false)
|
||||
|
@ -1,28 +1,22 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { CharacterHair } from '#entities/characterHair'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
|
||||
export default class CharacterHairCreateEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('gm:characterHair:create', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: undefined, callback: (response: boolean, characterType?: any) => void): Promise<void> {
|
||||
private async handleEvent(data: undefined, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
const character = await characterRepository.getById(this.socket.characterId!)
|
||||
if (!character) return callback(false)
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const newCharacterHair = new CharacterHair()
|
||||
await newCharacterHair.setName('New hair').save()
|
||||
|
||||
callback(true, newCharacterHair)
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
console.error('Error creating character hair:', error)
|
||||
callback(false)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||
import { UUID } from '#application/types'
|
||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||
|
||||
interface IPayload {
|
||||
id: UUID
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { CharacterHair } from '#entities/characterHair'
|
||||
import characterHairRepository from '#repositories/characterHairRepository'
|
||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||
|
||||
interface IPayload {}
|
||||
|
||||
@ -13,7 +13,10 @@ export default class characterHairListEvent extends BaseEvent {
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const characterHairRepository = new CharacterHairRepository()
|
||||
const items = await characterHairRepository.getAll()
|
||||
await characterHairRepository.getEntityManager().populate(items, ['sprite'])
|
||||
|
||||
return callback(items)
|
||||
} catch (error) {
|
||||
this.logger.error('gm:characterHair:list error', error)
|
||||
|
@ -2,7 +2,6 @@ import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { CharacterGender } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import CharacterHairRepository from '#repositories/characterHairRepository'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
|
||||
type Payload = {
|
||||
@ -22,14 +21,16 @@ export default class CharacterHairUpdateEvent extends BaseEvent {
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const sprite = await SpriteRepository.getById(data.spriteId)
|
||||
const characterHair = await CharacterHairRepository.getById(data.id)
|
||||
const spriteRepository = new SpriteRepository()
|
||||
const sprite = await spriteRepository.getById(data.spriteId)
|
||||
if (!sprite) return callback(false)
|
||||
|
||||
if (!characterHair) {
|
||||
return callback(false)
|
||||
}
|
||||
const characterHairRepository = new CharacterHairRepository()
|
||||
const characterHair = await characterHairRepository.getById(data.id)
|
||||
if (!characterHair) return callback(false)
|
||||
|
||||
await characterHair.setName(data.name).setGender(data.gender).setIsSelectable(data.isSelectable).setSprite(sprite).setUpdatedAt(new Date()).save()
|
||||
|
||||
await characterHair.setName(data.name).setGender(data.gender).setIsSelectable(data.isSelectable).setSprite(sprite!).update()
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
this.logger.error(`Error updating character hair: ${error instanceof Error ? error.message : String(error)}`)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { UUID } from '#application/types'
|
||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
|
||||
interface IPayload {
|
||||
id: UUID
|
||||
@ -15,7 +15,8 @@ export default class CharacterTypeDeleteEvent extends BaseEvent {
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const characterType = await CharacterTypeRepository.getById(data.id)
|
||||
const characterTypeRepository = new CharacterTypeRepository()
|
||||
const characterType = await characterTypeRepository.getById(data.id)
|
||||
if (!characterType) return callback(false)
|
||||
|
||||
await characterType.delete()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { CharacterType } from '#entities/characterType'
|
||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||
|
||||
interface IPayload {}
|
||||
|
||||
@ -13,7 +13,10 @@ export default class CharacterTypeListEvent extends BaseEvent {
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const items = await CharacterTypeRepository.getAll()
|
||||
const characterTypeRepository = new CharacterTypeRepository()
|
||||
const items = await characterTypeRepository.getAll()
|
||||
await characterTypeRepository.getEntityManager().populate(items, ['sprite'])
|
||||
|
||||
return callback(items)
|
||||
} catch (error) {
|
||||
this.logger.error('gm:characterType:list error', error)
|
||||
|
@ -1,53 +1,41 @@
|
||||
import { CharacterGender, CharacterRace } from '@prisma/client'
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
import prisma from '#application/prisma'
|
||||
import { TSocket } from '#application/types'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { CharacterGender, CharacterRace } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import CharacterTypeRepository from '#repositories/characterTypeRepository'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
|
||||
type Payload = {
|
||||
id: number
|
||||
id: UUID
|
||||
name: string
|
||||
gender: CharacterGender
|
||||
race: CharacterRace
|
||||
isSelectable: boolean
|
||||
spriteId: string
|
||||
spriteId: UUID
|
||||
}
|
||||
|
||||
export default class CharacterTypeUpdateEvent {
|
||||
constructor(
|
||||
private readonly io: Server,
|
||||
private readonly socket: TSocket
|
||||
) {}
|
||||
|
||||
export default class CharacterTypeUpdateEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('gm:characterType:update', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: Payload, callback: (success: boolean) => void): Promise<void> {
|
||||
const character = await characterRepository.getById(this.socket.characterId!)
|
||||
if (!character) return callback(false)
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.characterType.update({
|
||||
where: { id: data.id },
|
||||
data: {
|
||||
name: data.name,
|
||||
gender: data.gender,
|
||||
race: data.race,
|
||||
isSelectable: data.isSelectable,
|
||||
spriteId: data.spriteId
|
||||
}
|
||||
})
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
callback(true)
|
||||
const characterTypeRepository = new CharacterTypeRepository()
|
||||
const characterType = await characterTypeRepository.getById(data.id)
|
||||
if (!characterType) return callback(false)
|
||||
|
||||
const spriteRepository = new SpriteRepository()
|
||||
const sprite = await spriteRepository.getById(data.spriteId)
|
||||
if (!sprite) return callback(false)
|
||||
|
||||
await characterType.setName(data.name).setGender(data.gender).setRace(data.race).setIsSelectable(data.isSelectable).setSprite(sprite).save()
|
||||
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
callback(false)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +1,22 @@
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
import prisma from '#application/prisma'
|
||||
import { TSocket } from '#application/types'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
|
||||
export default class ItemCreateEvent {
|
||||
constructor(
|
||||
private readonly io: Server,
|
||||
private readonly socket: TSocket
|
||||
) {}
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { Item } from '#entities/item'
|
||||
|
||||
export default class ItemCreateEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('gm:item:create', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: undefined, callback: (response: boolean, item?: any) => void): Promise<void> {
|
||||
try {
|
||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
||||
if (!character) return callback(false)
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
const newItem = new Item()
|
||||
await newItem.setName('New Item').setItemType('WEAPON').setStackable(false).setRarity('COMMON').setSprite(null).save()
|
||||
|
||||
const newItem = await prisma.item.create({
|
||||
data: {
|
||||
name: 'New Item',
|
||||
itemType: 'WEAPON',
|
||||
stackable: false,
|
||||
rarity: 'COMMON',
|
||||
spriteId: null
|
||||
}
|
||||
})
|
||||
|
||||
callback(true, newItem)
|
||||
return callback(true, newItem)
|
||||
} catch (error) {
|
||||
console.error('Error creating item:', error)
|
||||
callback(false)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +1,30 @@
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
import { gameMasterLogger } from '#application/logger'
|
||||
import prisma from '#application/prisma'
|
||||
import { TSocket } from '#application/types'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { UUID } from '#application/types'
|
||||
import ItemRepository from '#repositories/itemRepository'
|
||||
|
||||
interface IPayload {
|
||||
id: string
|
||||
id: UUID
|
||||
}
|
||||
|
||||
export default class ItemDeleteEvent {
|
||||
constructor(
|
||||
private readonly io: Server,
|
||||
private readonly socket: TSocket
|
||||
) {}
|
||||
|
||||
export default class ItemDeleteEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('gm:item:remove', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: boolean) => void): Promise<void> {
|
||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
||||
if (!character) return callback(false)
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.item.delete({
|
||||
where: { id: data.id }
|
||||
})
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
callback(true)
|
||||
const itemRepository = new ItemRepository()
|
||||
const item = await itemRepository.getById(data.id)
|
||||
if (!item) return callback(false)
|
||||
|
||||
await item.delete()
|
||||
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
gameMasterLogger.error(`Error deleting item ${data.id}: ${error instanceof Error ? error.message : String(error)}`)
|
||||
callback(false)
|
||||
this.logger.error(`Error deleting item ${data.id}: ${error instanceof Error ? error.message : String(error)}`)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,25 @@
|
||||
import { Item } from '@prisma/client'
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
import { gameMasterLogger } from '#application/logger'
|
||||
import { TSocket } from '#application/types'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
import itemRepository from '#repositories/itemRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { Item } from '#entities/item'
|
||||
import ItemRepository from '#repositories/itemRepository'
|
||||
|
||||
interface IPayload {}
|
||||
|
||||
export default class ItemListEvent {
|
||||
constructor(
|
||||
private readonly io: Server,
|
||||
private readonly socket: TSocket
|
||||
) {}
|
||||
|
||||
export default class ItemListEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('gm:item:list', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: Item[]) => void): Promise<void> {
|
||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
||||
if (!character) {
|
||||
gameMasterLogger.error('gm:item:list error', 'Character not found')
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const itemRepository = new ItemRepository()
|
||||
const items = await itemRepository.getAll()
|
||||
|
||||
return callback(items)
|
||||
} catch (error) {
|
||||
this.logger.error('gm:item:list error', error)
|
||||
return callback([])
|
||||
}
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
gameMasterLogger.info(`User ${character.id} tried to list items but is not a game master.`)
|
||||
return callback([])
|
||||
}
|
||||
|
||||
// get all items
|
||||
const items = await itemRepository.getAll()
|
||||
callback(items)
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,41 @@
|
||||
import { ItemType, ItemRarity } from '@prisma/client'
|
||||
import { Server } from 'socket.io'
|
||||
|
||||
import { gameMasterLogger } from '#application/logger'
|
||||
import prisma from '#application/prisma'
|
||||
import { TSocket } from '#application/types'
|
||||
import characterRepository from '#repositories/characterRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { ItemType, ItemRarity } from '#application/enums'
|
||||
import { UUID } from '#application/types'
|
||||
import ItemRepository from '#repositories/itemRepository'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
|
||||
type Payload = {
|
||||
id: string
|
||||
id: UUID
|
||||
name: string
|
||||
description: string | null
|
||||
description: string
|
||||
itemType: ItemType
|
||||
stackable: boolean
|
||||
rarity: ItemRarity
|
||||
spriteId: string | null
|
||||
spriteId: UUID
|
||||
}
|
||||
|
||||
export default class ItemUpdateEvent {
|
||||
constructor(
|
||||
private readonly io: Server,
|
||||
private readonly socket: TSocket
|
||||
) {}
|
||||
|
||||
export default class ItemUpdateEvent extends BaseEvent {
|
||||
public listen(): void {
|
||||
this.socket.on('gm:item:update', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: Payload, callback: (success: boolean) => void): Promise<void> {
|
||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
||||
if (!character) return callback(false)
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.item.update({
|
||||
where: { id: data.id },
|
||||
data: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
itemType: data.itemType,
|
||||
stackable: data.stackable,
|
||||
rarity: data.rarity,
|
||||
spriteId: data.spriteId
|
||||
}
|
||||
})
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const itemRepository = new ItemRepository()
|
||||
const item = await itemRepository.getById(data.id)
|
||||
if (!item) return callback(false)
|
||||
|
||||
const spriteRepository = new SpriteRepository()
|
||||
const sprite = await spriteRepository.getById(data.spriteId)
|
||||
if (!sprite) return callback(false)
|
||||
|
||||
await item.setName(data.name).setDescription(data.description).setItemType(data.itemType).setStackable(data.stackable).setRarity(data.rarity).setSprite(sprite).save()
|
||||
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
gameMasterLogger.error(`Error updating item: ${error instanceof Error ? error.message : String(error)}`)
|
||||
console.error(error)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import ObjectRepository from '#repositories/mapObjectRepository'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { MapObject } from '#entities/mapObject'
|
||||
import MapObjectRepository from '#repositories/mapObjectRepository'
|
||||
|
||||
interface IPayload {}
|
||||
|
||||
@ -10,10 +10,17 @@ export default class MapObjectListEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: MapObject[]) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
// get all objects
|
||||
const objects = await ObjectRepository.getAll()
|
||||
return callback(objects)
|
||||
// Get all map objects
|
||||
const mapObjectRepository = new MapObjectRepository()
|
||||
const mapObjects = await mapObjectRepository.getAll()
|
||||
|
||||
return callback(mapObjects)
|
||||
} catch (error) {
|
||||
this.logger.error('gm:mapObject:list error', error)
|
||||
return callback([])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import fs from 'fs'
|
||||
import Storage from '#application/storage'
|
||||
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import MapObjectRepository from '#repositories/mapObjectRepository'
|
||||
import Storage from '#application/storage'
|
||||
import { UUID } from '#application/types'
|
||||
import MapObjectRepository from '#repositories/mapObjectRepository'
|
||||
|
||||
interface IPayload {
|
||||
mapObjectId: UUID
|
||||
@ -14,9 +15,8 @@ export default class MapObjectRemoveEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: boolean) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
// remove the tile from the disk
|
||||
const finalFilePath = Storage.getPublicPath('map_objects', data.mapObjectId + '.png')
|
||||
fs.unlink(finalFilePath, async (err) => {
|
||||
@ -26,7 +26,8 @@ export default class MapObjectRemoveEvent extends BaseEvent {
|
||||
return
|
||||
}
|
||||
|
||||
await (await MapObjectRepository.getById(data.mapObjectId))?.delete()
|
||||
const mapObjectRepository = new MapObjectRepository()
|
||||
await (await mapObjectRepository.getById(data.mapObjectId))?.delete()
|
||||
|
||||
return callback(true)
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { UUID } from '#application/types'
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { UUID } from '#application/types'
|
||||
import MapObjectRepository from '#repositories/mapObjectRepository'
|
||||
|
||||
type Payload = {
|
||||
@ -8,7 +8,6 @@ type Payload = {
|
||||
tags: string[]
|
||||
originX: number
|
||||
originY: number
|
||||
isAnimated: boolean
|
||||
frameRate: number
|
||||
frameWidth: number
|
||||
frameHeight: number
|
||||
@ -23,7 +22,9 @@ export default class MapObjectUpdateEvent extends BaseEvent {
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const mapObject = await MapObjectRepository.getById(data.id)
|
||||
const mapObjectRepository = new MapObjectRepository()
|
||||
|
||||
const mapObject = await mapObjectRepository.getById(data.id)
|
||||
if (!mapObject) return callback(false)
|
||||
|
||||
await mapObject
|
||||
@ -31,11 +32,10 @@ export default class MapObjectUpdateEvent extends BaseEvent {
|
||||
.setTags(data.tags)
|
||||
.setOriginX(data.originX)
|
||||
.setOriginY(data.originY)
|
||||
.setIsAnimated(data.isAnimated)
|
||||
.setFrameRate(data.frameRate)
|
||||
.setFrameWidth(data.frameWidth)
|
||||
.setFrameHeight(data.frameHeight)
|
||||
.update()
|
||||
.save()
|
||||
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
|
@ -2,8 +2,9 @@ import fs from 'fs/promises'
|
||||
import { writeFile } from 'node:fs/promises'
|
||||
|
||||
import sharp from 'sharp'
|
||||
import Storage from '#application/storage'
|
||||
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import Storage from '#application/storage'
|
||||
import { MapObject } from '#entities/mapObject'
|
||||
|
||||
interface IObjectData {
|
||||
@ -32,7 +33,7 @@ export default class MapObjectUploadEvent extends BaseEvent {
|
||||
|
||||
// Create new map object and save it to database
|
||||
const mapObject = new MapObject()
|
||||
await mapObject.setName(key).setTags([]).setOriginX(0).setOriginY(0).setFrameWidth(width).setFrameHeight(height).save()
|
||||
await mapObject.setName('New map object').setTags([]).setOriginX(0).setOriginY(0).setFrameWidth(width).setFrameHeight(height).save()
|
||||
|
||||
// Save image to disk
|
||||
const uuid = mapObject.getId()
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { UUID } from '#application/types'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
import CharacterRepository from '#repositories/characterRepository'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
|
||||
interface CopyPayload {
|
||||
@ -17,19 +16,24 @@ export default class SpriteCopyEvent extends BaseEvent {
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const sourceSprite = await SpriteRepository.getById(payload.id)
|
||||
const spriteRepository = new SpriteRepository()
|
||||
const sourceSprite = await spriteRepository.getById(payload.id)
|
||||
|
||||
if (!sourceSprite) {
|
||||
throw new Error('Source sprite not found')
|
||||
this.logger.error('gm:sprite:copy error', 'Source sprite not found')
|
||||
return callback(false)
|
||||
}
|
||||
|
||||
// Populate source sprite with spriteActions
|
||||
await spriteRepository.getEntityManager().populate(sourceSprite, ['spriteActions'])
|
||||
|
||||
const newSprite = new Sprite()
|
||||
await newSprite.setName(`${sourceSprite.getName()} (Copy)`).setSpriteActions(sourceSprite.getSpriteActions()).save()
|
||||
|
||||
callback(true)
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
this.logger.error(`Error copying sprite:`, String(error))
|
||||
callback(false)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,17 +15,19 @@ export default class GMSpriteDeleteEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: Payload, callback: (response: boolean) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
await this.deleteSpriteFolder(data.id)
|
||||
await (await SpriteRepository.getById(data.id))?.delete()
|
||||
|
||||
const spriteRepository = new SpriteRepository()
|
||||
await (await spriteRepository.getById(data.id))?.delete()
|
||||
|
||||
this.logger.info(`Sprite ${data.id} deleted.`)
|
||||
callback(true)
|
||||
return callback(true)
|
||||
} catch (error: any) {
|
||||
this.logger.error('gm:sprite:delete error', error.message)
|
||||
callback(false)
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Sprite } from '@prisma/client'
|
||||
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { Sprite } from '#entities/sprite'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
|
||||
interface IPayload {}
|
||||
@ -11,10 +10,18 @@ export default class SpriteListEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: Sprite[]) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
// get all sprites
|
||||
const sprites = await SpriteRepository.getAll()
|
||||
callback(sprites)
|
||||
// Get all sprites
|
||||
const spriteRepository = new SpriteRepository()
|
||||
const sprites = await spriteRepository.getAll()
|
||||
await spriteRepository.getEntityManager().populate(sprites, ['spriteActions'])
|
||||
|
||||
return callback(sprites)
|
||||
} catch (error) {
|
||||
this.logger.error('gm:sprite:list error', error)
|
||||
return callback([])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,8 +369,6 @@ export default class SpriteUpdateEvent extends BaseEvent {
|
||||
sprites: action.sprites,
|
||||
originX: action.originX,
|
||||
originY: action.originY,
|
||||
isAnimated: action.isAnimated,
|
||||
isLooping: action.isLooping,
|
||||
frameWidth: action.frameWidth,
|
||||
frameHeight: action.frameHeight,
|
||||
frameRate: action.frameRate
|
||||
|
@ -15,13 +15,15 @@ export default class GMTileDeleteEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: Payload, callback: (response: boolean) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
this.logger.info(`Deleting tile ${data.id}`)
|
||||
|
||||
await this.deleteTileFile(data.id)
|
||||
await (await TileRepository.getById(data.id))?.delete()
|
||||
|
||||
const tileRepository = new TileRepository()
|
||||
await (await tileRepository.getById(data.id))?.delete()
|
||||
|
||||
this.logger.info(`Tile ${data.id} deleted successfully.`)
|
||||
return callback(true)
|
||||
|
@ -10,10 +10,16 @@ export default class TileListEven extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: IPayload, callback: (response: Tile[]) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
try {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
// get all tiles
|
||||
const tiles = await TileRepository.getAll()
|
||||
return callback(tiles)
|
||||
// Get all tiles
|
||||
const tileRepository = new TileRepository()
|
||||
const tiles = await tileRepository.getAll()
|
||||
return callback(tiles)
|
||||
} catch (error) {
|
||||
this.logger.error('gm:tile:list error', error)
|
||||
return callback([])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,13 +14,16 @@ export default class TileUpdateEvent extends BaseEvent {
|
||||
}
|
||||
|
||||
private async handleEvent(data: Payload, callback: (success: boolean) => void): Promise<void> {
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
try {
|
||||
const tile = await TileRepository.getById(data.id)
|
||||
if (!(await this.isCharacterGM())) return
|
||||
|
||||
const tileRepository = new TileRepository()
|
||||
|
||||
const tile = await tileRepository.getById(data.id)
|
||||
if (!tile) return callback(false)
|
||||
|
||||
await tile.setName(data.name).setTags(data.tags).update()
|
||||
await tile.setName(data.name).setTags(data.tags).save()
|
||||
|
||||
return callback(true)
|
||||
} catch (error) {
|
||||
return callback(false)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { Map } from '#entities/map'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
import { Map, MapCacheT } from '#entities/map'
|
||||
|
||||
type Payload = {
|
||||
name: string
|
||||
@ -13,11 +12,11 @@ export default class MapCreateEvent extends BaseEvent {
|
||||
this.socket.on('gm:map:create', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleEvent(data: Payload, callback: (response: Map[]) => void): Promise<void> {
|
||||
private async handleEvent(data: Payload, callback: (response: MapCacheT | false) => 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.`)
|
||||
this.logger.info(`GM ${(await this.getCharacter())!.getId()} has created a new map via map editor.`)
|
||||
|
||||
const map = new Map()
|
||||
await map
|
||||
@ -27,12 +26,11 @@ export default class MapCreateEvent extends BaseEvent {
|
||||
.setTiles(Array.from({ length: data.height }, () => Array.from({ length: data.width }, () => 'blank_tile')))
|
||||
.save()
|
||||
|
||||
const mapList = await MapRepository.getAll()
|
||||
return callback(mapList)
|
||||
return callback(await map.cache())
|
||||
} catch (error: any) {
|
||||
this.logger.error('gm:map:create error', error.message)
|
||||
this.socket.emit('notification', { message: 'Failed to create map.' })
|
||||
return callback([])
|
||||
return callback(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,8 @@ export default class MapDeleteEvent extends BaseEvent {
|
||||
try {
|
||||
this.logger.info(`Deleting map ${data.mapId}`)
|
||||
|
||||
await (await MapRepository.getById(data.mapId))?.delete()
|
||||
const mapRepository = new MapRepository()
|
||||
await (await mapRepository.getById(data.mapId))?.delete()
|
||||
|
||||
this.logger.info(`Map ${data.mapId} deleted successfully.`)
|
||||
return callback(true)
|
||||
|
@ -1,25 +0,0 @@
|
||||
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: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:list error', error.message)
|
||||
return callback([])
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ import { BaseEvent } from '#application/base/baseEvent'
|
||||
import { UUID } from '#application/types'
|
||||
import { Map } from '#entities/map'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
import Database from '#application/database'
|
||||
|
||||
interface IPayload {
|
||||
mapId: UUID
|
||||
@ -24,17 +23,15 @@ export default class MapRequestEvent extends BaseEvent {
|
||||
return callback(null)
|
||||
}
|
||||
|
||||
const map = await MapRepository.getById(data.mapId)
|
||||
|
||||
const mapRepository = new MapRepository()
|
||||
const map = await mapRepository.getById(data.mapId)
|
||||
await mapRepository.getEntityManager().populate(map!, mapRepository.POPULATE_MAP_EDITOR as any)
|
||||
|
||||
if (!map) {
|
||||
this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request map ${data.mapId} but it does not exist.`)
|
||||
return callback(null)
|
||||
}
|
||||
|
||||
console.log(map)
|
||||
await Database.getEntityManager().populate(map, ['mapEventTiles', 'placedMapObjects'])
|
||||
|
||||
return callback(map)
|
||||
} catch (error: any) {
|
||||
this.logger.error('gm:map:request error', error.message)
|
||||
|
@ -5,9 +5,9 @@ import { Map } from '#entities/map'
|
||||
import { MapEffect } from '#entities/mapEffect'
|
||||
import { MapEventTile } from '#entities/mapEventTile'
|
||||
import { MapEventTileTeleport } from '#entities/mapEventTileTeleport'
|
||||
import { PlacedMapObject } from '#entities/placedMapObject'
|
||||
import mapManager from '#managers/mapManager'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
import { PlacedMapObject } from '#entities/placedMapObject'
|
||||
|
||||
interface IPayload {
|
||||
mapId: UUID
|
||||
@ -21,16 +21,13 @@ interface IPayload {
|
||||
positionX: number
|
||||
positionY: number
|
||||
teleport?: {
|
||||
toMapId: UUID
|
||||
toMap: Map
|
||||
toPositionX: number
|
||||
toPositionY: number
|
||||
toRotation: number
|
||||
}
|
||||
}[]
|
||||
mapEffects: {
|
||||
effect: string
|
||||
strength: number
|
||||
}[]
|
||||
mapEffects: MapEffect[]
|
||||
placedMapObjects: PlacedMapObject[]
|
||||
}
|
||||
|
||||
@ -51,13 +48,16 @@ export default class MapUpdateEvent extends BaseEvent {
|
||||
return callback(null)
|
||||
}
|
||||
|
||||
let map = await MapRepository.getById(data.mapId)
|
||||
const mapRepository = new MapRepository()
|
||||
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)
|
||||
}
|
||||
|
||||
await mapRepository.getEntityManager().populate(map, mapRepository.POPULATE_MAP_EDITOR as any)
|
||||
|
||||
// Validation logic remains the same
|
||||
if (data.tiles.length > data.height) {
|
||||
data.tiles = data.tiles.slice(0, data.height)
|
||||
@ -68,14 +68,14 @@ export default class MapUpdateEvent extends BaseEvent {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove map event tiles and placed map objects that are out of bounds
|
||||
data.mapEventTiles = data.mapEventTiles.filter((tile) => tile.positionX >= 0 && tile.positionX < data.width && tile.positionY >= 0 && tile.positionY < data.height)
|
||||
|
||||
data.placedMapObjects = data.placedMapObjects.filter((obj) => obj.positionX >= 0 && obj.positionX < data.width && obj.positionY >= 0 && obj.positionY < data.height)
|
||||
|
||||
// Clear existing collections
|
||||
map.mapEventTiles.removeAll()
|
||||
map.placedMapObjects.removeAll()
|
||||
map.mapEffects.removeAll()
|
||||
map.getMapEventTiles().removeAll()
|
||||
map.getPlacedMapObjects().removeAll()
|
||||
map.getMapEffects().removeAll()
|
||||
|
||||
// Create and add new map event tiles
|
||||
for (const tile of data.mapEventTiles) {
|
||||
@ -83,7 +83,7 @@ export default class MapUpdateEvent extends BaseEvent {
|
||||
|
||||
if (tile.teleport) {
|
||||
const teleport = new MapEventTileTeleport()
|
||||
.setToMap((await MapRepository.getById(tile.teleport.toMapId))!)
|
||||
.setToMap((await mapRepository.getById(tile.teleport.toMap.id))!)
|
||||
.setToPositionX(tile.teleport.toPositionX)
|
||||
.setToPositionY(tile.teleport.toPositionY)
|
||||
.setToRotation(tile.teleport.toRotation)
|
||||
@ -96,21 +96,24 @@ export default class MapUpdateEvent extends BaseEvent {
|
||||
|
||||
// Create and add new map objects
|
||||
for (const object of data.placedMapObjects) {
|
||||
const mapObject = new PlacedMapObject().setMapObject(object.mapObject).setDepth(object.depth).setIsRotated(object.isRotated).setPositionX(object.positionX).setPositionY(object.positionY).setMap(map)
|
||||
const mapObject = new PlacedMapObject().setMapObject(object.mapObject).setIsRotated(object.isRotated).setPositionX(object.positionX).setPositionY(object.positionY).setMap(map)
|
||||
|
||||
map.placedMapObjects.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()
|
||||
await map.setName(data.name).setWidth(data.width).setHeight(data.height).setTiles(data.tiles).setPvp(data.pvp).setUpdatedAt(new Date()).save()
|
||||
|
||||
// Reload map from database to get fresh data
|
||||
map = await MapRepository.getById(data.mapId)
|
||||
map = await mapRepository.getById(data.mapId)
|
||||
await mapRepository.getEntityManager().populate(map!, mapRepository.POPULATE_MAP_EDITOR as any)
|
||||
|
||||
if (!map) {
|
||||
this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist after update.`)
|
||||
@ -123,7 +126,7 @@ export default class MapUpdateEvent extends BaseEvent {
|
||||
|
||||
return callback(map)
|
||||
} catch (error: any) {
|
||||
this.logger.error(`gm:mapObject:update error: ${error instanceof Error ? error.message : String(error)}`)
|
||||
this.emitError(`gm:map:update error: ${error instanceof Error ? error.message + error.stack : String(error)}`)
|
||||
return callback(null)
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,15 @@ export default class LoginEvent extends BaseEvent {
|
||||
this.socket.on('login', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private handleEvent(): void {
|
||||
private async handleEvent() {
|
||||
try {
|
||||
if (!this.socket.userId) {
|
||||
this.logger.warn('Login attempt without user data')
|
||||
return
|
||||
}
|
||||
|
||||
this.socket.emit('logged_in', { user: UserRepository.getById(this.socket.userId) })
|
||||
const userRepository = new UserRepository()
|
||||
this.socket.emit('logged_in', { user: userRepository.getById(this.socket.userId) })
|
||||
this.logger.info(`User logged in: ${this.socket.userId}`)
|
||||
} catch (error: any) {
|
||||
this.logger.error('login error: ' + error.message)
|
||||
|
@ -2,13 +2,12 @@ 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 MapEventTileRepository from '#repositories/mapEventTileRepository'
|
||||
import CharacterService from '#services/characterService'
|
||||
import MapEventTileService from '#services/mapEventTileService'
|
||||
import TeleportService from '#services/teleportService'
|
||||
|
||||
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))
|
||||
@ -16,7 +15,7 @@ export default class CharacterMove extends BaseEvent {
|
||||
|
||||
private async handleEvent({ positionX, positionY }: { positionX: number; positionY: number }): Promise<void> {
|
||||
const mapCharacter = MapManager.getCharacterById(this.socket.characterId!)
|
||||
if (!mapCharacter?.character) {
|
||||
if (!mapCharacter?.getCharacter()) {
|
||||
this.logger.error('map:character:move error: Character not found or not initialized')
|
||||
return
|
||||
}
|
||||
@ -39,8 +38,8 @@ export default class CharacterMove extends BaseEvent {
|
||||
await this.moveAlongPath(mapCharacter, path)
|
||||
}
|
||||
|
||||
private async moveAlongPath(mapCharacter: MapCharacter, path: Array<{ x: number; y: number }>): Promise<void> {
|
||||
const { character } = mapCharacter
|
||||
private async moveAlongPath(mapCharacter: MapCharacter, path: Array<{ positionX: number; positionY: number }>): Promise<void> {
|
||||
const character = mapCharacter.getCharacter()
|
||||
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
if (!mapCharacter.isMoving || mapCharacter.currentPath !== path) {
|
||||
@ -48,26 +47,26 @@ export default class CharacterMove extends BaseEvent {
|
||||
}
|
||||
|
||||
const [start, end] = [path[i], path[i + 1]]
|
||||
character.rotation = CharacterService.calculateRotation(start.x, start.y, end.x, end.y)
|
||||
character.setRotation(CharacterService.calculateRotation(start.positionX, start.positionY, end.positionX, end.positionY))
|
||||
|
||||
const mapEventTile = await mapEventTileRepository.getEventTileByMapIdAndPosition(character.map.id, Math.floor(end.x), Math.floor(end.y))
|
||||
const mapEventTileRepository = new MapEventTileRepository()
|
||||
const mapEventTile = await mapEventTileRepository.getEventTileByMapIdAndPosition(character.getMap().getId(), Math.floor(end.positionX), Math.floor(end.positionY))
|
||||
|
||||
if (mapEventTile?.type === 'BLOCK') break
|
||||
if (mapEventTile?.type === 'TELEPORT' && mapEventTile.teleport) {
|
||||
await this.handleMapEventTile(mapEventTile as MapEventTileWithTeleport)
|
||||
break
|
||||
return
|
||||
}
|
||||
|
||||
// Update position first
|
||||
character.positionX = end.x
|
||||
character.positionY = end.y
|
||||
character.setPositionX(end.positionX).setPositionY(end.positionY)
|
||||
|
||||
// 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,
|
||||
positionX: character.getPositionX(),
|
||||
positionY: character.getPositionY(),
|
||||
rotation: character.getRotation(),
|
||||
isMoving: true
|
||||
})
|
||||
|
||||
@ -80,14 +79,13 @@ export default class CharacterMove extends BaseEvent {
|
||||
}
|
||||
|
||||
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)
|
||||
if (mapEventTile.getTeleport()) {
|
||||
await TeleportService.teleportCharacter(this.socket.characterId!, {
|
||||
targetMapId: mapEventTile.getTeleport()!.getToMap().getId(),
|
||||
targetX: mapEventTile.getTeleport()!.getToPositionX(),
|
||||
targetY: mapEventTile.getTeleport()!.getToPositionY(),
|
||||
rotation: mapEventTile.getTeleport()!.getToRotation()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,108 +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, 50))
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
try {
|
||||
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
|
||||
}
|
||||
|
||||
character.positionX = end.x
|
||||
character.positionY = end.y
|
||||
|
||||
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()
|
||||
}
|
||||
} finally {
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
import fs from 'fs'
|
||||
|
||||
import { Request, Response } from 'express'
|
||||
|
||||
import { BaseController } from '#application/base/baseController'
|
||||
import Database from '#application/database'
|
||||
import Storage from '#application/storage'
|
||||
import { AssetData, UUID } from '#application/types'
|
||||
import SpriteRepository from '#repositories/spriteRepository'
|
||||
import TileRepository from '#repositories/tileRepository'
|
||||
import MapRepository from '#repositories/mapRepository'
|
||||
|
||||
export class AssetsController extends BaseController {
|
||||
/**
|
||||
* List tiles
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async listTiles(req: Request, res: Response) {
|
||||
const assets: AssetData[] = []
|
||||
const tiles = await TileRepository.getAll()
|
||||
|
||||
for (const tile of tiles) {
|
||||
assets.push({ key: tile.getId(), data: '/assets/tiles/' + tile.getId() + '.png', group: 'tiles', updatedAt: tile.getUpdatedAt() } as AssetData)
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, assets)
|
||||
}
|
||||
|
||||
/**
|
||||
* List tiles by map
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async listTilesByMap(req: Request, res: Response) {
|
||||
const mapId = req.params.mapId as UUID
|
||||
|
||||
if (!mapId) {
|
||||
return this.sendError(res, 'Invalid map ID', 400)
|
||||
}
|
||||
|
||||
const map = await MapRepository.getById(mapId)
|
||||
if (!map) {
|
||||
return this.sendError(res, 'Map not found', 404)
|
||||
}
|
||||
|
||||
const assets: AssetData[] = []
|
||||
const tiles = await TileRepository.getByMapId(mapId)
|
||||
|
||||
for (const tile of tiles) {
|
||||
assets.push({ key: tile.getId(), data: '/assets/tiles/' + tile.getId() + '.png', group: 'tiles', updatedAt: tile.getUpdatedAt() } as AssetData)
|
||||
}
|
||||
|
||||
return this.sendSuccess(res, assets)
|
||||
}
|
||||
|
||||
/**
|
||||
* List sprite actions
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async listSpriteActions(req: Request, res: Response) {
|
||||
const spriteId = req.params.spriteId as UUID
|
||||
|
||||
if (!spriteId) {
|
||||
return this.sendError(res, 'Invalid sprite ID', 400)
|
||||
}
|
||||
|
||||
const sprite = await SpriteRepository.getById(spriteId)
|
||||
if (!sprite) {
|
||||
return this.sendError(res, 'Sprite not found', 404)
|
||||
}
|
||||
|
||||
await Database.getEntityManager().populate(sprite, ['spriteActions'])
|
||||
|
||||
const assets: AssetData[] = sprite.spriteActions.getItems().map((spriteAction) => ({
|
||||
key: sprite.getId() + '-' + spriteAction.getAction(),
|
||||
data: '/assets/sprites/' + sprite.getId() + '/' + spriteAction.getAction() + '.png',
|
||||
group: spriteAction.getIsAnimated() ? 'sprite_animations' : 'sprites',
|
||||
updatedAt: sprite.getUpdatedAt(),
|
||||
originX: Number(spriteAction.getOriginX().toString()),
|
||||
originY: Number(spriteAction.getOriginY().toString()),
|
||||
isAnimated: spriteAction.getIsAnimated(),
|
||||
frameRate: spriteAction.getFrameRate(),
|
||||
frameWidth: spriteAction.getFrameWidth(),
|
||||
frameHeight: spriteAction.getFrameHeight(),
|
||||
frameCount: spriteAction.getSprites()?.length
|
||||
}))
|
||||
|
||||
return this.sendSuccess(res, assets)
|
||||
}
|
||||
|
||||
/**
|
||||
* Download asset
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public async downloadAsset(req: Request, res: Response) {
|
||||
const { type, spriteId, file } = req.params
|
||||
|
||||
const assetPath = type === 'sprites' && spriteId ? Storage.getPublicPath(type, spriteId, file) : Storage.getPublicPath(type, file)
|
||||
|
||||
if (!fs.existsSync(assetPath)) {
|
||||
this.logger.error(`File not found: ${assetPath}`)
|
||||
return this.sendError(res, 'Asset not found', 404)
|
||||
}
|
||||
|
||||
res.sendFile(assetPath, (err) => {
|
||||
if (err) {
|
||||
this.logger.error('Error sending file:' + err)
|
||||
this.sendError(res, 'Error downloading the asset', 500)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user