more SQL
This commit is contained in:
@@ -47,11 +47,17 @@ FetchContent_Declare(
|
|||||||
GIT_TAG master
|
GIT_TAG master
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
nlohmann_json
|
||||||
|
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
|
||||||
# Enable exceptions in rapidyaml
|
# Enable exceptions in rapidyaml
|
||||||
set(RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS ON CACHE BOOL "" FORCE)
|
set(RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS ON CACHE BOOL "" FORCE)
|
||||||
set(RYML_DBG OFF CACHE BOOL "" FORCE)
|
set(RYML_DBG OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(rapidyaml glm tinyxml2 sqlitecpp rapidjson)
|
FetchContent_MakeAvailable(rapidyaml glm tinyxml2 sqlitecpp rapidjson nlohmann_json)
|
||||||
|
|
||||||
# Create the main executable
|
# Create the main executable
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
@@ -60,6 +66,7 @@ add_executable(${PROJECT_NAME} ${SOURCES})
|
|||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ryml::ryml)
|
target_link_libraries(${PROJECT_NAME} PUBLIC ryml::ryml)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC tinyxml2::tinyxml2)
|
target_link_libraries(${PROJECT_NAME} PUBLIC tinyxml2::tinyxml2)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC SQLiteCpp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC SQLiteCpp)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC nlohmann_json::nlohmann_json)
|
||||||
|
|
||||||
# Add include directories for rapidyaml
|
# Add include directories for rapidyaml
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${rapidyaml_SOURCE_DIR}/src)
|
target_include_directories(${PROJECT_NAME} PRIVATE ${rapidyaml_SOURCE_DIR}/src)
|
||||||
|
|||||||
46
include/database_generation/populate_configs.h
Normal file
46
include/database_generation/populate_configs.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <SQLiteCpp/SQLiteCpp.h>
|
||||||
|
|
||||||
|
#include "configs/achievements.h"
|
||||||
|
#include "configs/harvestables.h"
|
||||||
|
#include "configs/items.h"
|
||||||
|
#include "configs/loot.h"
|
||||||
|
#include "configs/npcs.h"
|
||||||
|
#include "configs/shops.h"
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
// Items
|
||||||
|
void CreateItemTables(SQLite::Database& db);
|
||||||
|
void PopulateItemEntry(SQLite::Database& db, const Item& item);
|
||||||
|
void PopulateItemDB(SQLite::Database& db, const std::vector<Item>& items);
|
||||||
|
|
||||||
|
// Achievements
|
||||||
|
void CreateAchievementTables(SQLite::Database& db);
|
||||||
|
void PopulateAchievementEntry(SQLite::Database& db, const Achievement& achievement);
|
||||||
|
void PopulateAchievementDB(SQLite::Database& db, const std::vector<Achievement>& achievements);
|
||||||
|
|
||||||
|
// Harvestables
|
||||||
|
void CreateHarvestableTables(SQLite::Database& db);
|
||||||
|
void PopulateHarvestableEntry(SQLite::Database& db, const Harvestable& harvestable);
|
||||||
|
void PopulateHarvestableDB(SQLite::Database& db, const std::vector<Harvestable>& harvestables);
|
||||||
|
|
||||||
|
// Loot
|
||||||
|
void CreateLootTables(SQLite::Database& db);
|
||||||
|
void PopulateLootTableEntry(SQLite::Database& db, const LootTable& lootTable);
|
||||||
|
void PopulateLootDB(SQLite::Database& db, const std::vector<LootTable>& lootTables);
|
||||||
|
|
||||||
|
// NPCs
|
||||||
|
void CreateNPCTables(SQLite::Database& db);
|
||||||
|
void PopulateNPCEntry(SQLite::Database& db, const NPC& npc);
|
||||||
|
void PopulateNPCDB(SQLite::Database& db, const std::vector<NPC>& npcs);
|
||||||
|
|
||||||
|
// Shops
|
||||||
|
void CreateShopTables(SQLite::Database& db);
|
||||||
|
void PopulateShopEntry(SQLite::Database& db, const Shop& shop);
|
||||||
|
void PopulateShopDB(SQLite::Database& db, const std::vector<Shop>& shops);
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
506
src/database_generation/populate_configs.cpp
Normal file
506
src/database_generation/populate_configs.cpp
Normal file
@@ -0,0 +1,506 @@
|
|||||||
|
#include "database_generation/populate_configs.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
void CreateItemTables(SQLite::Database& db) {
|
||||||
|
// Main items table
|
||||||
|
std::string createItemsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS items (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
price INTEGER,
|
||||||
|
abilityid INTEGER,
|
||||||
|
learnabilityid INTEGER,
|
||||||
|
skill INTEGER,
|
||||||
|
category INTEGER,
|
||||||
|
slot INTEGER,
|
||||||
|
tool INTEGER,
|
||||||
|
generation INTEGER,
|
||||||
|
level INTEGER,
|
||||||
|
foodlevel INTEGER,
|
||||||
|
foodamount INTEGER,
|
||||||
|
foodfrequency INTEGER,
|
||||||
|
foodtime INTEGER,
|
||||||
|
maxstack INTEGER,
|
||||||
|
book INTEGER,
|
||||||
|
stackable BOOLEAN,
|
||||||
|
twohanded BOOLEAN,
|
||||||
|
undroppable BOOLEAN,
|
||||||
|
hidemilestone BOOLEAN,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT,
|
||||||
|
comment TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Item stats table
|
||||||
|
std::string createItemStatsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS item_stats (
|
||||||
|
item_id INTEGER,
|
||||||
|
stat_type INTEGER,
|
||||||
|
value INTEGER,
|
||||||
|
is_percentage BOOLEAN,
|
||||||
|
FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Item craftings table
|
||||||
|
std::string createItemCraftingsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS item_craftings (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
item_id INTEGER,
|
||||||
|
workbench INTEGER,
|
||||||
|
crafting_skill INTEGER,
|
||||||
|
checks TEXT,
|
||||||
|
FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Crafting items table
|
||||||
|
std::string createCraftingItemsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS crafting_items (
|
||||||
|
crafting_id INTEGER,
|
||||||
|
required_item_id INTEGER,
|
||||||
|
amount INTEGER,
|
||||||
|
FOREIGN KEY (crafting_id) REFERENCES item_craftings(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
db.exec(createItemsTableSQL);
|
||||||
|
db.exec(createItemStatsTableSQL);// TODO: add indices
|
||||||
|
db.exec(createItemCraftingsTableSQL);
|
||||||
|
db.exec(createCraftingItemsTableSQL);
|
||||||
|
std::cout << "Created items-related tables." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateItemEntry(SQLite::Database& db, const Item& item) {
|
||||||
|
// Insert into main items table
|
||||||
|
SQLite::Statement insertItem(db, R"(
|
||||||
|
INSERT INTO items (
|
||||||
|
id, price, abilityid, learnabilityid, skill, category, slot, tool, generation,
|
||||||
|
level, foodlevel, foodamount, foodfrequency, foodtime, maxstack, book,
|
||||||
|
stackable, twohanded, undroppable, hidemilestone, name, description, comment
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||||
|
)");
|
||||||
|
|
||||||
|
insertItem.bind(1, item.id);
|
||||||
|
insertItem.bind(2, item.price);
|
||||||
|
insertItem.bind(3, item.abilityid);
|
||||||
|
insertItem.bind(4, item.learnabilityid);
|
||||||
|
insertItem.bind(5, static_cast<int>(item.skill));
|
||||||
|
insertItem.bind(6, static_cast<int>(item.category));
|
||||||
|
insertItem.bind(7, static_cast<int>(item.slot));
|
||||||
|
insertItem.bind(8, static_cast<int>(item.tool));
|
||||||
|
insertItem.bind(9, static_cast<int>(item.generation));
|
||||||
|
insertItem.bind(10, item.level);
|
||||||
|
insertItem.bind(11, item.foodlevel);
|
||||||
|
insertItem.bind(12, item.foodamount);
|
||||||
|
insertItem.bind(13, item.foodfrequency);
|
||||||
|
insertItem.bind(14, item.foodtime);
|
||||||
|
insertItem.bind(15, item.maxstack);
|
||||||
|
insertItem.bind(16, item.book);
|
||||||
|
insertItem.bind(17, item.stackable);
|
||||||
|
insertItem.bind(18, item.twohanded);
|
||||||
|
insertItem.bind(19, item.undroppable);
|
||||||
|
insertItem.bind(20, item.hidemilestone);
|
||||||
|
insertItem.bind(21, item.name);
|
||||||
|
insertItem.bind(22, item.description);
|
||||||
|
insertItem.bind(23, item.comment);
|
||||||
|
|
||||||
|
insertItem.exec();
|
||||||
|
|
||||||
|
// Insert stats
|
||||||
|
SQLite::Statement insertStat(db, "INSERT INTO item_stats (item_id, stat_type, value, is_percentage) VALUES (?, ?, ?, ?);");
|
||||||
|
for (const auto& stat : item.stats) {
|
||||||
|
insertStat.bind(1, item.id);
|
||||||
|
insertStat.bind(2, static_cast<int>(stat.type));
|
||||||
|
insertStat.bind(3, stat.value);
|
||||||
|
insertStat.bind(4, stat.isPercentage);
|
||||||
|
insertStat.exec();
|
||||||
|
insertStat.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert craftings
|
||||||
|
SQLite::Statement insertCrafting(db, "INSERT INTO item_craftings (item_id, workbench, crafting_skill, checks) VALUES (?, ?, ?, ?);");
|
||||||
|
SQLite::Statement insertCraftingItem(db, "INSERT INTO crafting_items (crafting_id, required_item_id, amount) VALUES (?, ?, ?);");
|
||||||
|
for (const auto& crafting : item.craftings) {
|
||||||
|
insertCrafting.bind(1, item.id);
|
||||||
|
insertCrafting.bind(2, static_cast<int>(crafting.workbench));
|
||||||
|
insertCrafting.bind(3, static_cast<int>(crafting.craftingskill));
|
||||||
|
insertCrafting.bind(4, crafting.checks);
|
||||||
|
insertCrafting.exec();
|
||||||
|
long long craftingId = db.getLastInsertRowid();
|
||||||
|
insertCrafting.reset();
|
||||||
|
|
||||||
|
for (const auto& reqItem : crafting.craftingitems) {
|
||||||
|
insertCraftingItem.bind(1, static_cast<int64_t>(craftingId));
|
||||||
|
insertCraftingItem.bind(2, reqItem.itemId);
|
||||||
|
insertCraftingItem.bind(3, reqItem.amount);
|
||||||
|
insertCraftingItem.exec();
|
||||||
|
insertCraftingItem.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateItemDB(SQLite::Database& db, const std::vector<Item>& items) {
|
||||||
|
CreateItemTables(db);
|
||||||
|
for (const auto& item : items) {
|
||||||
|
PopulateItemEntry(db, item);
|
||||||
|
}
|
||||||
|
std::cout << "Populated " << items.size() << " items into the database." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateAchievementTables(SQLite::Database& db) {
|
||||||
|
// Main achievements table
|
||||||
|
std::string createAchievementsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS achievements (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
points INTEGER,
|
||||||
|
category INTEGER,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT,
|
||||||
|
icon TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Achievement requirements table
|
||||||
|
std::string createAchievementRequirementsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS achievement_requirements (
|
||||||
|
achievement_id INTEGER,
|
||||||
|
action INTEGER,
|
||||||
|
target_id INTEGER,
|
||||||
|
count INTEGER,
|
||||||
|
description TEXT,
|
||||||
|
FOREIGN KEY (achievement_id) REFERENCES achievements(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
db.exec(createAchievementsTableSQL);
|
||||||
|
db.exec(createAchievementRequirementsTableSQL);
|
||||||
|
std::cout << "Created achievement-related tables." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateAchievementEntry(SQLite::Database& db, const Achievement& achievement) {
|
||||||
|
// Insert into main achievements table
|
||||||
|
SQLite::Statement insertAchievement(db, R"(
|
||||||
|
INSERT INTO achievements (
|
||||||
|
id, points, category, name, description, icon
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?);
|
||||||
|
)");
|
||||||
|
|
||||||
|
insertAchievement.bind(1, achievement.id);
|
||||||
|
insertAchievement.bind(2, achievement.points);
|
||||||
|
insertAchievement.bind(3, achievement.category);
|
||||||
|
insertAchievement.bind(4, achievement.name);
|
||||||
|
insertAchievement.bind(5, achievement.description);
|
||||||
|
insertAchievement.bind(6, achievement.icon);
|
||||||
|
|
||||||
|
insertAchievement.exec();
|
||||||
|
|
||||||
|
// Insert requirements
|
||||||
|
SQLite::Statement insertRequirement(db, "INSERT INTO achievement_requirements (achievement_id, action, target_id, count, description) VALUES (?, ?, ?, ?, ?);");
|
||||||
|
for (const auto& req : achievement.requirements) {
|
||||||
|
insertRequirement.bind(1, achievement.id);
|
||||||
|
insertRequirement.bind(2, static_cast<int>(req.action));
|
||||||
|
insertRequirement.bind(3, req.targetId);
|
||||||
|
insertRequirement.bind(4, req.count);
|
||||||
|
insertRequirement.bind(5, req.description);
|
||||||
|
insertRequirement.exec();
|
||||||
|
insertRequirement.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateAchievementDB(SQLite::Database& db, const std::vector<Achievement>& achievements) {
|
||||||
|
CreateAchievementTables(db);
|
||||||
|
for (const auto& achievement : achievements) {
|
||||||
|
PopulateAchievementEntry(db, achievement);
|
||||||
|
}
|
||||||
|
std::cout << "Populated " << achievements.size() << " achievements into the database." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateHarvestableTables(SQLite::Database& db) {
|
||||||
|
// Main harvestables table
|
||||||
|
std::string createHarvestablesTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS harvestables (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
level INTEGER,
|
||||||
|
respawn_time INTEGER,
|
||||||
|
skill INTEGER,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Harvestable loot table
|
||||||
|
std::string createHarvestableLootTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS harvestable_loot (
|
||||||
|
harvestable_id INTEGER,
|
||||||
|
item_id INTEGER,
|
||||||
|
amount INTEGER,
|
||||||
|
chance INTEGER,
|
||||||
|
FOREIGN KEY (harvestable_id) REFERENCES harvestables(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
db.exec(createHarvestablesTableSQL);
|
||||||
|
db.exec(createHarvestableLootTableSQL);
|
||||||
|
std::cout << "Created harvestable-related tables." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateHarvestableEntry(SQLite::Database& db, const Harvestable& harvestable) {
|
||||||
|
// Insert into main harvestables table
|
||||||
|
SQLite::Statement insertHarvestable(db, R"(
|
||||||
|
INSERT INTO harvestables (
|
||||||
|
id, level, respawn_time, skill, name, description
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?);
|
||||||
|
)");
|
||||||
|
|
||||||
|
insertHarvestable.bind(1, harvestable.id);
|
||||||
|
insertHarvestable.bind(2, harvestable.level);
|
||||||
|
insertHarvestable.bind(3, harvestable.respawnTime);
|
||||||
|
insertHarvestable.bind(4, static_cast<int>(harvestable.skill));
|
||||||
|
insertHarvestable.bind(5, harvestable.name);
|
||||||
|
insertHarvestable.bind(6, harvestable.description);
|
||||||
|
|
||||||
|
insertHarvestable.exec();
|
||||||
|
|
||||||
|
// Insert loot
|
||||||
|
SQLite::Statement insertLoot(db, "INSERT INTO harvestable_loot (harvestable_id, item_id, amount, chance) VALUES (?, ?, ?, ?);");
|
||||||
|
for (const auto& entry : harvestable.loot) {
|
||||||
|
insertLoot.bind(1, harvestable.id);
|
||||||
|
insertLoot.bind(2, entry.itemId);
|
||||||
|
insertLoot.bind(3, entry.amount);
|
||||||
|
insertLoot.bind(4, entry.chance);
|
||||||
|
insertLoot.exec();
|
||||||
|
insertLoot.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateHarvestableDB(SQLite::Database& db, const std::vector<Harvestable>& harvestables) {
|
||||||
|
CreateHarvestableTables(db);
|
||||||
|
for (const auto& harvestable : harvestables) {
|
||||||
|
PopulateHarvestableEntry(db, harvestable);
|
||||||
|
}
|
||||||
|
std::cout << "Populated " << harvestables.size() << " harvestables into the database." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateLootTables(SQLite::Database& db) {
|
||||||
|
// Main loot_tables table
|
||||||
|
std::string createLootTablesTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS loot_tables (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Loot entries table
|
||||||
|
std::string createLootEntriesTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS loot_entries (
|
||||||
|
loot_table_id INTEGER,
|
||||||
|
item_id INTEGER,
|
||||||
|
min_amount INTEGER,
|
||||||
|
max_amount INTEGER,
|
||||||
|
chance INTEGER,
|
||||||
|
level INTEGER,
|
||||||
|
FOREIGN KEY (loot_table_id) REFERENCES loot_tables(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
db.exec(createLootTablesTableSQL);
|
||||||
|
db.exec(createLootEntriesTableSQL);
|
||||||
|
std::cout << "Created loot-related tables." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateLootTableEntry(SQLite::Database& db, const LootTable& lootTable) {
|
||||||
|
// Insert into main loot_tables table
|
||||||
|
SQLite::Statement insertLootTable(db, R"(
|
||||||
|
INSERT INTO loot_tables (
|
||||||
|
id, name, description
|
||||||
|
) VALUES (?, ?, ?);
|
||||||
|
)");
|
||||||
|
|
||||||
|
insertLootTable.bind(1, lootTable.id);
|
||||||
|
insertLootTable.bind(2, lootTable.name);
|
||||||
|
insertLootTable.bind(3, lootTable.description);
|
||||||
|
|
||||||
|
insertLootTable.exec();
|
||||||
|
|
||||||
|
// Insert entries
|
||||||
|
SQLite::Statement insertEntry(db, "INSERT INTO loot_entries (loot_table_id, item_id, min_amount, max_amount, chance, level) VALUES (?, ?, ?, ?, ?, ?);");
|
||||||
|
for (const auto& entry : lootTable.entries) {
|
||||||
|
insertEntry.bind(1, lootTable.id);
|
||||||
|
insertEntry.bind(2, entry.itemId);
|
||||||
|
insertEntry.bind(3, entry.minAmount);
|
||||||
|
insertEntry.bind(4, entry.maxAmount);
|
||||||
|
insertEntry.bind(5, entry.chance);
|
||||||
|
insertEntry.bind(6, entry.level);
|
||||||
|
insertEntry.exec();
|
||||||
|
insertEntry.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateLootDB(SQLite::Database& db, const std::vector<LootTable>& lootTables) {
|
||||||
|
CreateLootTables(db);
|
||||||
|
for (const auto& lootTable : lootTables) {
|
||||||
|
PopulateLootTableEntry(db, lootTable);
|
||||||
|
}
|
||||||
|
std::cout << "Populated " << lootTables.size() << " loot tables into the database." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateNPCTables(SQLite::Database& db) {
|
||||||
|
// Main npcs table
|
||||||
|
std::string createNPCsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS npcs (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
level INTEGER,
|
||||||
|
health INTEGER,
|
||||||
|
mana INTEGER,
|
||||||
|
experience INTEGER,
|
||||||
|
loot_table_id INTEGER,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT,
|
||||||
|
faction TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// NPC stats table
|
||||||
|
std::string createNPCStatsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS npc_stats (
|
||||||
|
npc_id INTEGER,
|
||||||
|
stat_type INTEGER,
|
||||||
|
value INTEGER,
|
||||||
|
FOREIGN KEY (npc_id) REFERENCES npcs(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// NPC loot items table
|
||||||
|
std::string createNPCLootItemsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS npc_loot_items (
|
||||||
|
npc_id INTEGER,
|
||||||
|
item_id INTEGER,
|
||||||
|
FOREIGN KEY (npc_id) REFERENCES npcs(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
db.exec(createNPCsTableSQL);
|
||||||
|
db.exec(createNPCStatsTableSQL);
|
||||||
|
db.exec(createNPCLootItemsTableSQL);
|
||||||
|
std::cout << "Created NPC-related tables." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateNPCEntry(SQLite::Database& db, const NPC& npc) {
|
||||||
|
// Insert into main npcs table
|
||||||
|
SQLite::Statement insertNPC(db, R"(
|
||||||
|
INSERT INTO npcs (
|
||||||
|
id, level, health, mana, experience, loot_table_id, name, description, faction
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||||
|
)");
|
||||||
|
|
||||||
|
insertNPC.bind(1, npc.id);
|
||||||
|
insertNPC.bind(2, npc.level);
|
||||||
|
insertNPC.bind(3, npc.health);
|
||||||
|
insertNPC.bind(4, npc.mana);
|
||||||
|
insertNPC.bind(5, npc.experience);
|
||||||
|
insertNPC.bind(6, npc.lootTableId);
|
||||||
|
insertNPC.bind(7, npc.name);
|
||||||
|
insertNPC.bind(8, npc.description);
|
||||||
|
insertNPC.bind(9, npc.faction);
|
||||||
|
|
||||||
|
insertNPC.exec();
|
||||||
|
|
||||||
|
// Insert stats
|
||||||
|
SQLite::Statement insertStat(db, "INSERT INTO npc_stats (npc_id, stat_type, value) VALUES (?, ?, ?);");
|
||||||
|
for (const auto& stat : npc.stats) {
|
||||||
|
insertStat.bind(1, npc.id);
|
||||||
|
insertStat.bind(2, static_cast<int>(stat.type));
|
||||||
|
insertStat.bind(3, stat.value);
|
||||||
|
insertStat.exec();
|
||||||
|
insertStat.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert loot items
|
||||||
|
SQLite::Statement insertLootItem(db, "INSERT INTO npc_loot_items (npc_id, item_id) VALUES (?, ?);");
|
||||||
|
for (const auto& itemId : npc.lootItems) {
|
||||||
|
insertLootItem.bind(1, npc.id);
|
||||||
|
insertLootItem.bind(2, itemId);
|
||||||
|
insertLootItem.exec();
|
||||||
|
insertLootItem.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateNPCDB(SQLite::Database& db, const std::vector<NPC>& npcs) {
|
||||||
|
CreateNPCTables(db);
|
||||||
|
for (const auto& npc : npcs) {
|
||||||
|
PopulateNPCEntry(db, npc);
|
||||||
|
}
|
||||||
|
std::cout << "Populated " << npcs.size() << " NPCs into the database." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateShopTables(SQLite::Database& db) {
|
||||||
|
// Main shops table
|
||||||
|
std::string createShopsTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS shops (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT,
|
||||||
|
location TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Shop inventory table
|
||||||
|
std::string createShopInventoryTableSQL = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS shop_inventory (
|
||||||
|
shop_id INTEGER,
|
||||||
|
item_id INTEGER,
|
||||||
|
price INTEGER,
|
||||||
|
stock INTEGER,
|
||||||
|
level_required INTEGER,
|
||||||
|
FOREIGN KEY (shop_id) REFERENCES shops(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
db.exec(createShopsTableSQL);
|
||||||
|
db.exec(createShopInventoryTableSQL);
|
||||||
|
std::cout << "Created shop-related tables." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateShopEntry(SQLite::Database& db, const Shop& shop) {
|
||||||
|
// Insert into main shops table
|
||||||
|
SQLite::Statement insertShop(db, R"(
|
||||||
|
INSERT INTO shops (
|
||||||
|
id, name, description, location
|
||||||
|
) VALUES (?, ?, ?, ?);
|
||||||
|
)");
|
||||||
|
|
||||||
|
insertShop.bind(1, shop.id);
|
||||||
|
insertShop.bind(2, shop.name);
|
||||||
|
insertShop.bind(3, shop.description);
|
||||||
|
insertShop.bind(4, shop.location);
|
||||||
|
|
||||||
|
insertShop.exec();
|
||||||
|
|
||||||
|
// Insert inventory
|
||||||
|
SQLite::Statement insertItem(db, "INSERT INTO shop_inventory (shop_id, item_id, price, stock, level_required) VALUES (?, ?, ?, ?, ?);");
|
||||||
|
for (const auto& item : shop.inventory) {
|
||||||
|
insertItem.bind(1, shop.id);
|
||||||
|
insertItem.bind(2, item.itemId);
|
||||||
|
insertItem.bind(3, item.price);
|
||||||
|
insertItem.bind(4, item.stock);
|
||||||
|
insertItem.bind(5, item.levelRequired);
|
||||||
|
insertItem.exec();
|
||||||
|
insertItem.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateShopDB(SQLite::Database& db, const std::vector<Shop>& shops) {
|
||||||
|
CreateShopTables(db);
|
||||||
|
for (const auto& shop : shops) {
|
||||||
|
PopulateShopEntry(db, shop);
|
||||||
|
}
|
||||||
|
std::cout << "Populated " << shops.size() << " shops into the database." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
73
src/main.cpp
73
src/main.cpp
@@ -1,11 +1,19 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <SQLiteCpp/SQLiteCpp.h>
|
||||||
|
|
||||||
#include "project_parser.h"
|
#include "project_parser.h"
|
||||||
#include "tree_builder.h"
|
#include "tree_builder.h"
|
||||||
#include "assets/scene.hpp"
|
#include "assets/scene.hpp"
|
||||||
#include "configs/items.h"
|
#include "configs/items.h"
|
||||||
|
#include "configs/achievements.h"
|
||||||
|
#include "configs/harvestables.h"
|
||||||
|
#include "configs/loot.h"
|
||||||
|
#include "configs/npcs.h"
|
||||||
|
#include "configs/shops.h"
|
||||||
|
#include "database_generation/populate_configs.h"
|
||||||
|
|
||||||
using namespace cursebreaker;
|
using namespace cursebreaker;
|
||||||
|
|
||||||
@@ -19,5 +27,70 @@ int main() {
|
|||||||
BuildTree(scene);
|
BuildTree(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load configs from XML
|
||||||
|
std::string configPath = "../../CBAssets/_GameAssets/";
|
||||||
|
loadItemsFromXML(configPath + "items.xml");
|
||||||
|
loadAchievementsFromXML(configPath + "achievements.xml");
|
||||||
|
loadHarvestablesFromXML(configPath + "harvestables.xml");
|
||||||
|
loadLootTablesFromXML(configPath + "loot.xml");
|
||||||
|
loadNPCsFromXML(configPath + "npcs.xml");
|
||||||
|
loadShopsFromXML(configPath + "shops.xml");
|
||||||
|
|
||||||
|
// Create in-memory database
|
||||||
|
SQLite::Database memDB(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
|
||||||
|
|
||||||
|
// Populate database with configs
|
||||||
|
std::vector<Item> itemsVec;
|
||||||
|
for (const auto& pair : getAllItems()) {
|
||||||
|
itemsVec.push_back(pair.second);
|
||||||
|
}
|
||||||
|
PopulateItemDB(memDB, itemsVec);
|
||||||
|
|
||||||
|
std::vector<Achievement> achievementsVec;
|
||||||
|
for (const auto& pair : getAllAchievements()) {
|
||||||
|
achievementsVec.push_back(pair.second);
|
||||||
|
}
|
||||||
|
PopulateAchievementDB(memDB, achievementsVec);
|
||||||
|
|
||||||
|
std::vector<Harvestable> harvestablesVec;
|
||||||
|
for (const auto& pair : getAllHarvestables()) {
|
||||||
|
harvestablesVec.push_back(pair.second);
|
||||||
|
}
|
||||||
|
PopulateHarvestableDB(memDB, harvestablesVec);
|
||||||
|
|
||||||
|
std::vector<LootTable> lootVec;
|
||||||
|
for (const auto& pair : getAllLootTables()) {
|
||||||
|
lootVec.push_back(pair.second);
|
||||||
|
}
|
||||||
|
PopulateLootDB(memDB, lootVec);
|
||||||
|
|
||||||
|
std::vector<NPC> npcsVec;
|
||||||
|
for (const auto& pair : getAllNPCs()) {
|
||||||
|
npcsVec.push_back(pair.second);
|
||||||
|
}
|
||||||
|
PopulateNPCDB(memDB, npcsVec);
|
||||||
|
|
||||||
|
std::vector<Shop> shopsVec;
|
||||||
|
for (const auto& pair : getAllShops()) {
|
||||||
|
shopsVec.push_back(pair.second);
|
||||||
|
}
|
||||||
|
PopulateShopDB(memDB, shopsVec);
|
||||||
|
|
||||||
|
// Save to file
|
||||||
|
{
|
||||||
|
SQLite::Database fileDB("cursebreaker.db", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
|
||||||
|
sqlite3* srcHandle = memDB.getHandle();
|
||||||
|
sqlite3* dstHandle = fileDB.getHandle();
|
||||||
|
sqlite3_backup* backup = sqlite3_backup_init(dstHandle, "main", srcHandle, "main");
|
||||||
|
if (backup) {
|
||||||
|
sqlite3_backup_step(backup, -1);
|
||||||
|
sqlite3_backup_finish(backup);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to initialize backup" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Database created and saved to cursebreaker.db" << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -462,4 +462,4 @@ void ParseProject(const std::filesystem::path& projectRoot)
|
|||||||
project.m_prefabAssets = ParsePrefabs(std::vector<AssetPath>(prefabFiles.begin(), prefabFiles.end()), project.m_prefabsMap);
|
project.m_prefabAssets = ParsePrefabs(std::vector<AssetPath>(prefabFiles.begin(), prefabFiles.end()), project.m_prefabsMap);
|
||||||
|
|
||||||
project.m_sceneAssets = ParseScenes(std::vector<AssetPath>(tilesFiles.begin(), tilesFiles.end()));
|
project.m_sceneAssets = ParseScenes(std::vector<AssetPath>(tilesFiles.begin(), tilesFiles.end()));
|
||||||
}
|
}} // namespace cursebreaker
|
||||||
|
|||||||
Reference in New Issue
Block a user