313 lines
9.0 KiB
PHP
313 lines
9.0 KiB
PHP
<?php
|
|
|
|
/*
|
|
The second URI segment determines the step/page we are on.
|
|
*/
|
|
|
|
class InstallModule
|
|
{
|
|
public static function handle()
|
|
{
|
|
$s = App::$req->uri(1) ?? ''; // second segment
|
|
$m = App::$req->method; // request method
|
|
|
|
if ($s == '' || $s == 'intro') return self::intro();
|
|
if ($s == 'database' && $m == 'POST') return self::database();
|
|
if ($s == 'finish' && $m == 'POST') return self::finish();
|
|
return self::fourOhFour();
|
|
}
|
|
|
|
private static function intro()
|
|
{
|
|
echo render('install/layout', ['title' => 'Intro', 'step' => 'first']);
|
|
}
|
|
|
|
private static function database()
|
|
{
|
|
$istart = microtime(true); // time the database setup
|
|
if (!isset($_POST['mode'])) redirect('/install'); // redirect if no mode
|
|
$complete = $_POST['mode'] == 'complete'; // complete or partial setup
|
|
$defaults = SERVER.'/database/packs/Default/';
|
|
|
|
// if the database already exists, have the app remake it
|
|
App::performDatabaseReset();
|
|
|
|
// @Settings
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'settings' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'game_name' TEXT DEFAULT 'Dragon Knight',
|
|
'game_version' TEXT DEFAULT '1.0',
|
|
'game_dev' TEXT DEFAULT 'Sharkk',
|
|
'game_url' TEXT DEFAULT 'https://dragonknight.dev',
|
|
'game_size' INT DEFAULT 250,
|
|
'game_open' INT DEFAULT 1,
|
|
'admin_email' TEXT DEFAULT 'admin@dragonknight.dev',
|
|
'forum_type' INT DEFAULT 1,
|
|
'forum_url' TEXT DEFAULT '',
|
|
'verify_email' INT DEFAULT 1,
|
|
'show_news' INT DEFAULT 1,
|
|
'show_online' INT DEFAULT 1,
|
|
'show_babble' INT DEFAULT 1,
|
|
'tp_growth' INT DEFAULT 1,
|
|
'stat_point_gain' INT DEFAULT 5
|
|
);");
|
|
|
|
// insert default settings
|
|
App::$db->q("INSERT INTO settings DEFAULT VALUES;");
|
|
|
|
// @Classes
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'classes' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'name' TEXT DEFAULT '',
|
|
'start_hp' INT DEFAULT 0,
|
|
'start_mp' INT DEFAULT 0,
|
|
'start_str' INT DEFAULT 0,
|
|
'start_atk' INT DEFAULT 0,
|
|
'start_dex' INT DEFAULT 0,
|
|
'start_def' INT DEFAULT 0,
|
|
'growth_hp' INT DEFAULT 0,
|
|
'growth_mp' INT DEFAULT 0,
|
|
'growth_str' INT DEFAULT 0,
|
|
'growth_atk' INT DEFAULT 0,
|
|
'growth_dex' INT DEFAULT 0,
|
|
'growth_def' INT DEFAULT 0
|
|
);");
|
|
|
|
if ($complete) {
|
|
// add default classes if complete install
|
|
App::$db->insertFromCSV('classes', "$defaults/classes.csv");
|
|
} else {
|
|
// there must be at least one class for user creation to work
|
|
App::$db->q("INSERT INTO classes (name) VALUES ('Adventurer');");
|
|
}
|
|
|
|
// @Babble
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'babble' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'author' INTEGER NOT NULL,
|
|
'babble' TEXT NOT NULL,
|
|
'posted' DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);");
|
|
|
|
// @Drops
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'drops' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'name' TEXT NOT NULL,
|
|
'level' INTEGER DEFAULT 1,
|
|
'type' INTEGER DEFAULT 1,
|
|
'attr' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// add default drops if complete install
|
|
if ($complete) App::$db->insertFromCSV('drops', "$defaults/drops.csv");
|
|
|
|
// @Forum
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'forum' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'posted' DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
'new_post' DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
'author' INTEGER NOT NULL,
|
|
'subject' TEXT DEFAULT '',
|
|
'message' TEXT DEFAULT '',
|
|
'locked' INTEGER DEFAULT 0,
|
|
'sticky' INTEGER DEFAULT 0,
|
|
'parent' INTEGER DEFAULT 0,
|
|
'posts' INTEGER DEFAULT 0,
|
|
'views' INTEGER DEFAULT 0,
|
|
'hidden' INTEGER DEFAULT 0
|
|
);");
|
|
|
|
// @Items
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'items' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'type' INTEGER DEFAULT 1,
|
|
'name' TEXT NOT NULL,
|
|
'cost' INTEGER DEFAULT 0,
|
|
'attr' TEXT DEFAULT '',
|
|
'icon' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// add default items if complete install
|
|
if ($complete) App::$db->insertFromCSV('items', "$defaults/items.csv");
|
|
|
|
// @Monsters
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'monsters' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'name' TEXT NOT NULL,
|
|
'level' INTEGER DEFAULT 1,
|
|
'hp' INTEGER DEFAULT 1,
|
|
'atk' INTEGER DEFAULT 1,
|
|
'def' INTEGER DEFAULT 1,
|
|
'exp' INTEGER DEFAULT 1,
|
|
'gold' INTEGER DEFAULT 1,
|
|
'immune' INTEGER DEFAULT 0,
|
|
'image' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// add default monsters if complete install
|
|
if ($complete) App::$db->insertFromCSV('monsters', "$defaults/monsters.csv");
|
|
|
|
// @News
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'news' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'author' INTEGER DEFAULT 1,
|
|
'title' TEXT DEFAULT '',
|
|
'content' TEXT DEFAULT '',
|
|
'posted' DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);");
|
|
|
|
// @Spells
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'spells' (
|
|
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
'name' TEXT NOT NULL,
|
|
'type' INTEGER DEFAULT 1,
|
|
'mp' INTEGER DEFAULT 0,
|
|
'effect' TEXT DEFAULT '',
|
|
'icon' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// add default spells if complete install
|
|
if ($complete) App::$db->insertFromCSV('spells', "$defaults/spells.csv");
|
|
|
|
// @LearnedSpells
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'class_spells' (
|
|
'level' INTEGER NOT NULL,
|
|
'class_id' INTEGER NOT NULL,
|
|
'spell_id' INTEGER NOT NULL
|
|
);");
|
|
|
|
// add default class spells if complete install
|
|
if ($complete) App::$db->insertFromCSV('class_spells', "$defaults/class_spells.csv");
|
|
|
|
// @Towns
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'towns' (
|
|
'id' INTEGER PRIMARY KEY,
|
|
'name' TEXT NOT NULL,
|
|
'x' INTEGER DEFAULT 0,
|
|
'y' INTEGER DEFAULT 0,
|
|
'inn_cost' INTEGER DEFAULT 0,
|
|
'map_cost' INTEGER DEFAULT 5,
|
|
'tp_cost' INTEGER DEFAULT 0,
|
|
'shop_list' TEXT DEFAULT '',
|
|
'image' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// add default towns if complete install
|
|
if ($complete) App::$db->insertFromCSV('towns', "$defaults/towns.csv");
|
|
|
|
// @Players
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'players' (
|
|
'id' INTEGER PRIMARY KEY,
|
|
'username' TEXT NOT NULL,
|
|
'password' TEXT NOT NULL,
|
|
'email' TEXT DEFAULT '',
|
|
'verified' INTEGER DEFAULT 1,
|
|
'registered' DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
'last_online' DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
'currently' INTEGER DEFAULT 0,
|
|
'role' INTEGER DEFAULT 1,
|
|
'class_id' INTEGER DEFAULT 1,
|
|
'level' INTEGER DEFAULT 1,
|
|
'exp' INTEGER DEFAULT 0,
|
|
'exp2l' INTEGER DEFAULT 0,
|
|
'gold' INTEGER DEFAULT 0,
|
|
'stat_points' INTEGER DEFAULT 0,
|
|
'hp' INTEGER DEFAULT 0,
|
|
'max_hp' INTEGER DEFAULT 0,
|
|
'mp' INTEGER DEFAULT 0,
|
|
'max_mp' INTEGER DEFAULT 0,
|
|
'tp' INTEGER DEFAULT 5,
|
|
'max_tp' INTEGER DEFAULT 5,
|
|
'str' INTEGER DEFAULT 0,
|
|
'atk' INTEGER DEFAULT 0,
|
|
'dex' INTEGER DEFAULT 0,
|
|
'def' INTEGER DEFAULT 0,
|
|
'weapon_id' INTEGER DEFAULT 0,
|
|
'armor_id' INTEGER DEFAULT 0,
|
|
'shield_id' INTEGER DEFAULT 0,
|
|
'slot_1_id' INTEGER DEFAULT 0,
|
|
'slot_2_id' INTEGER DEFAULT 0,
|
|
'slot_3_id' INTEGER DEFAULT 0,
|
|
'spells' TEXT DEFAULT '',
|
|
'maps' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// @Fights
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'fights' (
|
|
'id' INTEGER PRIMARY KEY,
|
|
'p_id' INTEGER DEFAULT 1,
|
|
'm_id' INTEGER DEFAULT 1,
|
|
'turn' INTEGER DEFAULT 1,
|
|
'p_hp' INTEGER DEFAULT 0,
|
|
'p_maxhp' INTEGER DEFAULT 0,
|
|
'p_mp' INTEGER DEFAULT 0,
|
|
'p_maxmp' INTEGER DEFAULT 0,
|
|
'm_hp' INTEGER DEFAULT 0,
|
|
'm_maxhp' INTEGER DEFAULT 0,
|
|
'effects' TEXT DEFAULT ''
|
|
);");
|
|
|
|
// @Sessions
|
|
App::$db->q("CREATE TABLE IF NOT EXISTS 'sessions' (
|
|
'player_id' INTEGER NOT NULL UNIQUE,
|
|
'token' TEXT NOT NULL,
|
|
'expires' DATETIME NOT NULL
|
|
);");
|
|
|
|
// Create the .installed file in the server folder
|
|
file_put_contents(SERVER.'/.installed', 'Installed on '.date('Y-m-d H:i:s'));
|
|
|
|
echo render('install/layout', ['title' => 'Database Setup', 'step' => 'second', 'complete' => $complete, 'start' => $istart]);
|
|
}
|
|
|
|
private static function finish()
|
|
{
|
|
$errors = [];
|
|
|
|
// Make sure our info is at least mostly valid
|
|
if (!required(['username', 'password', 'email'])) {
|
|
$errors[] = 'All fields are required.';
|
|
} else {
|
|
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
|
|
$errors[] = 'Invalid email address format.';
|
|
}
|
|
|
|
if (strlen($_POST['password']) < 6) {
|
|
$errors[] = 'Password must be at least 6 characters long.';
|
|
}
|
|
}
|
|
|
|
// Make sure the class selection is present
|
|
$class = $_POST['class'] ?? 1;
|
|
|
|
// If we have any errors, bail to the form and let the user know
|
|
if (!empty($errors)) {
|
|
echo render('install/layout', ['title' => 'Admin Account', 'step' => 'third', 'errors' => $errors, 'complete' => $_POST['complete'] ?? false]);
|
|
exit;
|
|
}
|
|
|
|
// Create the admin account
|
|
Player::create([
|
|
'username' => trim($_POST['username']),
|
|
'password' => password_hash($_POST['password'], PASSWORD_ARGON2ID),
|
|
'email' => trim($_POST['email']),
|
|
'class_id' => $class,
|
|
'verified' => 1,
|
|
'role' => 5,
|
|
'level' => $_POST['level'] ?? 1
|
|
]);
|
|
|
|
// login the admin
|
|
App::$auth->login($_POST['username'], $_POST['password']);
|
|
|
|
// Render the finished page!
|
|
echo render('install/layout', ['title' => 'Finished!', 'step' => 'done', 'name' => $_POST['username'], 'complete' => $_POST['complete'] ?? false]);
|
|
|
|
}
|
|
|
|
private static function fourOhFour()
|
|
{
|
|
echo render('install/layout', ['title' => 'Four Oh Four', 'step' => 'four']);
|
|
}
|
|
}
|