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:
linencloth
2010-10-16 12:59:53 +02:00
parent 3bd1ee0665
commit ae213dd580
9 changed files with 122 additions and 53 deletions
@@ -0,0 +1,2 @@
DELETE FROM `trinity_string` WHERE `entry` = 819;
INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES (819, "City");
+13 -6
View File
@@ -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) : 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 // set special flags if built-in channel
ChatChannelsEntry const* ch = GetChannelEntryFor(channel_id); if (ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(channel_id)) // check whether it's a built-in channel
if (ch) // it's built-in channel
{ {
channel_id = ch->ChannelID; // built-in channel
m_announce = false; // no join/leave announces m_announce = false; // no join/leave announces
m_flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels 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 else // it's custom channel
{ {
channel_id = 0;
m_flags |= CHANNEL_FLAG_CUSTOM; m_flags |= CHANNEL_FLAG_CUSTOM;
//load not built in channel if saved //load not built in channel if saved
std::string _name(name); std::string _name(name);
@@ -852,7 +851,7 @@ void Channel::MakeYouLeft(WorldPacket *data)
{ {
MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE);
*data << uint32(GetChannelId()); *data << uint32(GetChannelId());
*data << uint8(0); // can be 0x00 and 0x01 *data << uint8(IsConstant());
} }
// done 0x04 // done 0x04
@@ -1090,7 +1089,11 @@ void Channel::JoinNotify(uint64 guid)
data << uint8(GetFlags()); data << uint8(GetFlags());
data << uint32(GetNumPlayers()); data << uint32(GetNumPlayers());
data << GetName(); data << GetName();
SendToAll(&data);
if (IsConstant())
SendToAllButOne(&data, guid);
else
SendToAll(&data);
} }
void Channel::LeaveNotify(uint64 guid) void Channel::LeaveNotify(uint64 guid)
@@ -1100,6 +1103,10 @@ void Channel::LeaveNotify(uint64 guid)
data << uint8(GetFlags()); data << uint8(GetFlags());
data << uint32(GetNumPlayers()); data << uint32(GetNumPlayers());
data << GetName(); data << GetName();
SendToAll(&data);
if (IsConstant())
SendToAllButOne(&data, guid);
else
SendToAll(&data);
} }
-12
View File
@@ -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) bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
{ {
if (requiredTotemCategoryId == 0) if (requiredTotemCategoryId == 0)
+1 -3
View File
@@ -49,8 +49,6 @@ enum ContentLevels
}; };
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId); ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id);
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId); bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
void Zone2MapCoordinates(float &x, float &y, uint32 zone); void Zone2MapCoordinates(float &x, float &y, uint32 zone);
@@ -75,7 +73,7 @@ extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore;
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore; extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore; extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore;
extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore; extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
//extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; -- accessed using function, no usable index extern DBCStorage <ChatChannelsEntry> sChatChannelsStore;
extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore; extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
extern DBCStorage <CharTitlesEntry> sCharTitlesStore; extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
extern DBCStorage <ChrClassesEntry> sChrClassesStore; extern DBCStorage <ChrClassesEntry> sChrClassesStore;
+1 -1
View File
@@ -31,7 +31,7 @@ const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
const char BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx"; const char BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx";
const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi"; const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx"; const char ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store) // ChatChannelsEntryfmt, index not used (more compact store)
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
+83 -29
View File
@@ -5184,6 +5184,20 @@ void Player::RepopAtGraveyard()
TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); 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) void Player::JoinedChannel(Channel *c)
{ {
m_channels.push_back(c); m_channels.push_back(c);
@@ -5210,8 +5224,8 @@ void Player::CleanupChannels()
void Player::UpdateLocalChannels(uint32 newZone) void Player::UpdateLocalChannels(uint32 newZone)
{ {
if (m_channels.empty()) if (GetSession()->PlayerLoading() && !IsBeingTeleportedFar())
return; return; // The client handles it automatically after loading, but not after teleporting
AreaTableEntry const* current_zone = GetAreaEntryByAreaID(newZone); AreaTableEntry const* current_zone = GetAreaEntryByAreaID(newZone);
if (!current_zone) if (!current_zone)
@@ -5223,38 +5237,78 @@ void Player::UpdateLocalChannels(uint32 newZone)
std::string current_zone_name = current_zone->area_name[GetSession()->GetSessionDbcLocale()]; 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; if (ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i))
// 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)
{ {
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 if ((channel->flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId())
(*i)->Leave(GetGUID(),false); // not send leave channel, it already replaced at client continue; // Should not join to these channels automatically
std::string name = (*i)->GetName(); // store name, (*i)erase in LeftChannel
LeftChannel(*i); // remove from player's channel list Channel* usedChannel = NULL;
cMgr->LeftChannel(name); // delete if empty
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() void Player::LeaveLFGChannel()
+2
View File
@@ -1878,6 +1878,8 @@ class Player : public Unit, public GridObject<Player>
void SetMovement(PlayerMovementType pType); void SetMovement(PlayerMovementType pType);
bool CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone);
void JoinedChannel(Channel *c); void JoinedChannel(Channel *c);
void LeftChannel(Channel *c); void LeftChannel(Channel *c);
void CleanupChannels(); void CleanupChannels();
+3 -1
View File
@@ -728,7 +728,9 @@ enum TrinityStrings
LANG_COMMAND_CREATURETEMPLATE_NOTFOUND = 817, LANG_COMMAND_CREATURETEMPLATE_NOTFOUND = 817,
LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818, 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) // Level 4 (CLI only commands)
LANG_COMMAND_EXIT = 1000, LANG_COMMAND_EXIT = 1000,
@@ -27,7 +27,23 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
uint8 unknown1, unknown2; uint8 unknown1, unknown2;
std::string channelname, pass; 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; recvPacket >> channelname;
if (channelname.empty()) if (channelname.empty())