Compare commits
2 Commits
afd565a507
...
2263134e55
Author | SHA1 | Date | |
---|---|---|---|
2263134e55 | |||
9da77307af |
BIN
database/auth.db
BIN
database/auth.db
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
database/live.db
BIN
database/live.db
Binary file not shown.
|
@ -28,7 +28,7 @@ if (!isset($argv[1])) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure it's a valid database
|
// make sure it's a valid database
|
||||||
if (!in_array($argv[1], [AUTH, LIVE, FIGHTS, BPS])) {
|
if (!in_array($argv[1], [AUTH, LIVE, FIGHTS, BPS, 'reset'])) {
|
||||||
eln(red('Invalid database: ') . $argv[1]);
|
eln(red('Invalid database: ') . $argv[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,8 @@ $drop = isset($argv[2]) && $argv[2] === '-d';
|
||||||
The Auth database is used to store user information - not player info, but user info.
|
The Auth database is used to store user information - not player info, but user info.
|
||||||
Usernames, passwords, email, session tokens, etc.
|
Usernames, passwords, email, session tokens, etc.
|
||||||
*/
|
*/
|
||||||
if ($database === AUTH) {
|
if ($database === AUTH || $database === 'reset') {
|
||||||
if ($drop) {
|
if ($drop || $database === 'reset') {
|
||||||
unlink(__DIR__ . '/../' . AUTH);
|
unlink(__DIR__ . '/../' . AUTH);
|
||||||
eln(red('Dropped database: ') . 'auth.db');
|
eln(red('Dropped database: ') . 'auth.db');
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ if ($database === AUTH) {
|
||||||
password TEXT NOT NULL,
|
password TEXT NOT NULL,
|
||||||
auth INT NOT NULL DEFAULT 0,
|
auth INT NOT NULL DEFAULT 0,
|
||||||
char_id INTEGER NOT NULL DEFAULT 0,
|
char_id INTEGER NOT NULL DEFAULT 0,
|
||||||
|
char_slots INTEGER NOT NULL DEFAULT 3,
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
last_login DATETIME DEFAULT CURRENT_TIMESTAMP
|
last_login DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
@ -76,6 +77,7 @@ if ($database === AUTH) {
|
||||||
token TEXT NOT NULL UNIQUE,
|
token TEXT NOT NULL UNIQUE,
|
||||||
expires INTEGER NOT NULL
|
expires INTEGER NOT NULL
|
||||||
)');
|
)');
|
||||||
|
$db->exec('CREATE INDEX idx_sessions_user_id ON sessions (user_id)');
|
||||||
|
|
||||||
created_or_error($r, 'sessions');
|
created_or_error($r, 'sessions');
|
||||||
|
|
||||||
|
@ -86,20 +88,21 @@ if ($database === AUTH) {
|
||||||
token TEXT NOT NULL UNIQUE,
|
token TEXT NOT NULL UNIQUE,
|
||||||
created INTEGER NOT NULL
|
created INTEGER NOT NULL
|
||||||
)');
|
)');
|
||||||
|
$db->exec('CREATE INDEX idx_tokens_user_id ON tokens (user_id)');
|
||||||
|
|
||||||
created_or_error($r, 'tokens');
|
created_or_error($r, 'tokens');
|
||||||
|
|
||||||
eln(green('Created database: ') . 'auth.db');
|
eln(green('Created database: ') . 'auth.db');
|
||||||
|
|
||||||
exit(0);
|
if ($database !== 'reset') exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Fights database is used to store information about fights.
|
The Fights database is used to store information about fights.
|
||||||
A fight is a battle between two characters; players or NPCs.
|
A fight is a battle between two characters; players or NPCs.
|
||||||
*/
|
*/
|
||||||
if ($database === FIGHTS) {
|
if ($database === FIGHTS || $database === 'reset') {
|
||||||
if ($drop) {
|
if ($drop || $database === 'reset') {
|
||||||
unlink(__DIR__ . '/../' . FIGHTS);
|
unlink(__DIR__ . '/../' . FIGHTS);
|
||||||
eln(red('Dropped database: ') . 'fights.db');
|
eln(red('Dropped database: ') . 'fights.db');
|
||||||
}
|
}
|
||||||
|
@ -148,6 +151,8 @@ if ($database === FIGHTS) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_pve_char_id ON pve (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'pve');
|
created_or_error($r, 'pve');
|
||||||
|
|
||||||
|
@ -191,6 +196,10 @@ if ($database === FIGHTS) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char1_id
|
||||||
|
$db->exec('CREATE INDEX idx_pvp_char1_id ON pvp (char1_id)');
|
||||||
|
// Create an index for char2_id
|
||||||
|
$db->exec('CREATE INDEX idx_pvp_char2_id ON pvp (char2_id)');
|
||||||
|
|
||||||
created_or_error($r, 'pvp');
|
created_or_error($r, 'pvp');
|
||||||
|
|
||||||
|
@ -201,6 +210,8 @@ if ($database === FIGHTS) {
|
||||||
fight_id INTEGER NOT NULL,
|
fight_id INTEGER NOT NULL,
|
||||||
info TEXT NOT NULL
|
info TEXT NOT NULL
|
||||||
)');
|
)');
|
||||||
|
// Create an index for fight_id
|
||||||
|
$db->exec('CREATE INDEX idx_pve_logs_fight_id ON pve_logs (fight_id)');
|
||||||
|
|
||||||
created_or_error($r, 'pve_logs');
|
created_or_error($r, 'pve_logs');
|
||||||
|
|
||||||
|
@ -211,19 +222,21 @@ if ($database === FIGHTS) {
|
||||||
fight_id INTEGER NOT NULL,
|
fight_id INTEGER NOT NULL,
|
||||||
info TEXT NOT NULL
|
info TEXT NOT NULL
|
||||||
)');
|
)');
|
||||||
|
// Create an index for fight_id
|
||||||
|
$db->exec('CREATE INDEX idx_pvp_logs_fight_id ON pvp_logs (fight_id)');
|
||||||
|
|
||||||
created_or_error($r, 'pvp_logs');
|
created_or_error($r, 'pvp_logs');
|
||||||
|
|
||||||
eln(green('Created database: ') . 'fights.db');
|
eln(green('Created database: ') . 'fights.db');
|
||||||
|
|
||||||
exit(0);
|
if ($database !== 'reset') exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Blueprints database is used to store information about items, weapons, armor, etc.
|
The Blueprints database is used to store information about items, weapons, armor, etc.
|
||||||
*/
|
*/
|
||||||
if ($database === BPS) {
|
if ($database === BPS || $database === 'reset') {
|
||||||
if ($drop) {
|
if ($drop || $database === 'reset') {
|
||||||
unlink(__DIR__ . '/../' . BPS);
|
unlink(__DIR__ . '/../' . BPS);
|
||||||
eln(red('Dropped database: ') . 'blueprints.db');
|
eln(red('Dropped database: ') . 'blueprints.db');
|
||||||
}
|
}
|
||||||
|
@ -294,20 +307,38 @@ if ($database === BPS) {
|
||||||
|
|
||||||
eln(green('Created database: ') . 'blueprints.db');
|
eln(green('Created database: ') . 'blueprints.db');
|
||||||
|
|
||||||
exit(0);
|
if ($database !== 'reset') exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Live database is used to store information about players, NPCs, guilds, etc.
|
The Live database is used to store information about players, NPCs, guilds, etc.
|
||||||
*/
|
*/
|
||||||
if ($database === LIVE) {
|
if ($database === LIVE || $database === 'reset') {
|
||||||
if ($drop) {
|
if ($drop || $database === 'reset') {
|
||||||
unlink(__DIR__ . '/../' . LIVE);
|
unlink(__DIR__ . '/../' . LIVE);
|
||||||
eln(red('Dropped database: ') . 'live.db');
|
eln(red('Dropped database: ') . 'live.db');
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = new SQLite3(__DIR__ . '/../' . LIVE);
|
$db = new SQLite3(__DIR__ . '/../' . LIVE);
|
||||||
|
|
||||||
|
// Blog posts
|
||||||
|
$db->exec('DROP TABLE IF EXISTS blog');
|
||||||
|
$r = $db->exec('CREATE TABLE blog (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
author_id INTEGER NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
slug TEXT NOT NULL UNIQUE,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)');
|
||||||
|
// Create an index for author_id
|
||||||
|
$db->exec('CREATE INDEX idx_blog_author_id ON blog (author_id)');
|
||||||
|
// Create an index for the slug
|
||||||
|
$db->exec('CREATE INDEX idx_blog_slug ON blog (slug)');
|
||||||
|
|
||||||
|
created_or_error($r, 'blog');
|
||||||
|
|
||||||
// Characters
|
// Characters
|
||||||
$db->exec('DROP TABLE IF EXISTS characters');
|
$db->exec('DROP TABLE IF EXISTS characters');
|
||||||
$r = $db->exec('CREATE TABLE characters (
|
$r = $db->exec('CREATE TABLE characters (
|
||||||
|
@ -322,8 +353,8 @@ if ($database === LIVE) {
|
||||||
max_hp INTEGER NOT NULL DEFAULT 20,
|
max_hp INTEGER NOT NULL DEFAULT 20,
|
||||||
current_mp INTEGER NOT NULL DEFAULT 10,
|
current_mp INTEGER NOT NULL DEFAULT 10,
|
||||||
max_mp INTEGER NOT NULL DEFAULT 10,
|
max_mp INTEGER NOT NULL DEFAULT 10,
|
||||||
current_tp INTEGER NOT NULL DEFAULT 0,
|
current_tp INTEGER NOT NULL DEFAULT 1,
|
||||||
max_tp INTEGER NOT NULL DEFAULT 0,
|
max_tp INTEGER NOT NULL DEFAULT 1,
|
||||||
power INTEGER NOT NULL DEFAULT 0,
|
power INTEGER NOT NULL DEFAULT 0,
|
||||||
accuracy INTEGER NOT NULL DEFAULT 0,
|
accuracy INTEGER NOT NULL DEFAULT 0,
|
||||||
penetration INTEGER NOT NULL DEFAULT 0,
|
penetration INTEGER NOT NULL DEFAULT 0,
|
||||||
|
@ -337,6 +368,8 @@ if ($database === LIVE) {
|
||||||
inv_slots INTEGER NOT NULL DEFAULT 10,
|
inv_slots INTEGER NOT NULL DEFAULT 10,
|
||||||
attrib_points INTEGER NOT NULL DEFAULT 0
|
attrib_points INTEGER NOT NULL DEFAULT 0
|
||||||
)');
|
)');
|
||||||
|
// Create an index for user_id
|
||||||
|
$db->exec('CREATE INDEX idx_characters_user_id ON characters (user_id)');
|
||||||
|
|
||||||
created_or_error($r, 'characters');
|
created_or_error($r, 'characters');
|
||||||
|
|
||||||
|
@ -367,31 +400,37 @@ if ($database === LIVE) {
|
||||||
max_hp INTEGER NOT NULL DEFAULT 0,
|
max_hp INTEGER NOT NULL DEFAULT 0,
|
||||||
max_mp INTEGER NOT NULL DEFAULT 0
|
max_mp INTEGER NOT NULL DEFAULT 0
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_char_gear_char_id ON char_gear (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'char_gear');
|
created_or_error($r, 'char_gear');
|
||||||
|
|
||||||
// Player inventory
|
// Player inventory
|
||||||
$db->exec('DROP TABLE IF EXISTS char_inventory');
|
$db->exec('DROP TABLE IF EXISTS char_inventory');
|
||||||
$r = $db->exec('CREATE TABLE inventory (
|
$r = $db->exec('CREATE TABLE char_inventory (
|
||||||
char_id INTEGER NOT NULL,
|
char_id INTEGER NOT NULL,
|
||||||
item_id INTEGER NOT NULL
|
item_id INTEGER NOT NULL
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_inventory_char_id ON char_inventory (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'inventory');
|
created_or_error($r, 'char_inventory');
|
||||||
|
|
||||||
// Player wallet
|
// Player wallet
|
||||||
$db->exec('DROP TABLE IF EXISTS char_wallets');
|
$db->exec('DROP TABLE IF EXISTS wallets');
|
||||||
$r = $db->exec('CREATE TABLE char_wallets (
|
$r = $db->exec('CREATE TABLE wallets (
|
||||||
char_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
silver INTEGER NOT NULL DEFAULT 10,
|
silver INTEGER NOT NULL DEFAULT 10,
|
||||||
stargem INTEGER NOT NULL DEFAULT 0
|
stargem INTEGER NOT NULL DEFAULT 0
|
||||||
)');
|
)');
|
||||||
|
// Create an index for user_id
|
||||||
|
$db->exec('CREATE INDEX idx_wallets_user_id ON wallets (user_id)');
|
||||||
|
|
||||||
created_or_error($r, 'char_wallets');
|
created_or_error($r, 'wallets');
|
||||||
|
|
||||||
// Player bank
|
// Player bank
|
||||||
$db->exec('DROP TABLE IF EXISTS char_bank');
|
$db->exec('DROP TABLE IF EXISTS char_bank');
|
||||||
$r = $db->exec('CREATE TABLE bank (
|
$r = $db->exec('CREATE TABLE char_bank (
|
||||||
char_id INTEGER NOT NULL,
|
char_id INTEGER NOT NULL,
|
||||||
slots INTEGER NOT NULL DEFAULT 5,
|
slots INTEGER NOT NULL DEFAULT 5,
|
||||||
silver INTEGER NOT NULL DEFAULT 0,
|
silver INTEGER NOT NULL DEFAULT 0,
|
||||||
|
@ -399,17 +438,23 @@ if ($database === LIVE) {
|
||||||
can_collect INTEGER NOT NULL DEFAULT 1,
|
can_collect INTEGER NOT NULL DEFAULT 1,
|
||||||
last_collected DATETIME DEFAULT CURRENT_TIMESTAMP
|
last_collected DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_bank_char_id ON char_bank (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'bank');
|
created_or_error($r, 'char_bank');
|
||||||
|
|
||||||
// Banked items
|
// Banked items
|
||||||
$db->exec('DROP TABLE IF EXISTS char_banked_items');
|
$db->exec('DROP TABLE IF EXISTS char_banked_items');
|
||||||
$r = $db->exec('CREATE TABLE banked_items (
|
$r = $db->exec('CREATE TABLE char_banked_items (
|
||||||
char_id INTEGER NOT NULL,
|
char_id INTEGER NOT NULL,
|
||||||
item_id INTEGER NOT NULL
|
item_id INTEGER NOT NULL
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_banked_items_char_id ON char_banked_items (char_id)');
|
||||||
|
// Create an index for item_id
|
||||||
|
$db->exec('CREATE INDEX idx_banked_items_item_id ON char_banked_items (item_id)');
|
||||||
|
|
||||||
created_or_error($r, 'banked_items');
|
created_or_error($r, 'char_banked_items');
|
||||||
|
|
||||||
// Towns
|
// Towns
|
||||||
$db->exec('DROP TABLE IF EXISTS towns');
|
$db->exec('DROP TABLE IF EXISTS towns');
|
||||||
|
@ -423,6 +468,8 @@ if ($database === LIVE) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for the x, y location
|
||||||
|
$db->exec('CREATE INDEX idx_towns_location ON towns (x, y)');
|
||||||
|
|
||||||
created_or_error($r, 'towns');
|
created_or_error($r, 'towns');
|
||||||
|
|
||||||
|
@ -443,6 +490,8 @@ if ($database === LIVE) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for the x, y location
|
||||||
|
$db->exec('CREATE INDEX idx_shops_location ON shops (x, y)');
|
||||||
|
|
||||||
created_or_error($r, 'shops');
|
created_or_error($r, 'shops');
|
||||||
|
|
||||||
|
@ -459,6 +508,8 @@ if ($database === LIVE) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for the x, y location
|
||||||
|
$db->exec('CREATE INDEX idx_inns_location ON inns (x, y)');
|
||||||
|
|
||||||
created_or_error($r, 'inns');
|
created_or_error($r, 'inns');
|
||||||
|
|
||||||
|
@ -474,6 +525,8 @@ if ($database === LIVE) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for leader_id
|
||||||
|
$db->exec('CREATE INDEX idx_guilds_leader_id ON guilds (leader_id)');
|
||||||
|
|
||||||
created_or_error($r, 'guilds');
|
created_or_error($r, 'guilds');
|
||||||
|
|
||||||
|
@ -485,6 +538,8 @@ if ($database === LIVE) {
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
permissions TEXT NOT NULL
|
permissions TEXT NOT NULL
|
||||||
)');
|
)');
|
||||||
|
// Create an index for guild_id
|
||||||
|
$db->exec('CREATE INDEX idx_guild_ranks_guild_id ON guild_ranks (guild_id)');
|
||||||
|
|
||||||
created_or_error($r, 'guild_ranks');
|
created_or_error($r, 'guild_ranks');
|
||||||
|
|
||||||
|
@ -498,6 +553,10 @@ if ($database === LIVE) {
|
||||||
donated INTEGER NOT NULL DEFAULT 0,
|
donated INTEGER NOT NULL DEFAULT 0,
|
||||||
joined DATETIME DEFAULT CURRENT_TIMESTAMP
|
joined DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for guild_id
|
||||||
|
$db->exec('CREATE INDEX idx_guild_members_guild_id ON guild_members (guild_id)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_guild_members_char_id ON guild_members (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'guild_members');
|
created_or_error($r, 'guild_members');
|
||||||
|
|
||||||
|
@ -514,6 +573,8 @@ if ($database === LIVE) {
|
||||||
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
updated DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)');
|
)');
|
||||||
|
// Create an index for the x, y location
|
||||||
|
$db->exec('CREATE INDEX idx_npcs_location ON npcs (x, y)');
|
||||||
|
|
||||||
created_or_error($r, 'npcs');
|
created_or_error($r, 'npcs');
|
||||||
|
|
||||||
|
@ -524,6 +585,8 @@ if ($database === LIVE) {
|
||||||
town_id INTEGER NOT NULL,
|
town_id INTEGER NOT NULL,
|
||||||
rep INTEGER NOT NULL DEFAULT 0
|
rep INTEGER NOT NULL DEFAULT 0
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_char_town_rep_char_id ON char_town_rep (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'char_town_rep');
|
created_or_error($r, 'char_town_rep');
|
||||||
|
|
||||||
|
@ -568,6 +631,8 @@ if ($database === LIVE) {
|
||||||
trait_id INTEGER NOT NULL,
|
trait_id INTEGER NOT NULL,
|
||||||
value INTEGER NOT NULL DEFAULT 0
|
value INTEGER NOT NULL DEFAULT 0
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_char_traits_char_id ON char_traits (char_id)');
|
||||||
|
|
||||||
created_or_error($r, 'char_traits');
|
created_or_error($r, 'char_traits');
|
||||||
|
|
||||||
|
@ -579,12 +644,16 @@ if ($database === LIVE) {
|
||||||
y INTEGER NOT NULL,
|
y INTEGER NOT NULL,
|
||||||
currently INTEGER NOT NULL DEFAULT 0
|
currently INTEGER NOT NULL DEFAULT 0
|
||||||
)');
|
)');
|
||||||
|
// Create an index for char_id
|
||||||
|
$db->exec('CREATE INDEX idx_char_locations_char_id ON char_locations (char_id)');
|
||||||
|
// Create an index for x, y location
|
||||||
|
$db->exec('CREATE INDEX idx_char_locations_location ON char_locations (x, y)');
|
||||||
|
|
||||||
created_or_error($r, 'char_locations');
|
created_or_error($r, 'char_locations');
|
||||||
|
|
||||||
eln(green('Created database: ') . 'live.db');
|
eln(green('Created database: ') . 'live.db');
|
||||||
|
|
||||||
exit(0);
|
if ($database !== 'reset') exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function created_or_error(bool $result, string $table): void
|
function created_or_error(bool $result, string $table): void
|
||||||
|
|
|
@ -74,6 +74,19 @@ body {
|
||||||
border-color: #32373E #24282D #212429;
|
border-color: #32373E #24282D #212429;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
background-color: #e57373;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(139, 0, 0, 0.1));
|
||||||
|
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #d32f2f #c62828 #b71c1c;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #d95c5c;
|
||||||
|
border-color: #b71c1c #a52727 #8e1f1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
@ -150,7 +163,7 @@ footer {
|
||||||
height: 34px;
|
height: 34px;
|
||||||
color: white;
|
color: white;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
background-image: url('/assets/img/deco-bar2.jpg');
|
background-image: url('/assets/img/bar.jpg');
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -169,6 +182,11 @@ span.badge {
|
||||||
color: #111111;
|
color: #111111;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
padding: 0.1rem 0.25rem;
|
padding: 0.1rem 0.25rem;
|
||||||
|
|
||||||
|
&.dark {
|
||||||
|
background-color: #444c55;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-1 { margin-bottom: 0.25rem; margin-top: 0.25rem; }
|
.my-1 { margin-bottom: 0.25rem; margin-top: 0.25rem; }
|
||||||
|
@ -258,3 +276,70 @@ span.badge {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#debug-query-log {
|
||||||
|
padding: 2rem;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
#center section {
|
||||||
|
&:not(:last-child) {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:has(.badge), h2:has(.badge), h3:has(.badge), h4:has(.badge), h5:has(.badge), h6:has(.badge) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > .badge {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
position: relative;
|
||||||
|
min-height: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
background: #f8f8f9;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
line-height: 1.4285rem;
|
||||||
|
color: rgba(0, 0, 0, .87);
|
||||||
|
transition: opacity .1s ease, color .1s ease, background .1s ease, box-shadow .1s ease;
|
||||||
|
border-radius: .28571429rem;
|
||||||
|
box-shadow: 0 0 0 1px rgba(34, 36, 38, .22) inset, 0 0 0 0 transparent;
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
background-color: #f0f9eb;
|
||||||
|
color: #2c662d;
|
||||||
|
border-color: #b3dc9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
background-color: #f9e9eb;
|
||||||
|
color: #9f3a38;
|
||||||
|
border-color: #e0b4b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
background-color: #fff8e1;
|
||||||
|
color: #573a08;
|
||||||
|
border-color: #f9e79f;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.info {
|
||||||
|
background-color: #f0f9fb;
|
||||||
|
color: #2c7fba;
|
||||||
|
border-color: #b3d7f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
color: #2c2c2c;
|
||||||
|
border-color: #b3b3b3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,3 +21,124 @@
|
||||||
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
||||||
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
|
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
.radio-block {
|
||||||
|
& > input[type="radio"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > label {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
border: none;
|
||||||
|
font-size: 1rem;
|
||||||
|
background: #f7f8fa linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));
|
||||||
|
box-shadow: 0 1px 0 1px rgba(255, 255, 255, 0.3) inset, 0 0 0 1px #adb2bb inset;
|
||||||
|
color: #111111;
|
||||||
|
padding: 0.5rem 1rem 0.5rem;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
user-select: none;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, background 0.1s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));
|
||||||
|
box-shadow: 0 1px 0 1px rgba(255, 255, 255, 0.3) inset, 0 0 0 1px #adb2bb inset;
|
||||||
|
color: rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .badge {
|
||||||
|
background-color: #444c55;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active > label {
|
||||||
|
background-color: #444c55;
|
||||||
|
color: #ffffff;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #3D444C #2F353B #2C3137;
|
||||||
|
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
|
||||||
|
& > .badge {
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
color: #111111;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the radio button is checked, change the background color of the label
|
||||||
|
& > input[type="radio"]:checked + label {
|
||||||
|
background-color: #5a9bd4;
|
||||||
|
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(60, 100, 150, 0.1));
|
||||||
|
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #4a8ab0 #3a7a9c #2a6a88;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the radio button is disabled, show a normal cursor
|
||||||
|
& > input[type="radio"]:disabled + label {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
.radio-block-2 {
|
||||||
|
& > input[type="radio"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > label {
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.character-select > .radio-block {
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: 0.15rem;
|
||||||
|
|
||||||
|
& > input[type="radio"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 0.15rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color, background-color 0.2s ease;
|
||||||
|
padding: 0.5rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .badge {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active > label {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the radio button is checked, change the background color of the label */
|
||||||
|
& > input[type="radio"]:checked + label {
|
||||||
|
background-color: #f4cc67;
|
||||||
|
color: #111111;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the radio button is disabled, show a normal cursor */
|
||||||
|
& > input[type="radio"]:disabled + label {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
@ -28,10 +28,11 @@ router_post($r, '/auth/logout', 'auth_controller_logout_post');
|
||||||
/*
|
/*
|
||||||
Characters
|
Characters
|
||||||
*/
|
*/
|
||||||
router_get($r, '/characters', 'char_controller_select_get');
|
router_get($r, '/characters', 'char_controller_list_get');
|
||||||
router_post($r, '/character/create', 'char_controller_create_post');
|
router_post($r, '/characters', 'char_controller_list_post');
|
||||||
router_post($r, '/character/select', 'auth_controller_change_character_post');
|
|
||||||
router_get($r, '/character/create-first', 'char_controller_create_first_get');
|
router_get($r, '/character/create-first', 'char_controller_create_first_get');
|
||||||
|
router_post($r, '/character/create', 'char_controller_create_post');
|
||||||
|
router_post($r, '/character/delete', 'char_controller_delete_post');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Router
|
Router
|
||||||
|
|
|
@ -63,8 +63,7 @@ function must_have_character(): void
|
||||||
{
|
{
|
||||||
// If there is a character selected, make sure the session is up to date.
|
// If there is a character selected, make sure the session is up to date.
|
||||||
if ($_SESSION['user']['char_id'] !== 0) {
|
if ($_SESSION['user']['char_id'] !== 0) {
|
||||||
$char = db_query(db_live(), 'SELECT * FROM characters WHERE id = :c', [':c' => $_SESSION['user']['char_id']])->fetchArray(SQLITE3_ASSOC);
|
char();
|
||||||
$_SESSION['char'] = $char;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ function c_logout_button(): string
|
||||||
*/
|
*/
|
||||||
function c_char_bar(): string
|
function c_char_bar(): string
|
||||||
{
|
{
|
||||||
if (!char()) return '';
|
if (char() === false) return '';
|
||||||
return render('components/char_bar', ['char' => char()]);
|
return render('components/char_bar', ['char' => char()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,3 +30,35 @@ function c_left_nav(int $activeTab): string
|
||||||
{
|
{
|
||||||
return render('components/left_nav', ['activeTab' => $activeTab]);
|
return render('components/left_nav', ['activeTab' => $activeTab]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the debug query log.
|
||||||
|
*/
|
||||||
|
function c_debug_query_log(): string
|
||||||
|
{
|
||||||
|
return render('components/debug_query_log');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the character select radio buttons.
|
||||||
|
*/
|
||||||
|
function c_char_select_box(int $id, array $char): string
|
||||||
|
{
|
||||||
|
return render('components/char_select_box', ['id' => $id, 'char' => $char]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render an alert with a given type and message.
|
||||||
|
*/
|
||||||
|
function c_alert(string $t, string $m): string
|
||||||
|
{
|
||||||
|
return "<div class=\"alert $t\">$m</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a form field.
|
||||||
|
*/
|
||||||
|
function c_form_field(string $type, string $name, string $id, string $placeholder, bool $required = false): string
|
||||||
|
{
|
||||||
|
return render('components/form_field', ['type' => $type, 'name' => $name, 'id' => $id, 'placeholder' => $placeholder, 'required' => $required]);
|
||||||
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ function auth_controller_register_post(): void
|
||||||
|
|
||||||
// If there are errors at this point, send them to the page with errors flashed.
|
// If there are errors at this point, send them to the page with errors flashed.
|
||||||
if (!empty($errors)) {
|
if (!empty($errors)) {
|
||||||
flash('errors', $errors);
|
flash('alert-registration', ['errors', $errors]);
|
||||||
redirect('/auth/register');
|
redirect('/auth/register');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ function auth_controller_register_post(): void
|
||||||
|
|
||||||
// If there are errors at this point, send them to the page with errors flashed.
|
// If there are errors at this point, send them to the page with errors flashed.
|
||||||
if (!empty($errors)) {
|
if (!empty($errors)) {
|
||||||
flash('errors', $errors);
|
flash('alert-registration', ['errors', $errors]);
|
||||||
redirect('/auth/register');
|
redirect('/auth/register');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ function auth_controller_register_post(): void
|
||||||
if ($user === false) router_error(400);
|
if ($user === false) router_error(400);
|
||||||
|
|
||||||
$_SESSION['user'] = user_find($u);
|
$_SESSION['user'] = user_find($u);
|
||||||
|
wallet_create($_SESSION['user']['id']);
|
||||||
redirect('/character/create-first');
|
redirect('/character/create-first');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,28 +170,3 @@ function auth_controller_logout_post(): void
|
||||||
set_cookie('remember_me', '', 1);
|
set_cookie('remember_me', '', 1);
|
||||||
redirect('/');
|
redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the user's currently selected character.
|
|
||||||
*/
|
|
||||||
function auth_controller_change_character_post(): void
|
|
||||||
{
|
|
||||||
auth_only();
|
|
||||||
must_have_character();
|
|
||||||
csrf_ensure();
|
|
||||||
|
|
||||||
$char_id = (int) ($_POST['char_id'] ?? 0);
|
|
||||||
|
|
||||||
// If the character ID is the current character, do nothing.
|
|
||||||
if ($char_id === $_SESSION['user']['char_id']) redirect('/');
|
|
||||||
|
|
||||||
// Make sure the character ID is valid.
|
|
||||||
if (char_exists($char_id) === false) throw new Exception('Invalid character ID. (acccp)');
|
|
||||||
|
|
||||||
// Make sure the user owns the character.
|
|
||||||
if (char_belongs_to_user($char_id, $_SESSION['user']['id']) === false) router_error(999);
|
|
||||||
|
|
||||||
change_user_character($char_id);
|
|
||||||
|
|
||||||
redirect('/');
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,14 +3,110 @@
|
||||||
/**
|
/**
|
||||||
* Display a list of characters for the currently logged in user.
|
* Display a list of characters for the currently logged in user.
|
||||||
*/
|
*/
|
||||||
function char_controller_select_get(): void
|
function char_controller_list_get(): void
|
||||||
{
|
{
|
||||||
auth_only();
|
auth_only();
|
||||||
must_have_character();
|
must_have_character();
|
||||||
|
|
||||||
$chars = char_list(user('id'));
|
$chars = char_list(user('id'));
|
||||||
|
|
||||||
echo render('layouts/basic', ['view' => 'pages/chars/select', 'chars' => $chars, 'activeTab' => nav_tabs['chars']]);
|
echo render('layouts/basic', ['view' => 'pages/chars/list', 'chars' => $chars, 'activeTab' => nav_tabs['chars']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an action from the character list page.
|
||||||
|
*/
|
||||||
|
function char_controller_list_post(): void
|
||||||
|
{
|
||||||
|
auth_only();
|
||||||
|
must_have_character();
|
||||||
|
csrf_ensure();
|
||||||
|
|
||||||
|
$char_id = (int) ($_POST['char_id'] ?? 0);
|
||||||
|
$action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
|
// If the character ID is not a number, or the action is not a string, return a 400.
|
||||||
|
if (!is_numeric($char_id) || !is_string($action)) router_error(400);
|
||||||
|
|
||||||
|
// If the action is not one of the allowed actions, return a 400.
|
||||||
|
if (!in_array($action, ['select', 'delete'])) router_error(400);
|
||||||
|
|
||||||
|
// If the action is to select a character, change the user's selected character.
|
||||||
|
if ($action === 'select') {
|
||||||
|
// If the character ID is the current character, do nothing.
|
||||||
|
if ($char_id === $_SESSION['user']['char_id'] || $char_id === 0) {
|
||||||
|
flash('info', 'You are already using that character.');
|
||||||
|
redirect('/characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the character ID is valid.
|
||||||
|
if (char_exists($char_id) === false) throw new Exception('Invalid character ID. (acccp)');
|
||||||
|
|
||||||
|
// Make sure the user owns the character.
|
||||||
|
if (!char_belongs_to_user($char_id, $_SESSION['user']['id'])) router_error(999);
|
||||||
|
|
||||||
|
change_user_character($char_id);
|
||||||
|
|
||||||
|
flash('success', 'Switched to character ' . char('name') . '!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the action is to delete a character, move to the confirmation page.
|
||||||
|
if ($action === 'delete') {
|
||||||
|
// Make sure the character ID is valid.
|
||||||
|
if (char_exists($char_id) === false) throw new Exception('Invalid character ID. (accdp)');
|
||||||
|
|
||||||
|
// Make sure the user owns the character.
|
||||||
|
if (!char_belongs_to_user($char_id, $_SESSION['user']['id'])) router_error(999);
|
||||||
|
|
||||||
|
$char = char_find($char_id);
|
||||||
|
|
||||||
|
echo render('layouts/basic', ['view' => 'pages/chars/delete', 'char' => $char, 'activeTab' => nav_tabs['chars']]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect('/characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a character for the currently logged in user.
|
||||||
|
*/
|
||||||
|
function char_controller_delete_post(): void
|
||||||
|
{
|
||||||
|
auth_only();
|
||||||
|
must_have_character();
|
||||||
|
csrf_ensure();
|
||||||
|
|
||||||
|
$char_id = (int) ($_POST['char_id'] ?? 0);
|
||||||
|
$name = $_POST['name'] ?? '';
|
||||||
|
|
||||||
|
// If the character ID is not a number, return a 400.
|
||||||
|
if (!is_numeric($char_id)) router_error(400);
|
||||||
|
|
||||||
|
// Make sure the character ID is valid.
|
||||||
|
if (char_exists($char_id) === false) throw new Exception('Invalid character ID. (acddp)');
|
||||||
|
|
||||||
|
// Make sure the user owns the character.
|
||||||
|
if (!char_belongs_to_user($char_id, $_SESSION['user']['id'])) router_error(999);
|
||||||
|
|
||||||
|
$char = char_find($char_id);
|
||||||
|
|
||||||
|
// Confirm the name matches the name of the character.
|
||||||
|
if ($char['name'] !== $_POST['name']) {
|
||||||
|
flash('error', 'Failed to delete character. Name confirmation did not match.');
|
||||||
|
redirect('/characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the character
|
||||||
|
char_delete($char_id);
|
||||||
|
|
||||||
|
// If the character being deleted is the currently selected character, select the first character.
|
||||||
|
if ($_SESSION['user']['char_id'] === $char_id) {
|
||||||
|
$chars = char_list(user('id'));
|
||||||
|
if (count($chars) > 0) change_user_character($chars[0]['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
flash('error', 'Character ' . $char['name'] . ' deleted.');
|
||||||
|
redirect('/characters');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,8 +153,8 @@ function char_controller_create_post(): void
|
||||||
|
|
||||||
// If there are errors at this point, send them to the page with errors flashed.
|
// If there are errors at this point, send them to the page with errors flashed.
|
||||||
if (!empty($errors)) {
|
if (!empty($errors)) {
|
||||||
flash('errors', $errors);
|
flash('alert-cl2', ['errors', $errors]);
|
||||||
redirect('/');
|
redirect('/characters');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the character
|
// Create the character
|
||||||
|
@ -67,11 +163,12 @@ function char_controller_create_post(): void
|
||||||
|
|
||||||
// Create the auxiliary tables
|
// Create the auxiliary tables
|
||||||
char_location_create($char);
|
char_location_create($char);
|
||||||
char_wallet_create($char);
|
|
||||||
char_gear_create($char);
|
char_gear_create($char);
|
||||||
|
|
||||||
// Set the character as the user's selected character
|
// Set the character as the user's selected character
|
||||||
change_user_character($char);
|
change_user_character($char);
|
||||||
|
|
||||||
redirect('/');
|
flash('alert_character_list_1', ['success', 'Character ' . $name . ' created!']);
|
||||||
|
redirect('/characters');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,28 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a connection to a database.
|
||||||
|
*/
|
||||||
|
function db_open(string $path): SQLite3
|
||||||
|
{
|
||||||
|
$db = new SQLite3($path);
|
||||||
|
|
||||||
|
// Increase cache size to 32MB
|
||||||
|
$db->exec('PRAGMA cache_size = 32000');
|
||||||
|
// Enable WAL mode
|
||||||
|
$db->exec('PRAGMA journal_mode = WAL');
|
||||||
|
// Move temp store to memory
|
||||||
|
$db->exec('PRAGMA temp_store = MEMORY');
|
||||||
|
|
||||||
|
return $db;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a connection to the auth database.
|
* Return a connection to the auth database.
|
||||||
*/
|
*/
|
||||||
function db_auth(): SQLite3
|
function db_auth(): SQLite3
|
||||||
{
|
{
|
||||||
return $GLOBALS['db_auth'] ??= new SQLite3(__DIR__ . '/../database/auth.db');
|
return $GLOBALS['db_auth'] ??= db_open(__DIR__ . '/../database/auth.db');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +30,7 @@ function db_auth(): SQLite3
|
||||||
*/
|
*/
|
||||||
function db_live(): SQLite3
|
function db_live(): SQLite3
|
||||||
{
|
{
|
||||||
return $GLOBALS['db_live'] ??= new SQLite3(__DIR__ . '/../database/live.db');
|
return $GLOBALS['db_live'] ??= db_open(__DIR__ . '/../database/live.db');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +39,7 @@ function db_live(): SQLite3
|
||||||
*/
|
*/
|
||||||
function db_fights(): SQLite3
|
function db_fights(): SQLite3
|
||||||
{
|
{
|
||||||
return $GLOBALS['db_fights'] ??= new SQLite3(__DIR__ . '/../database/fights.db');
|
return $GLOBALS['db_fights'] ??= db_open(__DIR__ . '/../database/fights.db');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,7 +48,7 @@ function db_fights(): SQLite3
|
||||||
*/
|
*/
|
||||||
function db_blueprints(): SQLite3
|
function db_blueprints(): SQLite3
|
||||||
{
|
{
|
||||||
return $GLOBALS['db_blueprints'] ??= new SQLite3(__DIR__ . '/../database/blueprints.db');
|
return $GLOBALS['db_blueprints'] ??= db_open(__DIR__ . '/../database/blueprints.db');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +60,7 @@ function db_query(SQLite3 $db, string $query, array $params = []): SQLite3Result
|
||||||
$stmt = $db->prepare($query);
|
$stmt = $db->prepare($query);
|
||||||
if (!empty($params)) foreach ($params as $key => $value) $stmt->bindValue($key, $value, getSQLiteType($value));
|
if (!empty($params)) foreach ($params as $key => $value) $stmt->bindValue($key, $value, getSQLiteType($value));
|
||||||
$GLOBALS['queries']++;
|
$GLOBALS['queries']++;
|
||||||
|
db_log($query);
|
||||||
return $stmt->execute();
|
return $stmt->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +70,7 @@ function db_query(SQLite3 $db, string $query, array $params = []): SQLite3Result
|
||||||
function db_exec(SQLite3 $db, string $query): bool
|
function db_exec(SQLite3 $db, string $query): bool
|
||||||
{
|
{
|
||||||
$GLOBALS['queries']++;
|
$GLOBALS['queries']++;
|
||||||
|
db_log($query);
|
||||||
return $db->exec($query);
|
return $db->exec($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +80,9 @@ function db_exec(SQLite3 $db, string $query): bool
|
||||||
*/
|
*/
|
||||||
function db_exists(SQLite3 $db, string $table, string $column, mixed $value): bool
|
function db_exists(SQLite3 $db, string $table, string $column, mixed $value): bool
|
||||||
{
|
{
|
||||||
$result = db_query($db, "SELECT 1 FROM $table WHERE $column = :v LIMIT 1", [':v' => $value]);
|
$query = "SELECT 1 FROM $table WHERE $column = :v LIMIT 1";
|
||||||
|
$result = db_query($db, $query, [':v' => $value]);
|
||||||
|
db_log($query);
|
||||||
return $result->fetchArray(SQLITE3_NUM) !== false;
|
return $result->fetchArray(SQLITE3_NUM) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,3 +98,11 @@ function getSQLiteType(mixed $value): int
|
||||||
default => SQLITE3_TEXT
|
default => SQLITE3_TEXT
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the given query string to the db debug log.
|
||||||
|
*/
|
||||||
|
function db_log(string $query): void
|
||||||
|
{
|
||||||
|
if (env('debug', false)) $GLOBALS['query_log'][] = $query;
|
||||||
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ function redirect(string $location): void
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flash a message to the session, or retrieve an existing flash value.
|
* Flash data to the session, or retrieve an existing flash value. Returns false if the key does not exist.
|
||||||
*/
|
*/
|
||||||
function flash(string $key, mixed $value = ''): mixed
|
function flash(string $key, mixed $value = ''): mixed
|
||||||
{
|
{
|
||||||
|
@ -129,13 +129,23 @@ function user_selected_char(): int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the current user has a selected char and the data is in the session, retrieve either the full array of data
|
* If the current user has a selected char and the data is in the session, retrieve either the full array of data
|
||||||
* or a specific field.
|
* or a specific field. If there is no character data, populate it.
|
||||||
*/
|
*/
|
||||||
function char(string $field = ''): mixed
|
function char(string $field = ''): mixed
|
||||||
{
|
{
|
||||||
if (empty($_SESSION['char'])) return false;
|
// If there is no user, return false
|
||||||
if ($field === '') return $_SESSION['char'];
|
if (empty($_SESSION['user'])) return false;
|
||||||
return $_SESSION['char'][$field] ?? false;
|
|
||||||
|
if (empty($GLOBALS['char'])) {
|
||||||
|
$GLOBALS['char'] = db_query(
|
||||||
|
db_live(),
|
||||||
|
"SELECT * FROM characters WHERE id = :c",
|
||||||
|
[':c' => user_selected_char()]
|
||||||
|
)->fetchArray(SQLITE3_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field === '') return $GLOBALS['char'];
|
||||||
|
return $GLOBALS['char'][$field] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,7 +155,7 @@ function change_user_character(int $char_id): void
|
||||||
{
|
{
|
||||||
$_SESSION['user']['char_id'] = $char_id;
|
$_SESSION['user']['char_id'] = $char_id;
|
||||||
db_query(db_auth(), "UPDATE users SET char_id = :c WHERE id = :u", [':c' => $char_id, ':u' => user('id')]);
|
db_query(db_auth(), "UPDATE users SET char_id = :c WHERE id = :u", [':c' => $char_id, ':u' => user('id')]);
|
||||||
$_SESSION['char'] = char_find($char_id);
|
$GLOBALS['char'] = char_find($char_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,3 +167,32 @@ function percent(int $num, int $denom, int $precision = 4): int
|
||||||
$p = ($num / $denom) * 100;
|
$p = ($num / $denom) * 100;
|
||||||
return $p < 0 ? 0 : round($p, $precision);
|
return $p < 0 ? 0 : round($p, $precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the account wallet. On first execution it will populate $GLOBALS['wallet'] with the wallet data. This way
|
||||||
|
* the data is up to date with every request without having to query the database every use within, for example, a
|
||||||
|
* template. Will return false if the field does not exist, or the entire wallet array if no field is specified.
|
||||||
|
*/
|
||||||
|
function wallet(string $field = ''): array|int|false
|
||||||
|
{
|
||||||
|
if (empty($GLOBALS['wallet'])) {
|
||||||
|
$GLOBALS['wallet'] = db_query(
|
||||||
|
db_live(),
|
||||||
|
"SELECT * FROM wallets WHERE user_id = :u",
|
||||||
|
[':u' => user('id')]
|
||||||
|
)->fetchArray(SQLITE3_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field === '') return $GLOBALS['wallet'];
|
||||||
|
return $GLOBALS['wallet'][$field] ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format an array of strings to a ul element.
|
||||||
|
*/
|
||||||
|
function array_to_ul(array $array): string
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
foreach ($array as $item) $html .= "<li>$item</li>";
|
||||||
|
return "<ul>$html</ul>";
|
||||||
|
}
|
||||||
|
|
|
@ -61,22 +61,6 @@ function char_location_create(int $char_id, int $x = 0, int $y = 0, int $current
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a character's wallet. A character's wallet is where they store their currencies. Can optionally specify the
|
|
||||||
* starting balances of the wallet. Returns the created wallet's ID. If a currency is set to -1, the starting_silver
|
|
||||||
* or starting_star_gems fields from the env will be used.
|
|
||||||
*/
|
|
||||||
function char_wallet_create(int $char_id, int $silver = -1, int $starGems = -1): void
|
|
||||||
{
|
|
||||||
if (db_query(db_live(), "INSERT INTO char_wallets (char_id, silver, stargem) VALUES (:p, :s, :sg)", [
|
|
||||||
':p' => $char_id,
|
|
||||||
':s' => $silver === -1 ? env('start_silver', 10) : $silver,
|
|
||||||
':sg' => $starGems === -1 ? env('start_star_gems', 0) : $starGems
|
|
||||||
]) === false) {
|
|
||||||
throw new Exception('Failed to create character wallet. (cwc)');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the character's gear table. A character's gear is where they store their equipped items.
|
* Create the character's gear table. A character's gear is where they store their equipped items.
|
||||||
* @TODO: implement initial gear
|
* @TODO: implement initial gear
|
||||||
|
@ -88,23 +72,6 @@ function char_gear_create(int $char_id, array $initialGear = []): void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the character's bank account. The bank stores items and currency, with an interest rate based on
|
|
||||||
* the bank account's tier. The bank account has a limited number of slots, which can be increased by upgrading
|
|
||||||
* the bank account. The bank account starts with 0 silver and 5 slots.
|
|
||||||
*/
|
|
||||||
function char_bank_create(int $char_id, int $slots = 5, int $silver = 0, int $tier = 0): void
|
|
||||||
{
|
|
||||||
if (db_query(db_live(), "INSERT INTO char_banks (char_id, slots, silver, tier) VALUES (:p, :s, :si, :t)", [
|
|
||||||
':p' => $char_id,
|
|
||||||
':s' => $slots,
|
|
||||||
':si' => $silver,
|
|
||||||
':t' => $tier
|
|
||||||
]) === false) {
|
|
||||||
throw new Exception('Failed to create character bank. (cbc)');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a charcter by their ID. Returns the character's data as an associative array.
|
* Get a charcter by their ID. Returns the character's data as an associative array.
|
||||||
*/
|
*/
|
||||||
|
@ -152,16 +119,6 @@ function char_get_location(int $char_id): array
|
||||||
return $location;
|
return $location;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a character's wallet by their character ID. Returns the wallet's data as an associative array.
|
|
||||||
*/
|
|
||||||
function char_get_wallet(int $char_id): array
|
|
||||||
{
|
|
||||||
$wallet = db_query(db_live(), "SELECT * FROM char_wallets WHERE char_id = :p", [':p' => $char_id])->fetchArray(SQLITE3_ASSOC);
|
|
||||||
if ($wallet === false) throw new Exception('Wallet not found. (cgw)');
|
|
||||||
return $wallet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See if a character name exists.
|
* See if a character name exists.
|
||||||
*/
|
*/
|
||||||
|
@ -187,3 +144,89 @@ function char_belongs_to_user(int $char_id, int $user_id): bool
|
||||||
if ($char === false) throw new Exception('Character not found. (cbtu)');
|
if ($char === false) throw new Exception('Character not found. (cbtu)');
|
||||||
return $char['user_id'] === $user_id;
|
return $char['user_id'] === $user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a character by their ID. This will delete all associated data tables as well.
|
||||||
|
*/
|
||||||
|
function char_delete(int $char_id): void
|
||||||
|
{
|
||||||
|
// Delete the character
|
||||||
|
if (db_query(db_live(), "DELETE FROM characters WHERE id = :p", [':p' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get item IDs from the character's inventory
|
||||||
|
$items = db_query(db_live(), "SELECT item_id FROM char_inventory WHERE char_id = :p", [':p' => $char_id]);
|
||||||
|
// delete the character's inventory and items
|
||||||
|
while ($row = $items->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
if (db_query(db_live(), "DELETE FROM char_inventory WHERE char_id = :c", [':c' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character inventory. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db_query(db_live(), "DELETE FROM items WHERE id = :p", [':p' => $row['id']]) === false) {
|
||||||
|
throw new Exception('Failed to delete character item slots. (cd)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the character's location
|
||||||
|
if (db_query(db_live(), "DELETE FROM char_locations WHERE char_id = :p", [':p' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character location. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the character's gear
|
||||||
|
if (db_query(db_live(), "DELETE FROM char_gear WHERE char_id = :p", [':p' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character gear. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the character's bank
|
||||||
|
if (db_query(db_live(), "DELETE FROM char_bank WHERE char_id = :p", [':p' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character bank. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete character's banked items
|
||||||
|
if (db_query(db_live(), "DELETE FROM char_banked_items WHERE char_id = :p", [':p' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character bank items. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the user's guild membership
|
||||||
|
if (db_query(db_live(), "DELETE FROM guild_members WHERE char_id = :p", [':p' => $char_id]) === false) {
|
||||||
|
throw new Exception('Failed to delete character guild membership. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the character was a guild leader, hand leadership to the next highest ranking member
|
||||||
|
$guild = db_query(db_live(), "SELECT id FROM guilds WHERE leader_id = :p", [':p' => $char_id])->fetchArray(SQLITE3_ASSOC);
|
||||||
|
if ($guild !== false) {
|
||||||
|
$members = db_query(db_live(), "SELECT char_id FROM guild_members WHERE guild_id = :p ORDER BY rank DESC", [':p' => $guild['id']]);
|
||||||
|
$newLeader = $members->fetchArray(SQLITE3_ASSOC);
|
||||||
|
if ($newLeader !== false) {
|
||||||
|
db_query(db_live(), "UPDATE guilds SET leader_id = :p WHERE id = :g", [':p' => $newLeader['char_id'], ':g' => $guild['id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a list of all pve fight IDs.
|
||||||
|
$pve = db_query(db_fights(), "SELECT id FROM pve WHERE char_id = :p", [':p' => $char_id]);
|
||||||
|
// Get a list of all pvp fight IDs.
|
||||||
|
$pvp = db_query(db_fights(), "SELECT id FROM pvp WHERE char1_id = :p OR char2_id = :p", [':p' => $char_id]);
|
||||||
|
|
||||||
|
// Delete all pve fights
|
||||||
|
while ($row = $pve->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
if (db_query(db_fights(), "DELETE FROM pve WHERE id = :p", [':p' => $row['id']]) === false) {
|
||||||
|
throw new Exception('Failed to delete pve fight. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db_query(db_fights(), "DELETE FROM pve_logs WHERE fight_id = :p", [':p' => $row['id']]) === false) {
|
||||||
|
throw new Exception('Failed to delete pve fight logs. (cd)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all pvp fights
|
||||||
|
while ($row = $pvp->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
if (db_query(db_fights(), "DELETE FROM pvp WHERE id = :p", [':p' => $row['id']]) === false) {
|
||||||
|
throw new Exception('Failed to delete pvp fight. (cd)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db_query(db_fights(), "DELETE FROM pvp_logs WHERE fight_id = :p", [':p' => $row['id']]) === false) {
|
||||||
|
throw new Exception('Failed to delete pvp fight logs. (cd)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -35,3 +35,18 @@ function user_delete(string|int $user): SQLite3Result|false
|
||||||
{
|
{
|
||||||
return db_query(db_auth(), "DELETE FROM users WHERE username = :u OR email = :u OR id = :u", [':u' => $user]);
|
return db_query(db_auth(), "DELETE FROM users WHERE username = :u OR email = :u OR id = :u", [':u' => $user]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an account wallet. Can optionally specify the starting balances of the wallet. Returns the created wallet's
|
||||||
|
* ID. If a currency is set to -1, the starting_silver or starting_star_gems fields from the env will be used.
|
||||||
|
*/
|
||||||
|
function wallet_create(int $user_id, int $silver = -1, int $starGems = -1): void
|
||||||
|
{
|
||||||
|
if (db_query(db_live(), "INSERT INTO wallets (user_id, silver, stargem) VALUES (:u, :s, :sg)", [
|
||||||
|
':u' => $user_id,
|
||||||
|
':s' => $silver === -1 ? env('start_silver', 10) : $silver,
|
||||||
|
':sg' => $starGems === -1 ? env('start_star_gems', 0) : $starGems
|
||||||
|
]) === false) {
|
||||||
|
throw new Exception('Failed to create wallet. (wc)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,4 +27,8 @@
|
||||||
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Travel Points<br><?= $char['current_tp'] ?> / <?= $char['max_tp'] ?>"></div>
|
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Travel Points<br><?= $char['current_tp'] ?> / <?= $char['max_tp'] ?>"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<?= wallet('silver') ?> Silver
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
7
templates/components/char_select_box.php
Normal file
7
templates/components/char_select_box.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="radio-block <?= $id === user('char_id') ? 'active' : '' ?>">
|
||||||
|
<input type="radio" name="char_id" value="<?= $id ?>" id="char_<?= $id ?>"<?= $id === user('char_id') ? 'disabled' : '' ?>>
|
||||||
|
<label for="char_<?= $id ?>">
|
||||||
|
<?= $char['name'] ?>
|
||||||
|
<span class="badge"><?= $char['level'] ?></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
5
templates/components/debug_query_log.php
Normal file
5
templates/components/debug_query_log.php
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<div id="debug-query-log">
|
||||||
|
<h3>Query Log</h3>
|
||||||
|
<p class="mb-2"><?= $GLOBALS['queries'] ?> queries were executed.</p>
|
||||||
|
<?php if (!empty($GLOBALS['query_log'])) foreach ($GLOBALS['query_log'] as $query) echo "<p>$query</p>"; ?>
|
||||||
|
</div>
|
|
@ -49,6 +49,8 @@
|
||||||
<p>v<?= env('version') ?></p>
|
<p>v<?= env('version') ?></p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<?php if (env('debug', false)) echo c_debug_query_log(); ?>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import Tooltip from '/assets/scripts/tooltip.js';
|
import Tooltip from '/assets/scripts/tooltip.js';
|
||||||
Tooltip.init();
|
Tooltip.init();
|
||||||
|
|
24
templates/pages/chars/delete.php
Normal file
24
templates/pages/chars/delete.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<div class="container-960">
|
||||||
|
<h1 class="my-4">Delete Character</h1>
|
||||||
|
|
||||||
|
<p class="mb-2">
|
||||||
|
<b>Warning!</b> This action is irreversible. Once you delete a character, it is gone forever. All items, banked items and currency,
|
||||||
|
fight records, and other data associated with the character will be lost.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="mb-4">
|
||||||
|
Are you <b>absolutely sure</b> you want to <b>delete this character</b>? If so, type the character's name below to confirm.
|
||||||
|
Otherwise, click the back button to cancel.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form action="/character/delete" method="post">
|
||||||
|
<?= csrf_field() ?>
|
||||||
|
<input type="hidden" name="char_id" value="<?= $char['id'] ?>">
|
||||||
|
|
||||||
|
<label for="name">Type <b><?= $char['name'] ?></b> below.</label>
|
||||||
|
<input id="name" class="form control mb-2" type="text" name="name" placeholder="Character Name">
|
||||||
|
|
||||||
|
<button class="ui button danger" type="submit">Delete</button>
|
||||||
|
<a class="ui button" href="/characters">Back</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
45
templates/pages/chars/list.php
Normal file
45
templates/pages/chars/list.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<section>
|
||||||
|
<?php
|
||||||
|
if (($f = flash('alert_character_list_1')) !== false) echo c_alert($f[0], $f[1]);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h1>Characters <span class="badge"><?= count($chars) . '/' . user('char_slots') ?></span></h1>
|
||||||
|
<?php
|
||||||
|
if (count($chars) > 0): ?>
|
||||||
|
<form action="/characters" method="post">
|
||||||
|
<input type="hidden" name="csrf" value="<?= csrf() ?>">
|
||||||
|
|
||||||
|
<div class="my-4 character-select">
|
||||||
|
<?php foreach ($chars as $id => $char) echo c_char_select_box($id, $char); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="ui button primary" name="action" value="select">Select</button>
|
||||||
|
<button type="submit" class="ui button danger" name="action" value="delete">Delete</button>
|
||||||
|
</form>
|
||||||
|
<?php else: ?>
|
||||||
|
<!-- Should never see this particular message. If you have, there's a bug. -->
|
||||||
|
<p>You have no characters.</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<?php
|
||||||
|
if (($f = flash('alert_character_list_2')) !== false) echo c_alert($f[0], $f[1]);
|
||||||
|
if (($f = flash('errors_create_character')) !== false) echo c_alert('danger', array_to_ul($f));
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if (user('char_slots') > count($chars)): ?>
|
||||||
|
<h2>Create a new character</h2>
|
||||||
|
<?php $num_slots_left = user('char_slots') - count($chars); ?>
|
||||||
|
<p>You have <b><?= $num_slots_left ?> <?= $num_slots_left === 1 ? 'slot' : 'slots' ?></b> left.</p>
|
||||||
|
<form action="/character/create" method="post">
|
||||||
|
<input type="hidden" name="csrf" value="<?= csrf() ?>">
|
||||||
|
|
||||||
|
<div class="my-4">
|
||||||
|
<input class="form control" type="text" name="name" id="name" placeholder="Character name" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="ui button secondary">Create</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
|
@ -1,16 +0,0 @@
|
||||||
<h1>Characters</h1>
|
|
||||||
<?php
|
|
||||||
$list = char_list(user('id'));
|
|
||||||
if (count($list) > 0): ?>
|
|
||||||
<form action="/character/select" method="post">
|
|
||||||
<input type="hidden" name="csrf" value="<?= csrf() ?>">
|
|
||||||
<?php foreach ($list as $id => $char): ?>
|
|
||||||
<input type="radio" name="char_id" value="<?= $id ?>" id="char_<?= $id ?>">
|
|
||||||
<label for="char_<?= $id ?>"><?= $char['name'] ?> (Level <?= $char['level'] ?>)</label><br>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<input type="submit" value="Select Character">
|
|
||||||
</form>
|
|
||||||
<?php else: ?>
|
|
||||||
<!-- Should never see this particular message. If you have, there's a bug. -->
|
|
||||||
<p>You have no characters.</p>
|
|
||||||
<?php endif; ?>
|
|
Loading…
Reference in New Issue
Block a user