Fix item iterator logic + refactor terminal output while happy path

main
Alex 2 weeks ago
parent 8b50abda63
commit 1eb2fb17b0

@ -256,6 +256,8 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
std::vector<bot_skill> skills_to_delete;
std::vector<bot_inv_item> items_to_delete;
ShowInfo("Processing Account %d ...\n", account_id);
// Check if the account exists
if (!login_accounts->load_num(login_accounts, &acc, account_id)) {
ShowNotice("Attempt to delete non-existent account (account_id: %d)\n", account_id);
@ -285,11 +287,12 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
// First pass: Collect char_ids to delete based on config
CharakterDBIterator* iter_chars = charakters->iterator(charakters); // Create the iterator
char_ids_to_delete.clear();
while (iter_chars->next(iter_chars, &charakter)) {
//ShowDebug("Charakter %s scanned\n", charakter.name);
if (charakter.account_id == account_id) {
//ShowInfo("Charakter %s marked for deletion\n", charakter.name);
//ShowDebug("Charakter %s marked for deletion\n", charakter.name);
char_ids_to_delete.push_back(charakter.char_id);
}
}
@ -297,7 +300,7 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
// Second pass: Delete the collected charakters
for (const auto& char_id : char_ids_to_delete) {
ShowInfo("Deleting charakter with ID %d.\n", char_id);
ShowInfo("Deleting character with ID %d.\n", char_id);
if (!charakters->remove(charakters, char_id)) {
ShowError("Failed to delete charakter (char_id: %s)\n", char_id);
continue; // Deletion failed
@ -306,6 +309,7 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
// Step 3B: Attempt to delete skills of the char (if any)
// First pass: Collect skill_ids to delete based on config
SkillDBIterator* iter_skills = skills->iterator(skills, char_id); // Create the iterator
skills_to_delete.clear();
while (iter_skills->next(iter_skills, char_id, &skill)) {
std::string id_str = convert_skill_id_to_str(skill.skill_id);
//ShowDebug("Skill %s found. Schedule for deletion...\n", id_str.c_str());
@ -316,47 +320,58 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
// Second pass: Delete the collected skills
int skill_count = 0;
for (const auto& skill_entry : skills_to_delete) {
//ShowInfo("Deleting skill with ID %d.\n", char_id);
//ShowDebug("Deleting skill with ID %d.\n", char_id);
if (!skills->remove(skills, char_id, skill_entry.skill_id)) {
ShowError("Failed to delete skill (skill_id: %s)\n", skill_entry.skill_id);
continue; // Deletion failed
}
else {
//ShowNotice("Deleting of skill %s from char_id %d was successful\n", convert_skill_id_to_str(skill_entry.skill_id), char_id);
//ShowDebug("Deleting of skill %s from char_id %d was successful\n", convert_skill_id_to_str(skill_entry.skill_id), char_id);
skill_count++;
}
}
ShowNotice("Skill cleanup for char_id %d completed. %d skills cleaned.\n", char_id, skill_count);
ShowDebug("Marco\n"); //TODO Prüfn warum hier iterator keine validen items wirft
ShowStatus("Skill cleanup for char_id %d completed. %d skills cleaned.\n", char_id, skill_count);
// Step 3C: Attempt to delete inventory of the char (if any)
// First pass: Collect inv_item_ids to delete based on config
InventoryDBIterator* iter_inventory = inventory->iterator(inventory, char_id); // Create the iterator
ShowDebug("Polo1\n");
while (iter_inventory->next(iter_inventory, char_id, &item)) {
ShowDebug("Polo iter loop\n");
std::string id_str = convert_item_id_to_name(item.item_id);
ShowDebug("Item %s found. Schedule for deletion...\n", id_str.c_str());
items_to_delete.clear();
while (iter_inventory->next(iter_inventory, &item)) {
//std::string id_str = convert_item_id_to_name(item.item_id);
//ShowDebug("Item id %d found. Schedule for deletion...\n", item.item_id);
items_to_delete.push_back(item);
}
iter_inventory->destroy(iter_inventory); // Destroy the iterator after use
ShowDebug("Polo2\n");
//ShowDebug("Item-Scan completed.\n");
bot_item_bundle bundle;
bundle.items = items_to_delete;
//dump_item_bundle(bundle);
// Second pass: Delete the collected items
int item_count = 0;
for (const auto& inv_item_entry : items_to_delete) {
ShowInfo("Deleting item with ID %d.\n", inv_item_entry.inventory_id);
//ShowInfo("Attempting to delete item with inventory ID %u and item id %u.\n", inv_item_entry.inventory_id, inv_item_entry.item_id);
if (!inventory->remove(inventory, char_id, inv_item_entry.inventory_id)) {
ShowError("Failed to delete item (item_id: %s)\n", inv_item_entry.item_id);
continue; // Deletion failed
}
else {
ShowNotice("Deleting of item %s from char_id %d was successful\n", convert_item_id_to_aegisname(inv_item_entry.item_id), char_id);
ShowError("Failed to delete item (item_id: %u, char_id: %u)\n", inv_item_entry.item_id, char_id);
continue; // Log failure but continue with next item
}
// Verify deletion
//std::string aegisname = convert_item_id_to_aegisname(inv_item_entry.item_id);
//ShowDebug("Successfully deleted item %s (item_id: %u) from char_id: %u\n", aegisname.c_str(), inv_item_entry.item_id, char_id);
item_count++;
}
ShowDebug("Polo3\n");
ShowStatus("Item cleanup for char_id %d completed. %d items cleaned.\n", char_id, item_count);
ShowStatus("Character cleanup for char_id %d completed.\n", char_id);
}
ShowNotice("Bot account deletion completed (account: %s, id: %d)\n\n", acc.userid, acc.account_id);
ShowInfo("Bot account cleanup completed (account: %s, id: %d)\n\n", acc.userid, acc.account_id);
return 0; // Success
}
@ -772,12 +787,12 @@ int brokk_apply_item_loadout(bot_item_bundle& item_bundle, int& char_id) {
}
// Log success single item
std::string aegisname = convert_item_id_to_aegisname(item.item_id);
ShowNotice("Item %s added to character char_id: %d)\n", aegisname.c_str(), item.char_id);
//ShowNotice("Item %s added to character char_id: %d)\n", aegisname.c_str(), item.char_id);
item_count++;
}
// Log success
ShowStatus("Successfully added %d Items to characters inventory (name: %s, char_id: %d)\n", item_count, char_name.c_str(), char_id);
//ShowDebug("Successfully added %d Items to characters inventory (name: %s, char_id: %d)\n", item_count, char_name.c_str(), char_id);
return -1; // Success
}
@ -964,6 +979,7 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
uint32 account_id = acc.account_id;
// Iterate over each character for this bot account
ShowStatus("Bot account: %s (ID: %u) created.\n", userid_str.c_str(), account_id);
if (bot.contains("characters")) {
const auto& json_characters = bot["characters"];
@ -994,16 +1010,18 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
// Step2: build data of character
new_char.account_id = account_id;
new_char.char_id = -1;
ShowInfo("Preparing build data for bot character %s ...\n", char_name.c_str());
ShowStatus("Applied character meta data for bot char %s .\n", char_name.c_str());
prepare_character_build_data(new_char, json_character, bot_job_db);
ShowStatus("Applied build data for bot character %s .\n", char_name.c_str());
// Step3: appearance of character
ShowInfo("Preparing appearance of bot character %s ...\n", char_name.c_str());
prepare_character_appearance_data(new_char, json_character);
ShowStatus("Applied appearance data for bot character %s .\n", char_name.c_str());
// Step4: location data of character
ShowInfo("Preparing location data for bot character %s ...\n", char_name.c_str());
prepare_character_location_data(new_char, json_character);
ShowStatus("Applied location data for bot character %s .\n", char_name.c_str());
// All char table related data is collected and can be saved to allow further steps (skills/items/equip)
int new_char_id = 0;
@ -1024,6 +1042,7 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
ShowError("Character creation for '%s 'failed: %s\n",new_char.name, e.what());
continue;
}
ShowStatus("DB entry for bot character %s created.\n", char_name.c_str());
// Step5: Skills
// Prepare skills inside a skill bundle
@ -1045,79 +1064,35 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
continue;
}
// ShowNotice("Skills successfully teached to character (name: %s, char_id: %d, sex: %c)\n", new_char.name, new_char.char_id, new_char.sex);
ShowStatus("Teached %d skills to bot character %s .\n", skill_bundle.skills.size(), char_name.c_str());
// Step6: Items
// Prepare items inside a item bundle
ShowInfo("Preparing inventory data for bot character %s ...\n", char_name.c_str());
bot_item_bundle item_bundle{};
bot_item_bundle item_bundle{};
prepare_item_bundle(item_bundle, new_char_id, json_character);
// All inventory table related data is collected and can be saved
try {
/* Lock-out while in debug
if (!brokk_apply_item_loadout(item_bundle, new_char_id)) {
ShowError("Failed to create inventory entry for: %s\n", new_char.name);
continue;
}*/
}
}
catch (const std::exception& e) {
ShowError("skill creation for '%s 'failed: %s\n", new_char.name, e.what());
continue;
}
ShowStatus("Items successfully handed out to character (name: %s, char_id: %d, sex: %c)\n", new_char.name, new_char.char_id, new_char.sex);
ShowStatus("%d Items successfully handed out to character (name: %s, char_id: %d, sex: %c)\n", item_bundle.items.size(), new_char.name, new_char.char_id, new_char.sex);
//Step5: Equipment
//ShowInfo("Preparing equipment for bot character %s ...\n", char_name.c_str());
ShowStatus("Bot-Character creation and administration completed (name: %s, char_id: %d, sex: %c)\n\n", new_char.name, new_char.char_id, new_char.sex);
/*****
* Validating/Applying skill build
*****
// DEBUG: check skill plausibility
const auto& skill_bundle = character["skills"];
ShowDebug("Skill bundle: %s\n", skill_bundle.dump(4).c_str()); // Ensure `skill_bundle` is structured as expected
for (const auto& skill : skill_bundle.items()) {
ShowDebug("Skill: %s", skill.key().c_str());
std::unordered_map<uint16, uint16> required_skill;
//skill >> required_skill;
std::string skill_str = skill.key();
int skill_id = convert_skill_str_to_id(skill_str.c_str());
if (skill_id < 0) { // Assuming negative IDs are invalid
ShowError("Invalid skill ID for skill string: %s\n", skill_str.c_str());
continue; // Skip this iteration
}
std::unordered_map<uint16, uint16> parsed_skill_bundle;
for (const auto& skill : skill_bundle.items()) {
uint16 skill_id = convert_skill_str_to_id(skill.key().c_str());
uint16 level = skill.value(); // Assuming the value represents the skill level
parsed_skill_bundle[skill_id] = level;
}
bool skill_plausible = check_skill_requirements(start_job, skill_id, parsed_skill_bundle);
if (skill_plausible) {
ShowDebug("all requirements met for skill %s \n", skill.key());
}
else {
ShowDebug("some requirements not met for skill %s , Cancel creation process?\n", skill.key());
continue;
}
}*/
// Create the character for this account
// TODO rebuild to:
// if (!brokk_create_character(new_char, skill_build_data, item_data, equip_data true))
/*
if (!brokk_create_character(account_id, char_name.c_str(), slot, base_level, job_level, str, agi, vit, int_, dex, luk, hair_style, hair_color, start_job, sex, true))
{
ShowError("Failed to create charakter (char_name: %s)\n", char_name);
continue; // Skip to the next charakter
}*/
}
}
@ -1125,7 +1100,10 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
ShowError("No 'characters' array found for bot (userid: %s)\n", userid);
}
ShowStatus("Bot account: %s (ID: %u) creation completed.\n\n", userid_str.c_str(), account_id);
}
ShowStatus("Bot account creation process completed.\n");
// Other initialization logic
//setup_periodic_cleanup_timer(); // Set up the cleanup timer

