diff --git a/Build.PL b/Build.PL index 0c6d690..95e6c75 100755 --- a/Build.PL +++ b/Build.PL @@ -9,16 +9,17 @@ my $build = Module::Build->new( dist_author => 'Sergio Iglesias ', dist_abstract => 'Juego de L3TDE.', requires => { - 'Mojolicious' => 0, - 'Moo' => 0, - 'Params::ValidationCompiler' => 0, - 'Types::Standard' => 0, - 'Crypt::URandom' => 0, - 'Crypt::Bcrypt' => 0, - 'DBIx::Class' => 0, + 'Mojolicious' => 0, + 'Moo' => 0, + 'Params::ValidationCompiler' => 0, + 'Types::Standard' => 0, + 'Crypt::URandom' => 0, + 'Crypt::Bcrypt' => 0, + 'DBIx::Class' => 0, 'DBIx::Class::DeploymentHandler' => 0, - 'UUID::URandom' => 0, - 'Module::Pluggable' => 0, + 'UUID::URandom' => 0, + 'Module::Pluggable' => 0, + 'Redis' => 0, }, ); $build->create_build_script; diff --git a/dbicdh/PostgreSQL/deploy/4/001-auto-__VERSION.sql b/dbicdh/PostgreSQL/deploy/4/001-auto-__VERSION.sql new file mode 100644 index 0000000..c03f8ca --- /dev/null +++ b/dbicdh/PostgreSQL/deploy/4/001-auto-__VERSION.sql @@ -0,0 +1,18 @@ +-- +-- Created by SQL::Translator::Producer::PostgreSQL +-- Created on Mon Jun 5 04:01:49 2023 +-- +; +-- +-- Table: dbix_class_deploymenthandler_versions +-- +CREATE TABLE "dbix_class_deploymenthandler_versions" ( + "id" serial NOT NULL, + "version" character varying(50) NOT NULL, + "ddl" text, + "upgrade_sql" text, + PRIMARY KEY ("id"), + CONSTRAINT "dbix_class_deploymenthandler_versions_version" UNIQUE ("version") +); + +; diff --git a/dbicdh/PostgreSQL/deploy/4/001-auto.sql b/dbicdh/PostgreSQL/deploy/4/001-auto.sql new file mode 100644 index 0000000..432ed9c --- /dev/null +++ b/dbicdh/PostgreSQL/deploy/4/001-auto.sql @@ -0,0 +1,258 @@ +-- +-- Created by SQL::Translator::Producer::PostgreSQL +-- Created on Mon Jun 5 04:02:06 2023 +-- +; +-- +-- Table: equipment +-- +CREATE TABLE "equipment" ( + "uuid" uuid NOT NULL, + PRIMARY KEY ("uuid") +); + +; +-- +-- Table: inventories +-- +CREATE TABLE "inventories" ( + "uuid" uuid NOT NULL, + PRIMARY KEY ("uuid") +); + +; +-- +-- Table: players +-- +CREATE TABLE "players" ( + "uuid" uuid NOT NULL, + "username" text NOT NULL, + "encrypted_password" text NOT NULL, + "email" text NOT NULL, + "verified" boolean NOT NULL, + "verification_token" text, + "register_date" timestamp DEFAULT NOW() NOT NULL, + "last_activity" timestamp DEFAULT NOW() NOT NULL, + PRIMARY KEY ("uuid"), + CONSTRAINT "unique_constraint_email" UNIQUE ("email"), + CONSTRAINT "unique_constraint_username" UNIQUE ("username") +); + +; +-- +-- Table: skill_like_lists +-- +CREATE TABLE "skill_like_lists" ( + "uuid" uuid DEFAULT uuid_generate_v4() NOT NULL, + PRIMARY KEY ("uuid") +); + +; +-- +-- Table: stats +-- +CREATE TABLE "stats" ( + "uuid" uuid NOT NULL, + "health" integer NOT NULL, + "mana" integer NOT NULL, + "strength" integer NOT NULL, + "resistance" integer NOT NULL, + "magic" integer NOT NULL, + "speed" integer NOT NULL, + "intelligence" integer NOT NULL, + PRIMARY KEY ("uuid") +); + +; +-- +-- Table: equipment_items +-- +CREATE TABLE "equipment_items" ( + "kind" text NOT NULL, + "equipment" uuid NOT NULL, + "identifier" text NOT NULL, + "quantity" integer NOT NULL, + PRIMARY KEY ("kind", "equipment") +); +CREATE INDEX "equipment_items_idx_equipment" on "equipment_items" ("equipment"); + +; +-- +-- Table: inventory_items +-- +CREATE TABLE "inventory_items" ( + "uuid" uuid DEFAULT uuid_generate_v4() NOT NULL, + "inventory" uuid NOT NULL, + "identifier" text NOT NULL, + "quantity" integer NOT NULL, + PRIMARY KEY ("uuid") +); +CREATE INDEX "inventory_items_idx_inventory" on "inventory_items" ("inventory"); + +; +-- +-- Table: skill_like_items +-- +CREATE TABLE "skill_like_items" ( + "identifier" text NOT NULL, + "owner_list" uuid NOT NULL, + "level" integer DEFAULT 1 NOT NULL, + PRIMARY KEY ("identifier", "owner_list") +); +CREATE INDEX "skill_like_items_idx_owner_list" on "skill_like_items" ("owner_list"); + +; +-- +-- Table: teams +-- +CREATE TABLE "teams" ( + "uuid" uuid NOT NULL, + "leader" uuid, + "name" text NOT NULL, + "planet" text NOT NULL, + "super_area" text NOT NULL, + "area" text NOT NULL, + "location" text NOT NULL, + PRIMARY KEY ("uuid"), + CONSTRAINT "u_name" UNIQUE ("name") +); +CREATE INDEX "teams_idx_leader" on "teams" ("leader"); + +; +-- +-- Table: player_pjs +-- +CREATE TABLE "player_pjs" ( + "uuid" uuid DEFAULT uuid_generate_v4() NOT NULL, + "owner" uuid NOT NULL, + "full_name" text NOT NULL, + "short_name" text NOT NULL, + "nick" text NOT NULL, + "race" text NOT NULL, + "team" uuid NOT NULL, + "creation_date" timestamp DEFAULT NOW() NOT NULL, + "last_activity" timestamp DEFAULT NOW() NOT NULL, + "experience" integer DEFAULT 1 NOT NULL, + "equipment" uuid NOT NULL, + "born_stats" uuid NOT NULL, + "training_stats" uuid NOT NULL, + "skills" uuid NOT NULL, + "spells" uuid NOT NULL, + "inventory" uuid NOT NULL, + "health" integer NOT NULL, + "mana" integer NOT NULL, + PRIMARY KEY ("uuid") +); +CREATE INDEX "player_pjs_idx_born_stats" on "player_pjs" ("born_stats"); +CREATE INDEX "player_pjs_idx_equipment" on "player_pjs" ("equipment"); +CREATE INDEX "player_pjs_idx_inventory" on "player_pjs" ("inventory"); +CREATE INDEX "player_pjs_idx_owner" on "player_pjs" ("owner"); +CREATE INDEX "player_pjs_idx_skills" on "player_pjs" ("skills"); +CREATE INDEX "player_pjs_idx_spells" on "player_pjs" ("spells"); +CREATE INDEX "player_pjs_idx_team" on "player_pjs" ("team"); +CREATE INDEX "player_pjs_idx_training_stats" on "player_pjs" ("training_stats"); + +; +-- +-- Table: player_companion_npcs +-- +CREATE TABLE "player_companion_npcs" ( + "uuid" uuid DEFAULT uuid_generate_v4() NOT NULL, + "owner" uuid NOT NULL, + "identifier" text NOT NULL, + "nick" text, + "race" text NOT NULL, + "level" integer DEFAULT 1 NOT NULL, + "exp" integer DEFAULT 1 NOT NULL, + "equipment" uuid NOT NULL, + "stats" uuid NOT NULL, + "skills" uuid NOT NULL, + "spells" uuid NOT NULL, + "inventory" uuid NOT NULL, + PRIMARY KEY ("uuid") +); +CREATE INDEX "player_companion_npcs_idx_equipment" on "player_companion_npcs" ("equipment"); +CREATE INDEX "player_companion_npcs_idx_inventory" on "player_companion_npcs" ("inventory"); +CREATE INDEX "player_companion_npcs_idx_owner" on "player_companion_npcs" ("owner"); +CREATE INDEX "player_companion_npcs_idx_skills" on "player_companion_npcs" ("skills"); +CREATE INDEX "player_companion_npcs_idx_spells" on "player_companion_npcs" ("spells"); +CREATE INDEX "player_companion_npcs_idx_stats" on "player_companion_npcs" ("stats"); + +; +-- +-- Foreign Key Definitions +-- + +; +ALTER TABLE "equipment_items" ADD CONSTRAINT "equipment_items_fk_equipment" FOREIGN KEY ("equipment") + REFERENCES "equipment" ("uuid") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE "inventory_items" ADD CONSTRAINT "inventory_items_fk_inventory" FOREIGN KEY ("inventory") + REFERENCES "inventories" ("uuid") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE "skill_like_items" ADD CONSTRAINT "skill_like_items_fk_owner_list" FOREIGN KEY ("owner_list") + REFERENCES "skill_like_lists" ("uuid") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE "teams" ADD CONSTRAINT "teams_fk_leader" FOREIGN KEY ("leader") + REFERENCES "player_pjs" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_born_stats" FOREIGN KEY ("born_stats") + REFERENCES "stats" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_equipment" FOREIGN KEY ("equipment") + REFERENCES "equipment" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_inventory" FOREIGN KEY ("inventory") + REFERENCES "inventories" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_owner" FOREIGN KEY ("owner") + REFERENCES "players" ("uuid") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_skills" FOREIGN KEY ("skills") + REFERENCES "skill_like_lists" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_spells" FOREIGN KEY ("spells") + REFERENCES "skill_like_lists" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_team" FOREIGN KEY ("team") + REFERENCES "teams" ("uuid") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE "player_pjs" ADD CONSTRAINT "player_pjs_fk_training_stats" FOREIGN KEY ("training_stats") + REFERENCES "stats" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_companion_npcs" ADD CONSTRAINT "player_companion_npcs_fk_equipment" FOREIGN KEY ("equipment") + REFERENCES "equipment" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_companion_npcs" ADD CONSTRAINT "player_companion_npcs_fk_inventory" FOREIGN KEY ("inventory") + REFERENCES "inventories" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_companion_npcs" ADD CONSTRAINT "player_companion_npcs_fk_owner" FOREIGN KEY ("owner") + REFERENCES "player_pjs" ("uuid") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE "player_companion_npcs" ADD CONSTRAINT "player_companion_npcs_fk_skills" FOREIGN KEY ("skills") + REFERENCES "skill_like_lists" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_companion_npcs" ADD CONSTRAINT "player_companion_npcs_fk_spells" FOREIGN KEY ("spells") + REFERENCES "skill_like_lists" ("uuid") DEFERRABLE; + +; +ALTER TABLE "player_companion_npcs" ADD CONSTRAINT "player_companion_npcs_fk_stats" FOREIGN KEY ("stats") + REFERENCES "stats" ("uuid") DEFERRABLE; + +; diff --git a/dbicdh/PostgreSQL/upgrade/1-4/001-auto.sql b/dbicdh/PostgreSQL/upgrade/1-4/001-auto.sql new file mode 100644 index 0000000..5645114 --- /dev/null +++ b/dbicdh/PostgreSQL/upgrade/1-4/001-auto.sql @@ -0,0 +1,66 @@ +-- Convert schema '/home/sergio/LasTres/script/../dbicdh/_source/deploy/1/001-auto.yml' to '/home/sergio/LasTres/script/../dbicdh/_source/deploy/4/001-auto.yml':; + +; +BEGIN; + +; +ALTER TABLE player_pjs DROP CONSTRAINT player_pjs_fk_owner; + +; +ALTER TABLE player_pjs DROP CONSTRAINT player_pjs_fk_stats; + +; +DROP INDEX player_pjs_idx_stats; + +; +ALTER TABLE player_pjs DROP COLUMN level; + +; +ALTER TABLE player_pjs DROP COLUMN exp; + +; +ALTER TABLE player_pjs DROP COLUMN stats; + +; +ALTER TABLE player_pjs ADD COLUMN experience integer DEFAULT 1 NOT NULL; + +; +ALTER TABLE player_pjs ADD COLUMN born_stats uuid NOT NULL; + +; +ALTER TABLE player_pjs ADD COLUMN training_stats uuid NOT NULL; + +; +ALTER TABLE player_pjs ADD COLUMN health integer NOT NULL; + +; +ALTER TABLE player_pjs ADD COLUMN mana integer NOT NULL; + +; +CREATE INDEX player_pjs_idx_born_stats on player_pjs (born_stats); + +; +CREATE INDEX player_pjs_idx_training_stats on player_pjs (training_stats); + +; +ALTER TABLE player_pjs ADD CONSTRAINT player_pjs_fk_born_stats FOREIGN KEY (born_stats) + REFERENCES stats (uuid) DEFERRABLE; + +; +ALTER TABLE player_pjs ADD CONSTRAINT player_pjs_fk_owner FOREIGN KEY (owner) + REFERENCES players (uuid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE; + +; +ALTER TABLE player_pjs ADD CONSTRAINT player_pjs_fk_training_stats FOREIGN KEY (training_stats) + REFERENCES stats (uuid) DEFERRABLE; + +; +ALTER TABLE stats DROP COLUMN charisma; + +; +ALTER TABLE teams ALTER COLUMN leader DROP NOT NULL; + +; + +COMMIT; + diff --git a/dbicdh/PostgreSQL/upgrade/3-4/001-auto.sql b/dbicdh/PostgreSQL/upgrade/3-4/001-auto.sql new file mode 100644 index 0000000..8085f89 --- /dev/null +++ b/dbicdh/PostgreSQL/upgrade/3-4/001-auto.sql @@ -0,0 +1,15 @@ +-- Convert schema '/home/sergio/LasTres/script/../dbicdh/_source/deploy/3/001-auto.yml' to '/home/sergio/LasTres/script/../dbicdh/_source/deploy/4/001-auto.yml':; + +; +BEGIN; + +; +ALTER TABLE player_pjs ADD COLUMN health integer NOT NULL; + +; +ALTER TABLE player_pjs ADD COLUMN mana integer NOT NULL; + +; + +COMMIT; + diff --git a/dbicdh/_source/deploy/4/001-auto-__VERSION.yml b/dbicdh/_source/deploy/4/001-auto-__VERSION.yml new file mode 100644 index 0000000..61dfa16 --- /dev/null +++ b/dbicdh/_source/deploy/4/001-auto-__VERSION.yml @@ -0,0 +1,91 @@ +--- +schema: + procedures: {} + tables: + dbix_class_deploymenthandler_versions: + constraints: + - deferrable: 1 + expression: '' + fields: + - id + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - version + match_type: '' + name: dbix_class_deploymenthandler_versions_version + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: UNIQUE + fields: + ddl: + data_type: text + default_value: ~ + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: ddl + order: 3 + size: + - 0 + id: + data_type: int + default_value: ~ + is_auto_increment: 1 + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: id + order: 1 + size: + - 0 + upgrade_sql: + data_type: text + default_value: ~ + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: upgrade_sql + order: 4 + size: + - 0 + version: + data_type: varchar + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 1 + name: version + order: 2 + size: + - 50 + indices: [] + name: dbix_class_deploymenthandler_versions + options: [] + order: 1 + triggers: {} + views: {} +translator: + add_drop_table: 0 + filename: ~ + no_comments: 0 + parser_args: + sources: + - __VERSION + parser_type: SQL::Translator::Parser::DBIx::Class + producer_args: {} + producer_type: SQL::Translator::Producer::YAML + show_warnings: 0 + trace: 0 + version: 1.63 diff --git a/dbicdh/_source/deploy/4/001-auto.yml b/dbicdh/_source/deploy/4/001-auto.yml new file mode 100644 index 0000000..e93c1c3 --- /dev/null +++ b/dbicdh/_source/deploy/4/001-auto.yml @@ -0,0 +1,1282 @@ +--- +schema: + procedures: {} + tables: + equipment: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + fields: + uuid: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: [] + name: equipment + options: [] + order: 1 + equipment_items: + constraints: + - deferrable: 1 + expression: '' + fields: + - kind + - equipment + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - equipment + match_type: '' + name: equipment_items_fk_equipment + on_delete: CASCADE + on_update: CASCADE + options: [] + reference_fields: + - uuid + reference_table: equipment + type: FOREIGN KEY + fields: + equipment: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: equipment + order: 2 + size: + - 0 + identifier: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: identifier + order: 3 + size: + - 0 + kind: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: kind + order: 1 + size: + - 0 + quantity: + data_type: Integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: quantity + order: 4 + size: + - 0 + indices: + - fields: + - equipment + name: equipment_items_idx_equipment + options: [] + type: NORMAL + name: equipment_items + options: [] + order: 6 + inventories: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + fields: + uuid: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: [] + name: inventories + options: [] + order: 2 + inventory_items: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - inventory + match_type: '' + name: inventory_items_fk_inventory + on_delete: CASCADE + on_update: CASCADE + options: [] + reference_fields: + - uuid + reference_table: inventories + type: FOREIGN KEY + fields: + identifier: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: identifier + order: 3 + size: + - 0 + inventory: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: inventory + order: 2 + size: + - 0 + quantity: + data_type: Integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: quantity + order: 4 + size: + - 0 + uuid: + data_type: uuid + default_value: !!perl/ref + =: uuid_generate_v4() + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: + - fields: + - inventory + name: inventory_items_idx_inventory + options: [] + type: NORMAL + name: inventory_items + options: [] + order: 7 + player_companion_npcs: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - equipment + match_type: '' + name: player_companion_npcs_fk_equipment + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: equipment + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - inventory + match_type: '' + name: player_companion_npcs_fk_inventory + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: inventories + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - owner + match_type: '' + name: player_companion_npcs_fk_owner + on_delete: CASCADE + on_update: CASCADE + options: [] + reference_fields: + - uuid + reference_table: player_pjs + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - skills + match_type: '' + name: player_companion_npcs_fk_skills + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: skill_like_lists + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - spells + match_type: '' + name: player_companion_npcs_fk_spells + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: skill_like_lists + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - stats + match_type: '' + name: player_companion_npcs_fk_stats + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: stats + type: FOREIGN KEY + fields: + equipment: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: equipment + order: 8 + size: + - 0 + exp: + data_type: integer + default_value: !!perl/ref + =: 1 + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: exp + order: 7 + size: + - 0 + identifier: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: identifier + order: 3 + size: + - 0 + inventory: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: inventory + order: 12 + size: + - 0 + level: + data_type: integer + default_value: !!perl/ref + =: 1 + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: level + order: 6 + size: + - 0 + nick: + data_type: text + default_value: ~ + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: nick + order: 4 + size: + - 0 + owner: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: owner + order: 2 + size: + - 0 + race: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: race + order: 5 + size: + - 0 + skills: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: skills + order: 10 + size: + - 0 + spells: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: spells + order: 11 + size: + - 0 + stats: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: stats + order: 9 + size: + - 0 + uuid: + data_type: uuid + default_value: !!perl/ref + =: uuid_generate_v4() + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: + - fields: + - equipment + name: player_companion_npcs_idx_equipment + options: [] + type: NORMAL + - fields: + - inventory + name: player_companion_npcs_idx_inventory + options: [] + type: NORMAL + - fields: + - owner + name: player_companion_npcs_idx_owner + options: [] + type: NORMAL + - fields: + - skills + name: player_companion_npcs_idx_skills + options: [] + type: NORMAL + - fields: + - spells + name: player_companion_npcs_idx_spells + options: [] + type: NORMAL + - fields: + - stats + name: player_companion_npcs_idx_stats + options: [] + type: NORMAL + name: player_companion_npcs + options: [] + order: 11 + player_pjs: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - born_stats + match_type: '' + name: player_pjs_fk_born_stats + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: stats + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - equipment + match_type: '' + name: player_pjs_fk_equipment + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: equipment + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - inventory + match_type: '' + name: player_pjs_fk_inventory + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: inventories + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - owner + match_type: '' + name: player_pjs_fk_owner + on_delete: CASCADE + on_update: CASCADE + options: [] + reference_fields: + - uuid + reference_table: players + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - skills + match_type: '' + name: player_pjs_fk_skills + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: skill_like_lists + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - spells + match_type: '' + name: player_pjs_fk_spells + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: skill_like_lists + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - team + match_type: '' + name: player_pjs_fk_team + on_delete: CASCADE + on_update: CASCADE + options: [] + reference_fields: + - uuid + reference_table: teams + type: FOREIGN KEY + - deferrable: 1 + expression: '' + fields: + - training_stats + match_type: '' + name: player_pjs_fk_training_stats + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: stats + type: FOREIGN KEY + fields: + born_stats: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: born_stats + order: 12 + size: + - 0 + creation_date: + data_type: timestamp + default_value: !!perl/ref + =: NOW() + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: creation_date + order: 8 + size: + - 0 + equipment: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: equipment + order: 11 + size: + - 0 + experience: + data_type: integer + default_value: !!perl/ref + =: 1 + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: experience + order: 10 + size: + - 0 + full_name: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: full_name + order: 3 + size: + - 0 + health: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: health + order: 17 + size: + - 0 + inventory: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: inventory + order: 16 + size: + - 0 + last_activity: + data_type: timestamp + default_value: !!perl/ref + =: NOW() + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: last_activity + order: 9 + size: + - 0 + mana: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: mana + order: 18 + size: + - 0 + nick: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: nick + order: 5 + size: + - 0 + owner: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: owner + order: 2 + size: + - 0 + race: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: race + order: 6 + size: + - 0 + short_name: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: short_name + order: 4 + size: + - 0 + skills: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: skills + order: 14 + size: + - 0 + spells: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: spells + order: 15 + size: + - 0 + team: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: team + order: 7 + size: + - 0 + training_stats: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: training_stats + order: 13 + size: + - 0 + uuid: + data_type: uuid + default_value: !!perl/ref + =: uuid_generate_v4() + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: + - fields: + - born_stats + name: player_pjs_idx_born_stats + options: [] + type: NORMAL + - fields: + - equipment + name: player_pjs_idx_equipment + options: [] + type: NORMAL + - fields: + - inventory + name: player_pjs_idx_inventory + options: [] + type: NORMAL + - fields: + - owner + name: player_pjs_idx_owner + options: [] + type: NORMAL + - fields: + - skills + name: player_pjs_idx_skills + options: [] + type: NORMAL + - fields: + - spells + name: player_pjs_idx_spells + options: [] + type: NORMAL + - fields: + - team + name: player_pjs_idx_team + options: [] + type: NORMAL + - fields: + - training_stats + name: player_pjs_idx_training_stats + options: [] + type: NORMAL + name: player_pjs + options: [] + order: 10 + players: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - email + match_type: '' + name: unique_constraint_email + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: UNIQUE + - deferrable: 1 + expression: '' + fields: + - username + match_type: '' + name: unique_constraint_username + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: UNIQUE + fields: + email: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 1 + name: email + order: 4 + size: + - 0 + encrypted_password: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: encrypted_password + order: 3 + size: + - 0 + last_activity: + data_type: timestamp + default_value: !!perl/ref + =: NOW() + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: last_activity + order: 8 + size: + - 0 + register_date: + data_type: timestamp + default_value: !!perl/ref + =: NOW() + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: register_date + order: 7 + size: + - 0 + username: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 1 + name: username + order: 2 + size: + - 0 + uuid: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + verification_token: + data_type: text + default_value: ~ + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: verification_token + order: 6 + size: + - 0 + verified: + data_type: boolean + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: verified + order: 5 + size: + - 0 + indices: [] + name: players + options: [] + order: 3 + skill_like_items: + constraints: + - deferrable: 1 + expression: '' + fields: + - identifier + - owner_list + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - owner_list + match_type: '' + name: skill_like_items_fk_owner_list + on_delete: CASCADE + on_update: CASCADE + options: [] + reference_fields: + - uuid + reference_table: skill_like_lists + type: FOREIGN KEY + fields: + identifier: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: identifier + order: 1 + size: + - 0 + level: + data_type: integer + default_value: !!perl/ref + =: 1 + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: level + order: 3 + size: + - 0 + owner_list: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: owner_list + order: 2 + size: + - 0 + indices: + - fields: + - owner_list + name: skill_like_items_idx_owner_list + options: [] + type: NORMAL + name: skill_like_items + options: [] + order: 8 + skill_like_lists: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + fields: + uuid: + data_type: uuid + default_value: !!perl/ref + =: uuid_generate_v4() + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: [] + name: skill_like_lists + options: [] + order: 4 + stats: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + fields: + health: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: health + order: 2 + size: + - 0 + intelligence: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: intelligence + order: 8 + size: + - 0 + magic: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: magic + order: 6 + size: + - 0 + mana: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: mana + order: 3 + size: + - 0 + resistance: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: resistance + order: 5 + size: + - 0 + speed: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: speed + order: 7 + size: + - 0 + strength: + data_type: integer + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: strength + order: 4 + size: + - 0 + uuid: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: [] + name: stats + options: [] + order: 5 + teams: + constraints: + - deferrable: 1 + expression: '' + fields: + - uuid + match_type: '' + name: '' + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: PRIMARY KEY + - deferrable: 1 + expression: '' + fields: + - name + match_type: '' + name: u_name + on_delete: '' + on_update: '' + options: [] + reference_fields: [] + reference_table: '' + type: UNIQUE + - deferrable: 1 + expression: '' + fields: + - leader + match_type: '' + name: teams_fk_leader + on_delete: '' + on_update: '' + options: [] + reference_fields: + - uuid + reference_table: player_pjs + type: FOREIGN KEY + fields: + area: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: area + order: 6 + size: + - 0 + leader: + data_type: uuid + default_value: ~ + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: leader + order: 2 + size: + - 0 + location: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: location + order: 7 + size: + - 0 + name: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 1 + name: name + order: 3 + size: + - 0 + planet: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: planet + order: 4 + size: + - 0 + super_area: + data_type: text + default_value: ~ + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: super_area + order: 5 + size: + - 0 + uuid: + data_type: uuid + default_value: ~ + is_nullable: 0 + is_primary_key: 1 + is_unique: 0 + name: uuid + order: 1 + size: + - 0 + indices: + - fields: + - leader + name: teams_idx_leader + options: [] + type: NORMAL + name: teams + options: [] + order: 9 + triggers: {} + views: {} +translator: + add_drop_table: 0 + filename: ~ + no_comments: 0 + parser_args: + sources: + - CompanionNPC + - Equipment + - EquipmentItem + - Inventory + - InventoryItem + - PJ + - Player + - SkillLikeItem + - SkillLikeList + - Stats + - Team + parser_type: SQL::Translator::Parser::DBIx::Class + producer_args: {} + producer_type: SQL::Translator::Producer::YAML + show_warnings: 0 + trace: 0 + version: 1.63 diff --git a/js-src/components/game.tsx b/js-src/components/game.tsx index d0dcc15..c7ee577 100644 --- a/js-src/components/game.tsx +++ b/js-src/components/game.tsx @@ -1,12 +1,14 @@ import * as React from 'react' +import { PJ } from '@lastres/pj' + import UpperPanel from '@lastres/components/upper-panel' import BottomPanel from '@lastres/components/bottom-panel' import PJSelectionMenu from '@lastres/components/pj-selection-menu' export interface GameProps { - setSelectedPJ: (set: string | null) => void - selectedPJ: string | null + setSelectedPJ: (set: PJ | null) => void + selectedPJ: PJ | null userWantsToCreatePJ: boolean setUserWantsToCreatePJ: (set: boolean) => void error: string | null @@ -26,6 +28,18 @@ export default function Game (props: GameProps): JSX.Element { ) } + window.setTimeout(() => { + const locationProtocol = window.location.protocol + if (locationProtocol == null) { + return + } + const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws' + const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`) + webSocket.onopen = () => { + webSocket.send(JSON.stringify({hola: "mundo"})) + }; + + }, 1); return ( <> diff --git a/js-src/components/page.tsx b/js-src/components/page.tsx index 9003859..f8df638 100644 --- a/js-src/components/page.tsx +++ b/js-src/components/page.tsx @@ -1,5 +1,7 @@ import * as React from 'react' +import { PJ } from '@lastres/pj' + import LoginPage from '@lastres/components/login-page' import Game from '@lastres/components/game' import { checkLogin } from '@lastres/login' @@ -11,7 +13,7 @@ export default function Page (): JSX.Element { const [userWantsToCreatePJ, setUserWantsToCreatePJ] = React.useState(false) const [isAskingForRegistration, setIsAskingForRegistration] = React.useState(false) const [error, setError] = React.useState(null) - const [selectedPJ, setSelectedPJ] = React.useState(null) + const [selectedPJ, setSelectedPJ] = React.useState(null) checkLogin(setError, setIsLoggedIn) if (!isLoggedIn) { return notLoggedRender(setIsLoggedIn, isAskingForRegistration, setIsAskingForRegistration, error, setError) diff --git a/js-src/components/pj-creation-menu.tsx b/js-src/components/pj-creation-menu.tsx index 15313ea..9634225 100644 --- a/js-src/components/pj-creation-menu.tsx +++ b/js-src/components/pj-creation-menu.tsx @@ -1,8 +1,10 @@ import * as React from 'react' +import { PJ } from '@lastres/pj' + export interface PJCreationMenuProps { error: string | null - setSelectedPJ: (set: string | null) => void + setSelectedPJ: (set: PJ | null) => void setUserWantsToCreatePJ: (set: boolean) => void setError: (set: string | null) => void } diff --git a/js-src/components/pj-health-like-bar.tsx b/js-src/components/pj-health-like-bar.tsx new file mode 100644 index 0000000..1543e32 --- /dev/null +++ b/js-src/components/pj-health-like-bar.tsx @@ -0,0 +1,14 @@ +import * as React from 'react' + +export interface PJHealthLikeBarProps { + value: number + max: number +} +export default function PJHealthLikeBar(props: PJHealthLikeBarProps): JSX.Element { + const percentage = ((props.value / props.max) * 100) + '%'; + return ( +
+
+
+ ) +} diff --git a/js-src/components/pj-list-selection.tsx b/js-src/components/pj-list-selection.tsx new file mode 100644 index 0000000..0cf68da --- /dev/null +++ b/js-src/components/pj-list-selection.tsx @@ -0,0 +1,42 @@ +import * as React from 'react' +import { PJ } from '@lastres/pj' +import PJHealthLikeBar from '@lastres/components/pj-health-like-bar' + +interface PJListSelectionProps { + pjs: PJ[] | null + setSelectedPJ: (set: PJ | null) => void +} + +export default function PJListSelection(props: PJListSelectionProps) { + const pjs = props.pjs + if (pjs === null) { + return ( + <> + + ) + } + return ( + <> + { + pjs.map( (item, i) => + { + props.setSelectedPJ(item) + }} + href="#" + key={i}> + {item.full_name} + {item.short_name} + {item.nick} + + + ) + } + + ) +} diff --git a/js-src/components/pj-selection-menu.tsx b/js-src/components/pj-selection-menu.tsx index c81d8fe..24e5f70 100644 --- a/js-src/components/pj-selection-menu.tsx +++ b/js-src/components/pj-selection-menu.tsx @@ -1,8 +1,10 @@ import * as React from 'react' import PJCreationMenu from '@lastres/components/pj-creation-menu' +import PJListSelection from '@lastres/components/pj-list-selection' +import { PJ, fetchMyPjs } from '@lastres/pj' export interface PJSelectionMenuProps { - setSelectedPJ: (set: string | null) => void + setSelectedPJ: (set: PJ | null) => void setUserWantsToCreatePJ: (set: boolean) => void userWantsToCreatePJ: boolean error: string | null @@ -10,6 +12,7 @@ export interface PJSelectionMenuProps { } export default function PJSelectionMenu (props: PJSelectionMenuProps): JSX.Element { + const [pjs, setPJs] = React.useState(null) const createPJ = (): void => { props.setUserWantsToCreatePJ(true) } @@ -22,6 +25,10 @@ export default function PJSelectionMenu (props: PJSelectionMenuProps): JSX.Eleme setError={props.setError}/> ) } + if (pjs === null) { + fetchMyPjs(props.setError) + .then((pjs)=> { setPJs(pjs) }) + } return (
@@ -29,6 +36,7 @@ export default function PJSelectionMenu (props: PJSelectionMenuProps): JSX.Eleme

Selecciona un Personaje

diff --git a/js-src/pj.ts b/js-src/pj.ts new file mode 100644 index 0000000..b6c7c9f --- /dev/null +++ b/js-src/pj.ts @@ -0,0 +1,32 @@ +export interface PJ { + full_name: string + short_name: string + nick: string + health: number + mana: number + max_mana: number + max_health: number + race: string + uuid: string +} + +export async function fetchMyPjs(setError: (set: string | null) => void): Promise { + const response = await fetch('/my/pjs', { + method: 'GET', + mode: 'same-origin', + cache: 'no-cache' + }).catch((error) => { + console.log(error); + setError('Error recuperando tus pjs') + }) + if (response === undefined) { + return [] + } + const statusCode = response.status + const data = await response.json() + if (statusCode !== 200) { + setError(data.error) + return [] + } + return data +} diff --git a/lib/LasTres.pm b/lib/LasTres.pm index 4327a9b..9406d51 100644 --- a/lib/LasTres.pm +++ b/lib/LasTres.pm @@ -34,11 +34,12 @@ sub startup ($self) { my $sessions = Mojolicious::Sessions->new; $sessions->cookie_name('LasTres'); - $sessions->default_expiration(86400); + $sessions->default_expiration(0); # Normal route to controller $r->get('/')->to('Root#index'); $r->get('/races/playable')->to('Race#playable'); + $r->get('/my/pjs')->to('PJ#list_my_pjs'); $r->post('/player/register')->to('Player#register'); $r->post('/player/login')->to('Player#login'); diff --git a/lib/LasTres/Controller/PJ.pm b/lib/LasTres/Controller/PJ.pm index bdaae6f..909771e 100644 --- a/lib/LasTres/Controller/PJ.pm +++ b/lib/LasTres/Controller/PJ.pm @@ -7,6 +7,8 @@ use warnings; use UUID::URandom qw/create_uuid_string/; +use Try::Tiny; + use LasTres::DAO::PJs; use LasTres::DAO::Equipments; use LasTres::DAO::Teams; @@ -26,6 +28,36 @@ my $result_set_stats = LasTres::DAO::Stats->ResultSet; my $result_set_skill_like_list = LasTres::DAO::SkillLikeLists->ResultSet; my $result_set_inventory = LasTres::DAO::Inventories->ResultSet; +sub list_my_pjs ($self) { + my $user = $self->user; + if ( !defined $user ) { + return $self->render( + status => 401, + json => { error => 'You must login first.' } + ); + } + my @pjs = $user->pjs; + my @pjs_hash = ( + map { + { + uuid => $_->uuid, + full_name => $_->full_name, + short_name => $_->short_name, + nick => $_->nick, + race => $_->race, + health => $_->health, + max_health => $_->max_health, + mana => $_->mana, + max_mana => $_->max_mana, + } + } @pjs + ); + return $self->render( + status => 200, + json => \@pjs_hash, + ); +} + sub create ($self) { my %param = %{ $self->req->json }; my $user = $self->user; @@ -77,19 +109,23 @@ sub create ($self) { if ( !defined $race ) { return $self->_invalid_race; } - eval { + my $exception; + try { $schema->txn_do( sub { $self->_insert_new_player( $owner, $full_name, $short_name, $nick, $race ); } ); - }; - if ($@) { - if ( $@ =~ /Rollback failed/ ) { + } + catch { + $exception = $_; + if ( $_ =~ /Rollback failed/ ) { say STDERR "Unable to rollback failed transaction:"; } - say STDERR $@; + say STDERR $_; + }; + if ( defined $exception ) { return $self->render( status => 500, json => { error => 'Database error' }, @@ -172,9 +208,10 @@ sub _insert_new_player ( $self, $owner, $full_name, $short_name, $nick, $race ) skills => $uuid_skills, spells => $uuid_spells, inventory => $uuid_inventory, + health => 999, + mana => 999, } )->insert; - die "Error setting leader"; $team->leader($uuid_pj); $team->update; } diff --git a/lib/LasTres/Controller/Websocket.pm b/lib/LasTres/Controller/Websocket.pm index 85ef8d1..78f8a19 100644 --- a/lib/LasTres/Controller/Websocket.pm +++ b/lib/LasTres/Controller/Websocket.pm @@ -5,28 +5,71 @@ use v5.36.0; use strict; use warnings; -use Mojo::Base 'Mojolicious::Controller', -signatures; +use JSON qw/encode_json/; +use UUID::URandom qw/create_uuid_string/; -sub ws($self) { +use Mojo::Base 'Mojolicious::Controller', -signatures; +use Data::Dumper; + +use LasTres::Redis; +use LasTres::DAO::PJs; +use LasTres::Controller::Websocket::InputPackets; + +my %sessions; +my $result_set_pjs = LasTres::DAO::PJs->ResultSet; + +my $redis = LasTres::Redis->new; +my $input_packets = LasTres::Controller::Websocket::InputPackets->new; + +sub ws ($self) { my $user = $self->user; - if (!defined $user) { + if ( !defined $user ) { return $self->render( status => 401, - json => { + json => { error => 'You are not logged in.', } ); } - if (!$user->verified) { - return $self->render( - status => 401, - json => { - error => 'Your user is not verified.', - } - ); + my $session_uuid = create_uuid_string; + $sessions{$session_uuid} = { + user => $user, + controller => $self, + uuid => $session_uuid, + }; + my $session = $sessions{$session_uuid}; + $self->on( + json => sub ( $self, $hash ) { + $self->_handle_packet( $session, $hash ); + } + ); + $self->on( + finish => sub ( $self, $code, $reason ) { + delete $sessions{$session_uuid}; + say STDERR +"Websocket for user @{[$user->username]} closed with status $code and reason $reason."; + } + ); +} + +{ + sub _handle_packet ( $self, $session, $hash ) { + my $command = $hash->{command}; + if ( !defined $command ) { + say STDERR "No command."; + $self->send( encode_json( { error => "No command" } ) ); + return; + } + my $input_packet = $input_packets->hash->{$command) + + if ( !defined $input_packet ) { + say STDERR "Unknown command $command."; + $self->send( + encode_json( { error => "Unknown command $command" } ) ); + return; + } + my $data = $hash->{data}; + return $input_packet->handle( $self, $session, $data ); } - $self->on(json => sub($self, $hash) { - $self->_handle_packet($user, $hash); - }); } 1; diff --git a/lib/LasTres/Controller/Websocket/InputPacket.pm b/lib/LasTres/Controller/Websocket/InputPacket.pm new file mode 100644 index 0000000..d7acb8c --- /dev/null +++ b/lib/LasTres/Controller/Websocket/InputPacket.pm @@ -0,0 +1,13 @@ +package LasTres::Controller::Websocket::InputPacket; + +use v5.36.0; + +use strict; +use warnings; + +use feature 'signatures'; + +use Moo::Role; + +requires qw/new handle identifier/; +1; diff --git a/lib/LasTres/Controller/Websocket/InputPacket/Init.pm b/lib/LasTres/Controller/Websocket/InputPacket/Init.pm new file mode 100644 index 0000000..d3b79f0 --- /dev/null +++ b/lib/LasTres/Controller/Websocket/InputPacket/Init.pm @@ -0,0 +1,42 @@ +package LasTres::Controller::Websocket::InputPacket::Init; + +use v5.36.0; + +use strict; +use warnings; + +use Moo; + +use LasTres::Redis; + +with 'LasTres::Controller::Websocket::InputPacket'; + +sub identifier { + return 'init'; +} + +my $redis = LasTres::Redis->new; + +sub handle ( $self, $ws, $session, $data ) { + if (ref $data ne 'HASH') { + return $ws->send( encode_json( { error => "Data should be a hashref." } ) ); + } + my $pj_uuid = $data->{pj_uuid}; + if ( !defined $pj_uuid ) { + return $ws->send( encode_json( { error => "No pj sent." } ) ); + } + my @pjs = $result_set_pjs->search( { uuid => $pj_uuid } ); + if ( !scalar @pjs ) { + return $ws->send( + encode_json( { error => 'This pj does not exists' } ) ); + } + my $pj = $pjs[0]; + my $user = $session->{user}; + if ( $pj->owner->uuid ne $user->uuid ) { + return $ws->send( + encode_json( { error => 'You are not the owner of this pj.' } ) ); + } + $session->{pj} = $pj; +} + +1; diff --git a/lib/LasTres/Controller/Websocket/InputPackets.pm b/lib/LasTres/Controller/Websocket/InputPackets.pm new file mode 100644 index 0000000..dcb6573 --- /dev/null +++ b/lib/LasTres/Controller/Websocket/InputPackets.pm @@ -0,0 +1,28 @@ +package LasTres::Controller::Websocket::InputPackets; + +use v5.36.0; + +use strict; +use warnings; + +use Moo; + +use Module::Pluggable search_path => ['LasTres::Controller::Websocket::InputPacket'], + instantiate => 'new', + on_require_error => sub ($plugin, $error) { + die $error; + }; + + +has hash => ( + is => 'lazy', +); + +sub _build_hash($self) { + my %hash; + for my $packet ($self->plugins()) { + $hash{$packet->identifier} = $packet; + } + return \%hash; +} +1; diff --git a/lib/LasTres/Controller/Websocket/OutputPacket.pm b/lib/LasTres/Controller/Websocket/OutputPacket.pm new file mode 100644 index 0000000..e58ea56 --- /dev/null +++ b/lib/LasTres/Controller/Websocket/OutputPacket.pm @@ -0,0 +1,22 @@ +package LasTres::Controller::Websocket::OutputPacket; + +use v5.36.0; + +use strict; +use warnings; + +use Moo::Role; + +requires qw/new identifier data/; + +sub send ( $self, $ws ) { + return $ws->send( + encode_json( + { + command => $self->identifier, + data => $self->data + } + ) + ); +} +1; diff --git a/lib/LasTres/Controller/Websocket/OutputPacket/Info.pm b/lib/LasTres/Controller/Websocket/OutputPacket/Info.pm new file mode 100644 index 0000000..c1a8b21 --- /dev/null +++ b/lib/LasTres/Controller/Websocket/OutputPacket/Info.pm @@ -0,0 +1,51 @@ +package LasTres::Controller::Websocket::OutputPacket::Info; + +use v5.36.0; + +use strict; +use warnings; + +use feature 'signatures'; + +with 'LasTres::Controller::Websocket::OutputPacket'; + +has clear => ( + is => 'rw', +); + +has team_pjs => ( + is => 'rw', +); + +has location_data => ( + is => 'rw', +); + +sub identifier { + return 'info'; +} + +sub data($self) { + my $clear = $self->clear; + my $team_pjs = $self->team_pjs; + my $location_data = $self->location_data; + return { + ( + (defined $clear) + ? (clear => $clear) + : () + ), + ( + (defined $team_pjs) + ? (team_pjs => $team_pjs) + : () + ), + ( + (defined $location_data) + ? (location_data => $location_data) + : () + ) + }; +} + +1; diff --git a/lib/LasTres/Redis.pm b/lib/LasTres/Redis.pm new file mode 100644 index 0000000..9664dfc --- /dev/null +++ b/lib/LasTres/Redis.pm @@ -0,0 +1,30 @@ +package LasTres::Redis; + +use v5.36.0; + +use strict; +use warnings; + +use feature 'signatures'; + +use parent 'Redis'; + +use LasTres::Schema; +our $VERSION = $LasTres::Schema::VERSION; + + +{ + my $cached_redis; + sub new { + my $class = shift; + if (!defined $cached_redis) { + $cached_redis = $class->SUPER::new(@_); + } + return $cached_redis; + } +} + +sub prefix { + return "LasTres::Redis::$VERSION"; +} +1; diff --git a/lib/LasTres/Schema.pm b/lib/LasTres/Schema.pm index 3db6f32..251c203 100644 --- a/lib/LasTres/Schema.pm +++ b/lib/LasTres/Schema.pm @@ -1,5 +1,5 @@ package LasTres::Schema; -our $VERSION = 3; +our $VERSION = 4; use v5.36.0; @@ -14,27 +14,31 @@ use parent 'DBIx::Class::Schema'; __PACKAGE__->load_namespaces(); +my $schema; sub Schema($class) { - my $app = LasTres->new; - my $config = $app->{config}; - my $database_config = $config->{database}; - my $dbname = $database_config->{dbname}; - my $host = $database_config->{host}; - my $port = $database_config->{port}; - my $user = $database_config->{user}; - my $password = $database_config->{password}; - my $dsn = 'dbi:Pg:'; - if (!defined $dbname) { - die "The key database/dbname must be configured."; + if (!defined $schema) { + my $app = LasTres->new; + my $config = $app->{config}; + my $database_config = $config->{database}; + my $dbname = $database_config->{dbname}; + my $host = $database_config->{host}; + my $port = $database_config->{port}; + my $user = $database_config->{user}; + my $password = $database_config->{password}; + my $dsn = 'dbi:Pg:'; + if (!defined $dbname) { + die "The key database/dbname must be configured."; + } + $dsn .= "dbname=$dbname"; + if (defined $host) { + $dsn .= ";host=$host"; + } + if (defined $port) { + $dsn .= ";port=$port"; + } + # Undef is perfectly fine for username and password. + $schema = $class->connect($dsn, $user, $password, {auto_savepoint => 1}); } - $dsn .= "dbname=$dbname"; - if (defined $host) { - $dsn .= ";host=$host"; - } - if (defined $port) { - $dsn .= ";port=$port"; - } - # Undef is perfectly fine for username and password. - return $class->connect($dsn, $user, $password); + return $schema; } 1; diff --git a/lib/LasTres/Schema/Result/PJ.pm b/lib/LasTres/Schema/Result/PJ.pm index d4eb1fe..ba63a93 100644 --- a/lib/LasTres/Schema/Result/PJ.pm +++ b/lib/LasTres/Schema/Result/PJ.pm @@ -5,96 +5,200 @@ use v5.36.0; use strict; use warnings; +use feature 'signatures'; + use parent 'DBIx::Class::Core'; +use Data::Dumper; + +use LasTres::Schema; + +use Moo; + __PACKAGE__->table('player_pjs'); __PACKAGE__->add_columns( uuid => { - data_type => 'uuid', + data_type => 'uuid', default_value => \'uuid_generate_v4()', - is_nullable => 0, + is_nullable => 0, }, owner => { - data_type => 'uuid', - is_nullable => 0, + data_type => 'uuid', + is_nullable => 0, is_foreign_key => 1, }, full_name => { - data_type => 'text', + data_type => 'text', is_nullable => 0, }, short_name => { - data_type => 'text', + data_type => 'text', is_nullable => 0, }, nick => { - data_type => 'text', + data_type => 'text', is_nullable => 0, }, race => { - data_type => 'text', + data_type => 'text', is_nullable => 0, }, team => { - data_type => 'uuid', + data_type => 'uuid', is_nullable => 0, }, creation_date => { - data_type => 'timestamp', + data_type => 'timestamp', default_value => \'NOW()', - is_nullable => 0, + is_nullable => 0, }, last_activity => { - data_type => 'timestamp', + data_type => 'timestamp', default_value => \'NOW()', - is_nullable => 0, + is_nullable => 0, }, experience => { - data_type => 'integer', + data_type => 'integer', default_value => \'1', - is_nullable => 0, + is_nullable => 0, }, equipment => { - data_type => 'uuid', - is_nullable => 0, + data_type => 'uuid', + is_nullable => 0, is_foreign_key => 1, }, born_stats => { - data_type => 'uuid', + data_type => 'uuid', is_foreign_key => 1, - is_nullable => 0, + is_nullable => 0, }, training_stats => { - data_type => 'uuid', + data_type => 'uuid', is_foreign_key => 1, - is_nullable => 0, + is_nullable => 0, }, skills => { - data_type => 'uuid', - is_nullable => 0, + data_type => 'uuid', + is_nullable => 0, is_foreign_key => 1, }, spells => { - data_type => 'uuid', - is_nullable => 0, + data_type => 'uuid', + is_nullable => 0, is_foreign_key => 1, }, inventory => { - data_type => 'uuid', + data_type => 'uuid', + is_nullable => 0, + }, + health => { + data_type => 'integer', + accessor => '_health', + is_nullable => 0, + }, + mana => { + data_type => 'integer', + accessor => '_mana', is_nullable => 0, } ); __PACKAGE__->set_primary_key('uuid'); -__PACKAGE__->has_many('npcs', 'LasTres::Schema::Result::CompanionNPC', 'owner'); -__PACKAGE__->belongs_to('born_stats', 'LasTres::Schema::Result::Stats'); -__PACKAGE__->belongs_to('training_stats', 'LasTres::Schema::Result::Stats'); -__PACKAGE__->belongs_to('inventory', 'LasTres::Schema::Result::Inventory'); -__PACKAGE__->belongs_to('skills', 'LasTres::Schema::Result::SkillLikeList'); -__PACKAGE__->belongs_to('spells', 'LasTres::Schema::Result::SkillLikeList'); -__PACKAGE__->belongs_to('equipment', 'LasTres::Schema::Result::Equipment'); -__PACKAGE__->belongs_to('team', 'LasTres::Schema::Result::Team'); -__PACKAGE__->belongs_to('owner', 'LasTres::Schema::Result::Player'); +__PACKAGE__->has_many( 'npcs', 'LasTres::Schema::Result::CompanionNPC', + 'owner' ); +__PACKAGE__->belongs_to( 'born_stats', 'LasTres::Schema::Result::Stats' ); +__PACKAGE__->belongs_to( 'training_stats', 'LasTres::Schema::Result::Stats' ); +__PACKAGE__->belongs_to( 'inventory', 'LasTres::Schema::Result::Inventory' ); +__PACKAGE__->belongs_to( 'skills', 'LasTres::Schema::Result::SkillLikeList' ); +__PACKAGE__->belongs_to( 'spells', 'LasTres::Schema::Result::SkillLikeList' ); +__PACKAGE__->belongs_to( 'equipment', 'LasTres::Schema::Result::Equipment' ); +__PACKAGE__->belongs_to( 'team', 'LasTres::Schema::Result::Team' ); +__PACKAGE__->belongs_to( 'owner', 'LasTres::Schema::Result::Player' ); + +my $columns = __PACKAGE__->columns_info; +for my $column_name (keys %$columns) { + my $column = $columns->{$column_name}; + my $is_nullable = $column->{is_nullable}; + $is_nullable //= 0; + my $required = !$is_nullable; + has $column_name => ( + is => 'rw', + required => $required, + accessor => "_moo_$column_name", + ); +} + +sub max_health ($self) { + my $races = LasTres::Races->new; + my $race = $races->hash_playable->{$self->race}; + my $health_base_race = $race->base_stats->health; + my $health_born = $self->born_stats->health; + my $health_training = $self->training_stats->health; + my $health_mix = + 2 * $health_base_race + $health_born + ( $health_training / 4 ); + my $health_scaled = ( ( $health_mix * $self->level ) / 100 ); + return int($health_scaled + $self->level + 10); +} + +sub max_mana ($self) { + my $races = LasTres::Races->new; + my $race = $races->hash_playable->{$self->race}; + my $mana_base_race = $race->base_stats->mana; + my $mana_born = $self->born_stats->mana; + my $mana_training = $self->training_stats->mana; + my $mana_mix = + 2 * $mana_base_race + $mana_born + ( $mana_training / 4 ); + my $mana_scaled = ( ( $mana_mix * $self->level ) / 100 ); + return int($mana_scaled + $self->level + 10); +} + +sub health { + my $self = shift; + my $health_to_set = shift; + my $schema = LasTres::Schema->Schema; + $schema->txn_do(sub { + if (defined $health_to_set) { + $self->_health($health_to_set); + $self->update; + } + my $health = $self->_health; + if ($health < 0) { + $self->_health(0); + $self->update; + } + if ($health > $self->max_health) { + $self->_health($self->max_health); + $self->update; + } + }); + return $self->_health; +} + +sub mana { + my $self = shift; + my $mana_to_set = shift; + my $schema = LasTres::Schema->Schema; + $schema->txn_do(sub { + if (defined $mana_to_set) { + $self->_mana($mana_to_set); + $self->update; + } + my $mana = $self->_mana; + if ($mana < 0) { + $self->_mana(0); + $self->update; + } + if ($mana > $self->max_mana) { + $self->_mana($self->max_mana); + $self->update; + } + }); + return $self->_mana; +} + +sub level ($self) { + return $self->experience**( 1 / 3 ); +} 1; diff --git a/lib/LasTres/Schema/Result/Team.pm b/lib/LasTres/Schema/Result/Team.pm index c24e389..bcae2c5 100644 --- a/lib/LasTres/Schema/Result/Team.pm +++ b/lib/LasTres/Schema/Result/Team.pm @@ -26,22 +26,43 @@ __PACKAGE__->add_columns( planet => { data_type => 'text', is_nullable => 0, + accessor => '_planet', }, super_area => { data_type => 'text', is_nullable => 0, + accessor => '_super_area', }, area => { data_type => 'text', is_nullable => 0, + accessor => '_area', }, location => { data_type => 'text', is_nullable => 0, + accessor => '_location', }, ); - +sub location { + my $self = shift; + my $location = shift; + if (defined $location) { + $self->_location($location->identifier); + my $area = $location->parent; + $self->_area($area->identifier); + my $super_area = $area->parent; + $self->_super_area($super_area->identifier) + my $planet = $super_area->parent; + $self->_planet($planet->identifier); + } + my $location = $self->_location; + my $area = $self->_area; + my $super_area = $self->_super_area; + my $planet = $self->_planet; + return $location; +} __PACKAGE__->set_primary_key('uuid'); __PACKAGE__->add_unique_constraint(u_name => ['name']); __PACKAGE__->has_many('members', 'LasTres::Schema::Result::PJ', 'team'); diff --git a/public/css/styles.css b/public/css/styles.css index af78ffc..886993a 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -1,7 +1,8 @@ body { margin: 0px; padding: 0px; - min-height: 100%; } + min-height: 100%; + background: ghostwhite; } body div.width-max-content { width: max-content; } body div#game-container { @@ -65,6 +66,7 @@ body { box-shadow: 3px 1px 3px 3px #333; color: blue; display: flex; + flex-direction: column; align-items: center; justify-content: center; text-align: center; @@ -72,6 +74,15 @@ body { body div.pj-selection-menu div.pj-selection-menu-container div.pj-list a:hover { color: yellow; background: gray; } + body div.pj-selection-menu div.pj-selection-menu-container div.pj-list a label { + width: 90%; } + body div.pj-selection-menu div.pj-selection-menu-container div.pj-list a label div.bar { + width: 100%; + height: 1em; + border: solid 1px black; } + body div.pj-selection-menu div.pj-selection-menu-container div.pj-list a label div.bar div.filled { + background: lightgreen; + height: 100%; } body div.login-container { display: flex; justify-content: center; diff --git a/public/css/styles.scss b/public/css/styles.scss index 2fa37d2..bd550b8 100644 --- a/public/css/styles.scss +++ b/public/css/styles.scss @@ -2,6 +2,7 @@ body { margin: 0px; padding: 0px; min-height: 100%; + background: ghostwhite; div.width-max-content { width: max-content; } @@ -73,6 +74,7 @@ body { box-shadow: 3px 1px 3px 3px #333; color: blue; display: flex; + flex-direction: column; align-items: center; justify-content: center; text-align: center; @@ -81,6 +83,18 @@ body { background: gray; } text-decoration: none; + label { + width: 90%; + div.bar { + width: 100%; + height: 1em; + border: solid 1px black; + div.filled { + background: lightgreen; + height: 100%; + } + } + } } } } diff --git a/public/js/bundle.js b/public/js/bundle.js index ac629d5..a6e81b8 100644 --- a/public/js/bundle.js +++ b/public/js/bundle.js @@ -96,7 +96,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Game)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/upper-panel */ \"./js-src/components/upper-panel.tsx\");\n/* harmony import */ var _lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/bottom-panel */ \"./js-src/components/bottom-panel.tsx\");\n/* harmony import */ var _lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/components/pj-selection-menu */ \"./js-src/components/pj-selection-menu.tsx\");\n\n\n\n\nfunction Game(props) {\n if (props.selectedPJ === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__[\"default\"], { setSelectedPJ: props.setSelectedPJ, userWantsToCreatePJ: props.userWantsToCreatePJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError })));\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/game.tsx?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Game)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/upper-panel */ \"./js-src/components/upper-panel.tsx\");\n/* harmony import */ var _lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/bottom-panel */ \"./js-src/components/bottom-panel.tsx\");\n/* harmony import */ var _lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/components/pj-selection-menu */ \"./js-src/components/pj-selection-menu.tsx\");\n\n\n\n\nfunction Game(props) {\n if (props.selectedPJ === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__[\"default\"], { setSelectedPJ: props.setSelectedPJ, userWantsToCreatePJ: props.userWantsToCreatePJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError })));\n }\n window.setTimeout(() => {\n const locationProtocol = window.location.protocol;\n if (locationProtocol == null) {\n return;\n }\n const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws';\n const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`);\n webSocket.onopen = () => {\n webSocket.send(JSON.stringify({ hola: \"mundo\" }));\n };\n }, 1);\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/game.tsx?"); /***/ }), @@ -130,13 +130,33 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ }), +/***/ "./js-src/components/pj-health-like-bar.tsx": +/*!**************************************************!*\ + !*** ./js-src/components/pj-health-like-bar.tsx ***! + \**************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PJHealthLikeBar)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n\nfunction PJHealthLikeBar(props) {\n const percentage = ((props.value / props.max) * 100) + '%';\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"bar\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"filled\", style: { width: percentage } })));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/pj-health-like-bar.tsx?"); + +/***/ }), + +/***/ "./js-src/components/pj-list-selection.tsx": +/*!*************************************************!*\ + !*** ./js-src/components/pj-list-selection.tsx ***! + \*************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PJListSelection)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-health-like-bar */ \"./js-src/components/pj-health-like-bar.tsx\");\n\n\nfunction PJListSelection(props) {\n const pjs = props.pjs;\n if (pjs === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null));\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, pjs.map((item, i) => react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"a\", { onClick: () => {\n props.setSelectedPJ(item);\n }, href: \"#\", key: i },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", null, item.full_name),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", null, item.short_name),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", null, item.nick),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"label\", null,\n \"Salud\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { value: item.health, max: item.max_health })),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"label\", null,\n \"Mana\",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_health_like_bar__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { value: item.mana, max: item.max_mana }))))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/pj-list-selection.tsx?"); + +/***/ }), + /***/ "./js-src/components/pj-selection-menu.tsx": /*!*************************************************!*\ !*** ./js-src/components/pj-selection-menu.tsx ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PJSelectionMenu)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_creation_menu__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-creation-menu */ \"./js-src/components/pj-creation-menu.tsx\");\n\n\nfunction PJSelectionMenu(props) {\n const createPJ = () => {\n props.setUserWantsToCreatePJ(true);\n };\n if (props.userWantsToCreatePJ) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_creation_menu__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { setSelectedPJ: props.setSelectedPJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError }));\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-selection-menu\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-selection-menu-container\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"h1\", null, \"L3TDE\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"h2\", null, \"Selecciona un Personaje\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-list\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"a\", { onClick: createPJ, href: \"#\" }, \"Crear un nuevo personaje\")))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/pj-selection-menu.tsx?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PJSelectionMenu)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_creation_menu__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-creation-menu */ \"./js-src/components/pj-creation-menu.tsx\");\n/* harmony import */ var _lastres_components_pj_list_selection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/pj-list-selection */ \"./js-src/components/pj-list-selection.tsx\");\n/* harmony import */ var _lastres_pj__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/pj */ \"./js-src/pj.ts\");\n\n\n\n\nfunction PJSelectionMenu(props) {\n const [pjs, setPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const createPJ = () => {\n props.setUserWantsToCreatePJ(true);\n };\n if (props.userWantsToCreatePJ) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_creation_menu__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { setSelectedPJ: props.setSelectedPJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError }));\n }\n if (pjs === null) {\n (0,_lastres_pj__WEBPACK_IMPORTED_MODULE_3__.fetchMyPjs)(props.setError)\n .then((pjs) => { setPJs(pjs); });\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-selection-menu\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-selection-menu-container\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"h1\", null, \"L3TDE\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"h2\", null, \"Selecciona un Personaje\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"pj-list\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"a\", { onClick: createPJ, href: \"#\" }, \"Crear un nuevo personaje\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_list_selection__WEBPACK_IMPORTED_MODULE_2__[\"default\"], { setSelectedPJ: props.setSelectedPJ, pjs: pjs })))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/pj-selection-menu.tsx?"); /***/ }), @@ -178,6 +198,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var reac eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ checkLogin: () => (/* binding */ checkLogin)\n/* harmony export */ });\nfunction checkLogin(setError, setIsLoggedIn) {\n fetch('/player/check_login', {\n method: 'POST',\n mode: 'same-origin',\n cache: 'no-cache'\n }).then(async (response) => {\n const data = await response.json();\n if (data.is_login === 1) {\n setIsLoggedIn(true);\n }\n }).catch((error) => {\n console.log(error);\n });\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/login.ts?"); +/***/ }), + +/***/ "./js-src/pj.ts": +/*!**********************!*\ + !*** ./js-src/pj.ts ***! + \**********************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ fetchMyPjs: () => (/* binding */ fetchMyPjs)\n/* harmony export */ });\nasync function fetchMyPjs(setError) {\n const response = await fetch('/my/pjs', {\n method: 'GET',\n mode: 'same-origin',\n cache: 'no-cache'\n }).catch((error) => {\n console.log(error);\n setError('Error recuperando tus pjs');\n });\n if (response === undefined) {\n return [];\n }\n const statusCode = response.status;\n const data = await response.json();\n if (statusCode !== 200) {\n setError(data.error);\n return [];\n }\n return data;\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/pj.ts?"); + /***/ }) /******/ }); diff --git a/script/prepare.pl b/script/prepare.pl index 3e93297..d20b6b4 100644 --- a/script/prepare.pl +++ b/script/prepare.pl @@ -1,5 +1,5 @@ #!/usr/bin/env perl - + use strict; use warnings; use aliased 'DBIx::Class::DeploymentHandler' => 'DH'; @@ -7,15 +7,15 @@ use Getopt::Long; use FindBin; use lib "$FindBin::Bin/../lib"; use LasTres::Schema; - + my $force_overwrite = 1; - + unless ( GetOptions( 'force_overwrite!' => \$force_overwrite ) ) { die "Invalid options"; } - + my $schema = LasTres::Schema->Schema; - + my $dh = DH->new( { schema => $schema, @@ -25,11 +25,15 @@ my $dh = DH->new( force_overwrite => $force_overwrite, } ); - + $dh->prepare_deploy; eval { - $dh->prepare_upgrade; + $dh->prepare_upgrade({ + from_version => $LasTres::Schema::VERSION - 1, + to_version => $LasTres::Schema::VERSION + }); }; if ($@) { + print "$@\n"; $dh->prepare_install; }