From 6f13d0cfbc4bd61c93170ce35c78be4bf6529dc2 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 21 Feb 2013 22:13:33 -0800 Subject: [PATCH] Partial work on loot tables (non-compiling) --- common/CMakeLists.txt | 2 + common/EMuShareMem.h | 2 +- common/eq_packet_structs.h | 17 + common/fixed_memory_variable_hash_set.h | 241 +++++++++++ {zone => common}/loottable.h | 31 +- common/shareddb.cpp | 514 ++++++++++++++++++------ common/shareddb.h | 52 +-- shared_memory/CMakeLists.txt | 2 + shared_memory/items.cpp | 3 - shared_memory/loot.cpp | 50 +++ shared_memory/loot.h | 25 ++ shared_memory/main.cpp | 20 +- shared_memory/skill_caps.cpp | 1 - tests/CMakeLists.txt | 5 +- tests/fixed_memory_variable_test.h | 132 ++++++ tests/main.cpp | 2 + zone/CMakeLists.txt | 1 - zone/client_packet.cpp | 8 +- zone/doors.cpp | 32 -- zone/loottables.cpp | 228 ----------- zone/npc.h | 2 +- zone/parser.cpp | 4 - zone/zonedb.h | 8 +- zone/zonedump.h | 14 - 24 files changed, 909 insertions(+), 487 deletions(-) create mode 100644 common/fixed_memory_variable_hash_set.h rename {zone => common}/loottable.h (52%) create mode 100644 shared_memory/loot.cpp create mode 100644 shared_memory/loot.h create mode 100644 tests/fixed_memory_variable_test.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index c7ff86d62..2411919f2 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -132,6 +132,7 @@ SET(common_headers extprofile.h features.h fixed_memory_hash_set.h + fixed_memory_variable_hash_set.h guild_base.h guilds.h ipc_mutex.h @@ -142,6 +143,7 @@ SET(common_headers linked_list.h logsys.h logtypes.h + loottable.h mail_oplist.h md5.h memory_mapped_file.h diff --git a/common/EMuShareMem.h b/common/EMuShareMem.h index b7f726f74..9f69c0f34 100644 --- a/common/EMuShareMem.h +++ b/common/EMuShareMem.h @@ -24,7 +24,7 @@ #endif #include "../common/eq_packet_structs.h" #include "../zone/zonedump.h" -#include "../zone/loottable.h" +#include "../common/loottable.h" #include "SharedLibrary.h" //////////// diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 770cbd52e..7b8ca52b0 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -21,6 +21,7 @@ #include "types.h" #include #include +#include #include #include "../common/version.h" //#include "../common/item_struct.h" @@ -5039,6 +5040,22 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; +struct ServerLootItem_Struct { + uint32 item_id; + int16 equipSlot; + uint8 charges; + uint16 lootslot; + uint32 aug1; + uint32 aug2; + uint32 aug3; + uint32 aug4; + uint32 aug5; + uint8 minlevel; + uint8 maxlevel; +}; + +typedef std::list ItemList; + // Restore structure packing to default #pragma pack() diff --git a/common/fixed_memory_variable_hash_set.h b/common/fixed_memory_variable_hash_set.h new file mode 100644 index 000000000..7c3b0b004 --- /dev/null +++ b/common/fixed_memory_variable_hash_set.h @@ -0,0 +1,241 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _EQEMU_FIXED_MEMORY_VARIABLE_HASHSET_H +#define _EQEMU_FIXED_MEMORY_VARIABLE_HASHSET_H + +#include +#include "eqemu_exception.h" +#include "types.h" + +namespace EQEmu { + + /*! Simple HashSet designed to be used in fixed memory that may be difficult to use an + allocator for (shared memory), we assume all keys are unsigned int, values are a pointer and size + */ + template + class FixedMemoryVariableHashSet { + typedef uint32 key_type; + typedef T value_type; + typedef uint8 byte; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef uint32 size_type; + public: + /*! + Constructor which initializes the hash set + \param data Raw data + \param size Raw data size + \param max_element_id Number of offsets to store: eg highest "key" that will be used. + */ + FixedMemoryVariableHashSet(byte *data, size_type size, key_type max_element_id) { + data_ = data; + size_ = size; + remaining_size_ = size_ - (sizeof(key_type) * 3) - (sizeof(key_type) * (max_element_id + 1)); + + byte *ptr = data; + *reinterpret_cast(ptr) = max_element_id + 1; + offset_count_ = max_element_id + 1; + ptr += sizeof(key_type); + + *reinterpret_cast(ptr) = remaining_size_; + ptr += sizeof(key_type); + + *reinterpret_cast(ptr) = 0; + current_offset_ = 0; + ptr += sizeof(key_type); + + + offsets_ = reinterpret_cast(ptr); + memset(ptr, 0xFFFFFFFFU, sizeof(key_type) * (max_element_id + 1)); + ptr += sizeof(key_type) * (max_element_id + 1); + + elements_ = reinterpret_cast(ptr); + } + + /*! + Constructor which does not initialize the hash set. Builds the hash set from what data is + stored in the data pointer passed. + \param data Raw data + \param size Raw data size + */ + FixedMemoryVariableHashSet(byte *data, size_type size) { + data_ = data; + size_ = size; + + byte *ptr = data; + offset_count_ = *reinterpret_cast(ptr); + ptr += sizeof(key_type); + + remaining_size_ = *reinterpret_cast(ptr); + ptr += sizeof(key_type); + + current_offset_ = *reinterpret_cast(ptr); + ptr += sizeof(key_type); + + offsets_ = reinterpret_cast(ptr); + ptr += sizeof(key_type) * offset_count_; + + elements_ = reinterpret_cast(ptr); + } + + //! Copy Constructor + FixedMemoryVariableHashSet(const FixedMemoryVariableHashSet& other) : + data_(other.data_), + size_(other.size_), + offset_count_(other.offset_count_), + remaining_size_(other.remaining_size_), + current_offset_(other.current_offset_), + offsets_(other.offsets_), + elements_(other.elements_) + { + } + + //! RValue-Move Constructor +#ifdef EQEMU_RVALUE_MOVE + FixedMemoryVariableHashSet(FixedMemoryVariableHashSet&& other) : + data_(other.data_), + size_(other.size_), + offset_count_(other.offset_count_), + remaining_size_(other.remaining_size_), + current_offset_(other.current_offset_), + offsets_(other.offsets_), + elements_(other.elements_) + { + } +#endif + + //! Destructor + ~FixedMemoryVariableHashSet() { + } + + //! Assignment operator + const FixedMemoryVariableHashSet& operator=(const FixedMemoryVariableHashSet& other) { + data_ = other.data_; + size_ = other.size_; + offset_count_ = other.offset_count_; + remaining_size_ = other.remaining_size_; + current_offset_ = other.current_offset_; + offsets_ = other.offsets_; + elements_ = other.elements_; + return *this; + } + + //! Returns the number of bytes in the set currently + size_type size() const { + return size_ - remaining_size_; + } + + //! Returns the maximum number of bytes one can insert into the set. + size_type max_size() const { + return size_ - (sizeof(key_type) * 2); + } + + //! Returns the maximum key one can use with the set. + key_type max_key() const { + return offset_count_ > 0 ? (offset_count_ - 1) : 0; + } + + /*! + Retrieve value operator + \param i Index to retrieve the value from + */ + reference operator[](const key_type& i) { + if(i >= offset_count_) { + EQ_EXCEPT("Fixed Memory Variable Hash Set", "Index out of range"); + } + + if(offsets_[i] == 0xFFFFFFFFU) { + EQ_EXCEPT("Fixed Memory Variable Hash Set", "Element not found."); + } + + return *reinterpret_cast(&elements_[offsets_[i]]); + } + + /*! + Retrieve value function + \param i Index to retrieve the value from + */ + reference at(const key_type& i) { + if(i >= offset_count_) { + EQ_EXCEPT("Fixed Memory Variable Hash Set", "Index out of range"); + } + + if(offsets_[i] == 0xFFFFFFFFU) { + EQ_EXCEPT("Fixed Memory Variable Hash Set", "Element not found."); + } + + return *reinterpret_cast(&elements_[offsets_[i]]); + } + + /*! + Checks if there is a value at a certain index + \param i Index to check for a value + */ + bool exists(const key_type& i) const { + if(i >= offset_count_) { + return false; + } + + if(offsets_[i] == 0xFFFFFFFFU) { + return false; + } + + return true; + } + + /*! + Inserts a value into the set at a specific index + \param i Index to insert the value at + \param v Value to insert + */ + void insert(const key_type& i, byte *data, size_type size) { + if(i >= offset_count_) { + EQ_EXCEPT("Fixed Memory Variable Hash Set", "Index out of range."); + } + + if(size > remaining_size_) { + EQ_EXCEPT("Fixed Memory Hash Set", "Not enough room in hash set to insert this value."); + } + + if(offsets_[i] != 0xFFFFFFFFU) { + EQ_EXCEPT("Fixed Memory Hash Set", "Could not insert a repeat value at this index."); + } else { + offsets_[i] = current_offset_; + memcpy(&elements_[current_offset_], data, size); + + remaining_size_ -= size; + *reinterpret_cast(data_ + sizeof(key_type)) = remaining_size_; + + current_offset_ += size; + *reinterpret_cast(data_ + (sizeof(key_type) * 2)) = current_offset_; + } + } + + private: + unsigned char *data_; + size_type size_; + size_type remaining_size_; + key_type current_offset_; + key_type offset_count_; + key_type *offsets_; + byte *elements_; + }; +} // EQEmu + +#endif diff --git a/zone/loottable.h b/common/loottable.h similarity index 52% rename from zone/loottable.h rename to common/loottable.h index a06d71cc9..051c6c792 100644 --- a/zone/loottable.h +++ b/common/loottable.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,33 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* -alter table npc_types add column loottable_id int(11) unsigned not null; -create table loottable (id int(11) unsigned auto_increment primary key, name varchar(255) not null unique, -mincash int(11) unsigned not null, maxcash int(11) unsigned not null, avgcoin smallint(4) unsigned not null default 0); +#ifndef _EQEMU_LOOTTABLE_H +#define _EQEMU_LOOTTABLE_H -create table loottable_entries (loottable_id int(11) unsigned not null, lootdrop_id int(11) unsigned not null, -multiplier tinyint(2) unsigned default 1 not null, probability tinyint(2) unsigned default 100 not null, -primary key (loottable_id, lootdrop_id)); - -create table lootdrop (id int(11) unsigned auto_increment primary key, name varchar(255) not null unique); - -create table lootdrop_entries (lootdrop_id int(11) unsigned not null, item_id int(11) not null, -item_charges tinyint(2) default 1 not null, equip_item tinyint(2) unsigned not null, -chance tinyint(2) unsigned default 1 not null, primary key (lootdrop_id, item_id)); - -ALTER TABLE `loottable_entries` ADD `probability` FLOAT NOT NULL DEFAULT '100'; -*/ - - -#ifndef LOOTTABLE_H -#define LOOTTABLE_H -#include "zonedump.h" -#include "../common/linked_list.h" - -#include -using namespace std; #pragma pack(1) struct LootTableEntries_Struct { @@ -76,6 +53,4 @@ struct LootDrop_Struct { }; #pragma pack() -typedef list ItemList; - #endif diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 61fc726c5..5379daade 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -18,40 +18,25 @@ using namespace std; - extern LoadEMuShareMemDLL EMuShareMemDLL; -//hackish mechanism to support callbacks from sharedmem -SharedDatabase *SharedDatabase::s_usedb = NULL; - SharedDatabase::SharedDatabase() -: Database(), skill_caps_mmf(NULL), items_mmf(NULL), items_hash(NULL) +: Database(), skill_caps_mmf(NULL), items_mmf(NULL), items_hash(NULL), faction_mmf(NULL), loot_mmf(NULL) { - SDBInitVars(); - s_usedb = this; } SharedDatabase::SharedDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port) -: Database(host, user, passwd, database, port), skill_caps_mmf(NULL), items_mmf(NULL), items_hash(NULL) +: Database(host, user, passwd, database, port), skill_caps_mmf(NULL), items_mmf(NULL), items_hash(NULL), + faction_mmf(NULL), loot_mmf(NULL) { - SDBInitVars(); - s_usedb = this; -} - -void SharedDatabase::SDBInitVars() { - max_item = 0; - max_npc_type = 0; - - loottable_max = 0; - lootdrop_max = 0; - max_door_type = 0; - npcfactionlist_max = 0; } SharedDatabase::~SharedDatabase() { safe_delete(skill_caps_mmf); safe_delete(items_mmf); safe_delete(items_hash); + safe_delete(faction_mmf); + safe_delete(loot_mmf); } bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) @@ -753,41 +738,6 @@ int32 SharedDatabase::GetItemsCount(uint32* max_id) { return ret; } - -int32 SharedDatabase::GetNPCTypesCount(uint32* oMaxID) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - strcpy(query, "SELECT MAX(id), count(*) FROM npc_types"); - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - if (row != NULL && row[1] != 0) { - int32 ret = atoi(row[1]); - if (oMaxID) { - if (row[0]) - *oMaxID = atoi(row[0]); - else - *oMaxID = 0; - } - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - cerr << "Error in GetNPCTypesCount query '" << query << "' " << errbuf << endl; - safe_delete_array(query); - - return -1; - } - - return -1; -} - bool SharedDatabase::LoadItems() { if(items_mmf) { return true; @@ -1133,7 +1083,8 @@ string SharedDatabase::GetBook(const char *txtfile) bool SharedDatabase::extDBLoadNPCFactionLists(int32 iNPCFactionListCount, uint32 iMaxNPCFactionListID) { - return s_usedb->DBLoadNPCFactionLists(iNPCFactionListCount, iMaxNPCFactionListID); + return false; + //return s_usedb->DBLoadNPCFactionLists(iNPCFactionListCount, iMaxNPCFactionListID); } const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) { @@ -1150,8 +1101,7 @@ bool SharedDatabase::LoadNPCFactionLists() { cout << "Error: SharedDatabase::LoadNPCFactionLists-ShareMem: GetNPCFactionListsCount() returned < 0" << endl; return false; } - npcfactionlist_max = tmp_npcfactionlist_max; - bool ret = EMuShareMemDLL.NPCFactionList.DLLLoadNPCFactionLists(&extDBLoadNPCFactionLists, sizeof(NPCFactionList), &tmp, &npcfactionlist_max, MAX_NPC_FACTIONS); + bool ret = EMuShareMemDLL.NPCFactionList.DLLLoadNPCFactionLists(&extDBLoadNPCFactionLists, sizeof(NPCFactionList), &tmp, &tmp_npcfactionlist_max, MAX_NPC_FACTIONS); return ret; } @@ -1181,7 +1131,7 @@ bool SharedDatabase::DBLoadNPCFactionLists(int32 iNPCFactionListCount, uint32 iM mysql_free_result(result); return false; } - npcfactionlist_max = atoi(row[0]); + //npcfactionlist_max = atoi(row[0]); mysql_free_result(result); NPCFactionList tmpnfl; if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, primaryfaction, ignore_primary_assist from npc_faction"), errbuf, &result)) { @@ -1698,76 +1648,6 @@ const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { return NULL; // nothing here for now... database and/or sharemem pulls later } -void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << endl; - safe_delete_array(query); - } -} - -void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) { - cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << endl; - } - - safe_delete_array(query); -} - -void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT BotInspectMessage FROM bots WHERE BotID=%i", botid), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - cerr << "Error in GetBotInspectMessage query '" << query << "' " << errbuf << endl; - safe_delete_array(query); - } -} - -void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) { - cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << endl; - } - - safe_delete_array(query); -} - int SharedDatabase::GetMaxSpellID() { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = NULL; @@ -1921,3 +1801,379 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { safe_delete_array(query); } } + +bool SharedDatabase::LoadLoot() { + //char errbuf[MYSQL_ERRMSG_SIZE]; + //char *query = 0; + //MYSQL_RES *result; + //MYSQL_ROW row; + //uint32 tmpLootTableCount = 0; + //uint32 tmpLootTableEntriesCount = 0; + //uint32 tmpLootDropCount = 0; + //uint32 tmpLootDropEntriesCount = 0; + //if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id), count(*) FROM loottable"), errbuf, &result)) { + // safe_delete_array(query); + // if (mysql_num_rows(result) == 1) { + // row = mysql_fetch_row(result); + // if (row[0]) + // loottable_max = atoi(row[0]); + // else + // loottable_max = 0; + // tmpLootTableCount = atoi(row[1]); + // } + // else { + // mysql_free_result(result); + // return false; + // } + // mysql_free_result(result); + //} + //else { + // cerr << "Error in LoadLoot query, loottable part: '" << query << "' " << errbuf << endl; + // safe_delete_array(query); + // return false; + //} + //if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(*) FROM loottable_entries"), errbuf, &result)) { + // safe_delete_array(query); + // if (mysql_num_rows(result) == 1) { + // row = mysql_fetch_row(result); + // tmpLootTableEntriesCount = atoi(row[0]); + // } + // else { + // mysql_free_result(result); + // return false; + // } + // mysql_free_result(result); + //} + //else { + // cerr << "Error in LoadLoot query, loottable2 part: '" << query << "' " << errbuf << endl; + // safe_delete_array(query); + // return false; + //} + // + //if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id), count(*) FROM lootdrop"), errbuf, &result)) { + // safe_delete_array(query); + // if (mysql_num_rows(result) == 1) { + // row = mysql_fetch_row(result); + // if (row[0]) + // lootdrop_max = atoi(row[0]); + // else + // lootdrop_max = 0; + // tmpLootDropCount = atoi(row[1]); + // } + // else { + // mysql_free_result(result); + // return false; + // } + // mysql_free_result(result); + //} + //else { + // cerr << "Error in LoadLoot query, lootdrop1 part: '" << query << "' " << errbuf << endl; + // safe_delete_array(query); + // return false; + //} + //if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(lootdrop_id), count(*) FROM lootdrop_entries"), errbuf, &result)) { + // safe_delete_array(query); + // if (mysql_num_rows(result) == 1) { + // row = mysql_fetch_row(result); + // tmpLootDropEntriesCount = atoi(row[1]); + // } + // else { + // mysql_free_result(result); + // return false; + // } + // mysql_free_result(result); + //} + //else { + // cerr << "Error in LoadLoot query, lootdrop part: '" << query << "' " << errbuf << endl; + // safe_delete_array(query); + // return false; + //} + //return EMuShareMemDLL.Loot.DLLLoadLoot(&extDBLoadLoot, + // sizeof(LootTable_Struct), tmpLootTableCount, loottable_max, + // sizeof(LootTableEntries_Struct), tmpLootTableEntriesCount, + // sizeof(LootDrop_Struct), tmpLootDropCount, lootdrop_max, + // sizeof(LootDropEntries_Struct), tmpLootDropEntriesCount); + return false; +} + +void SharedDatabase::LoadLoot(void *ptr, uint32 loot_table_count, uint32 max_loot_table, uint32 loot_table_entries, + uint32 loot_drop_count, uint32 max_loot_drop, uint32 loot_drop_entries) +{ + uint8 *data = reinterpret_cast(ptr); + uint32 *loottable_max = reinterpret_cast(ptr); data += sizeof(uint32); + uint32 *lootdrop_max = reinterpret_cast(ptr); data += sizeof(uint32); + uint32 *lootdrop_offset = reinterpret_cast(ptr); data += sizeof(uint32); + uint32 *loottable_offset = reinterpret_cast(ptr); data += (sizeof(uint32) * (max_loot_table + 1)); + + *loottable_max = max_loot_table + 1; + *lootdrop_max = max_loot_drop + 1; + *loottable_offset = sizeof(uint32) * 3; + data += sizeof(uint32) * (*loottable_max + 1); + + uint32 *loottable_offsets = reinterpret_cast(reinterpret_cast(ptr) + (*loottable_offset)); + uint32 *lootdrop_offsets = NULL; + + const char *loottable_query = "SELECT * FROM loottable ORDER BY id"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + if(RunQuery(loottable_query, strlen(loottable_query), errbuf, &result)) { + while(row = mysql_fetch_row(result)) { + LootTable_Struct *table = reinterpret_cast(data); data += sizeof(LootTable_Struct); + + } + mysql_free_result(result); + } +} + +void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries, + uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries) +{ + loot_table_count = 0; + max_loot_table = 0; + loot_table_entries = 0; + loot_drop_count = 0; + max_loot_drop = 0; + loot_drop_entries = 0; + const char *count_query = "SELECT (SELECT COUNT(*) FROM loottable) as loot_table_count, " + "(SELECT COUNT(*) FROM lootdrop) as loot_drop_count"; + const char *max_query = "SELECT MAX(loottable.id) AS max_loot_table, MAX(lootdrop.id) as max_loot_drop" + " FROM loottable, lootdrop"; + const char *entries_count_query = "SELECT (SELECT COUNT(*) FROM loottable_entries) as loot_table_count, " + "(SELECT COUNT(*) FROM lootdrop_entries) as loot_drop_count"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(count_query, strlen(count_query), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + loot_table_count = static_cast(atoul(row[0])); + loot_drop_count = static_cast(atoul(row[1])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", max_query, errbuf); + return; + } + + if(RunQuery(max_query, strlen(max_query), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + max_loot_table = static_cast(atoul(row[0])); + max_loot_drop = static_cast(atoul(row[1])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", max_query, errbuf); + return; + } + + if(RunQuery(entries_count_query, strlen(entries_count_query), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + loot_table_entries = static_cast(atoul(row[0])); + loot_drop_entries = static_cast(atoul(row[1])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", entries_count_query, errbuf); + return; + } +} + +bool SharedDatabase::DBLoadLoot() { + LogFile->write(EQEMuLog::Status, "Loading Loot tables from database..."); + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + MYSQL_RES *result2; + uint32 i, tmpid = 0, tmpmincash = 0, tmpmaxcash = 0, tmpavgcoin = 0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, mincash, maxcash, avgcoin FROM loottable"), errbuf, &result)) { + safe_delete_array(query); + LootTable_Struct* tmpLT = 0; + while ((row = mysql_fetch_row(result))) { + tmpid = atoi(row[0]); + tmpmincash = atoi(row[1]); + tmpmaxcash = atoi(row[2]); + tmpavgcoin = atoi(row[3]); + if (RunQuery(query, MakeAnyLenString(&query, "SELECT loottable_id, lootdrop_id, droplimit, mindrop, multiplier, probability FROM loottable_entries WHERE loottable_id=%i", tmpid), errbuf, &result2)) { + safe_delete_array(query); + tmpLT = (LootTable_Struct*) new uchar[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * mysql_num_rows(result2))]; + memset(tmpLT, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * mysql_num_rows(result2))); + tmpLT->NumEntries = mysql_num_rows(result2); + tmpLT->mincash = tmpmincash; + tmpLT->maxcash = tmpmaxcash; + tmpLT->avgcoin = tmpavgcoin; + i=0; + while ((row = mysql_fetch_row(result2))) { + if (i >= tmpLT->NumEntries) { + mysql_free_result(result); + mysql_free_result(result2); + safe_delete_array(tmpLT); + cerr << "Error in ZoneDatabase::DBLoadLoot, i >= NumEntries" << endl; + return false; + } + tmpLT->Entries[i].lootdrop_id = atoi(row[1]); + tmpLT->Entries[i].droplimit = atoi(row[2]); + tmpLT->Entries[i].mindrop = atoi(row[3]); + tmpLT->Entries[i].multiplier = atoi(row[4]); + tmpLT->Entries[i].probability = atof(row[5]); + i++; + } + if (!EMuShareMemDLL.Loot.cbAddLootTable(tmpid, tmpLT)) { + mysql_free_result(result); + mysql_free_result(result2); + safe_delete_array(tmpLT); + cout << "Error in ZoneDatabase::DBLoadLoot: !cbAddLootTable(" << tmpid << ")" << endl; + return false; + } + safe_delete_array(tmpLT); + mysql_free_result(result2); + } + else { + mysql_free_result(result); + cerr << "Error in LoadLoot (memshare) #1 query '" << query << "' " << errbuf << endl; + safe_delete_array(query); + return false; + } + } + mysql_free_result(result); + } + else { + cerr << "Error in LoadLoot (memshare) #2 query '" << query << "' " << errbuf << endl; + safe_delete_array(query); + return false; + } + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM lootdrop", tmpid), errbuf, &result)) { + safe_delete_array(query); + LootDrop_Struct* tmpLD = 0; + while ((row = mysql_fetch_row(result))) { + tmpid = atoi(row[0]); + if (RunQuery(query, MakeAnyLenString(&query, "SELECT lootdrop_id, item_id, item_charges, equip_item, chance, minlevel, maxlevel, multiplier FROM lootdrop_entries WHERE lootdrop_id=%i order by chance desc", tmpid), errbuf, &result2)) { + safe_delete_array(query); + tmpLD = (LootDrop_Struct*) new uchar[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * mysql_num_rows(result2))]; + memset(tmpLD, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * mysql_num_rows(result2))); + tmpLD->NumEntries = mysql_num_rows(result2); + i=0; + while ((row = mysql_fetch_row(result2))) { + if (i >= tmpLD->NumEntries) { + mysql_free_result(result); + mysql_free_result(result2); + safe_delete_array(tmpLD); + cerr << "Error in ZoneDatabase::DBLoadLoot, i >= NumEntries" << endl; + return false; + } + tmpLD->Entries[i].item_id = atoi(row[1]); + tmpLD->Entries[i].item_charges = atoi(row[2]); + tmpLD->Entries[i].equip_item = atoi(row[3]); + tmpLD->Entries[i].chance = atof(row[4]); + tmpLD->Entries[i].minlevel = atoi(row[5]); + tmpLD->Entries[i].maxlevel = atoi(row[6]); + tmpLD->Entries[i].multiplier = atoi(row[7]); + i++; + } + if (!EMuShareMemDLL.Loot.cbAddLootDrop(tmpid, tmpLD)) { + mysql_free_result(result); + mysql_free_result(result2); + safe_delete_array(tmpLD); + cout << "Error in ZoneDatabase::DBLoadLoot: !cbAddLootDrop(" << tmpid << ")" << endl; + return false; + } + safe_delete_array(tmpLD); + mysql_free_result(result2); + } + else { + cerr << "Error in LoadLoot (memshare) #3 query '" << query << "' " << errbuf << endl; + mysql_free_result(result); + safe_delete_array(query); + return false; + } + } + mysql_free_result(result); + } + else { + cerr << "Error in LoadLoot (memshare) #4 query '" << query << "' " << errbuf << endl; + safe_delete_array(query); + return false; + } + + return true; +} + +const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { + return EMuShareMemDLL.Loot.GetLootTable(loottable_id); +} + +const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { + return EMuShareMemDLL.Loot.GetLootDrop(lootdrop_id); +} + +void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) { + safe_delete_array(query); + + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + memcpy(message, row[0], sizeof(InspectMessage_Struct)); + } + + mysql_free_result(result); + } + else { + cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << endl; + safe_delete_array(query); + } +} + +void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) { + cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << endl; + } + + safe_delete_array(query); +} + +void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT BotInspectMessage FROM bots WHERE BotID=%i", botid), errbuf, &result)) { + safe_delete_array(query); + + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + memcpy(message, row[0], sizeof(InspectMessage_Struct)); + } + + mysql_free_result(result); + } + else { + cerr << "Error in GetBotInspectMessage query '" << query << "' " << errbuf << endl; + safe_delete_array(query); + } +} + +void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) { + cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << endl; + } + + safe_delete_array(query); +} diff --git a/common/shareddb.h b/common/shareddb.h index 3a6873f0f..378a4612e 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -47,7 +47,7 @@ public: void SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message); void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message); void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message); - + bool GetCommandSettings(map &commands); uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID); /* @@ -76,28 +76,29 @@ public: /* * Shared Memory crap */ - inline const uint32 GetMaxItem() { return max_item; } - inline const uint32 GetMaxLootTableID() { return loottable_max; } - inline const uint32 GetMaxLootDropID() { return lootdrop_max; } - inline const uint32 GetMaxNPCType() { return max_npc_type; } - inline const uint32 GetMaxNPCFactionList() { return npcfactionlist_max; } - const EvolveInfo* GetEvolveInfo(uint32 loregroup); - const NPCFactionList* GetNPCFactionEntry(uint32 id); - const LootTable_Struct* GetLootTable(uint32 loottable_id); - const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id); - bool LoadLoot(); - bool LoadNPCFactionLists(); - bool GetCommandSettings(map &commands); - bool DBLoadItems(int32 iItemCount, uint32 iMaxItemID); - bool DBLoadNPCTypes(int32 iNPCTypeCount, uint32 iMaxNPCTypeID); - bool DBLoadNPCFactionLists(int32 iNPCFactionListCount, uint32 iMaxNPCFactionListID); - bool DBLoadLoot(); + //items int32 GetItemsCount(uint32* max_id = 0); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(); const Item_Struct* IterateItems(uint32* id); const Item_Struct* GetItem(uint32 id); + const EvolveInfo* GetEvolveInfo(uint32 loregroup); + + //faction lists + const NPCFactionList* GetNPCFactionEntry(uint32 id); + bool LoadNPCFactionLists(); + bool DBLoadNPCFactionLists(int32 iNPCFactionListCount, uint32 iMaxNPCFactionListID); + + //loot + void GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries, + uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries); + void LoadLoot(void *ptr, uint32 loot_table_count, uint32 max_loot_table, uint32 loot_table_entries, + uint32 loot_drop_count, uint32 max_loot_drop, uint32 loot_drop_entries); + bool LoadLoot(); + const LootTable_Struct* GetLootTable(uint32 loottable_id); + const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id); + bool DBLoadLoot(); void LoadSkillCaps(void *data); bool LoadSkillCaps(); @@ -109,31 +110,18 @@ public: void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID); protected: - void SDBInitVars(); /* * Private shared mem stuff */ - int32 GetNPCTypesCount(uint32* oMaxID = 0); int32 GetNPCFactionListsCount(uint32* oMaxID = 0); static bool extDBLoadNPCFactionLists(int32 iNPCFactionListCount, uint32 iMaxNPCFactionListID); - static bool extDBLoadLoot(); - - - uint32 max_item; - uint32 max_npc_type; - uint32 max_door_type; - uint32 npcfactionlist_max; - uint32 loottable_max; - uint32 lootdrop_max; - - uint32 npc_spells_maxid; EQEmu::MemoryMappedFile *items_mmf; EQEmu::FixedMemoryHashSet *items_hash; + EQEmu::MemoryMappedFile *faction_mmf; + EQEmu::MemoryMappedFile *loot_mmf; EQEmu::MemoryMappedFile *skill_caps_mmf; -private: - static SharedDatabase *s_usedb; }; diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 954419cc0..8bb4419cd 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(shared_memory_sources items.cpp + loot.cpp main.cpp spells.cpp skill_caps.cpp @@ -9,6 +10,7 @@ SET(shared_memory_sources SET(shared_memory_headers items.h + loot.h spells.h skill_caps.h ) diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 2a96f8188..6f606becb 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -22,9 +22,6 @@ #include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -#include "../common/spdat.h" -#include "../common/classes.h" -#include "../common/features.h" #include "../common/item_struct.h" void LoadItems(SharedDatabase *database) { diff --git a/shared_memory/loot.cpp b/shared_memory/loot.cpp new file mode 100644 index 000000000..25527336d --- /dev/null +++ b/shared_memory/loot.cpp @@ -0,0 +1,50 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "loot.h" +#include "../common/debug.h" +#include "../common/shareddb.h" +#include "../common/ipc_mutex.h" +#include "../common/memory_mapped_file.h" +#include "../common/eqemu_exception.h" +#include "../common/loottable.h" + +void LoadLoot(SharedDatabase *database) { + EQEmu::IPCMutex mutex("loot"); + mutex.Lock(); + + uint32 loottable_count, loottable_max, loottable_entries_count, lootdrop_count, lootdrop_max, lootdrop_entries_count; + database->GetLootTableInfo(loottable_max, loottable_entries_count, + lootdrop_max, lootdrop_entries_count); + uint32 size = (sizeof(uint32) *3) + + (sizeof(uint32) * (loottable_max + 1)) + + (sizeof(LootTable_Struct) * loottable_count) + + (sizeof(LootTableEntries_Struct) * loottable_entries_count) + + (sizeof(uint32) * (lootdrop_max + 1)) + + (sizeof(LootDrop_Struct) * lootdrop_count) + + (sizeof(LootDropEntries_Struct) * lootdrop_entries_count); + + EQEmu::MemoryMappedFile mmf("shared/loot", size); + mmf.ZeroFile(); + + void *ptr = mmf.Get(); + database->LoadLoot(ptr, loottable_count, loottable_max, loottable_entries_count, lootdrop_count, + lootdrop_max, lootdrop_entries_count); + mmf.SetLoaded(); + mutex.Unlock(); +} diff --git a/shared_memory/loot.h b/shared_memory/loot.h new file mode 100644 index 000000000..3967add0d --- /dev/null +++ b/shared_memory/loot.h @@ -0,0 +1,25 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_SHARED_MEMORY_LOOT_H +#define __EQEMU_SHARED_MEMORY_LOOT_H + +class SharedDatabase; +void LoadLoot(SharedDatabase *database); + +#endif diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 17d67da8e..d8807d289 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -25,6 +25,7 @@ #include "../common/rulesys.h" #include "../common/eqemu_exception.h" #include "items.h" +#include "loot.h" #include "skill_caps.h" #include "spells.h" @@ -52,10 +53,11 @@ int main(int argc, char **argv) { return 0; } - bool load_all = true; - bool load_items = true; - bool load_skill_caps = true; - bool load_spells = true; + bool load_all = false; + bool load_items = false; + bool load_loot = true; + bool load_skill_caps = false; + bool load_spells = false; if(load_all || load_items) { LogFile->write(EQEMuLog::Status, "Loading items..."); try { @@ -66,6 +68,16 @@ int main(int argc, char **argv) { } } + if(load_all || load_loot) { + LogFile->write(EQEMuLog::Status, "Loading loot..."); + try { + LoadLoot(&database); + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "%s", ex.what()); + return 0; + } + } + if(load_all || load_skill_caps) { LogFile->write(EQEMuLog::Status, "Loading skill caps..."); try { diff --git a/shared_memory/skill_caps.cpp b/shared_memory/skill_caps.cpp index 01c0cb6f6..8ba0bf73f 100644 --- a/shared_memory/skill_caps.cpp +++ b/shared_memory/skill_caps.cpp @@ -22,7 +22,6 @@ #include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -#include "../common/spdat.h" #include "../common/classes.h" #include "../common/features.h" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f3a23212d..5288e78e7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,9 +7,10 @@ SET(tests_sources ) SET(tests_headers - memory_mapped_file_test.h - ipc_mutex_test.h fixed_memory_test.h + fixed_memory_variable_test.h + ipc_mutex_test.h + memory_mapped_file_test.h ) ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) diff --git a/tests/fixed_memory_variable_test.h b/tests/fixed_memory_variable_test.h new file mode 100644 index 000000000..515238c50 --- /dev/null +++ b/tests/fixed_memory_variable_test.h @@ -0,0 +1,132 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_FIXED_MEMORY_VARIABLE_H +#define __EQEMU_TESTS_FIXED_MEMORY_VARIABLE_H + +#include "cppunit/cpptest.h" +#include "../common/fixed_memory_variable_hash_set.h" + +struct test_struct { + char name[512]; +}; + +class FixedMemoryVariableHashTest : public Test::Suite { + typedef void(FixedMemoryVariableHashTest::*TestFunction)(void); +public: + FixedMemoryVariableHashTest() { + size_ = 1024 + 12 + 2008; + data_ = new uint8[size_]; + memset(data_, 0, size_); + TEST_ADD(FixedMemoryVariableHashTest::InitTest); + TEST_ADD(FixedMemoryVariableHashTest::LoadTest); + TEST_ADD(FixedMemoryVariableHashTest::InsertTest); + TEST_ADD(FixedMemoryVariableHashTest::RetrieveTest); + TEST_ADD(FixedMemoryVariableHashTest::InsertAgainTest); + TEST_ADD(FixedMemoryVariableHashTest::RetrieveAgainTest); + TEST_ADD(FixedMemoryVariableHashTest::InsertAgainFailTest); + TEST_ADD(FixedMemoryVariableHashTest::RetrieveAgainFailTest); + } + ~FixedMemoryVariableHashTest() { + delete[] data_; + } + + void InitTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_, 501); + TEST_ASSERT(!hash.exists(0)); + TEST_ASSERT(!hash.exists(501)); + } + + void LoadTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + TEST_ASSERT(!hash.exists(0)); + TEST_ASSERT(!hash.exists(501)); + } + + void InsertTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + test_struct test; + memset(&test, 0, sizeof(test)); + strcpy(test.name, "Bill D."); + + hash.insert(0, reinterpret_cast(&test), sizeof(test)); + TEST_ASSERT(hash.exists(0)); + TEST_ASSERT(!hash.exists(501)); + } + + void RetrieveTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + TEST_ASSERT(hash.exists(0)); + TEST_ASSERT(!hash.exists(501)); + + test_struct test = hash[0]; + TEST_ASSERT(strcmp(test.name, "Bill D.") == 0); + } + + void InsertAgainTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + test_struct test; + memset(&test, 0, sizeof(test)); + strcpy(test.name, "Jimmy P."); + + hash.insert(501, reinterpret_cast(&test), sizeof(test)); + TEST_ASSERT(hash.exists(0)); + TEST_ASSERT(hash.exists(501)); + } + + void RetrieveAgainTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + TEST_ASSERT(hash.exists(0)); + TEST_ASSERT(hash.exists(501)); + + test_struct test = hash[501]; + TEST_ASSERT(strcmp(test.name, "Jimmy P.") == 0); + } + + void InsertAgainFailTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + test_struct test; + memset(&test, 0, sizeof(test)); + strcpy(test.name, "Tommy M."); + + try { + hash.insert(500, reinterpret_cast(&test), sizeof(test)); + } catch(std::exception&) { } + + TEST_ASSERT(hash.exists(0)); + TEST_ASSERT(hash.exists(501)); + TEST_ASSERT(!hash.exists(500)); + } + + void RetrieveAgainFailTest() { + EQEmu::FixedMemoryVariableHashSet hash(data_, size_); + TEST_ASSERT(hash.exists(0)); + TEST_ASSERT(hash.exists(501)); + TEST_ASSERT(!hash.exists(500)); + + try { + test_struct test = hash[500]; + TEST_ASSERT(false); + } catch(std::exception&) { } + } +private: + uint8 *data_; + uint32 size_; +}; + +#endif diff --git a/tests/main.cpp b/tests/main.cpp index 2031dc61d..ff7dc8095 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -39,6 +39,7 @@ #include "memory_mapped_file_test.h" #include "ipc_mutex_test.h" #include "fixed_memory_test.h" +#include "fixed_memory_variable_test.h" int main() { try { @@ -48,6 +49,7 @@ int main() { tests.add(std::auto_ptr(new MemoryMappedFileTest())); tests.add(std::auto_ptr(new IPCMutexTest())); tests.add(std::auto_ptr(new FixedMemoryHashTest())); + tests.add(std::auto_ptr(new FixedMemoryVariableHashTest())); tests.run(*output, true); } catch(...) { return -1; diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index ae0839b61..7bd121dab 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -111,7 +111,6 @@ SET(zone_headers guild_mgr.h hate_list.h horse.h - loottable.h map.h masterentity.h maxskill.h diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index eb7af64ca..e63bc0367 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -7867,7 +7867,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) // Verify there are no NODROP or items with a zero price bool TradeItemsValid = true; - for(int i=0; iItems[i] == 0) break; @@ -7897,11 +7897,11 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) return; } - for (int i=0;iItems[i]>0 && gis->Items[i]Items[i])!=0) + for (uint32 i = 0; i < max_items; i++) { + if(database.GetItem(gis->Items[i])) { database.SaveTraderItem(this->CharacterID(),gis->Items[i],gis->SerialNumber[i], gis->Charges[i],ints->ItemCost[i],i); - else { + } else { //return; //sony doesnt memset so assume done on first bad item break; } diff --git a/zone/doors.cpp b/zone/doors.cpp index bfeb4f765..febf4c1cd 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -665,38 +665,6 @@ int32 ZoneDatabase::GetDoorsDBCountPlusOne(const char *zone_name, int16 version) return -1; } -/* -extern "C" bool extDBLoadDoors(int32 iDoorCount, uint32 iMaxDoorID) { return database.DBLoadDoors(iDoorCount, iMaxDoorID); } -const Door* ZoneDatabase::GetDoor(uint8 door_id, const char* zone_name) { - for(uint32 i=0; i!=max_door_type;i++) - { - const Door* door; - door = GetDoorDBID(i); - if (!door) - continue; - if(door->door_id == door_id && strcasecmp(door->zone_name, zone_name) == 0) - return door; - } -return 0; -} - -const Door* ZoneDatabase::GetDoorDBID(uint32 db_id) { - return EMuShareMemDLL.Doors.GetDoor(db_id); -} - -bool ZoneDatabase::LoadDoors() { - if (!EMuShareMemDLL.Load()) - return false; - int32 tmp = 0; - tmp = GetDoorsCount(&max_door_type); - if (tmp == -1) { - cout << "Error: ZoneDatabase::LoadDoors-ShareMem: GetDoorsCount() returned < 0" << endl; - return false; - } - bool ret = EMuShareMemDLL.Doors.DLLLoadDoors(&extDBLoadDoors, sizeof(Door), &tmp, &max_door_type); - return ret; -}*/ - bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version) { LogFile->write(EQEMuLog::Status, "Loading Doors from database..."); char errbuf[MYSQL_ERRMSG_SIZE]; diff --git a/zone/loottables.cpp b/zone/loottables.cpp index db321d27a..75e442afc 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -28,234 +28,6 @@ using namespace std; #define snprintf _snprintf #endif -#include "../common/EMuShareMem.h" -extern LoadEMuShareMemDLL EMuShareMemDLL; -bool SharedDatabase::extDBLoadLoot() { - return s_usedb->DBLoadLoot(); -} - -bool SharedDatabase::LoadLoot() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 tmpLootTableCount = 0; - uint32 tmpLootTableEntriesCount = 0; - uint32 tmpLootDropCount = 0; - uint32 tmpLootDropEntriesCount = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id), count(*) FROM loottable"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (row[0]) - loottable_max = atoi(row[0]); - else - loottable_max = 0; - tmpLootTableCount = atoi(row[1]); - } - else { - mysql_free_result(result); - return false; - } - mysql_free_result(result); - } - else { - cerr << "Error in LoadLoot query, loottable part: '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(*) FROM loottable_entries"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - tmpLootTableEntriesCount = atoi(row[0]); - } - else { - mysql_free_result(result); - return false; - } - mysql_free_result(result); - } - else { - cerr << "Error in LoadLoot query, loottable2 part: '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id), count(*) FROM lootdrop"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (row[0]) - lootdrop_max = atoi(row[0]); - else - lootdrop_max = 0; - tmpLootDropCount = atoi(row[1]); - } - else { - mysql_free_result(result); - return false; - } - mysql_free_result(result); - } - else { - cerr << "Error in LoadLoot query, lootdrop1 part: '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(lootdrop_id), count(*) FROM lootdrop_entries"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - tmpLootDropEntriesCount = atoi(row[1]); - } - else { - mysql_free_result(result); - return false; - } - mysql_free_result(result); - } - else { - cerr << "Error in LoadLoot query, lootdrop part: '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - return EMuShareMemDLL.Loot.DLLLoadLoot(&extDBLoadLoot, - sizeof(LootTable_Struct), tmpLootTableCount, loottable_max, - sizeof(LootTableEntries_Struct), tmpLootTableEntriesCount, - sizeof(LootDrop_Struct), tmpLootDropCount, lootdrop_max, - sizeof(LootDropEntries_Struct), tmpLootDropEntriesCount); -} - -bool SharedDatabase::DBLoadLoot() { - LogFile->write(EQEMuLog::Status, "Loading Loot tables from database..."); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - MYSQL_RES *result2; - uint32 i, tmpid = 0, tmpmincash = 0, tmpmaxcash = 0, tmpavgcoin = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, mincash, maxcash, avgcoin FROM loottable"), errbuf, &result)) { - safe_delete_array(query); - LootTable_Struct* tmpLT = 0; - while ((row = mysql_fetch_row(result))) { - tmpid = atoi(row[0]); - tmpmincash = atoi(row[1]); - tmpmaxcash = atoi(row[2]); - tmpavgcoin = atoi(row[3]); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT loottable_id, lootdrop_id, droplimit, mindrop, multiplier, probability FROM loottable_entries WHERE loottable_id=%i", tmpid), errbuf, &result2)) { - safe_delete_array(query); - tmpLT = (LootTable_Struct*) new uchar[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * mysql_num_rows(result2))]; - memset(tmpLT, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * mysql_num_rows(result2))); - tmpLT->NumEntries = mysql_num_rows(result2); - tmpLT->mincash = tmpmincash; - tmpLT->maxcash = tmpmaxcash; - tmpLT->avgcoin = tmpavgcoin; - i=0; - while ((row = mysql_fetch_row(result2))) { - if (i >= tmpLT->NumEntries) { - mysql_free_result(result); - mysql_free_result(result2); - safe_delete_array(tmpLT); - cerr << "Error in ZoneDatabase::DBLoadLoot, i >= NumEntries" << endl; - return false; - } - tmpLT->Entries[i].lootdrop_id = atoi(row[1]); - tmpLT->Entries[i].droplimit = atoi(row[2]); - tmpLT->Entries[i].mindrop = atoi(row[3]); - tmpLT->Entries[i].multiplier = atoi(row[4]); - tmpLT->Entries[i].probability = atof(row[5]); - i++; - } - if (!EMuShareMemDLL.Loot.cbAddLootTable(tmpid, tmpLT)) { - mysql_free_result(result); - mysql_free_result(result2); - safe_delete_array(tmpLT); - cout << "Error in ZoneDatabase::DBLoadLoot: !cbAddLootTable(" << tmpid << ")" << endl; - return false; - } - safe_delete_array(tmpLT); - mysql_free_result(result2); - } - else { - mysql_free_result(result); - cerr << "Error in LoadLoot (memshare) #1 query '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - } - mysql_free_result(result); - } - else { - cerr << "Error in LoadLoot (memshare) #2 query '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM lootdrop", tmpid), errbuf, &result)) { - safe_delete_array(query); - LootDrop_Struct* tmpLD = 0; - while ((row = mysql_fetch_row(result))) { - tmpid = atoi(row[0]); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT lootdrop_id, item_id, item_charges, equip_item, chance, minlevel, maxlevel, multiplier FROM lootdrop_entries WHERE lootdrop_id=%i order by chance desc", tmpid), errbuf, &result2)) { - safe_delete_array(query); - tmpLD = (LootDrop_Struct*) new uchar[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * mysql_num_rows(result2))]; - memset(tmpLD, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * mysql_num_rows(result2))); - tmpLD->NumEntries = mysql_num_rows(result2); - i=0; - while ((row = mysql_fetch_row(result2))) { - if (i >= tmpLD->NumEntries) { - mysql_free_result(result); - mysql_free_result(result2); - safe_delete_array(tmpLD); - cerr << "Error in ZoneDatabase::DBLoadLoot, i >= NumEntries" << endl; - return false; - } - tmpLD->Entries[i].item_id = atoi(row[1]); - tmpLD->Entries[i].item_charges = atoi(row[2]); - tmpLD->Entries[i].equip_item = atoi(row[3]); - tmpLD->Entries[i].chance = atof(row[4]); - tmpLD->Entries[i].minlevel = atoi(row[5]); - tmpLD->Entries[i].maxlevel = atoi(row[6]); - tmpLD->Entries[i].multiplier = atoi(row[7]); - i++; - } - if (!EMuShareMemDLL.Loot.cbAddLootDrop(tmpid, tmpLD)) { - mysql_free_result(result); - mysql_free_result(result2); - safe_delete_array(tmpLD); - cout << "Error in ZoneDatabase::DBLoadLoot: !cbAddLootDrop(" << tmpid << ")" << endl; - return false; - } - safe_delete_array(tmpLD); - mysql_free_result(result2); - } - else { - cerr << "Error in LoadLoot (memshare) #3 query '" << query << "' " << errbuf << endl; - mysql_free_result(result); - safe_delete_array(query); - return false; - } - } - mysql_free_result(result); - } - else { - cerr << "Error in LoadLoot (memshare) #4 query '" << query << "' " << errbuf << endl; - safe_delete_array(query); - return false; - } - - return true; -} - -const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { - return EMuShareMemDLL.Loot.GetLootTable(loottable_id); -} - -const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { - return EMuShareMemDLL.Loot.GetLootDrop(lootdrop_id); -} - // Queries the loottable: adds item & coin to the npc void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) { _ZP(Database_AddLootTableToNPC); diff --git a/zone/npc.h b/zone/npc.h index 30585d1fa..f2fa91116 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -28,7 +28,7 @@ class NPC; using namespace std; #include "spawn2.h" -#include "loottable.h" +#include "../common/loottable.h" #include "zonedump.h" #include "QGlobals.h" #include "../common/rulesys.h" diff --git a/zone/parser.cpp b/zone/parser.cpp index df109e9cc..d11f2e820 100644 --- a/zone/parser.cpp +++ b/zone/parser.cpp @@ -498,10 +498,6 @@ void Parser::Event(QuestEventID event, uint32 npcid, const char * data, NPC* npc Parser::Parser() : DEFAULT_QUEST_PREFIX("default") { MainList.clear(); - pMaxNPCID = database.GetMaxNPCType(); - /*pNPCqstID = new int32[pMaxNPCID+1]; - for (uint32 i=0; i ItemList; public: ZoneDatabase(); ZoneDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port); @@ -482,8 +484,8 @@ protected: uint32 max_faction; Faction** faction_array; - - uint32 npc_spells_maxid; + uint32 max_door_type; + uint32 npc_spells_maxid; DBnpcspells_Struct** npc_spells_cache; bool* npc_spells_loadtried; uint8 item_minstatus[MAX_ITEM_ID]; diff --git a/zone/zonedump.h b/zone/zonedump.h index a237143bd..5f36de14c 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -161,20 +161,6 @@ charname varchar(30) not null, zonename varchar(16)not null, x float not null, y heading float not null, data blob not null, time timestamp(14), index zonename (zonename)); */ -struct ServerLootItem_Struct { - uint32 item_id; - int16 equipSlot; - uint8 charges; - uint16 lootslot; - uint32 aug1; - uint32 aug2; - uint32 aug3; - uint32 aug4; - uint32 aug5; - uint8 minlevel; - uint8 maxlevel; -}; - namespace player_lootitem { struct ServerLootItem_Struct {