@ -56,8 +56,8 @@ typedef struct InventoryDB_SQL {
typedef struct InventoryDBIterator_SQL {
InventoryDBIterator vtable; // public interface
InventoryDB_SQL* db;
int char_id;
int last_inv_item_id;
uint32 char_id;
uint32 last_inv_item_id;
} InventoryDBIterator_SQL;
/// internal functions
@ -71,7 +71,7 @@ static bool bot_inv_item_db_sql_remove(InventoryDB* self, const uint32 char_id,
static bool bot_inv_item_db_sql_load_num(InventoryDB* self, struct bot_inv_item* item);
static InventoryDBIterator* bot_inv_item_db_sql_iterator(InventoryDB* self, const uint32 char_id);
static void bot_inv_item_db_sql_iter_destroy(InventoryDBIterator* self);
static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, const uint32 char_id, struct bot_inv_item* item);
static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, struct bot_inv_item* item);
static bool bot_inv_item_db_fromsql(InventoryDB_SQL* db, struct bot_inv_item* item);
static bool bot_inv_item_db_tosql(InventoryDB_SQL* db, const struct bot_inv_item* item, bool is_new);
@ -286,7 +286,7 @@ static bool bot_inv_item_db_sql_create(InventoryDB* self, struct bot_inv_item* i
* @param char_id: id of char, the item belongs to
* @param inventory_id: if of item to delete
* @return true if successful, false if something has failed
*/
static bool bot_inv_item_db_sql_remove(InventoryDB* self, const uint32 char_id, const uint32 inventory_id) {
InventoryDB_SQL* db = (InventoryDB_SQL*)self;
Sql* sql_handle = db->bot_inventory;
@ -302,8 +302,66 @@ static bool bot_inv_item_db_sql_remove(InventoryDB* self, const uint32 char_id,
result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
return result;
}*/
static bool bot_inv_item_db_sql_remove(InventoryDB* self, const uint32 char_id, const uint32 inventory_id) {
InventoryDB_SQL* db = (InventoryDB_SQL*)self;
Sql* sql_handle = db->bot_inventory;
bool result = false;
// Start the transaction
//ShowDebug("Starting transaction for char_id: %u, inventory_id: %u\n", char_id, inventory_id);
if (SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION")) {
Sql_ShowDebug(sql_handle);
ShowError("Failed to start transaction for char_id: %u, inventory_id: %u\n", char_id, inventory_id);
return false;
}
// Attempt to delete the item
//ShowDebug("Attempting to delete item with char_id: %u, inventory_id: %u\n", char_id, inventory_id);
if (SQL_SUCCESS != Sql_Query(sql_handle,
"DELETE FROM `%s` WHERE `char_id` = %u AND `id` = %u",
db->inventory_db, char_id, inventory_id))
{
Sql_ShowDebug(sql_handle);
ShowError("Failed to delete item with char_id: %u, inventory_id: %u\n", char_id, inventory_id);
result = false;
}
else {
result = true;
//ShowDebug("Item deletion query executed successfully for char_id: %u, inventory_id: %u\n", char_id, inventory_id);
}
// Commit or rollback based on the result
//ShowDebug("%s transaction for char_id: %u, inventory_id: %u\n", result ? "Committing" : "Rolling back", char_id, inventory_id);
if (SQL_SUCCESS != Sql_QueryStr(sql_handle, result ? "COMMIT" : "ROLLBACK")) {
Sql_ShowDebug(sql_handle);
ShowError("%s transaction failed for char_id: %u, inventory_id: %u\n", result ? "Commit" : "Rollback", char_id, inventory_id);
result = false;
}
// Validate the deletion
if (result) {
//ShowDebug("Validating deletion of item_id: %u\n", inventory_id);
if (SQL_SUCCESS != Sql_Query(sql_handle,
"SELECT `id` FROM `%s` WHERE `id` = %u",
db->inventory_db, inventory_id))
{
Sql_ShowDebug(sql_handle);
ShowError("Failed to validate deletion of item_id: %u\n", inventory_id);
result = false;
}
else if (SQL_SUCCESS == Sql_NextRow(sql_handle)) {
ShowError("Item with id: %u still exists after deletion attempt.\n", inventory_id);
result = false;
}
else {
//ShowDebug("Item with id: %u successfully deleted.\n", inventory_id);
}
}
Sql_FreeResult(sql_handle);
return result;
}
/**
* Retrieve data from db and store it in the provided data structure.
* Filled data structure is done by delegation to bot_inv_item_db_fromsql.
@ -318,12 +376,31 @@ static bool bot_inv_item_db_sql_load_num(InventoryDB* self, struct bot_inv_item*
return bot_inv_item_db_fromsql(db, item);
}
void dump_item_bundle(const bot_item_bundle& item_bundle) {
ShowDebug("Dumping item bundle contents...\n");
if (item_bundle.items.empty()) {
ShowDebug("Item bundle is empty.\n");
return;
}
for (const auto& item : item_bundle.items) {
ShowDebug("Character ID: %u\n", item.char_id);
ShowDebug(" Inventory ID: %u\n", item.inventory_id);
ShowDebug(" Item ID: %u\n", item.item_id);
std::string item_name = convert_item_id_to_aegisname(item.item_id);
ShowDebug(" Item Name: %s\n", item_name.c_str());
ShowDebug(" Amount: %u\n", item.amount);
ShowDebug(" Equip Slot: %u\n", item.equip);
}
ShowDebug("End of item bundle dump.\n");
}
/**
* Create a new forward iterator.
* @param self: pointer to db iterator
* @return a new db iterator
*/
static InventoryDBIterator* bot_inv_item_db_sql_iterator(InventoryDB* self, const uint32 char_id) {
InventoryDB_SQL* db = (InventoryDB_SQL*)self;
InventoryDBIterator_SQL* iter = (InventoryDBIterator_SQL*)aCalloc(1, sizeof(InventoryDBIterator_SQL));
@ -337,6 +414,38 @@ static InventoryDBIterator* bot_inv_item_db_sql_iterator(InventoryDB* self, cons
iter->char_id = char_id;
iter->last_inv_item_id = -1;
return &iter->vtable;
} */
static InventoryDBIterator* bot_inv_item_db_sql_iterator(InventoryDB* self, const uint32 char_id) {
InventoryDB_SQL* db = (InventoryDB_SQL*)self;
if (!db) {
ShowError("InventoryDB_SQL is null.\n");
return nullptr;
}
InventoryDBIterator_SQL* iter = (InventoryDBIterator_SQL*)aCalloc(1, sizeof(InventoryDBIterator_SQL));
if (!iter) {
ShowError("Failed to allocate memory for InventoryDBIterator_SQL.\n");
return nullptr;
}
// Initialize vtable
iter->vtable.destroy = &bot_inv_item_db_sql_iter_destroy;
iter->vtable.next = &bot_inv_item_db_sql_iter_next;
// Initialize fields
iter->db = db;
iter->char_id = char_id;
iter->last_inv_item_id = 0;
if (!db->bot_inventory) {
ShowError("SQL handle is not initialized.\n");
aFree(iter);
return nullptr;
}
return &iter->vtable;
}
@ -352,11 +461,10 @@ static void bot_inv_item_db_sql_iter_destroy(InventoryDBIterator* self) {
/**
* Fetches the next inv item entry in the database.
* @param self: pointer to db iterator
* @param char_id: char_id of the bot the items belong to
* @param inventory_id: id of the inventory table the item belongs to
* @return true if next inventory entry found and filled, false if something has failed
*/
static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, const uint32 char_id, struct bot_inv_item* item) {
static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, struct bot_inv_item* item) {
InventoryDBIterator_SQL* iter = (InventoryDBIterator_SQL*)self;
InventoryDB_SQL* db = iter->db;
Sql* sql_handle = db->bot_inventory;
@ -374,8 +482,8 @@ static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, const uint3
SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, nullptr) &&
data != nullptr )
{// get item data
uint32 inventory_id;
inventory_id = atoi(data); uint32 skill_id;
uint32 inventory_id = atoi(data);
item->inventory_id = inventory_id;
if( bot_inv_item_db_fromsql(db, item) )
{
@ -384,6 +492,59 @@ static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, const uint3
return true;
}
}
Sql_FreeResult(sql_handle);
return false;
} */
static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, struct bot_inv_item* item) {
InventoryDBIterator_SQL* iter = (InventoryDBIterator_SQL*)self;
InventoryDB_SQL* db = iter->db;
Sql* sql_handle = db->bot_inventory;
char* data;
// Debugging: Check inputs
//ShowDebug("Fetching next item for char_id: %u, last_inv_item_id: %u\n", iter->char_id, iter->last_inv_item_id);
// Build and execute query
char query[256];
snprintf(query, sizeof(query),
"SELECT `id` FROM `%s` WHERE `char_id` = %u AND `id` > %u ORDER BY `id` ASC LIMIT 1",
db->inventory_db, iter->char_id, iter->last_inv_item_id);
//ShowDebug("Executing SQL Query: %s\n", query);
if (SQL_ERROR == Sql_Query(sql_handle, query)) {
Sql_ShowDebug(sql_handle);
return false;
}
// Process the next row
if (SQL_SUCCESS == Sql_NextRow(sql_handle) &&
SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, nullptr) &&
data != nullptr)
{
uint32 inventory_id = atoi(data);
if (inventory_id == 0) {
ShowError("Invalid inventory_id retrieved: %s\n", data);
Sql_FreeResult(sql_handle);
return false;
}
item->inventory_id = inventory_id;
//ShowDebug("Retrieved inventory_id: %u\n", inventory_id);
// Load item details
if (bot_inv_item_db_fromsql(db, item)) {
iter->last_inv_item_id = inventory_id;
Sql_FreeResult(sql_handle);
return true;
}
else {
ShowError("Failed to load item data for inventory_id: %u\n", inventory_id);
}
}
else {
//ShowDebug("No more items found for char_id: %u\n", iter->char_id);
}
Sql_FreeResult(sql_handle);
return false;
}
@ -395,7 +556,7 @@ static bool bot_inv_item_db_sql_iter_next(InventoryDBIterator* self, const uint3
* @param char_id: id of character, item belong to
* @param item_id: id of item to take data from
* @return true if successful, false if something has failed
*/
static bool bot_inv_item_db_fromsql(InventoryDB_SQL* db, struct bot_inv_item* item) {
Sql* sql_handle = db->bot_inventory;
char* data;
@ -403,11 +564,11 @@ static bool bot_inv_item_db_fromsql(InventoryDB_SQL* db, struct bot_inv_item* it
// retrieve login entry for the specified account
if( SQL_ERROR == Sql_Query(sql_handle,
#ifdef VIP_ENABLE
"SELECT `id`, `char_id`, `nameid`, `amount`, `equip`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `enchantgrade` FROM `%s` WHERE `char_id` = %d AND `id` = %d",
"SELECT `id`, `char_id`, `nameid`, `amount`, `equip`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `enchantgrade` FROM `%s` WHERE `id` = %d",
#else
"SELECT `id`, `char_id`, `nameid`, `amount`, `equip`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `enchantgrade` FROM `%s` WHERE `char_id` = %d AND `id` = %d",
"SELECT `id`, `char_id`, `nameid`, `amount`, `equip`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `enchantgrade` FROM `%s` WHERE `id` = %d",
#endif
db->inventory_db, item->char_id, item->inventory_id )
db->inventory_db, item->inventory_id )
) {
Sql_ShowDebug(sql_handle);
return false;
@ -459,6 +620,73 @@ static bool bot_inv_item_db_fromsql(InventoryDB_SQL* db, struct bot_inv_item* it
item->option_parm4 = 0;
item->option_val4 = 0;
return true;
} */
static bool bot_inv_item_db_fromsql(InventoryDB_SQL* db, struct bot_inv_item* item) {
Sql* sql_handle = db->bot_inventory;
char* data;
// Execute the query
if (SQL_ERROR == Sql_Query(sql_handle,
"SELECT `id`, `char_id`, `nameid`, `amount`, `equip`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `enchantgrade` "
"FROM `%s` WHERE `id` = %d",
db->inventory_db, item->inventory_id))
{
Sql_ShowDebug(sql_handle);
ShowError("SQL query failed for inventory ID: %d\n", item->inventory_id);
return false;
}
// Retrieve the next row
if (SQL_SUCCESS != Sql_NextRow(sql_handle)) {
ShowWarning("No inventory data found for ID: %d\n", item->inventory_id);
Sql_FreeResult(sql_handle);
return false;
}
// Parse data
auto parse_column = [&](int column_index, auto& target_field) -> bool {
if (SQL_SUCCESS != Sql_GetData(sql_handle, column_index, &data, nullptr) || data == nullptr) {
ShowError("Failed to retrieve column %d for inventory ID: %d\n", column_index, item->inventory_id);
return false;
}
target_field = atoi(data);
return true;
};
if (!parse_column(0, item->inventory_id) ||
!parse_column(1, item->char_id) ||
!parse_column(2, item->item_id) ||
!parse_column(3, item->amount) ||
!parse_column(4, item->equip) ||
!parse_column(5, item->refine) ||
!parse_column(6, item->attribute) ||
!parse_column(7, item->card0) ||
!parse_column(8, item->card1) ||
!parse_column(9, item->card2) ||
!parse_column(10, item->card3) ||
!parse_column(11, item->enchantgrade))
{
Sql_FreeResult(sql_handle);
return false;
}
Sql_FreeResult(sql_handle);
// Set default values
item->identify = 1; // Identified
item->expire_time = 0; // No expiration
item->favorite = 0;
item->bound = 0;
item->unique_id = 0;
item->equip_switch = 0;
item->option_id0 = item->option_parm0 = item->option_val0 = 0;
item->option_id1 = item->option_parm1 = item->option_val1 = 0;
item->option_id2 = item->option_parm2 = item->option_val2 = 0;
item->option_id3 = item->option_parm3 = item->option_val3 = 0;
item->option_id4 = item->option_parm4 = item->option_val4 = 0;
return true;
}
@ -522,11 +750,11 @@ static bool bot_inv_item_db_tosql(InventoryDB_SQL* db, const struct bot_inv_item
// Per default, amount of an allready existing item is updated here but currently (01/25) no valid usecase is defined yet
if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
#ifdef VIP_ENABLE
"UPDATE `%s` SET `amount`=? WHERE `char_id` = '%d' AND `id` = '%d'",
"UPDATE `%s` SET `amount`=? WHERE `id` = '%d'",
#else
"UPDATE `%s` SET `amount`=? WHERE `char_id` = '%d' AND `id` = '%d'",
"UPDATE `%s` SET `amount`=? WHERE `id` = '%d'",
#endif
db->inventory_db, item->char_id, item->inventory_id)
db->inventory_db, item->inventory_id)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_UINT32, (void*)item->amount, sizeof(item->amount))
#ifdef VIP_ENABLE
#endif
@ -598,7 +826,7 @@ void set_bot_inv_item_defaults(bot_inv_item& item) {
item.enchantgrade = 0;
}
int convert_item_aegisname_to_id(const char* aegisname)
uint32 convert_item_aegisname_to_id(const char* aegisname)
{
// Open the mapping JSON file
std::ifstream bot_itemdb_aegisname_to_id_file("conf/bot_helper_jsons/itemdb_converter_aegisname_to_id.json");
@ -628,13 +856,13 @@ int convert_item_aegisname_to_id(const char* aegisname)
return 0;
}
const int item_id = json_itemdb_aegisname_to_id[aegisname];
const uint32 item_id = json_itemdb_aegisname_to_id[aegisname];
//ShowStatus("aegisname found for Item_id %d\n",item_id);
return item_id;
}
std::string convert_item_id_to_name(int item_id)
std::string convert_item_id_to_name(uint32 item_id)
{
// Open the mapping JSON file
std::ifstream bot_itemdb_item_id_to_name_file("conf/bot_helper_jsons/itemdb_converter_id_to_name.json");
@ -645,14 +873,23 @@ std::string convert_item_id_to_name(int item_id)
// Parse the JSON file
json json_itemdb_id_to_name;
try {
bot_itemdb_item_id_to_name_file >> json_itemdb_id_to_name;
//bot_itemdb_item_id_to_name_file >> json_itemdb_id_to_name;
json test_json = json::parse(bot_itemdb_item_id_to_name_file);
//ShowDebug("Test parse successful: %s\n", test_json.dump().c_str());
}
catch (json::parse_error& e) {
ShowError("Error parsing itemdb_converter_id_to_name.json: %s\n", e.what());
return "UNKNOWN";
catch (const json::parse_error& e) {
ShowError("JSON parse error: %s\n", e.what());
}
catch (const std::exception& e) {
ShowError("General exception: %s\n", e.what());
}
catch (...) {
ShowError("Unknown error occurred during JSON parsing.\n");
}
// Close file after done with it
bot_itemdb_item_id_to_name_file.close();
//ShowStatus("Mapping item_id to item_name...\n");
@ -661,7 +898,7 @@ std::string convert_item_id_to_name(int item_id)
//ShowStatus("id=%s\n", id_str.c_str());
if (!json_itemdb_id_to_name.contains(id_str)) {
// Error: item_id is not inside json file
ShowWarning("Item_id \"%d\" was not found inside the itemdb. Skipped...", item_id);
ShowWarning("Item_id \"%d\" was not found inside the itemdb. Skipped...\n", item_id);
return "UNKNOWN";
}
@ -672,41 +909,38 @@ std::string convert_item_id_to_name(int item_id)
}
std::string convert_item_id_to_aegisname(int item_id)
{
// Open the mapping JSON file
std::string convert_item_id_to_aegisname(uint32 item_id) {
static json json_itemdb_id_to_aegisname;
static bool id_to_aegisname_is_loaded = false;
// Load the JSON file only once
if (!id_to_aegisname_is_loaded) {
std::ifstream bot_itemdb_item_id_to_aegisname_file("conf/bot_helper_jsons/itemdb_converter_id_to_aegisname.json");
if (!bot_itemdb_item_id_to_aegisname_file.is_open()) {
ShowError("Failed to open itemdb_converter_id_to_aegisname.json\n");
return "UNKNOWN";
}
// Parse the JSON file
json json_itemdb_id_to_aegisname;
try {
bot_itemdb_item_id_to_aegisname_file >> json_itemdb_id_to_aegisname;
id_to_aegisname_is_loaded = true;
}
catch (json::parse_error& e) {
ShowError("Error parsing itemdb_converter_id_to_name.json: %s\n", e.what());
ShowError("Error parsing itemdb_converter_id_to_aegisname.json: %s\n", e.what());
return "UNKNOWN";
}
// Close file after done with it
bot_itemdb_item_id_to_aegisname_file.close();
}
//ShowStatus("Mapping item_id to item aegisname...\n");
// Lookup the item ID in the JSON data
std::string id_str = std::to_string(item_id);
//ShowStatus("id=%s\n", id_str.c_str());
if (!json_itemdb_id_to_aegisname.contains(id_str)) {
// Error: item_id is not inside json file
ShowWarning("Item_id \"%d\" was not found inside the itemdb. Skipped...", item_id);
ShowWarning("Item_id \"%u\" was not found inside the itemdb. Skipped...", item_id);
return "UNKNOWN";
}
std::string item_name = json_itemdb_id_to_aegisname[id_str];
//ShowStatus("Entry found. Item Name: %s\n", item_name.c_str());
return item_name;
return json_itemdb_id_to_aegisname[id_str];
}
/*
@ -735,12 +969,7 @@ void prepare_item_bundle(bot_item_bundle& bundle, uint32 char_id, const nlohmann
ShowWarning("Item ID (Aegisname) %s is Invalid. Skipping...\n", item_name.c_str());
continue; // Skip invalid item
}
// Retrieve ingame name of the item
std::string ingame_name = convert_item_id_to_name(item_id);
if (ingame_name == "UNKNOWN") { // invalid ingame name
ShowWarning("Item id %d is Invalid. Skipping...\n", item_id);
continue; // Skip invalid item id
}
// Add the item to the item bundle
bot_inv_item new_item{};
@ -800,13 +1029,6 @@ void prepare_item_bundle(bot_item_bundle& bundle, uint32 char_id, const nlohmann
continue; // Skip invalid items
}
// Retrieve ingame name of the item
std::string ingame_name = convert_item_id_to_name(item_id);
if (ingame_name == "UNKNOWN") { // invalid ingame name
ShowWarning("Item id %d is Invalid. Skipping...\n", item_id);
continue; // Skip invalid item id
}
// Add the item to the item bundle
bot_inv_item new_item{};

@ -105,7 +105,7 @@ struct InventoryDBIterator {
/// @param self Iterator
/// @param item InvItem data
/// @return true if successful
bool (*next)(InventoryDBIterator* self, const uint32 char_id, struct bot_inv_item* item);
bool (*next)(InventoryDBIterator* self, struct bot_inv_item* item);
};
@ -180,9 +180,9 @@ struct InventoryDB {
};
void set_bot_inv_item_defaults(bot_inv_item& item);
int convert_item_aegisname_to_id(const char* aegisname);
std::string convert_item_id_to_name(int item_id);
std::string convert_item_id_to_aegisname(int item_id);
uint32 convert_item_aegisname_to_id(const char* aegisname);
std::string convert_item_id_to_name(uint32 item_id);
std::string convert_item_id_to_aegisname(uint32 item_id);
struct bot_item {
uint32 item_id;
@ -196,4 +196,5 @@ struct bot_item_bundle {
};
void prepare_item_bundle(bot_item_bundle& bundle, uint32 char_id, const nlohmann::json& character);
void dump_item_bundle(const bot_item_bundle& item_bundle);
#endif /* HELPER_INVENTORY_HPP */

@ -854,23 +854,6 @@ void BotSkillTreeDatabase::loadingFinished() {
TypesafeYamlDatabase::loadingFinished();
}
std::unordered_map<uint16, uint16> parse_skill_bundle(const nlohmann::json& skill_bundle) {
std::unordered_map<uint16, uint16> parsed_skill_bundle;
for (const auto& skill : skill_bundle.items()) {
uint16 skill_id = convert_skill_str_to_id(skill.key().c_str());
if (skill_id < 0) {
ShowError("Invalid skill ID for skill string: %s\n", skill.key().c_str());
continue; // Skip invalid skills
}
uint16 level = skill.value(); // Assuming the value represents the skill level
parsed_skill_bundle[skill_id] = level;
}
return parsed_skill_bundle;
}
void dump_skill_bundle(const bot_skill_bundle& skill_bundle) {
ShowDebug("Dumping skill bundle contents...\n");
if (skill_bundle.skills.empty()) {
@ -947,7 +930,7 @@ void validate_skill_bundle(bot_skill_bundle& skill_bundle, const char* job_id) {
// Update the skill bundle with valid skills
skill_bundle.skills = std::move(valid_skills);
ShowStatus("Skill bundle validation completed for job ID: %s.\n", job_id);
//ShowStatus("Skill bundle validation completed for job ID: %s.\n", job_id);
}
void prepare_skill_bundle(bot_skill_bundle& bundle, uint32 char_id, const nlohmann::json& character) {

Loading…
Cancel
Save