From 67143f1b8afbb0a0661d2b34bd46d43f5d71ddda Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 23 Jun 2015 17:39:06 -0700 Subject: [PATCH] Initial work on shared memory hotfixes --- common/item.cpp | 20 ++++- common/servertalk.h | 1 + common/shareddb.cpp | 137 ++++++++++++++-------------------- common/shareddb.h | 33 ++++---- shared_memory/base_data.cpp | 7 +- shared_memory/base_data.h | 3 +- shared_memory/items.cpp | 6 +- shared_memory/items.h | 4 +- shared_memory/loot.cpp | 9 ++- shared_memory/loot.h | 4 +- shared_memory/main.cpp | 67 ++++++++++------- shared_memory/npc_faction.cpp | 6 +- shared_memory/npc_faction.h | 4 +- shared_memory/skill_caps.cpp | 6 +- shared_memory/skill_caps.h | 4 +- shared_memory/spells.cpp | 8 +- shared_memory/spells.h | 4 +- world/net.cpp | 10 ++- world/zoneserver.cpp | 21 +++++- zone/command.cpp | 14 ++++ zone/command.h | 3 +- zone/net.cpp | 45 ++++------- zone/worldserver.cpp | 35 +++++++++ 23 files changed, 266 insertions(+), 185 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index 3e8be66ca..7c871e630 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1440,7 +1440,11 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) // ItemInst::ItemInst(const Item_Struct* item, int16 charges) { m_use_type = ItemInstNormal; - m_item = item; + if(item) { + m_item = new Item_Struct(*item); + } else { + m_item = nullptr; + } m_charges = charges; m_price = 0; m_attuned = false; @@ -1467,6 +1471,13 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) { ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_use_type = ItemInstNormal; m_item = db->GetItem(item_id); + if(m_item) { + m_item = new Item_Struct(*m_item); + } + else { + m_item = nullptr; + } + m_charges = charges; m_price = 0; m_merchantslot = 0; @@ -1515,7 +1526,11 @@ ItemInst::ItemInst(ItemInstTypes use_type) { ItemInst::ItemInst(const ItemInst& copy) { m_use_type=copy.m_use_type; - m_item=copy.m_item; + if(copy.m_item) + m_item = new Item_Struct(*copy.m_item); + else + m_item = nullptr; + m_charges=copy.m_charges; m_price=copy.m_price; m_color=copy.m_color; @@ -1568,6 +1583,7 @@ ItemInst::ItemInst(const ItemInst& copy) ItemInst::~ItemInst() { Clear(); + safe_delete(m_item); safe_delete(m_scaledItem); safe_delete(m_evolveInfo); } diff --git a/common/servertalk.h b/common/servertalk.h index af39bfaa4..586712110 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -84,6 +84,7 @@ #define ServerOP_QGlobalDelete 0x0064 #define ServerOP_DepopPlayerCorpse 0x0065 #define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues +#define ServerOP_ChangeSharedMem 0x0067 #define ServerOP_RaidAdd 0x0100 //in use #define ServerOP_RaidRemove 0x0101 //in use diff --git a/common/shareddb.cpp b/common/shareddb.cpp index aa4924665..40bb471d4 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -16,29 +16,16 @@ #include "string_util.h" SharedDatabase::SharedDatabase() -: Database(), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), faction_mmf(nullptr), faction_hash(nullptr), - loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), loot_drop_hash(nullptr), base_data_mmf(nullptr) +: Database() { } 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(nullptr), items_mmf(nullptr), items_hash(nullptr), - faction_mmf(nullptr), faction_hash(nullptr), loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), - loot_drop_hash(nullptr), base_data_mmf(nullptr) +: Database(host, user, passwd, database, port) { } SharedDatabase::~SharedDatabase() { - safe_delete(skill_caps_mmf); - safe_delete(items_mmf); - safe_delete(items_hash); - safe_delete(faction_mmf); - safe_delete(faction_hash); - safe_delete(loot_table_mmf); - safe_delete(loot_drop_mmf); - safe_delete(loot_table_hash); - safe_delete(loot_drop_hash); - safe_delete(base_data_mmf); } bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) @@ -797,28 +784,15 @@ void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) item_count = atoi(row[1]); } -bool SharedDatabase::LoadItems() { - if(items_mmf) { - return true; - } +bool SharedDatabase::LoadItems(const std::string &prefix) { + items_mmf.reset(nullptr); try { EQEmu::IPCMutex mutex("items"); mutex.Lock(); - items_mmf = new EQEmu::MemoryMappedFile("shared/items"); - - int32 items = -1; - uint32 max_item = 0; - GetItemsCount(items, max_item); - if(items == -1) { - EQ_EXCEPT("SharedDatabase", "Database returned no result"); - } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); - if(items_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size"); - } - - items_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), size); + std::string file_name = std::string("shared/") + prefix + std::string("items"); + items_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); + items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what()); @@ -1229,27 +1203,16 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co } -bool SharedDatabase::LoadNPCFactionLists() { - if(faction_hash) { - return true; - } +bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { + faction_mmf.reset(nullptr); + faction_hash.reset(nullptr); try { EQEmu::IPCMutex mutex("faction"); mutex.Lock(); - faction_mmf = new EQEmu::MemoryMappedFile("shared/faction"); - - uint32 list_count = 0; - uint32 max_lists = 0; - GetFactionListInfo(list_count, max_lists); - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size( - list_count, max_lists)); - - if(faction_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load npc factions because faction_mmf->Size() != size"); - } - - faction_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(faction_mmf->Get()), size); + std::string file_name = std::string("shared/") + prefix + std::string("faction"); + faction_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); + faction_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(faction_mmf->Get()), faction_mmf->Size())); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading npc factions: %s", ex.what()); @@ -1378,9 +1341,8 @@ bool SharedDatabase::GetCommandSettings(std::map &commands) { return true; } -bool SharedDatabase::LoadSkillCaps() { - if(skill_caps_mmf) - return true; +bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { + skill_caps_mmf.reset(nullptr); uint32 class_count = PLAYER_CLASS_COUNT; uint32 skill_count = HIGHEST_SKILL + 1; @@ -1390,11 +1352,8 @@ bool SharedDatabase::LoadSkillCaps() { try { EQEmu::IPCMutex mutex("skill_caps"); mutex.Lock(); - skill_caps_mmf = new EQEmu::MemoryMappedFile("shared/skill_caps"); - if(skill_caps_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Unable to load skill caps: skill_caps_mmf->Size() != size"); - } - + std::string file_name = std::string("shared/") + prefix + std::string("skill_caps"); + skill_caps_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); mutex.Unlock(); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "Error loading skill caps: %s", ex.what()); @@ -1542,8 +1501,29 @@ int SharedDatabase::GetMaxSpellID() { return atoi(row[0]); } +bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) { + spells_mmf.reset(nullptr); + + try { + EQEmu::IPCMutex mutex("spells"); + mutex.Lock(); + + std::string file_name = std::string("shared/") + prefix + std::string("spells"); + spells_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); + *records = *reinterpret_cast(spells_mmf->Get()); + *sp = reinterpret_cast((char*)spells_mmf->Get() + 4); + mutex.Unlock(); + } + catch(std::exception& ex) { + Log.Out(Logs::General, Logs::Error, "Error Loading Spells: %s", ex.what()); + return false; + } + return true; +} + void SharedDatabase::LoadSpells(void *data, int max_spells) { - SPDat_Spell_Struct *sp = reinterpret_cast(data); + *(uint32*)data = max_spells; + SPDat_Spell_Struct *sp = reinterpret_cast((char*)data + sizeof(uint32)); const std::string query = "SELECT * FROM spells_new ORDER BY id ASC"; auto results = QueryDatabase(query); @@ -1719,25 +1699,15 @@ int SharedDatabase::GetMaxBaseDataLevel() { return atoi(row[0]); } -bool SharedDatabase::LoadBaseData() { - if(base_data_mmf) { - return true; - } +bool SharedDatabase::LoadBaseData(const std::string &prefix) { + base_data_mmf.reset(nullptr); try { EQEmu::IPCMutex mutex("base_data"); mutex.Lock(); - base_data_mmf = new EQEmu::MemoryMappedFile("shared/base_data"); - - int size = 16 * (GetMaxBaseDataLevel() + 1) * sizeof(BaseDataStruct); - if(size == 0) { - EQ_EXCEPT("SharedDatabase", "Base Data size is zero"); - } - - if(base_data_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load base data because base_data_mmf->Size() != size"); - } + std::string file_name = std::string("shared/") + prefix + std::string("base_data"); + base_data_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Base Data: %s", ex.what()); @@ -1793,7 +1763,6 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) { bd->mana_factor = atof(row[8]); bd->endurance_factor = atof(row[9]); } - } const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { @@ -1967,21 +1936,23 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { } -bool SharedDatabase::LoadLoot() { - if(loot_table_mmf || loot_drop_mmf) - return true; +bool SharedDatabase::LoadLoot(const std::string &prefix) { + loot_table_mmf.reset(nullptr); + loot_drop_mmf.reset(nullptr); try { EQEmu::IPCMutex mutex("loot"); mutex.Lock(); - loot_table_mmf = new EQEmu::MemoryMappedFile("shared/loot_table"); - loot_table_hash = new EQEmu::FixedMemoryVariableHashSet( + std::string file_name_lt = std::string("shared/") + prefix + std::string("loot_table"); + loot_table_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name_lt)); + loot_table_hash = std::unique_ptr>(new EQEmu::FixedMemoryVariableHashSet( reinterpret_cast(loot_table_mmf->Get()), - loot_table_mmf->Size()); - loot_drop_mmf = new EQEmu::MemoryMappedFile("shared/loot_drop"); - loot_drop_hash = new EQEmu::FixedMemoryVariableHashSet( + loot_table_mmf->Size())); + std::string file_name_ld = std::string("shared/") + prefix + std::string("loot_drop"); + loot_drop_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name_ld)); + loot_drop_hash = std::unique_ptr>(new EQEmu::FixedMemoryVariableHashSet( reinterpret_cast(loot_drop_mmf->Get()), - loot_drop_mmf->Size()); + loot_drop_mmf->Size())); mutex.Unlock(); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "Error loading loot: %s", ex.what()); diff --git a/common/shareddb.h b/common/shareddb.h index aef325380..923e5b775 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -12,6 +12,7 @@ #include #include +#include class EvolveInfo; class Inventory; @@ -92,7 +93,7 @@ class SharedDatabase : public Database //items void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); - bool LoadItems(); + bool LoadItems(const std::string &prefix); const Item_Struct* IterateItems(uint32* id); const Item_Struct* GetItem(uint32 id); const EvolveInfo* GetEvolveInfo(uint32 loregroup); @@ -101,43 +102,45 @@ class SharedDatabase : public Database void GetFactionListInfo(uint32 &list_count, uint32 &max_lists); const NPCFactionList* GetNPCFactionEntry(uint32 id); void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists); - bool LoadNPCFactionLists(); + bool LoadNPCFactionLists(const std::string &prefix); //loot void GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries); void GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries); void LoadLootTables(void *data, uint32 size); void LoadLootDrops(void *data, uint32 size); - bool LoadLoot(); + bool LoadLoot(const std::string &prefix); const LootTable_Struct* GetLootTable(uint32 loottable_id); const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id); void LoadSkillCaps(void *data); - bool LoadSkillCaps(); + bool LoadSkillCaps(const std::string &prefix); uint16 GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level); uint8 GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level); int GetMaxSpellID(); + bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp); void LoadSpells(void *data, int max_spells); void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID); int GetMaxBaseDataLevel(); - bool LoadBaseData(); + bool LoadBaseData(const std::string &prefix); void LoadBaseData(void *data, int max_level); const BaseDataStruct* GetBaseData(int lvl, int cl); protected: - EQEmu::MemoryMappedFile *skill_caps_mmf; - EQEmu::MemoryMappedFile *items_mmf; - EQEmu::FixedMemoryHashSet *items_hash; - EQEmu::MemoryMappedFile *faction_mmf; - EQEmu::FixedMemoryHashSet *faction_hash; - EQEmu::MemoryMappedFile *loot_table_mmf; - EQEmu::FixedMemoryVariableHashSet *loot_table_hash; - EQEmu::MemoryMappedFile *loot_drop_mmf; - EQEmu::FixedMemoryVariableHashSet *loot_drop_hash; - EQEmu::MemoryMappedFile *base_data_mmf; + std::unique_ptr skill_caps_mmf; + std::unique_ptr items_mmf; + std::unique_ptr> items_hash; + std::unique_ptr faction_mmf; + std::unique_ptr> faction_hash; + std::unique_ptr loot_table_mmf; + std::unique_ptr> loot_table_hash; + std::unique_ptr loot_drop_mmf; + std::unique_ptr> loot_drop_hash; + std::unique_ptr base_data_mmf; + std::unique_ptr spells_mmf; }; #endif /*SHAREDDB_H_*/ diff --git a/shared_memory/base_data.cpp b/shared_memory/base_data.cpp index 086256cda..e82c5a2c1 100644 --- a/shared_memory/base_data.cpp +++ b/shared_memory/base_data.cpp @@ -23,7 +23,7 @@ #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -void LoadBaseData(SharedDatabase *database) { +void LoadBaseData(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("base_data"); mutex.Lock(); int records = (database->GetMaxBaseDataLevel() + 1); @@ -32,11 +32,12 @@ void LoadBaseData(SharedDatabase *database) { } uint32 size = records * 16 * sizeof(BaseDataStruct); - EQEmu::MemoryMappedFile mmf("shared/base_data", size); + + std::string file_name = std::string("shared/") + prefix + std::string("base_data"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); database->LoadBaseData(ptr, records); mutex.Unlock(); } - diff --git a/shared_memory/base_data.h b/shared_memory/base_data.h index c1f6c87ea..afa799eea 100644 --- a/shared_memory/base_data.h +++ b/shared_memory/base_data.h @@ -19,7 +19,8 @@ #ifndef __EQEMU_SHARED_MEMORY_BASE_DATA_H #define __EQEMU_SHARED_MEMORY_BASE_DATA_H +#include class SharedDatabase; -void LoadBaseData(SharedDatabase *database); +void LoadBaseData(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 48b81b6fc..02a102a8f 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -24,7 +24,7 @@ #include "../common/eqemu_exception.h" #include "../common/item_struct.h" -void LoadItems(SharedDatabase *database) { +void LoadItems(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("items"); mutex.Lock(); @@ -36,7 +36,9 @@ void LoadItems(SharedDatabase *database) { } uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); - EQEmu::MemoryMappedFile mmf("shared/items", size); + + std::string file_name = std::string("shared/") + prefix + std::string("items"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/items.h b/shared_memory/items.h index 21702eb50..cff9794fd 100644 --- a/shared_memory/items.h +++ b/shared_memory/items.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_ITEMS_H #define __EQEMU_SHARED_MEMORY_ITEMS_H +#include + class SharedDatabase; -void LoadItems(SharedDatabase *database); +void LoadItems(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/loot.cpp b/shared_memory/loot.cpp index 66982c05a..956383cd3 100644 --- a/shared_memory/loot.cpp +++ b/shared_memory/loot.cpp @@ -25,7 +25,7 @@ #include "../common/fixed_memory_variable_hash_set.h" #include "../common/loottable.h" -void LoadLoot(SharedDatabase *database) { +void LoadLoot(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("loot"); mutex.Lock(); @@ -44,8 +44,11 @@ void LoadLoot(SharedDatabase *database) { (loot_drop_count * sizeof(LootDrop_Struct)) + //loot table headers (loot_drop_entries_count * sizeof(LootDropEntries_Struct)); //number of loot table entries - EQEmu::MemoryMappedFile mmf_loot_table("shared/loot_table", loot_table_size); - EQEmu::MemoryMappedFile mmf_loot_drop("shared/loot_drop", loot_drop_size); + std::string file_name_lt = std::string("shared/") + prefix + std::string("loot_table"); + std::string file_name_ld = std::string("shared/") + prefix + std::string("loot_drop"); + + EQEmu::MemoryMappedFile mmf_loot_table(file_name_lt, loot_table_size); + EQEmu::MemoryMappedFile mmf_loot_drop(file_name_ld, loot_drop_size); mmf_loot_table.ZeroFile(); mmf_loot_drop.ZeroFile(); diff --git a/shared_memory/loot.h b/shared_memory/loot.h index df97ad321..27e812185 100644 --- a/shared_memory/loot.h +++ b/shared_memory/loot.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_LOOT_H #define __EQEMU_SHARED_MEMORY_LOOT_H +#include + class SharedDatabase; -void LoadLoot(SharedDatabase *database); +void LoadLoot(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 2623ccd26..3d47f217f 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -26,6 +26,7 @@ #include "../common/crash.h" #include "../common/rulesys.h" #include "../common/eqemu_exception.h" +#include "../common/string_util.h" #include "items.h" #include "npc_faction.h" #include "loot.h" @@ -61,6 +62,7 @@ int main(int argc, char **argv) { database.LoadLogSettings(Log.log_settings); Log.StartFileLogs(); + std::string hotfix_name = ""; bool load_all = true; bool load_items = false; bool load_factions = false; @@ -69,112 +71,125 @@ int main(int argc, char **argv) { bool load_spells = false; bool load_bd = false; if(argc > 1) { - load_all = false; - for(int i = 1; i < argc; ++i) { - switch(argv[i][0]) { - case 'a': - if(strcasecmp("all", argv[i]) == 0) { - load_all = true; - } - break; - + switch(argv[i][0]) { case 'b': if(strcasecmp("base_data", argv[i]) == 0) { load_bd = true; + load_all = false; } break; - + case 'i': if(strcasecmp("items", argv[i]) == 0) { load_items = true; + load_all = false; } break; - + case 'f': if(strcasecmp("factions", argv[i]) == 0) { load_factions = true; + load_all = false; } break; - + case 'l': if(strcasecmp("loot", argv[i]) == 0) { load_loot = true; + load_all = false; } break; - + case 's': if(strcasecmp("skill_caps", argv[i]) == 0) { load_skill_caps = true; + load_all = false; } else if(strcasecmp("spells", argv[i]) == 0) { load_spells = true; + load_all = false; } break; + case '-': { + auto split = SplitString(argv[i], '='); + if(split.size() >= 2) { + auto command = split[0]; + auto argument = split[1]; + if(strcasecmp("-hotfix", command.c_str()) == 0) { + hotfix_name = argument; + load_all = true; + } + } + break; + } } } } + if(hotfix_name.length() > 0) { + Log.Out(Logs::General, Logs::Status, "Writing data for hotfix '%s'", hotfix_name.c_str()); + } + if(load_all || load_items) { Log.Out(Logs::General, Logs::Status, "Loading items..."); try { - LoadItems(&database); + LoadItems(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_factions) { Log.Out(Logs::General, Logs::Status, "Loading factions..."); try { - LoadFactions(&database); + LoadFactions(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_loot) { Log.Out(Logs::General, Logs::Status, "Loading loot..."); try { - LoadLoot(&database); + LoadLoot(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_skill_caps) { Log.Out(Logs::General, Logs::Status, "Loading skill caps..."); try { - LoadSkillCaps(&database); + LoadSkillCaps(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_spells) { Log.Out(Logs::General, Logs::Status, "Loading spells..."); try { - LoadSpells(&database); + LoadSpells(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + if(load_all || load_bd) { Log.Out(Logs::General, Logs::Status, "Loading base data..."); try { - LoadBaseData(&database); + LoadBaseData(&database, hotfix_name); } catch(std::exception &ex) { Log.Out(Logs::General, Logs::Error, "%s", ex.what()); return 1; } } - + Log.CloseFileLogs(); - return 0; } diff --git a/shared_memory/npc_faction.cpp b/shared_memory/npc_faction.cpp index ebaeb3457..9ac8510bd 100644 --- a/shared_memory/npc_faction.cpp +++ b/shared_memory/npc_faction.cpp @@ -24,7 +24,7 @@ #include "../common/eqemu_exception.h" #include "../common/faction.h" -void LoadFactions(SharedDatabase *database) { +void LoadFactions(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("faction"); mutex.Lock(); @@ -33,7 +33,9 @@ void LoadFactions(SharedDatabase *database) { database->GetFactionListInfo(lists, max_list); uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(lists, max_list)); - EQEmu::MemoryMappedFile mmf("shared/faction", size); + + std::string file_name = std::string("shared/") + prefix + std::string("faction"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/npc_faction.h b/shared_memory/npc_faction.h index 52038dd9b..8fe5dbadb 100644 --- a/shared_memory/npc_faction.h +++ b/shared_memory/npc_faction.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_NPC_FACTION_H #define __EQEMU_SHARED_MEMORY_NPC_FACTION_H +#include + class SharedDatabase; -void LoadFactions(SharedDatabase *database); +void LoadFactions(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/skill_caps.cpp b/shared_memory/skill_caps.cpp index 94205ce72..153d06e13 100644 --- a/shared_memory/skill_caps.cpp +++ b/shared_memory/skill_caps.cpp @@ -25,7 +25,7 @@ #include "../common/classes.h" #include "../common/features.h" -void LoadSkillCaps(SharedDatabase *database) { +void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("skill_caps"); mutex.Lock(); @@ -33,7 +33,9 @@ void LoadSkillCaps(SharedDatabase *database) { uint32 skill_count = HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); - EQEmu::MemoryMappedFile mmf("shared/skill_caps", size); + + std::string file_name = std::string("shared/") + prefix + std::string("skill_caps"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/skill_caps.h b/shared_memory/skill_caps.h index e01dab4f4..90ae5733c 100644 --- a/shared_memory/skill_caps.h +++ b/shared_memory/skill_caps.h @@ -19,8 +19,10 @@ #ifndef __EQEMU_SHARED_MEMORY_SKILL_CAPS_H #define __EQEMU_SHARED_MEMORY_SKILL_CAPS_H +#include + class SharedDatabase; -void LoadSkillCaps(SharedDatabase *database); +void LoadSkillCaps(SharedDatabase *database, const std::string &prefix); #endif diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index 444f3b466..34cce35bc 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -24,7 +24,7 @@ #include "../common/eqemu_exception.h" #include "../common/spdat.h" -void LoadSpells(SharedDatabase *database) { +void LoadSpells(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("spells"); mutex.Lock(); int records = database->GetMaxSpellID() + 1; @@ -32,8 +32,10 @@ void LoadSpells(SharedDatabase *database) { EQ_EXCEPT("Shared Memory", "Unable to get any spells from the database."); } - uint32 size = records * sizeof(SPDat_Spell_Struct); - EQEmu::MemoryMappedFile mmf("shared/spells", size); + uint32 size = records * sizeof(SPDat_Spell_Struct) + sizeof(uint32); + + std::string file_name = std::string("shared/") + prefix + std::string("spells"); + EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); void *ptr = mmf.Get(); diff --git a/shared_memory/spells.h b/shared_memory/spells.h index 590ee0536..bde0f8233 100644 --- a/shared_memory/spells.h +++ b/shared_memory/spells.h @@ -19,7 +19,9 @@ #ifndef __EQEMU_SHARED_MEMORY_SPELLS_H #define __EQEMU_SHARED_MEMORY_SPELLS_H +#include + class SharedDatabase; -void LoadSpells(SharedDatabase *database); +void LoadSpells(SharedDatabase *database, const std::string &prefix); #endif diff --git a/world/net.cpp b/world/net.cpp index 434491a0a..135012f3c 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -294,6 +294,12 @@ int main(int argc, char** argv) { } Log.Out(Logs::General, Logs::World_Server, "Loading variables.."); database.LoadVariables(); + + char hotfix_name[256] = { 0 }; + if(database.GetVariable("hotfix_name", hotfix_name, 256)) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: %s", hotfix_name); + } + Log.Out(Logs::General, Logs::World_Server, "Loading zones.."); database.LoadZoneNames(); Log.Out(Logs::General, Logs::World_Server, "Clearing groups.."); @@ -303,10 +309,10 @@ int main(int argc, char** argv) { database.ClearRaidDetails(); database.ClearRaidLeader(); Log.Out(Logs::General, Logs::World_Server, "Loading items.."); - if (!database.LoadItems()) + if(!database.LoadItems(hotfix_name)) Log.Out(Logs::General, Logs::World_Server, "Error: Could not load item data. But ignoring"); Log.Out(Logs::General, Logs::World_Server, "Loading skill caps.."); - if (!database.LoadSkillCaps()) + if(!database.LoadSkillCaps(std::string(hotfix_name))) Log.Out(Logs::General, Logs::World_Server, "Error: Could not load skill cap data. But ignoring"); Log.Out(Logs::General, Logs::World_Server, "Loading guilds.."); guild_mgr.LoadGuilds(); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 17cac7f62..943f99bfb 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1286,10 +1286,6 @@ bool ZoneServer::Process() { case ServerOP_CZSignalNPC: case ServerOP_CZSetEntityVariableByNPCTypeID: case ServerOP_CZSignalClient: - { - zoneserver_list.SendPacket(pack); - break; - } case ServerOP_DepopAllPlayersCorpses: case ServerOP_DepopPlayerCorpse: case ServerOP_ReloadTitles: @@ -1301,6 +1297,23 @@ bool ZoneServer::Process() { zoneserver_list.SendPacket(pack); break; } + case ServerOP_ChangeSharedMem: { + std::string hotfix_name = std::string((char*)pack->pBuffer); + + Log.Out(Logs::General, Logs::World_Server, "Loading items..."); + if(!database.LoadItems(hotfix_name)) { + Log.Out(Logs::General, Logs::World_Server, "Error: Could not load item data. But ignoring"); + } + + Log.Out(Logs::General, Logs::World_Server, "Loading skill caps..."); + if(!database.LoadSkillCaps(hotfix_name)) { + Log.Out(Logs::General, Logs::World_Server, "Error: Could not load skill cap data. But ignoring"); + } + + zoneserver_list.SendPacket(pack); + break; + } + case ServerOP_RequestTellQueue: { ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer; diff --git a/zone/command.cpp b/zone/command.cpp index a286f92bd..6e1ca52e3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -361,6 +361,7 @@ int command_init(void) { command_add("setlsinfo", "[email] [password] - Set login server email address and password (if supported by login server)", 10, command_setlsinfo) || command_add("setpass", "[accountname] [password] - Set local password for accountname", 150, command_setpass) || command_add("setpvppoints", "[value] - Set your or your player target's PVP points", 100, command_setpvppoints) || + command_add("setsharedmem", "[hotfix_name] - Set your shared memory mapping to a specific hotfix", 250, command_set_shared_memory) || command_add("setskill", "[skillnum] [value] - Set your target's skill skillnum to value", 50, command_setskill) || command_add("setskillall", "[value] - Set all of your target's skills to value", 50, command_setskillall) || command_add("setstartzone", "[zoneid] - Set target's starting zone. Set to zero to allow the player to use /setstartcity", 80, command_setstartzone) || @@ -10655,3 +10656,16 @@ void command_mysqltest(Client *c, const Seperator *sep) } Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); } + +void command_set_shared_memory(Client *c, const Seperator *sep) { + std::string hotfix_name = sep->arg[1]; + c->Message(0, "Setting shared memory hotfix mapping to '%s'", hotfix_name.c_str()); + + database.SetVariable("hotfix_name", hotfix_name.c_str()); + + ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); + if(hotfix_name.length() > 0) { + strcpy((char*)pack.pBuffer, hotfix_name.c_str()); + } + worldserver.SendPacket(&pack); +} diff --git a/zone/command.h b/zone/command.h index 0560b8eff..6b9bb5fc9 100644 --- a/zone/command.h +++ b/zone/command.h @@ -325,7 +325,8 @@ void command_tune(Client *c, const Seperator *sep); void command_logtest(Client *c, const Seperator *sep); void command_mysqltest(Client *c, const Seperator *sep); void command_logs(Client *c, const Seperator *sep); - +void command_set_shared_memory(Client *c, const Seperator *sep); + #ifdef EQPROFILE void command_profiledump(Client *c, const Seperator *sep); void command_profilereset(Client *c, const Seperator *sep); diff --git a/zone/net.cpp b/zone/net.cpp index ef6b46836..658f0d308 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -107,7 +107,6 @@ QuestParserCollection *parse = 0; EQEmuLogSys Log; const SPDat_Spell_Struct* spells; -void LoadSpells(EQEmu::MemoryMappedFile **mmf); int32 SPDAT_RECORDS = -1; void Shutdown(); @@ -205,37 +204,44 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Zone_Server, "Loading Variables"); database.LoadVariables(); + char hotfix_name[256] = { 0 }; + if(database.GetVariable("hotfix_name", hotfix_name, 256)) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: %s", hotfix_name); + } + Log.Out(Logs::General, Logs::Zone_Server, "Loading zone names"); database.LoadZoneNames(); Log.Out(Logs::General, Logs::Zone_Server, "Loading items"); - if (!database.LoadItems()) { + if(!database.LoadItems(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading items FAILED!"); Log.Out(Logs::General, Logs::Error, "Failed. But ignoring error and going on..."); } Log.Out(Logs::General, Logs::Zone_Server, "Loading npc faction lists"); - if (!database.LoadNPCFactionLists()) { + if(!database.LoadNPCFactionLists(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading loot tables"); - if (!database.LoadLoot()) { + if(!database.LoadLoot(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading loot FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading skill caps"); - if (!database.LoadSkillCaps()) { + if(!database.LoadSkillCaps(std::string(hotfix_name))) { Log.Out(Logs::General, Logs::Error, "Loading skill caps FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading spells"); - EQEmu::MemoryMappedFile *mmf = nullptr; - LoadSpells(&mmf); + if(!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { + Log.Out(Logs::General, Logs::Error, "Loading spells FAILED!"); + return 1; + } Log.Out(Logs::General, Logs::Zone_Server, "Loading base data"); - if (!database.LoadBaseData()) { + if(!database.LoadBaseData(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading base data FAILED!"); return 1; } @@ -468,7 +474,6 @@ int main(int argc, char** argv) { safe_delete(lua_parser); #endif - safe_delete(mmf); safe_delete(Config); if (zone != 0) @@ -571,28 +576,6 @@ NetConnection::~NetConnection() { safe_delete_array(WorldAddress); } -void LoadSpells(EQEmu::MemoryMappedFile **mmf) { - int records = database.GetMaxSpellID() + 1; - - try { - EQEmu::IPCMutex mutex("spells"); - mutex.Lock(); - *mmf = new EQEmu::MemoryMappedFile("shared/spells"); - uint32 size = (*mmf)->Size(); - if(size != (records * sizeof(SPDat_Spell_Struct))) { - EQ_EXCEPT("Zone", "Unable to load spells: (*mmf)->Size() != records * sizeof(SPDat_Spell_Struct)"); - } - - spells = reinterpret_cast((*mmf)->Get()); - mutex.Unlock(); - } catch(std::exception &ex) { - Log.Out(Logs::General, Logs::Error, "Error loading spells: %s", ex.what()); - return; - } - - SPDAT_RECORDS = records; -} - /* Update Window Title with relevant information */ void UpdateWindowTitle(char* iNewTitle) { #ifdef _WINDOWS diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 517106aca..a1820366a 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1841,6 +1841,41 @@ void WorldServer::Process() { } break; } + + case ServerOP_ChangeSharedMem: + { + std::string hotfix_name = std::string((char*)pack->pBuffer); + Log.Out(Logs::General, Logs::Zone_Server, "Loading items"); + if(!database.LoadItems(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading items FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading npc faction lists"); + if(!database.LoadNPCFactionLists(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading loot tables"); + if(!database.LoadLoot(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading loot FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading skill caps"); + if(!database.LoadSkillCaps(std::string(hotfix_name))) { + Log.Out(Logs::General, Logs::Error, "Loading skill caps FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading spells"); + if(!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { + Log.Out(Logs::General, Logs::Error, "Loading spells FAILED!"); + } + + Log.Out(Logs::General, Logs::Zone_Server, "Loading base data"); + if(!database.LoadBaseData(hotfix_name)) { + Log.Out(Logs::General, Logs::Error, "Loading base data FAILED!"); + } + break; + } default: { std::cout << " Unknown ZSopcode:" << (int)pack->opcode; std::cout << " size:" << pack->size << std::endl;