aboutsummaryrefslogtreecommitdiff
path: root/src/server/database.cc
diff options
context:
space:
mode:
authorNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-12 21:57:46 +1100
committerNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-12 21:57:46 +1100
commite4483eca01b48b943cd0461e24a74ae1a3139ed4 (patch)
treeed58c3c246e3af1af337697695d780aa31f6ad9a /src/server/database.cc
parent1cc08c51eb4b0f95c30c0a98ad1fc5ad3459b2df (diff)
Update to most recent version (old initial commit)
Diffstat (limited to 'src/server/database.cc')
-rw-r--r--src/server/database.cc77
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(?, ?, ?);");