'Exploring', 1 => 'In Town', 2 => 'In Combat', 4 => 'In Shop', 5 => 'In Inn' ]; /** * Create a player. Only a user ID and a name are required. All other fields are optional. Pass a key-value array * of overrides to set additional fields. A player's name must be unique, but this function does not check for * that. Returns the created player's ID. */ function char_create(int $user_id, string $name, array $overrides = []): int { // Prep the data and merge in any overrides $data = ['user_id' => $user_id, 'name' => $name]; if (!empty($overrides)) $data = array_merge($data, $overrides); // Prep the fields for the query $k = array_keys($data); $f = implode(', ', $k); $v = implode(', ', array_map(fn($x) => ":$x", $k)); // Create the player! if (db_query(db_live(), "INSERT INTO characters ($f) VALUES ($v)", $data) === false) { // @TODO: Log this error throw new Exception('Failed to create player.'); } // Get the player ID return db_live()->lastInsertRowID(); } /** * Create a player's location record. A player's location is where they are in the game world. A player can only be * in one location at a time. Can define a starting location for the player. Default state is 'Exploring'. */ function char_location_create(int $char_id, int $x = 0, int $y = 0, int $currently = 0): void { if (db_query(db_live(), "INSERT INTO char_locations (char_id, x, y, currently) VALUES (:p, :x, :y, :c)", [ ':p' => $char_id, ':x' => $x, ':y' => $y, ':c' => $currently ]) === false) { throw new Exception('Failed to create player location.'); } } /** * Creates a player's wallet. A player'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 player wallet.'); } } /** * Create the player's gear table. A player's gear is where they store their equipped items. * @TODO: implement initial gear */ function char_gear_create(int $char_id, array $initialGear = []): void { if (db_query(db_live(), "INSERT INTO char_gear (char_id) VALUES (:p)", [':p' => $char_id]) === false) { throw new Exception('Failed to create player gear.'); } } /** * Create the player'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 player bank.'); } } /** * Get a charcter by their ID. Returns the character's data as an associative array. */ function char_find(int $char_id): array { $char = db_query(db_live(), "SELECT * FROM characters WHERE id = :id", [':id' => $char_id])->fetchArray(SQLITE3_ASSOC); if ($char === false) throw new Exception('Character not found.'); return $char; } /** * Count the number of players associated with an account ID. */ function char_count(int $user_id): int { $count = db_query(db_live(), "SELECT COUNT(*) FROM characters WHERE user_id = :u", [':u' => $user_id])->fetchArray(SQLITE3_NUM); if ($count === false) throw new Exception('Failed to count players.'); return (int) $count[0]; } /** * Get a an array of id => [name, level] for all players associated with an account ID. */ function char_list(int $user_id): array { $stmt = db_query(db_live(), "SELECT id, name, level FROM characters WHERE user_id = :u", [':u' => $user_id]); if ($stmt === false) throw new Exception('Failed to list players.'); $players = []; while ($row = $stmt->fetchArray(SQLITE3_ASSOC)) { $players[$row['id']] = ['name' => $row['name'], 'level' => $row['level']]; } return $players; } /** * Get a player's location info by their player ID. Returns the location's data as an associative array. */ function char_get_location(int $char_id): array { // Get the location $location = db_query(db_live(), "SELECT * FROM char_locations WHERE char_id = :p", [':p' => $char_id])->fetchArray(SQLITE3_ASSOC); if ($location === false) throw new Exception('Location not found.'); return $location; } /** * Get a player's wallet by their player 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.'); return $wallet; } /** * See if a player name exists. */ function char_nameExists(string $name): bool { $exists = db_query(db_live(), "SELECT COUNT(*) FROM characters WHERE name = :n", [':n' => $name])->fetchArray(SQLITE3_NUM); if ($exists === false) throw new Exception('Failed to check for player name.'); return (int) $exists[0] > 0; } /** * Checks whether a character exists at a certain ID. */ function char_exists(int $char_id): bool { return db_exists(db_live(), 'characters', 'id', $char_id); }