Core: Improve constant channel handling
- Implement area restrictions - Disable constant channels in arenas - Implement city requirement - Implement global constant channels - Fix some packets --HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
DELETE FROM `trinity_string` WHERE `entry` = 819;
|
||||
INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES (819, "City");
|
||||
@@ -26,10 +26,8 @@ Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team)
|
||||
: m_announce(true), m_moderate(false), m_name(name), m_password(""), m_flags(0), m_channelId(channel_id), m_ownerGUID(0), m_Team(Team)
|
||||
{
|
||||
// set special flags if built-in channel
|
||||
ChatChannelsEntry const* ch = GetChannelEntryFor(channel_id);
|
||||
if (ch) // it's built-in channel
|
||||
if (ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(channel_id)) // check whether it's a built-in channel
|
||||
{
|
||||
channel_id = ch->ChannelID; // built-in channel
|
||||
m_announce = false; // no join/leave announces
|
||||
|
||||
m_flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels
|
||||
@@ -48,6 +46,7 @@ Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team)
|
||||
}
|
||||
else // it's custom channel
|
||||
{
|
||||
channel_id = 0;
|
||||
m_flags |= CHANNEL_FLAG_CUSTOM;
|
||||
//load not built in channel if saved
|
||||
std::string _name(name);
|
||||
@@ -852,7 +851,7 @@ void Channel::MakeYouLeft(WorldPacket *data)
|
||||
{
|
||||
MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE);
|
||||
*data << uint32(GetChannelId());
|
||||
*data << uint8(0); // can be 0x00 and 0x01
|
||||
*data << uint8(IsConstant());
|
||||
}
|
||||
|
||||
// done 0x04
|
||||
@@ -1090,7 +1089,11 @@ void Channel::JoinNotify(uint64 guid)
|
||||
data << uint8(GetFlags());
|
||||
data << uint32(GetNumPlayers());
|
||||
data << GetName();
|
||||
SendToAll(&data);
|
||||
|
||||
if (IsConstant())
|
||||
SendToAllButOne(&data, guid);
|
||||
else
|
||||
SendToAll(&data);
|
||||
}
|
||||
|
||||
void Channel::LeaveNotify(uint64 guid)
|
||||
@@ -1100,6 +1103,10 @@ void Channel::LeaveNotify(uint64 guid)
|
||||
data << uint8(GetFlags());
|
||||
data << uint32(GetNumPlayers());
|
||||
data << GetName();
|
||||
SendToAll(&data);
|
||||
|
||||
if (IsConstant())
|
||||
SendToAllButOne(&data, guid);
|
||||
else
|
||||
SendToAll(&data);
|
||||
}
|
||||
|
||||
|
||||
@@ -729,18 +729,6 @@ ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
|
||||
}
|
||||
}
|
||||
|
||||
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id)
|
||||
{
|
||||
// not sorted, numbering index from 0
|
||||
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
|
||||
{
|
||||
ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i);
|
||||
if (ch && ch->ChannelID == channel_id)
|
||||
return ch;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
|
||||
{
|
||||
if (requiredTotemCategoryId == 0)
|
||||
|
||||
@@ -49,8 +49,6 @@ enum ContentLevels
|
||||
};
|
||||
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
|
||||
|
||||
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id);
|
||||
|
||||
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
|
||||
|
||||
void Zone2MapCoordinates(float &x, float &y, uint32 zone);
|
||||
@@ -75,7 +73,7 @@ extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore;
|
||||
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
|
||||
extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore;
|
||||
extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
|
||||
//extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; -- accessed using function, no usable index
|
||||
extern DBCStorage <ChatChannelsEntry> sChatChannelsStore;
|
||||
extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
|
||||
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
|
||||
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
|
||||
|
||||
@@ -31,7 +31,7 @@ const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
|
||||
const char BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx";
|
||||
const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
|
||||
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
|
||||
const char ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
|
||||
// ChatChannelsEntryfmt, index not used (more compact store)
|
||||
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
|
||||
const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
|
||||
|
||||
@@ -5184,6 +5184,20 @@ void Player::RepopAtGraveyard()
|
||||
TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
|
||||
}
|
||||
|
||||
bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone)
|
||||
{
|
||||
if (channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP)
|
||||
{
|
||||
if (zone->flags & AREA_FLAG_ARENA_INSTANCE)
|
||||
return false;
|
||||
|
||||
if ((channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) && !(zone->flags & AREA_FLAG_CAPITAL))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::JoinedChannel(Channel *c)
|
||||
{
|
||||
m_channels.push_back(c);
|
||||
@@ -5210,8 +5224,8 @@ void Player::CleanupChannels()
|
||||
|
||||
void Player::UpdateLocalChannels(uint32 newZone)
|
||||
{
|
||||
if (m_channels.empty())
|
||||
return;
|
||||
if (GetSession()->PlayerLoading() && !IsBeingTeleportedFar())
|
||||
return; // The client handles it automatically after loading, but not after teleporting
|
||||
|
||||
AreaTableEntry const* current_zone = GetAreaEntryByAreaID(newZone);
|
||||
if (!current_zone)
|
||||
@@ -5223,38 +5237,78 @@ void Player::UpdateLocalChannels(uint32 newZone)
|
||||
|
||||
std::string current_zone_name = current_zone->area_name[GetSession()->GetSessionDbcLocale()];
|
||||
|
||||
for (JoinedChannelsList::iterator i = m_channels.begin(), next; i != m_channels.end(); i = next)
|
||||
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
|
||||
{
|
||||
next = i; ++next;
|
||||
|
||||
// skip non built-in channels
|
||||
if (!(*i)->IsConstant())
|
||||
continue;
|
||||
|
||||
ChatChannelsEntry const* ch = GetChannelEntryFor((*i)->GetChannelId());
|
||||
if (!ch)
|
||||
continue;
|
||||
|
||||
if ((ch->flags & 4) == 4) // global channel without zone name in pattern
|
||||
continue;
|
||||
|
||||
// new channel
|
||||
char new_channel_name_buf[100];
|
||||
snprintf(new_channel_name_buf,100,ch->pattern[m_session->GetSessionDbcLocale()],current_zone_name.c_str());
|
||||
Channel* new_channel = cMgr->GetJoinChannel(new_channel_name_buf,ch->ChannelID);
|
||||
|
||||
if ((*i) != new_channel)
|
||||
if (ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i))
|
||||
{
|
||||
new_channel->Join(GetGUID(),""); // will output Changed Channel: N. Name
|
||||
if (!(channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP))
|
||||
continue; // Not zone dependent, don't handle it here
|
||||
|
||||
// leave old channel
|
||||
(*i)->Leave(GetGUID(),false); // not send leave channel, it already replaced at client
|
||||
std::string name = (*i)->GetName(); // store name, (*i)erase in LeftChannel
|
||||
LeftChannel(*i); // remove from player's channel list
|
||||
cMgr->LeftChannel(name); // delete if empty
|
||||
if ((channel->flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId())
|
||||
continue; // Should not join to these channels automatically
|
||||
|
||||
Channel* usedChannel = NULL;
|
||||
|
||||
for (JoinedChannelsList::iterator itr = m_channels.begin(); itr != m_channels.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->GetChannelId() == i)
|
||||
{
|
||||
usedChannel = *itr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Channel* removeChannel = NULL;
|
||||
Channel* joinChannel = NULL;
|
||||
bool sendRemove = true;
|
||||
|
||||
if (CanJoinConstantChannelInZone(channel, current_zone))
|
||||
{
|
||||
if (!(channel->flags & CHANNEL_DBC_FLAG_GLOBAL))
|
||||
{
|
||||
if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY && usedChannel)
|
||||
continue; // Already on the channel, as city channel names are not changing
|
||||
|
||||
char new_channel_name_buf[100];
|
||||
char const* currentNameExt;
|
||||
|
||||
if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY)
|
||||
currentNameExt = sObjectMgr.GetTrinityStringForDBCLocale(LANG_CHANNEL_CITY);
|
||||
else
|
||||
currentNameExt = current_zone_name.c_str();
|
||||
|
||||
snprintf(new_channel_name_buf, 100, channel->pattern[m_session->GetSessionDbcLocale()], currentNameExt);
|
||||
|
||||
joinChannel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID);
|
||||
if (usedChannel)
|
||||
{
|
||||
if (joinChannel != usedChannel)
|
||||
{
|
||||
removeChannel = usedChannel;
|
||||
sendRemove = false; // Do not send leave channel, it already replaced at client
|
||||
}
|
||||
else
|
||||
joinChannel = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
joinChannel = cMgr->GetJoinChannel(channel->pattern[m_session->GetSessionDbcLocale()], channel->ChannelID);
|
||||
}
|
||||
else
|
||||
removeChannel = usedChannel;
|
||||
|
||||
if (joinChannel)
|
||||
joinChannel->Join(GetGUID(), ""); // Changed Channel: ... or Joined Channel: ...
|
||||
|
||||
if (removeChannel)
|
||||
{
|
||||
removeChannel->Leave(GetGUID(), sendRemove); // Leave old channel
|
||||
std::string name = removeChannel->GetName(); // Store name, (*i)erase in LeftChannel
|
||||
LeftChannel(removeChannel); // Remove from player's channel list
|
||||
cMgr->LeftChannel(name); // Delete if empty
|
||||
}
|
||||
}
|
||||
}
|
||||
sLog.outDebug("Player: channels cleaned up!");
|
||||
}
|
||||
|
||||
void Player::LeaveLFGChannel()
|
||||
|
||||
@@ -1878,6 +1878,8 @@ class Player : public Unit, public GridObject<Player>
|
||||
|
||||
void SetMovement(PlayerMovementType pType);
|
||||
|
||||
bool CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone);
|
||||
|
||||
void JoinedChannel(Channel *c);
|
||||
void LeftChannel(Channel *c);
|
||||
void CleanupChannels();
|
||||
|
||||
@@ -728,7 +728,9 @@ enum TrinityStrings
|
||||
|
||||
LANG_COMMAND_CREATURETEMPLATE_NOTFOUND = 817,
|
||||
LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818,
|
||||
// Room for in-game strings 819-999 not used
|
||||
|
||||
LANG_CHANNEL_CITY = 819,
|
||||
// Room for in-game strings 820-999 not used
|
||||
|
||||
// Level 4 (CLI only commands)
|
||||
LANG_COMMAND_EXIT = 1000,
|
||||
|
||||
@@ -27,7 +27,23 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
|
||||
uint8 unknown1, unknown2;
|
||||
std::string channelname, pass;
|
||||
|
||||
recvPacket >> channel_id >> unknown1 >> unknown2;
|
||||
recvPacket >> channel_id;
|
||||
|
||||
if (channel_id)
|
||||
{
|
||||
ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channel_id);
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
AreaTableEntry const* current_zone = GetAreaEntryByAreaID(_player->GetZoneId());
|
||||
if (!current_zone)
|
||||
return;
|
||||
|
||||
if (!_player->CanJoinConstantChannelInZone(channel, current_zone))
|
||||
return;
|
||||
}
|
||||
|
||||
recvPacket >> unknown1 >> unknown2;
|
||||
recvPacket >> channelname;
|
||||
|
||||
if (channelname.empty())
|
||||
|
||||
Reference in New Issue
Block a user