]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Save player positions in database
authorElias Fleckenstein <eliasfleckenstein@web.de>
Sat, 25 Sep 2021 21:50:02 +0000 (23:50 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Sat, 25 Sep 2021 21:50:02 +0000 (23:50 +0200)
src/client/client_commands.c
src/client/client_commands.h
src/client/client_player.c
src/client/client_player.h
src/server/database.c
src/server/database.h
src/server/server_commands.c

index 808c47d4b100969946694651b59875e01a8d13dc..c047922fb15b0d897919c992d21bd2fbc0b8cc17 100644 (file)
@@ -3,6 +3,7 @@
 #include <dragontype/number.h>
 #include "client/client.h"
 #include "client/client_map.h"
+#include "client/client_player.h"
 #include "perlin.h"
 #include "util.h"
 
@@ -85,10 +86,24 @@ static bool info_handler(Client *client, bool good)
        return true;
 }
 
+static bool setpos_handler(Client *client, bool good)
+{
+       v3f64 pos;
+
+       if (! read_v3f64(client->fd, &pos))
+               return false;
+
+       if (good)
+               client_player_set_position(pos);
+
+       return true;
+}
+
 CommandHandler command_handlers[CLIENT_COMMAND_COUNT] = {
        {0},
        {&disconnect_handler, "DISCONNECT", CS_CREATED | CS_AUTH | CS_ACTIVE},
        {&auth_handler, "AUTH", CS_AUTH},
        {&block_handler, "BLOCK", CS_ACTIVE},
        {&info_handler, "INFO", CS_ACTIVE},
+       {&setpos_handler, "SETPOS", CS_ACTIVE},
 };
index d894a4a006a0666880686020bb91b616f37e30a0..7fd7b09c2329cf00719f08087ff83035233a137e 100644 (file)
@@ -8,6 +8,7 @@ typedef enum
        CC_AUTH,
        CC_BLOCK,
        CC_INFO,
+       CC_SETPOS,
        CLIENT_COMMAND_COUNT
 } ClientCommand;
 
index 4f26e2e5e71c0d1cc46580b3713973cfbd3a2993..b964f9e2d7f84ed41d5e7f92fb8b1c3636ca7add 100644 (file)
@@ -77,7 +77,7 @@ static bool can_jump()
 // ClientPlayer singleton constructor
 void client_player_init()
 {
-       client_player.pos = (v3f64) {0.0, 150.0, 0.0};
+       client_player.pos = (v3f64) {0.0, 0.0, 0.0};
        client_player.velocity = (v3f64) {0.0, 0.0, 0.0};
        client_player.box = (aabb3f64) {{-0.3, 0.0, -0.3}, {0.3, 1.75, 0.3}};
        client_player.yaw = client_player.pitch = 0.0f;
@@ -139,6 +139,14 @@ v3f64 client_player_get_position()
        return pos;
 }
 
+// set position (thread-safe)
+void client_player_set_position(v3f64 pos)
+{
+       pthread_rwlock_rdlock(&client_player.rwlock);
+       client_player.pos = pos;
+       pthread_rwlock_unlock(&client_player.rwlock);
+}
+
 // to be called every frame
 void client_player_tick(f64 dtime)
 {
index 16aacf97d6967f4666b7361df3268c9f8c85173c..69c8482fc72dedb6afdf429e9504c01e2968c0ea 100644 (file)
@@ -19,11 +19,12 @@ extern struct ClientPlayer
        Object *obj;                            // 3D mesh object (currently always invisible), not thread safe
 } client_player;
 
-void client_player_init();                             // ClientPlayer singleton constructor
-void client_player_deinit();                   // ClientPlayer singleton destructor
-void client_player_add_to_scene();             // create mesh object
-void client_player_jump();                             // jump if possible
-v3f64 client_player_get_position();            // get position (thread-safe)
-void client_player_tick(f64 dtime);            // to be called every frame
+void client_player_init();                                             // ClientPlayer singleton constructor
+void client_player_deinit();                                   // ClientPlayer singleton destructor
+void client_player_add_to_scene();                             // create mesh object
+void client_player_jump();                                             // jump if possible
+v3f64 client_player_get_position();                            // get position (thread-safe)
+void client_player_set_position(v3f64 pos);            // set position (thread-safe)
+void client_player_tick(f64 dtime);                            // to be called every frame
 
 #endif
index a61af6127e10d02b3d11b1dca4ace7d43e426dc4..c1ca01b2f8972607c56725f27194de4352b8c0b2 100644 (file)
@@ -36,8 +36,8 @@ static sqlite3_stmt *prepare_block_statement(MapBlock *block, const char *action
                return NULL;
        }
 
