#include <dragontype/number.h>
#include "client/client.h"
#include "client/client_map.h"
+#include "perlin.h"
#include "util.h"
static bool disconnect_handler(unused Client *client, bool good)
return ret;
}
-static bool simulation_distance_handler(Client *client, bool good)
+static bool info_handler(Client *client, bool good)
{
u32 simulation_distance;
+ s32 server_seed;
- if (! read_u32(client->fd, &simulation_distance))
+ if (! (read_u32(client->fd, &simulation_distance) && read_s32(client->fd, &server_seed)))
return false;
- if (good)
+ if (good) {
client_map_set_simulation_distance(simulation_distance);
+ seed = server_seed;
+ }
return true;
}
{&disconnect_handler, "DISCONNECT", CS_CREATED | CS_AUTH | CS_ACTIVE},
{&auth_handler, "AUTH", CS_AUTH},
{&block_handler, "BLOCK", CS_ACTIVE},
- {&simulation_distance_handler, "SIMULATION_DISTANCE", CS_ACTIVE},
+ {&info_handler, "INFO", CS_ACTIVE},
};
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
+#include <time.h>
#include "server/database.h"
#include "server/server_map.h"
+#include "perlin.h"
#include "util.h"
static sqlite3 *database;
// utility functions
+// prepare a SQLite3 statement
+static inline sqlite3_stmt *prepare_statement(const char *sql)
+{
+ sqlite3_stmt *stmt;
+ return sqlite3_prepare_v2(database, sql, -1, &stmt, NULL) == SQLITE_OK ? stmt : NULL;
+}
+
// print SQLite3 error message for failed block SQL statement
-static void print_block_error(MapBlock *block, const char *action)
+static inline void print_block_error(MapBlock *block, const char *action)
{
- printf("Database error with %s block at (%d, %d, %d): %s\n", action, block->pos.x, block->pos.y, block->pos.z, sqlite3_errmsg(database));
+ fprintf(stderr, "Database error with %s block at (%d, %d, %d): %s\n", action, block->pos.x, block->pos.y, block->pos.z, sqlite3_errmsg(database));
}
// prepare a SQLite3 block statement and bind the position
{
sqlite3_stmt *stmt;
- if (sqlite3_prepare_v2(database, sql, -1, &stmt, NULL) != SQLITE_OK) {
+ if (! (stmt = prepare_statement(sql))) {
print_block_error(block, action);
return NULL;
}
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);
+ return false;
+ }
+
+ sqlite3_bind_text(stmt, 1, key, strlen(key), SQLITE_TRANSIENT);
+
+ int rc = sqlite3_step(stmt);
+ bool found = rc == SQLITE_ROW;
+
+ if (found)
+ *value_ptr = sqlite3_column_int(stmt, 0);
+ else if (rc != SQLITE_DONE)
+ print_load_error(key);
+
+ sqlite3_finalize(stmt);
+ return found;
+}
+
+// save something to meta
+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);
+ return;
+ }
+
+ sqlite3_bind_text(stmt, 1, key, strlen(key), SQLITE_TRANSIENT);
+ sqlite3_bind_int(stmt, 2, value);
+
+ if (sqlite3_step(stmt) != SQLITE_DONE)
+ print_save_error(key);
+}
+
// public functions
// open and initialize world SQLite3 database
char *err;
if (sqlite3_open_v2("world.sqlite", &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL) != SQLITE_OK) {
- printf("Failed to open database: %s\n", sqlite3_errmsg(database));
- } else if (sqlite3_exec(database, "CREATE TABLE IF NOT EXISTS map (pos BLOB PRIMARY KEY, generated INT, size INT, data BLOB, mgsb_size INT, mgsb_data BLOB);", NULL, NULL, &err) != SQLITE_OK) {
- printf("Failed to initialize database: %s\n", err);
- sqlite3_free(err);
+ fprintf(stderr, "Failed to open database: %s\n", sqlite3_errmsg(database));
+ 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);",
+ };
+
+ for (int i = 0; i < 2; 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);
+ return;
+ }
+ }
+
+ if (! load_meta("seed", &seed)) {
+ srand(time(0));
+ seed = rand();
+ save_meta("seed", seed);
}
}