[12662] Basic implementaion of hotfixes

original author of this patch is Shauren
commit is based on 67e61b7e64
This commit is contained in:
sanctum32 2013-08-06 09:05:19 +03:00 committed by Antz
parent ea6eef5a13
commit b4db2f63dd
15 changed files with 386 additions and 4 deletions

View file

@ -1425,7 +1425,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) DEFAULT NULL,
`creature_ai_version` varchar(120) DEFAULT NULL,
`cache_id` int(10) DEFAULT '0',
`required_m12652_command` bit(1) default NULL
`required_12662_01_mangos_hotfix_data` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
/*!40101 SET character_set_client = @saved_cs_client */;
@ -1435,7 +1435,7 @@ CREATE TABLE `db_version` (
LOCK TABLES `db_version` WRITE;
/*!40000 ALTER TABLE `db_version` DISABLE KEYS */;
INSERT INTO `db_version` (`version`, `creature_ai_version`, `cache_id`, `required_c12602_01_mangos_npc_spellclick_spells`) VALUES
INSERT INTO `db_version` (`version`, `creature_ai_version`, `cache_id`, `required_12662_01_mangos_hotfix_data`) VALUES
('Mangos default database.','Creature EventAI not provided.',0,NULL);
/*!40000 ALTER TABLE `db_version` ENABLE KEYS */;
UNLOCK TABLES;
@ -2140,6 +2140,61 @@ INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`,
/*!40000 ALTER TABLE `gossip_menu_option` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `hotfix_data`
--
DROP TABLE IF EXISTS `hotfix_data`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `hotfix_data` (
`entry` int(10) unsigned NOT NULL,
`type` int(10) unsigned NOT NULL DEFAULT '0',
`hotfixDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`entry`,`type`,`hotfixDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `hotfix_data`
--
LOCK TABLES `hotfix_data` WRITE;
/*!40000 ALTER TABLE `hotfix_data` DISABLE KEYS */;
INSERT INTO `hotfix_data` (`entry`, `type`, `hotfixDate`) VALUES
('6948', '1344507586', '2011-11-23 08:34:13'),
('44623', '1344507586', '2011-11-23 08:34:04'),
('44625', '1344507586', '2011-11-23 08:34:04'),
('44626', '1344507586', '2011-11-23 08:34:04'),
('44632', '1344507586', '2011-11-23 08:34:04'),
('44812', '1344507586', '2011-11-23 08:34:00'),
('44834', '1344507586', '2011-11-23 08:34:00'),
('44835', '1344507586', '2011-11-23 08:34:00'),
('44836', '1344507586', '2011-11-23 08:34:00'),
('44837', '1344507586', '2011-11-23 08:34:00'),
('44838', '1344507586', '2011-11-23 08:34:00'),
('44839', '1344507586', '2011-11-23 08:34:00'),
('44840', '1344507586', '2011-11-23 08:34:00'),
('44844', '1344507586', '2011-11-23 08:34:00'),
('44853', '1344507586', '2011-11-23 08:34:00'),
('44854', '1344507586', '2011-11-23 08:34:00'),
('44855', '1344507586', '2011-11-23 08:34:00'),
('44856', '1344507586', '2011-11-23 08:34:00'),
('46784', '1344507586', '2011-11-23 08:34:00'),
('46793', '1344507586', '2011-11-23 08:34:00'),
('46796', '1344507586', '2011-11-23 08:34:00'),
('46797', '1344507586', '2011-11-23 08:34:00'),
('46887', '1344507586', '2011-11-23 08:34:00'),
('46888', '1344507586', '2011-11-23 08:34:00'),
('64488', '1344507586', '2011-11-23 08:34:13'),
('69847', '1344507586', '2011-11-23 08:34:03'),
('69847', '1344507586', '2011-11-23 08:34:06'),
('72068', '1344507586', '2011-11-23 08:34:03'),
('72068', '1344507586', '2011-11-23 08:34:06');
/*!40000 ALTER TABLE `hotfix_data` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `instance_encounters`
--

View file

@ -0,0 +1,38 @@
ALTER TABLE db_version CHANGE COLUMN required_m12654_command required_12662_01_mangos_hotfix_data bit;
CREATE TABLE `hotfix_data` (
`entry` int(10) unsigned NOT NULL,
`type` int(10) unsigned NOT NULL DEFAULT '0',
`hotfixDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`entry`,`type`,`hotfixDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `hotfix_data` VALUES ('6948', '1344507586', '2011-11-23 08:34:13');
INSERT INTO `hotfix_data` VALUES ('44623', '1344507586', '2011-11-23 08:34:04');
INSERT INTO `hotfix_data` VALUES ('44625', '1344507586', '2011-11-23 08:34:04');
INSERT INTO `hotfix_data` VALUES ('44626', '1344507586', '2011-11-23 08:34:04');
INSERT INTO `hotfix_data` VALUES ('44632', '1344507586', '2011-11-23 08:34:04');
INSERT INTO `hotfix_data` VALUES ('44812', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44834', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44835', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44836', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44837', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44838', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44839', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44840', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44844', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44853', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44854', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44855', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('44856', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('46784', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('46793', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('46796', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('46797', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('46887', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('46888', '1344507586', '2011-11-23 08:34:00');
INSERT INTO `hotfix_data` VALUES ('64488', '1344507586', '2011-11-23 08:34:13');
INSERT INTO `hotfix_data` VALUES ('69847', '1344507586', '2011-11-23 08:34:03');
INSERT INTO `hotfix_data` VALUES ('69847', '1344507586', '2011-11-23 08:34:06');
INSERT INTO `hotfix_data` VALUES ('72068', '1344507586', '2011-11-23 08:34:03');
INSERT INTO `hotfix_data` VALUES ('72068', '1344507586', '2011-11-23 08:34:06');

View file

@ -551,6 +551,7 @@ ChatCommand* ChatHandler::getCommandTable()
{ "gameobject_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
{ "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
{ "hotfix_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadHotfixDataCommand, "", NULL },
{ "item_convert", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemConvertCommand, "", NULL },
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },

View file

@ -427,6 +427,7 @@ class MANGOS_DLL_SPEC ChatHandler
bool HandleReloadGossipMenuCommand(char* args);
bool HandleReloadGOQuestRelationsCommand(char* args);
bool HandleReloadGOQuestInvRelationsCommand(char* args);
bool HandleReloadHotfixDataCommand(char* args);
bool HandleReloadItemConvertCommand(char* args);
bool HandleReloadItemEnchantementsCommand(char* args);
bool HandleReloadItemRequiredTragetCommand(char* args);

View file

@ -1315,3 +1315,171 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recv_data)
}
SendPacket(&data);
}
void WorldSession::SendItemDb2Reply(uint32 entry)
{
WorldPacket data(SMSG_DB_REPLY, 44);
ItemPrototype const* proto = sObjectMgr.GetItemPrototype(entry);
if (!proto)
{
data << uint32(-1); // entry
data << uint32(DB2_REPLY_ITEM);
data << uint32(time(NULL)); // hotfix date
data << uint32(0); // size of next block
SendPacket(&data);
return;
}
data << uint32(entry);
data << uint32(DB2_REPLY_ITEM);
data << uint32(sObjectMgr.GetHotfixDate(entry, DB2_REPLY_ITEM));
ByteBuffer buff;
buff << uint32(entry);
buff << uint32(proto->Class);
buff << uint32(proto->SubClass);
buff << int32(proto->Unk0);
buff << uint32(proto->Material);
buff << uint32(proto->DisplayInfoID);
buff << uint32(proto->InventoryType);
buff << uint32(proto->Sheath);
data << uint32(buff.size());
data.append(buff);
SendPacket(&data);
}
void WorldSession::SendItemSparseDb2Reply(uint32 entry)
{
WorldPacket data(SMSG_DB_REPLY, 526);
ItemPrototype const* proto = sObjectMgr.GetItemPrototype(entry);
if (!proto)
{
data << uint32(-1); // entry
data << uint32(DB2_REPLY_SPARSE);
data << uint32(time(NULL)); // hotfix date
data << uint32(0); // size of next block
SendPacket(&data);
return;
}
data << uint32(entry);
data << uint32(DB2_REPLY_SPARSE);
data << uint32(sObjectMgr.GetHotfixDate(entry, DB2_REPLY_SPARSE));
ByteBuffer buff;
buff << uint32(entry);
buff << uint32(proto->Quality);
buff << uint32(proto->Flags);
buff << uint32(proto->Flags2);
buff << float(proto->Unknown);
buff << float(proto->Unknown1);
buff << uint32(proto->BuyCount);
buff << int32(proto->BuyPrice);
buff << uint32(proto->SellPrice);
buff << uint32(proto->InventoryType);
buff << int32(proto->AllowableClass);
buff << int32(proto->AllowableRace);
buff << uint32(proto->ItemLevel);
buff << uint32(proto->RequiredLevel);
buff << uint32(proto->RequiredSkill);
buff << uint32(proto->RequiredSkillRank);
buff << uint32(proto->RequiredSpell);
buff << uint32(proto->RequiredHonorRank);
buff << uint32(proto->RequiredCityRank);
buff << uint32(proto->RequiredReputationFaction);
buff << uint32(proto->RequiredReputationRank);
buff << int32(proto->MaxCount);
buff << int32(proto->Stackable);
buff << uint32(proto->ContainerSlots);
for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
buff << uint32(proto->ItemStat[x].ItemStatType);
for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
buff << int32(proto->ItemStat[x].ItemStatValue);
for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
buff << int32(proto->ItemStat[x].ItemStatType2);
for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
buff << int32(proto->ItemStat[x].ItemStatValue2);
buff << uint32(proto->ScalingStatDistribution);
buff << uint32(proto->DamageType);
buff << uint32(proto->Delay);
buff << float(proto->RangedModRange);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
buff << int32(proto->Spells[x].SpellId);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
buff << uint32(proto->Spells[x].SpellTrigger);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
buff << int32(proto->Spells[x].SpellCharges);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
buff << int32(proto->Spells[x].SpellCooldown);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
buff << uint32(proto->Spells[x].SpellCategory);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
buff << int32(proto->Spells[x].SpellCategoryCooldown);
buff << uint32(proto->Bonding);
// item name
std::string name = proto->Name1;
buff << uint16(name.length());
if (name.length())
buff << name;
for (uint32 i = 0; i < 3; ++i) // other 3 names
buff << uint16(0);
std::string desc = proto->Description;
buff << uint16(desc.length());
if (desc.length())
buff << desc;
buff << uint32(proto->PageText);
buff << uint32(proto->LanguageID);
buff << uint32(proto->PageMaterial);
buff << uint32(proto->StartQuest);
buff << uint32(proto->LockID);
buff << int32(proto->Material);
buff << uint32(proto->Sheath);
buff << int32(proto->RandomProperty);
buff << int32(proto->RandomSuffix);
buff << uint32(proto->ItemSet);
buff << uint32(proto->Area);
buff << uint32(proto->Map);
buff << uint32(proto->BagFamily);
buff << uint32(proto->TotemCategory);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
buff << uint32(proto->Socket[x].Color);
for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
buff << uint32(proto->Socket[x].Content);
buff << uint32(proto->socketBonus);
buff << uint32(proto->GemProperties);
buff << float(proto->ArmorDamageModifier);
buff << int32(proto->Duration);
buff << uint32(proto->ItemLimitCategory);
buff << uint32(proto->HolidayId);
buff << float(proto->StatScalingFactor);
buff << uint32(proto->Unknown400_1);
buff << uint32(proto->Unknown400_2);
data << uint32(buff.size());
data.append(buff);
SendPacket(&data);
}

View file

@ -448,6 +448,14 @@ bool ChatHandler::HandleReloadConditionsCommand(char* /*args*/)
return true;
}
bool ChatHandler::HandleReloadHotfixDataCommand(char* /*args*/)
{
sLog.outString("Re-Loading hotfix data...");
sObjectMgr.LoadHotfixData();
SendGlobalSysMessage("DB table `hotfix_data` reloaded.");
return true;
}
bool ChatHandler::HandleReloadGossipMenuCommand(char* /*args*/)
{
sObjectMgr.LoadGossipMenus();

View file

@ -1525,3 +1525,39 @@ void WorldSession::HandleHearthandResurrect(WorldPacket& /*recv_data*/)
_player->ResurrectPlayer(100);
_player->TeleportToHomebind();
}
void WorldSession::HandleRequestHotfix(WorldPacket& recv_data)
{
uint32 type, count;
recv_data >> type;
count = recv_data.ReadBits(23);
std::vector<ObjectGuid> guids;
guids.reserve(count);
for (uint32 i = 0; i < count; ++i)
recv_data.ReadGuidMask<0, 4, 7, 2, 5, 3, 6, 1>(guids[i]);
uint32 entry;
for (uint32 i = 0; i < count; ++i)
{
recv_data.ReadGuidBytes<5, 6, 7, 0, 1, 3, 4>(guids[i]);
recv_data >> entry;
recv_data.ReadGuidBytes<2>(guids[i]);
switch (type)
{
case DB2_REPLY_ITEM:
SendItemDb2Reply(entry);
break;
case DB2_REPLY_SPARSE:
SendItemSparseDb2Reply(entry);
break;
default:
sLog.outError("CMSG_REQUEST_HOTFIX: Received unknown hotfix type: %u", type);
recv_data.rfinish();
break;
}
}
}

View file

@ -9961,3 +9961,38 @@ GameObjectDataPair const* FindGOData::GetResult() const
return i_anyData;
}
void ObjectMgr::LoadHotfixData()
{
uint32 count = 0;
m_hotfixData.clear();
QueryResult* result = WorldDatabase.Query("SELECT entry, type, UNIX_TIMESTAMP(hotfixDate) FROM hotfix_data");
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString(">> Loaded %u hotfix info entries. DB table `hotfix_data` is empty.", count);
return;
}
do
{
Field* fields = result->Fetch();
HotfixInfo info;
info.Entry = fields[0].GetUInt32();
info.Type = fields[1].GetUInt32();
info.Timestamp = fields[2].GetUInt32();
m_hotfixData.push_back(info);
++count;
}
while (result->NextRow());
delete result;
sLog.outString();
sLog.outString(">> Loaded %u hotfix info entries.", count);
}

View file

@ -467,6 +467,15 @@ enum SkillRangeType
SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial);
struct HotfixInfo
{
uint32 Type;
uint32 Timestamp;
uint32 Entry;
};
typedef std::vector<HotfixInfo> HotfixData;
#define MAX_PLAYER_NAME 12 // max allowed by client name length
#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length ( > MAX_PLAYER_NAME for support declined names )
#define MAX_PET_NAME 12 // max allowed by client name length
@ -1116,6 +1125,20 @@ class ObjectMgr
QuestRelationsMap& GetCreatureQuestRelationsMap() { return m_CreatureQuestRelations; }
uint32 GetModelForRace(uint32 sourceModelId, uint32 racemask);
void LoadHotfixData();
HotfixData const& GetHotfixData() const { return m_hotfixData; }
uint32 GetHotfixDate(uint32 entry, uint32 type) const
{
uint32 ret = 0;
for (HotfixData::const_iterator itr = m_hotfixData.begin(); itr != m_hotfixData.end(); ++itr)
if (itr->Entry == entry && itr->Type == type)
if (itr->Timestamp > ret)
ret = itr->Timestamp;
return ret ? ret : uint32(time(NULL));
}
protected:
// first free id for selected id type
@ -1252,6 +1275,8 @@ class ObjectMgr
CacheVendorItemMap m_mCacheVendorItemMap;
CacheTrainerSpellMap m_mCacheTrainerTemplateSpellMap;
CacheTrainerSpellMap m_mCacheTrainerSpellMap;
HotfixData m_hotfixData;
};
#define sObjectMgr MaNGOS::Singleton<ObjectMgr>::Instance()

View file

@ -1405,4 +1405,6 @@ void InitializeOpcodes()
OPCODE(SMSG_PVP_REWARDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(CMSG_REQUEST_PVP_OPTIONS_ENABLED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPvPOptionsEnabledOpcode );
OPCODE(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(CMSG_REQUEST_HOTFIX, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleRequestHotfix );
OPCODE(SMSG_DB_REPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
};

View file

@ -1423,6 +1423,8 @@ enum Opcodes
SMSG_PVP_REWARDS = 0x5DA4, // 4.3.4 15595
CMSG_REQUEST_PVP_OPTIONS_ENABLED = 0x24A1, // 4.3.4 15595
SMSG_PVP_OPTIONS_ENABLED = 0x50A1, // 4.3.4 15595
CMSG_REQUEST_HOTFIX = 0x2401, // 4.3.4 15595
SMSG_DB_REPLY = 0x38A4, // 4.3.4 15595
};
#define MAX_OPCODE_TABLE_SIZE 0xFFFF

View file

@ -1331,6 +1331,9 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading GM tickets...");
sTicketMgr.LoadGMTickets();
sLog.outString("Loading hotfix data...");
sObjectMgr.LoadHotfixData();
///- Handle outdated emails (delete/return)
sLog.outString("Returning old mails...");
sObjectMgr.ReturnOrDeleteOldMails(false);

View file

@ -67,6 +67,9 @@ enum AccountDataType
#define GLOBAL_CACHE_MASK 0x15
#define PER_CHARACTER_CACHE_MASK 0xEA
#define DB2_REPLY_ITEM 1344507586
#define DB2_REPLY_SPARSE 2442913102
struct AccountData
{
AccountData() : Time(0), Data("") {}
@ -863,6 +866,11 @@ class MANGOS_DLL_SPEC WorldSession
void HandleCalendarComplain(WorldPacket& recv_data);
void HandleCalendarGetNumPending(WorldPacket& recv_data);
// Hotfix handlers
void HandleRequestHotfix(WorldPacket& recv_data);
void SendItemDb2Reply(uint32 entry);
void SendItemSparseDb2Reply(uint32 entry);
void HandleSpellClick(WorldPacket& recv_data);
void HandleGetMirrorimageData(WorldPacket& recv_data);
void HandleAlterAppearanceOpcode(WorldPacket& recv_data);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "12661"
#define REVISION_NR "12662"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_c12631_01_characters_corpse"
#define REVISION_DB_MANGOS "required_m12654_command"
#define REVISION_DB_MANGOS "required_12662_01_mangos_hotfix_data"
#define REVISION_DB_REALMD "required_c12484_02_realmd_account_access"
#endif // __REVISION_SQL_H__