-       size_t psize = sizeof(s32) * 3;
-       s32 *pos = malloc(psize);
+       size_t psize = sizeof(u32) * 3;
+       u32 *pos = malloc(psize);
        pos[0] = htobe32(block->pos.x);
        pos[1] = htobe32(block->pos.y);
        pos[2] = htobe32(block->pos.z);
@@ -47,25 +47,13 @@ static sqlite3_stmt *prepare_block_statement(MapBlock *block, const char *action
        return stmt;
 }
 
-// print meta load error
-static inline void print_load_error(const char *key)
-{
-       fprintf(stderr, "Database error with loading %s: %s\n", key, sqlite3_errmsg(database));
-}
-
-// print meta save error
-static inline void print_save_error(const char *key)
-{
-       fprintf(stderr, "Database error with saving %s: %s\n", key, sqlite3_errmsg(database));
-}
-
 // load something from meta
 static bool load_meta(const char *key, int *value_ptr)
 {
        sqlite3_stmt *stmt;
 
        if (! (stmt = prepare_statement("SELECT value FROM meta WHERE key=?"))) {
-               print_load_error(key);
+               fprintf(stderr, "Database error with loading %s: %s\n", key, sqlite3_errmsg(database));
                return false;
        }
 
@@ -77,7 +65,7 @@ static bool load_meta(const char *key, int *value_ptr)
        if (found)
                *value_ptr = sqlite3_column_int(stmt, 0);
        else if (rc != SQLITE_DONE)
-               print_load_error(key);
+               fprintf(stderr, "Database error with loading %s: %s\n", key, sqlite3_errmsg(database));
 
        sqlite3_finalize(stmt);
        return found;
@@ -89,7 +77,7 @@ static void save_meta(const char *key, int value)
        sqlite3_stmt *stmt;
 
        if (! (stmt = prepare_statement("REPLACE INTO meta (key, value) VALUES(?1, ?2)"))) {
-               print_save_error(key);
+               fprintf(stderr, "Database error with saving %s: %s\n", key, sqlite3_errmsg(database));
                return;
        }
 
@@ -97,7 +85,20 @@ static void save_meta(const char *key, int value)
        sqlite3_bind_int(stmt, 2, value);
 
        if (sqlite3_step(stmt) != SQLITE_DONE)
-               print_save_error(key);
+               fprintf(stderr, "Database error with saving %s: %s\n", key, sqlite3_errmsg(database));
+
+       sqlite3_finalize(stmt);
+}
+
+// bind v3f64 to sqlite3 statement
+static inline void bind_v3f64(sqlite3_stmt *stmt, int idx, v3f64 pos)
+{
+       size_t psize = sizeof(f64) * 3;
+       f64 *blob = malloc(psize);
+       blob[0] = pos.x;
+       blob[1] = pos.y;
+       blob[2] = pos.z;
+       sqlite3_bind_blob(stmt, idx, blob, psize, &free);
 }
 
 // public functions
@@ -112,12 +113,13 @@ void database_init()
                return;
        }
 
