diff options
| author | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-12 21:57:46 +1100 |
|---|---|---|
| committer | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-12 21:57:46 +1100 |
| commit | e4483eca01b48b943cd0461e24a74ae1a3139ed4 (patch) | |
| tree | ed58c3c246e3af1af337697695d780aa31f6ad9a /src/server/database.cc | |
| parent | 1cc08c51eb4b0f95c30c0a98ad1fc5ad3459b2df (diff) | |
Update to most recent version (old initial commit)
Diffstat (limited to 'src/server/database.cc')
| -rw-r--r-- | src/server/database.cc | 77 |
1 files changed, 54 insertions, 23 deletions
diff --git a/src/server/database.cc b/src/server/database.cc index 077c86c..37f5757 100644 --- a/src/server/database.cc +++ b/src/server/database.cc @@ -3,14 +3,25 @@ namespace server { namespace database { +// because of all the things not to work, bit cast doesn't +template <typename T, typename U> +static T bit_cast(const U& src) noexcept { + static_assert(sizeof(T) == sizeof(U)); + + T dest; + std::memcpy(&dest, &src, sizeof(U)); + return dest; +} + sqlite3* get_database() noexcept { static sqlite3* const database = []() -> sqlite3* { std::filesystem::create_directory(server::state.directory); const std::string path = server::state.directory + "world.dat"; if (!std::filesystem::exists(path)) { - shared::print::warn( - "server: regenerating non-existent world data\n"); + shared::print::warn + << shared::print::time + << "server: regenerating non-existent world data\n"; } sqlite3* database = nullptr; @@ -59,8 +70,8 @@ static void finalise(sqlite3_stmt*& statement) noexcept { static void bind_int64(sqlite3_stmt*& statement, const int index, const std::uint64_t& key) noexcept { - if (const int status = sqlite3_bind_int64(statement, index, - std::bit_cast<std::int64_t>(key)); + if (const int status = + sqlite3_bind_int64(statement, index, bit_cast<std::int64_t>(key)); status != SQLITE_OK) { throw std::runtime_error(std::string{"sqlite bind int error \""} + sqlite3_errstr(status) + '\"'); @@ -121,8 +132,7 @@ void quit() noexcept { // We have to store our key in network byte order! static std::uint64_t make_key(const shared::math::coords& coords) noexcept { const auto to_64 = [](const std::int32_t& val, const int lshift) { - return static_cast<std::uint64_t>( - htonl(std::bit_cast<std::uint32_t>(val))) + return static_cast<std::uint64_t>(htonl(bit_cast<std::uint32_t>(val))) << lshift; }; @@ -145,14 +155,21 @@ maybe_read_chunk(const shared::math::coords& pos) noexcept { std::string blocks{addr, addr + sqlite3_column_bytes(statement, 0)}; finalise(statement); - shared::decompress_string(blocks); - proto::chunk chunk; - if (!chunk.ParseFromString(blocks)) { + std::optional<proto::chunk> chunk = [&]() -> std::optional<proto::chunk> { + const auto decompress = shared::maybe_decompress_string(blocks); + if (!decompress.has_value()) { + return std::nullopt; + } - shared::print::fault("server: chunk [" + std::to_string(pos.x) + ", " + - std::to_string(pos.z) + - "] failed to parse and was evicted\n"); + proto::chunk ret; + ret.ParseFromString(*decompress); + return ret; + }(); + if (!chunk.has_value()) { + shared::print::fault << shared::print::time << "server: chunk [" + << pos.x << ", " << pos.z + << "] failed to parse and was evicted\n"; statement = nullptr; prepare(statement, "DELETE FROM Chunks WHERE Chunks.coords = ?;"); bind_int64(statement, 1, make_key(pos)); @@ -160,14 +177,14 @@ maybe_read_chunk(const shared::math::coords& pos) noexcept { finalise(statement); return std::nullopt; } - return chunk; + return *chunk; } void write_chunk(const shared::math::coords& pos, const proto::chunk& chunk) noexcept { std::string blocks; chunk.SerializeToString(&blocks); - shared::compress_string(blocks); + blocks = shared::compress_string(blocks); sqlite3_stmt* statement = nullptr; @@ -195,17 +212,30 @@ maybe_read_player(const std::string& username) noexcept { const char* plr_adr = static_cast<const char*>(sqlite3_column_blob(statement, 0)); - std::string player_bytes{plr_adr, plr_adr + sqlite3_column_bytes(statement, 0)}; + std::string player_bytes{plr_adr, + plr_adr + sqlite3_column_bytes(statement, 0)}; const unsigned char* pass_adr = sqlite3_column_text(statement, 1); - std::string pass_bytes{pass_adr, pass_adr + sqlite3_column_bytes(statement, 1)}; + std::string pass_bytes{pass_adr, + pass_adr + sqlite3_column_bytes(statement, 1)}; finalise(statement); - shared::decompress_string(player_bytes); - proto::player player; - if (!player.ParseFromString(player_bytes)) { - shared::print::fault("server: player \"" + username + - "\" failed to parse and was evicted\n"); + const std::optional<proto::player> player = + [&]() -> std::optional<proto::player> { + const auto decompress = shared::maybe_decompress_string(player_bytes); + if (!decompress.has_value()) { + return std::nullopt; + } + + proto::player ret; + ret.ParseFromString(*decompress); + return ret; + }(); + + if (!player.has_value()) { + shared::print::fault << shared::print::time << "server: player \"" + << username + << "\" failed to parse and was evicted\n"; statement = nullptr; prepare(statement, "DELETE FROM Players WHERE Players.username = ?;"); @@ -214,14 +244,15 @@ maybe_read_player(const std::string& username) noexcept { finalise(statement); return std::nullopt; } - return std::make_pair(player, pass_bytes); + + return std::make_pair(*player, pass_bytes); } void write_player(const std::string& username, const std::string& password, const proto::player& player) noexcept { std::string player_bytes; player.SerializeToString(&player_bytes); - shared::compress_string(player_bytes); + player_bytes = shared::compress_string(player_bytes); sqlite3_stmt* statement = nullptr; prepare(statement, "INSERT OR REPLACE INTO Players VALUES(?, ?, ?);"); |
