Adding pj selection.
This commit is contained in:
parent
caa8fa7b75
commit
aa9c652fcb
1
Build.PL
1
Build.PL
@ -19,6 +19,7 @@ my $build = Module::Build->new(
|
||||
'DBIx::Class::DeploymentHandler' => 0,
|
||||
'UUID::URandom' => 0,
|
||||
'Module::Pluggable' => 0,
|
||||
'Redis' => 0,
|
||||
},
|
||||
);
|
||||
$build->create_build_script;
|
||||
|
18
dbicdh/PostgreSQL/deploy/4/001-auto-__VERSION.sql
Normal file
18
dbicdh/PostgreSQL/deploy/4/001-auto-__VERSION.sql
Normal file
@ -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")
|
||||
);
|
||||
|
||||
;
|
258
dbicdh/PostgreSQL/deploy/4/001-auto.sql
Normal file
258
dbicdh/PostgreSQL/deploy/4/001-auto.sql
Normal file
@ -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;
|
||||
|
||||
;
|
66
dbicdh/PostgreSQL/upgrade/1-4/001-auto.sql
Normal file
66
dbicdh/PostgreSQL/upgrade/1-4/001-auto.sql
Normal file
@ -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;
|
||||
|
15
dbicdh/PostgreSQL/upgrade/3-4/001-auto.sql
Normal file
15
dbicdh/PostgreSQL/upgrade/3-4/001-auto.sql
Normal file
@ -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;
|
||||
|
91
dbicdh/_source/deploy/4/001-auto-__VERSION.yml
Normal file
91
dbicdh/_source/deploy/4/001-auto-__VERSION.yml
Normal file
@ -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
|
1282
dbicdh/_source/deploy/4/001-auto.yml
Normal file
1282
dbicdh/_source/deploy/4/001-auto.yml
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 (
|
||||
<>
|
||||
<UpperPanel/>
|
||||
|
@ -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<boolean>(false)
|
||||
const [isAskingForRegistration, setIsAskingForRegistration] = React.useState<boolean>(false)
|
||||
const [error, setError] = React.useState<string | null>(null)
|
||||
const [selectedPJ, setSelectedPJ] = React.useState<string | null>(null)
|
||||
const [selectedPJ, setSelectedPJ] = React.useState<PJ | null>(null)
|
||||
checkLogin(setError, setIsLoggedIn)
|
||||
if (!isLoggedIn) {
|
||||
return notLoggedRender(setIsLoggedIn, isAskingForRegistration, setIsAskingForRegistration, error, setError)
|
||||
|
@ -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
|
||||
}
|
||||
|
14
js-src/components/pj-health-like-bar.tsx
Normal file
14
js-src/components/pj-health-like-bar.tsx
Normal file
@ -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 (
|
||||
<div className="bar">
|
||||
<div className="filled" style={{width: percentage}}></div>
|
||||
</div>
|
||||
)
|
||||
}
|
42
js-src/components/pj-list-selection.tsx
Normal file
42
js-src/components/pj-list-selection.tsx
Normal file
@ -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) =>
|
||||
<a onClick={() => {
|
||||
props.setSelectedPJ(item)
|
||||
}}
|
||||
href="#"
|
||||
key={i}>
|
||||
<span>{item.full_name}</span>
|
||||
<span>{item.short_name}</span>
|
||||
<span>{item.nick}</span>
|
||||
<label>
|
||||
Salud
|
||||
<PJHealthLikeBar value={item.health} max={item.max_health}/>
|
||||
</label>
|
||||
<label>
|
||||
Mana
|
||||
<PJHealthLikeBar value={item.mana} max={item.max_mana}/>
|
||||
</label>
|
||||
</a> )
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
@ -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<PJ[] | null>(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 (
|
||||
<div className="pj-selection-menu">
|
||||
<div className="pj-selection-menu-container">
|
||||
@ -29,6 +36,7 @@ export default function PJSelectionMenu (props: PJSelectionMenuProps): JSX.Eleme
|
||||
<h2>Selecciona un Personaje</h2>
|
||||
<div className="pj-list">
|
||||
<a onClick={createPJ} href="#">Crear un nuevo personaje</a>
|
||||
<PJListSelection setSelectedPJ={props.setSelectedPJ} pjs={pjs}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
32
js-src/pj.ts
Normal file
32
js-src/pj.ts
Normal file
@ -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<PJ[]> {
|
||||
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
|
||||
}
|
@ -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');
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -5,11 +5,25 @@ 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 => {
|
||||
@ -17,16 +31,45 @@ sub ws($self) {
|
||||
}
|
||||
);
|
||||
}
|
||||
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;
|
||||
|
13
lib/LasTres/Controller/Websocket/InputPacket.pm
Normal file
13
lib/LasTres/Controller/Websocket/InputPacket.pm
Normal file
@ -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;
|
42
lib/LasTres/Controller/Websocket/InputPacket/Init.pm
Normal file
42
lib/LasTres/Controller/Websocket/InputPacket/Init.pm
Normal file
@ -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;
|
28
lib/LasTres/Controller/Websocket/InputPackets.pm
Normal file
28
lib/LasTres/Controller/Websocket/InputPackets.pm
Normal file
@ -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;
|
22
lib/LasTres/Controller/Websocket/OutputPacket.pm
Normal file
22
lib/LasTres/Controller/Websocket/OutputPacket.pm
Normal file
@ -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;
|
51
lib/LasTres/Controller/Websocket/OutputPacket/Info.pm
Normal file
51
lib/LasTres/Controller/Websocket/OutputPacket/Info.pm
Normal file
@ -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;
|
30
lib/LasTres/Redis.pm
Normal file
30
lib/LasTres/Redis.pm
Normal file
@ -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;
|
@ -1,5 +1,5 @@
|
||||
package LasTres::Schema;
|
||||
our $VERSION = 3;
|
||||
our $VERSION = 4;
|
||||
|
||||
use v5.36.0;
|
||||
|
||||
@ -14,7 +14,9 @@ use parent 'DBIx::Class::Schema';
|
||||
|
||||
__PACKAGE__->load_namespaces();
|
||||
|
||||
my $schema;
|
||||
sub Schema($class) {
|
||||
if (!defined $schema) {
|
||||
my $app = LasTres->new;
|
||||
my $config = $app->{config};
|
||||
my $database_config = $config->{database};
|
||||
@ -35,6 +37,8 @@ sub Schema($class) {
|
||||
$dsn .= ";port=$port";
|
||||
}
|
||||
# Undef is perfectly fine for username and password.
|
||||
return $class->connect($dsn, $user, $password);
|
||||
$schema = $class->connect($dsn, $user, $password, {auto_savepoint => 1});
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
1;
|
||||
|
@ -5,8 +5,16 @@ 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(
|
||||
@ -83,18 +91,114 @@ __PACKAGE__->add_columns(
|
||||
inventory => {
|
||||
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;
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
|
@ -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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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?");
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
|
@ -28,8 +28,12 @@ my $dh = DH->new(
|
||||
|
||||
$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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user