182 lines
6.3 KiB
PHP
182 lines
6.3 KiB
PHP
<?php
|
|
|
|
/*
|
|
Players are the living, breathing entities that interact with the game world. They are inextricably linked to their
|
|
accounts, and are the primary means by which the player interacts with the game world. Separating the player from
|
|
the account allows for multiple players to be associated with a single account, and to prevent concurrency issues
|
|
when performing auth checks on the database.
|
|
|
|
When creating a player, we want to init all of the related data tables; wallets, inventory, bank, etc.
|
|
|
|
When retrieving a player, we will get the tables as-needed, to prevent allocating more memory than we need.
|
|
*/
|
|
|
|
const currently = [
|
|
0 => '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);
|
|
}
|