-       const char *init_stmts[2]= {
-               "CREATE TABLE IF NOT EXISTS map (pos BLOB PRIMARY KEY, generated INT, size INT, data BLOB, mgsb_size INT, mgsb_data BLOB);",
-               "CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INT);",
+       const char *init_stmts[3]= {
+               "CREATE TABLE IF NOT EXISTS map (pos BLOB PRIMARY KEY, generated INTEGER, size INTEGER, data BLOB, mgsb_size INTEGER, mgsb_data BLOB);",
+               "CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER);",
+               "CREATE TABLE IF NOT EXISTS players (name TEXT PRIMARY KEY, pos BLOB);"
        };
 
-       for (int i = 0; i < 2; i++) {
+       for (int i = 0; i < 3; i++) {
                if (sqlite3_exec(database, init_stmts[i], NULL, NULL, &err) != SQLITE_OK) {
                        fprintf(stderr, "Failed to initialize database: %s\n", err);
                        sqlite3_free(err);
@@ -201,3 +203,67 @@ void database_save_block(MapBlock *block)
 
        sqlite3_finalize(stmt);
 }
+
+// load player data from database
+bool database_load_player(char *name, v3f64 *pos_ptr)
+{
+       sqlite3_stmt *stmt;
+
+       if (! (stmt = prepare_statement("SELECT pos FROM players WHERE name=?"))) {
+               fprintf(stderr, "Database error with loading player %s: %s\n", name, sqlite3_errmsg(database));
+               return false;
+       }
+
+       sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_TRANSIENT);
+
+       int rc = sqlite3_step(stmt);
+       bool found = rc == SQLITE_ROW;
+
+       if (found) {
+               const f64 *pos = sqlite3_column_blob(stmt, 0);
+               *pos_ptr = (v3f64) {pos[0], pos[1], pos[2]};
+       } else if (rc != SQLITE_DONE) {
+               fprintf(stderr, "Database error with loading player %s: %s\n", name, sqlite3_errmsg(database));
+       }
+
+       sqlite3_finalize(stmt);
+       return found;
+}
+
+// insert new player into database
+void database_create_player(char *name, v3f64 pos)
+{
+       sqlite3_stmt *stmt;
+
+       if (! (stmt = prepare_statement("INSERT INTO players (name, pos) VALUES(?1, ?2)"))) {
+               fprintf(stderr, "Database error with creating player %s: %s\n", name, sqlite3_errmsg(database));
+               return;
+       }
+
+       sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_TRANSIENT);
+       bind_v3f64(stmt, 2, pos);
+
+       if (sqlite3_step(stmt) != SQLITE_DONE)
+               fprintf(stderr, "Database error with creating player %s: %s\n", name, sqlite3_errmsg(database));
+
+       sqlite3_finalize(stmt);
+}
+
+// update player position
+void database_update_player_pos(char *name, v3f64 pos)
+{
+       sqlite3_stmt *stmt;
+
+       if (! (stmt = prepare_statement("UPDATE players SET pos=?1 WHERE name=?2"))) {
+               fprintf(stderr, "Database error with updating player %s position: %s\n", name, sqlite3_errmsg(database));
+               return;
+       }
+
+       bind_v3f64(stmt, 1, pos);
+       sqlite3_bind_text(stmt, 2, name, strlen(name), SQLITE_TRANSIENT);
+
+       if (sqlite3_step(stmt) != SQLITE_DONE)
+               fprintf(stderr, "Database error with updating player %s position: %s\n", name, sqlite3_errmsg(database));
+
+       sqlite3_finalize(stmt);
+}
index 56ddfd0a4ed9acf1221a8889e0119d7e3a6c21cb..608eae7859cffe13d884b48afe4be9b42d9a0b41 100644 (file)
@@ -4,9 +4,11 @@
 #include <stdbool.h>
 #include "map.h"
 
-void database_init();                                          // open and initialize world SQLite3 database
-void database_deinit();                                                // close database
-bool database_load_block(MapBlock *block);     // load a block from map database (initializes state, mgs buffer and data), returns false on failure
-void database_save_block(MapBlock *block);     // save a block to database
-
+void database_init();                                                                          // open and initialize world SQLite3 database
+void database_deinit();                                                                                // close database
+bool database_load_block(MapBlock *block);                                     // load a block from map database (initializes state, mgs buffer and data), returns false on failure
+void database_save_block(MapBlock *block);                                     // save a block to database
+bool database_load_player(char *name, v3f64 *pos_ptr);         // load player data from database
+void database_create_player(char *name, v3f64 pos);                    // insert new player into database
+void database_update_player_pos(char *name, v3f64 pos);                // update player position
 #endif
index f001f58666f3a2a4eca3686079ab6573ea5101f6..5d1a1647847d200d8ae3930d523a834f8fa2c5d6 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include "server/database.h"
 #include "server/server.h"
 #include "server/server_map.h"
 #include "perlin.h"
@@ -34,6 +35,15 @@ static bool auth_handler(Client *client, bool good)
        if (success) {
                client->name = name;
                client->state = CS_ACTIVE;
+
+               if (! database_load_player(client->name, &client->pos)) {
+                       client->pos = (v3f64) {0.0, 150.0, 0.0};
+
+                       database_create_player(client->name, client->pos);
+               }
+
+               printf("%f %f %f\n", client->pos.x, client->pos.y, client->pos.z);
+
        } else {
                free(name);
        }
@@ -41,7 +51,9 @@ static bool auth_handler(Client *client, bool good)
        pthread_mutex_lock(&client->mtx);
        bool ret = write_u32(client->fd, CC_AUTH) && write_u8(client->fd, success);
        if (ret && success)
-               ret = ret && write_u32(client->fd, CC_INFO) && write_u32(client->fd, client->server->config.simulation_distance) && write_s32(client->fd, seed);
+               ret = ret
+                       && write_u32(client->fd, CC_INFO) && write_u32(client->fd, client->server->config.simulation_distance) && write_s32(client->fd, seed)
+                       && write_u32(client->fd, CC_SETPOS) && write_v3f64(client->fd, client->pos);
        pthread_mutex_unlock(&client->mtx);
 
        pthread_rwlock_unlock(&client->server->players_rwlck);
@@ -78,8 +90,10 @@ static bool pos_handler(Client *client, bool good)
        if (! read_v3f64(client->fd, &pos))
                return false;
 
-       if (good)
+       if (good) {
                client->pos = pos;
+               database_update_player_pos(client->name, client->pos);
+       }
 
        return true;
 }