#pragma once // SQLite persistence (WAL): accounts/characters, owned creatures, dex and a // small key/value table for world state (clock, weather). #include "Appearance.h" #include "Protocol.h" #include #include #include #include struct sqlite3; struct sqlite3_stmt; namespace bs { struct PlayerRow { int64_t id = 0; std::string token, name; Appearance look; float x = 0, z = 0, yaw = 0; int capsules = 0; bool introDone = false; int64_t createdAt = 0, lastSeen = 0; }; class Database { public: Database() = default; Database(const Database&) = delete; Database& operator=(const Database&) = delete; ~Database(); bool open(const std::string& path, std::string* error); void close(); bool loadPlayer(const std::string& token, PlayerRow& out); int64_t createPlayer(const PlayerRow& row); // returns the new id, 0 on failure void savePlayer(const PlayerRow& row); // everything but token / created_at void savePosition(int64_t id, float x, float z, float yaw); std::vector loadCreatures(int64_t owner); uint32_t insertCreature(int64_t owner, uint16_t species, int64_t caughtAt, bool inParty); // uid, 0 on failure void setInParty(uint32_t uid, bool inParty); void loadDex(int64_t owner, std::set& seen, std::set& caught); void markSeen(int64_t owner, uint16_t species); void markCaught(int64_t owner, uint16_t species); bool getWorld(const std::string& key, std::string& value); void setWorld(const std::string& key, const std::string& value); // Groups many writes into one transaction (shutdown, periodic saves). void begin(); void commit(); private: sqlite3_stmt* prepare(const char* sql); // cached, reset before reuse bool exec(const char* sql); sqlite3* db_ = nullptr; std::unordered_map stmts_; // keyed by the SQL literal }; std::string appearanceToJson(const Appearance& a); Appearance appearanceFromJson(const std::string& s); } // namespace bs