192 lines
5.0 KiB
C
192 lines
5.0 KiB
C
#include "models/database.h"
|
|
#include "models/assets.h"
|
|
|
|
#include "3rd_sqlite3.h"
|
|
#include "zpl.h"
|
|
|
|
#include "world/blocks.h"
|
|
#include "models/crafting.h"
|
|
#include "models/items.h"
|
|
|
|
#ifndef ECO2D_DB
|
|
#define ECO2D_DB "eco2d.db"
|
|
#endif
|
|
|
|
static sqlite3 *db;
|
|
static zpl_array(zpl_csv_object) csv_stack;
|
|
|
|
static
|
|
void sql_asset(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
|
|
if (argc == 1) {
|
|
const char *name = (const char *)sqlite3_value_text(argv[0]);
|
|
if (name) {
|
|
sqlite3_result_int(ctx, atoi(db_get(zpl_bprintf("SELECT id FROM assets WHERE name = '%s'", name), false)));
|
|
return;
|
|
}
|
|
}
|
|
|
|
sqlite3_result_null(ctx);
|
|
}
|
|
|
|
bool db_init() {
|
|
bool new_db = !zpl_fs_exists(ECO2D_DB);
|
|
sqlite3_open(ECO2D_DB, &db);
|
|
assert(db && "Failed to open database.");
|
|
|
|
zpl_array_init(csv_stack, zpl_heap());
|
|
sqlite3_create_function(db, "asset", 1, SQLITE_UTF8, NULL, sql_asset, NULL, NULL);
|
|
|
|
if (new_db) {
|
|
zpl_printf("[INFO] Creating new database...\n");
|
|
db_exec_file("art/queries/tables.sql");
|
|
assets_db_init();
|
|
|
|
db_exec_file("art/queries/resources.sql");
|
|
db_exec_file("art/queries/blocks.sql");
|
|
db_exec_file("art/queries/recipes.sql");
|
|
db_exec_file("art/queries/items.sql");
|
|
}
|
|
|
|
// initialise models db
|
|
zpl_printf("[INFO] Loading models from database...\n");
|
|
assets_db(); zpl_printf("[INFO] Assets loaded.\n");
|
|
blocks_db(); zpl_printf("[INFO] Blocks loaded.\n");
|
|
craft_db(); zpl_printf("[INFO] Recipes loaded.\n");
|
|
item_db(); zpl_printf("[INFO] Items loaded.\n");
|
|
return new_db;
|
|
}
|
|
|
|
void db_shutdown() {
|
|
sqlite3_close(db);
|
|
}
|
|
|
|
char *db_get(char *query, bool header) {
|
|
sqlite3_stmt *stmt;
|
|
int rc = sqlite3_prepare_v2(db, query, -1, &stmt, 0);
|
|
if (rc) {
|
|
zpl_printf("[ERROR] Failed to prepare query: %s\n", sqlite3_errmsg(db));
|
|
return 0;
|
|
}
|
|
|
|
zpl_string buf = zpl_string_make(zpl_heap(), "");
|
|
bool is_first=header;
|
|
int cols = sqlite3_column_count(stmt);
|
|
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
|
if (is_first) {
|
|
is_first = 0;
|
|
for (int i = 0; i < cols; i++) {
|
|
buf = zpl_string_appendc(buf, (const char *)sqlite3_column_name(stmt, i));
|
|
|
|
if (i < cols - 1) {
|
|
buf = zpl_string_appendc(buf, ",");
|
|
}
|
|
}
|
|
|
|
buf = zpl_string_appendc(buf, "\n");
|
|
}
|
|
for (int i = 0; i < cols; i++) {
|
|
const char *val = (const char *)sqlite3_column_text(stmt, i);
|
|
if (val == NULL)
|
|
val = "\"(null)\"";
|
|
buf = zpl_string_appendc(buf, val);
|
|
|
|
if (i < cols - 1) {
|
|
buf = zpl_string_appendc(buf, ",");
|
|
}
|
|
}
|
|
|
|
buf = zpl_string_appendc(buf, "\n");
|
|
}
|
|
sqlite3_finalize(stmt);
|
|
#if 0
|
|
char *data = zpl_bprintf("%s", buf);
|
|
zpl_string_free(buf);
|
|
#else //@leak
|
|
char *data = (char *)buf;
|
|
#endif
|
|
return data;
|
|
}
|
|
|
|
char *db_row(char *table, char *name) {
|
|
int kind = atoi(db_get(zpl_bprintf("SELECT id FROM assets WHERE name='%s';", name), 0));
|
|
return db_get(zpl_bprintf("SELECT * FROM %s WHERE kind='%d';", table, kind), 1);
|
|
}
|
|
|
|
bool db_csv(zpl_csv_object *csv, char *query) {
|
|
zpl_zero_item(csv);
|
|
char *res = db_get(query, 1);
|
|
assert(res);
|
|
return zpl_csv_parse(csv, res, zpl_heap(), 1);
|
|
}
|
|
|
|
bool db_row_csv(zpl_csv_object *csv, char *table, char *name) {
|
|
zpl_zero_item(csv);
|
|
char *res = db_row(table, name);
|
|
assert(res);
|
|
return zpl_csv_parse(csv, res, zpl_heap(), 1);
|
|
}
|
|
|
|
bool db_push(char *query) {
|
|
zpl_csv_object csv;
|
|
if (db_csv(&csv, query)) {
|
|
return false;
|
|
}
|
|
zpl_array_append(csv_stack, csv);
|
|
return true;
|
|
}
|
|
|
|
bool db_row_push(char *table, char *name) {
|
|
zpl_csv_object csv;
|
|
if (db_row_csv(&csv, table, name)) {
|
|
return false;
|
|
}
|
|
zpl_array_append(csv_stack, csv);
|
|
return true;
|
|
}
|
|
|
|
zpl_adt_node *db_field(char *field, int row) {
|
|
zpl_csv_object *csv = db_last();
|
|
for (int i = 0; i < zpl_array_count(csv->nodes); i++) {
|
|
if (!zpl_strcmp(csv->nodes[i].name, field)) {
|
|
return &csv->nodes[i].nodes[row];
|
|
}
|
|
}
|
|
assert(0 && "Field not found");
|
|
return NULL;
|
|
}
|
|
|
|
size_t db_rows() {
|
|
zpl_csv_object *csv = db_last();
|
|
return zpl_array_count(csv->nodes[0].nodes);
|
|
}
|
|
|
|
zpl_csv_object *db_last() {
|
|
assert(zpl_array_count(csv_stack) > 0);
|
|
return zpl_array_end(csv_stack);
|
|
}
|
|
|
|
void db_pop() {
|
|
assert(zpl_array_count(csv_stack) > 0);
|
|
zpl_csv_free(zpl_array_end(csv_stack));
|
|
zpl_array_pop(csv_stack);
|
|
}
|
|
|
|
bool db_exec_file(const char *sql) {
|
|
zpl_file_contents contents = zpl_file_read_contents(zpl_heap(), true, sql);
|
|
if (!db_exec(contents.data)) {
|
|
assert(0 && "Failed to create tables");
|
|
return false;
|
|
}
|
|
zpl_file_free_contents(&contents);
|
|
return true;
|
|
}
|
|
|
|
bool db_exec(const char *query) {
|
|
bool ok = !sqlite3_exec(db, query, 0, 0, 0);
|
|
if (!ok) {
|
|
zpl_printf("[ERROR] Failed to execute query: %s\n", sqlite3_errmsg(db));
|
|
}
|
|
return ok;
|
|
}
|
|
|