query( 'SELECT * FROM users WHERE id=? OR username=? COLLATE NOCASE OR email=? COLLATE NOCASE LIMIT 1;', [$id, $id, $id] ); if ($query === false) { return false; } $data = $query->fetchArray(SQLITE3_ASSOC); if ($data === false) { return false; } return new User($data); } /** * Return a list of spells from this user's spell list. */ public function spells(): array|false { return Lib::get_spells_from_list($this->spells); } /** * Restore all HP, MP, and TP values to their max. */ public function restore_points(): User { $this->currenthp = $this->maxhp; $this->currentmp = $this->maxmp; $this->currenttp = $this->maxtp; return $this; } /** * Sends a manual update to online time for this user. */ public function update_online_time(): void { if ($this->onlinetime && strtotime($this->onlinetime) > strtotime('-9 minutes')) { return; } Lib::db()->query('UPDATE users SET onlinetime=CURRENT_TIMESTAMP WHERE id=?;', [$this->id]); } /** * Heal HP by a given amount. Caps to max HP. Returns number of points restored. */ public function restore_hp(int $amount): int { $initial_hp = $this->currenthp; $this->currenthp += $amount; if ($this->currenthp > $this->maxhp) { $this->currenthp = $this->maxhp; } return $this->currenthp - $initial_hp; } /** * Save works just as it does on the Model class. In our case, though, user state changing may necessitate * OOB swaps for parts of the UI that have user data displayed. Left and right nav, for example. In these cases, * we set a flag in GLOBALS state to signify this. */ public function save(): bool { if (empty($this->changes)) { return true; } $placeholders = []; $values = []; foreach ($this->changes as $key => $value) { $placeholders[] = "$key=?"; $values[] = $value; } $values[] = $this->id; $query = 'UPDATE '.$this->table_name.' SET '.implode(', ', $placeholders).' WHERE id = ?;'; $result = Lib::db()->query($query, $values); if ($result === false) { return false; } $GLOBALS['state']['user-state-changed'] = true; return true; } }