Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4

Conflicts:
	src/server/game/Handlers/CharacterHandler.cpp
	src/server/game/World/World.h
This commit is contained in:
Vincent_Michael
2013-02-15 14:23:21 +01:00
12 changed files with 77 additions and 19 deletions
@@ -95,6 +95,20 @@ void LFGPlayerScript::OnMapChanged(Player* player)
if (sLFGMgr->inLfgDungeonMap(player->GetGUID(), map->GetId(), map->GetDifficulty()))
{
Group* group = player->GetGroup();
// This function is also called when players log in
// if for some reason the LFG system recognises the player as being in a LFG dungeon,
// but the player was loaded without a valid group, we'll teleport to homebind to prevent
// crashes or other undefined behaviour
if (!group)
{
sLFGMgr->LeaveLfg(player->GetGUID());
player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW);
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, 0.0f);
sLog->outError(LOG_FILTER_LFG, "LFGPlayerScript::OnMapChanged, Player %s (%u) is in LFG dungeon map but does not have a valid group! "
"Teleporting to homebind.", player->GetName().c_str(), player->GetGUIDLow());
return;
}
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
if (Player* member = itr->getSource())
player->GetSession()->SendNameQueryOpcode(member->GetGUID());
@@ -290,7 +290,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data
}
// Initialize loot duplicate count depending on raid difficulty
if (GetMap()->IsRaid() && GetMap()->GetSpawnMode() & RAID_DIFFICULTY_MASK_25MAN)
if (GetMap()->Is25ManRaid())
loot.maxDuplicates = 3;
SetEntry(Entry); // normal entry always
@@ -260,7 +260,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
AIM_Initialize();
// Initialize loot duplicate count depending on raid difficulty
if (map->IsRaid() && map->GetSpawnMode() & RAID_DIFFICULTY_MASK_25MAN)
if (map->Is25ManRaid())
loot.maxDuplicates = 3;
return true;
@@ -7662,6 +7662,9 @@ uint32 Player::GetZoneIdFromDB(uint64 guid)
float posy = fields[2].GetFloat();
float posz = fields[3].GetFloat();
if (!sMapStore.LookupEntry(map))
return 0;
zone = sMapMgr->GetZoneId(map, posx, posy, posz);
if (zone > 0)
+32 -3
View File
@@ -229,7 +229,7 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
bitBuffer.WriteBit(1);
if (result)
{
_allowedCharsToLogin.clear();
_legitCharacters.clear();
charCount = uint32(result->GetRowCount());
bitBuffer.reserve(24 * charCount / 8);
@@ -245,7 +245,9 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
Player::BuildEnumData(result, &dataBuffer, &bitBuffer);
_allowedCharsToLogin.insert(guidLow);
_legitCharacters.insert(guidLow);
if (!sWorld->HasCharacterNameData(guidLow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
sWorld->AddCharacterNameData(guidLow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
} while (result->NextRow());
bitBuffer.FlushBits();
@@ -800,7 +802,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
sLog->outDebug(LOG_FILTER_NETWORKIO, "Character (Guid: %u) logging in", GUID_LOPART(playerGuid));
if (!CharCanLogin(GUID_LOPART(playerGuid)))
if (!IsLegitCharacterForAccount(GUID_LOPART(playerGuid)))
{
sLog->outError(LOG_FILTER_NETWORKIO, "Account (%u) can't login with that character (%u).", GetAccountId(), GUID_LOPART(playerGuid));
KickPlayer();
@@ -1473,6 +1475,15 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
std::string newName;
recvData >> guid;
if (!IsLegitCharacterForAccount(GUID_LOPART(guid)))
{
sLog->outError(LOG_FILTER_NETWORKIO, "Account %u, IP: %s tried to customise character %u, but it does not belong to their account!",
GetAccountId(), GetRemoteAddress().c_str(), GUID_LOPART(guid));
recvData.rfinish();
KickPlayer();
return;
}
recvData >> newName;
uint8 gender, skin, face, hairStyle, hairColor, facialHair;
@@ -1704,6 +1715,16 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
std::string newname;
uint8 gender, skin, face, hairStyle, hairColor, facialHair, race;
recvData >> guid;
if (!IsLegitCharacterForAccount(GUID_LOPART(guid)))
{
sLog->outError(LOG_FILTER_NETWORKIO, "Account %u, IP: %s tried to factionchange character %u, but it does not belong to their account!",
GetAccountId(), GetRemoteAddress().c_str(), GUID_LOPART(guid));
recvData.rfinish();
KickPlayer();
return;
}
recvData >> newname;
recvData >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face >> race;
@@ -1711,6 +1732,14 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
// get the players old (at this moment current) race
CharacterNameData const* nameData = sWorld->GetCharacterNameData(lowGuid);
if (!nameData)
{
WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1);
data << uint8(CHAR_CREATE_ERROR);
SendPacket(&data);
return;
}
uint8 oldRace = nameData->m_race;
uint8 playerClass = nameData->m_class;
uint8 level = nameData->m_level;
+5 -4
View File
@@ -105,16 +105,17 @@ Map* MapManager::CreateBaseMap(uint32 id)
{
TRINITY_GUARD(ACE_Thread_Mutex, Lock);
const MapEntry* entry = sMapStore.LookupEntry(id);
if (entry && entry->Instanceable())
{
MapEntry const* entry = sMapStore.LookupEntry(id);
ASSERT(entry);
if (entry->Instanceable())
map = new MapInstanced(id, i_gridCleanUpDelay);
}
else
{
map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY);
map->LoadRespawnTimes();
}
i_maps[id] = map;
}
+2 -2
View File
@@ -489,14 +489,14 @@ void ScriptMgr::OnGroupRateCalculation(float& rate, uint32 count, bool isRaid)
}
#define SCR_MAP_BGN(M, V, I, E, C, T) \
if (V->GetEntry()->T()) \
if (V->GetEntry() && V->GetEntry()->T()) \
{ \
FOR_SCRIPTS(M, I, E) \
{ \
MapEntry const* C = I->second->GetEntry(); \
if (!C) \
continue; \
if (entry->MapID == V->GetId()) \
if (C->MapID == V->GetId()) \
{
#define SCR_MAP_END \
+3 -3
View File
@@ -974,14 +974,14 @@ class WorldSession
void LogUnprocessedTail(WorldPacket* packet);
// EnumData helpers
bool CharCanLogin(uint32 lowGUID)
bool IsLegitCharacterForAccount(uint32 lowGUID)
{
return _allowedCharsToLogin.find(lowGUID) != _allowedCharsToLogin.end();
return _legitCharacters.find(lowGUID) != _legitCharacters.end();
}
// this stores the GUIDs of the characters who can login
// characters who failed on Player::BuildEnumData shouldn't login
std::set<uint32> _allowedCharsToLogin;
std::set<uint32> _legitCharacters;
uint32 m_GUIDLow; // set loggined or recently logout player (while m_playerRecentlyLogout set)
Player* _player;
+1 -1
View File
@@ -753,8 +753,8 @@ class World
void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level);
void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
void UpdateCharacterNameDataLevel(uint32 guid, uint8 level);
void DeleteCharacterNameData(uint32 guid) { _characterNameDataMap.erase(guid); }
bool HasCharacterNameData(uint32 guid) { return _characterNameDataMap.find(guid) != _characterNameDataMap.end(); }
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
@@ -148,6 +148,7 @@ class boss_drakkari_colossus : public CreatureScript
DoCast(SPELL_EMERGE);
break;
case ACTION_FREEZE_COLOSSUS:
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->SetReactState(REACT_PASSIVE);
@@ -33,6 +33,7 @@
RASocket::RASocket()
{
_minLevel = uint8(ConfigMgr::GetIntDefault("RA.MinLevel", 3));
_commandExecuting = false;
}
RASocket::~RASocket()
@@ -59,6 +60,12 @@ int RASocket::handle_close(ACE_HANDLE, ACE_Reactor_Mask)
sLog->outInfo(LOG_FILTER_REMOTECOMMAND, "Closing connection");
peer().close_reader();
wait();
// While the above wait() will wait for the ::svc() to finish, it will not wait for the async event
// RASocket::commandfinished to be completed. Calling destroy() before the latter function ends
// will lead to using a freed pointer -> crash.
while (_commandExecuting.value())
ACE_OS::sleep(1);
destroy();
return 0;
}
@@ -150,6 +157,7 @@ int RASocket::process_command(const std::string& command)
return -1;
}
_commandExecuting = true;
CliCommandHolder* cmd = new CliCommandHolder(this, command.c_str(), &RASocket::zprint, &RASocket::commandFinished);
sWorld->QueueCliCommand(cmd);
@@ -412,10 +420,11 @@ void RASocket::commandFinished(void* callbackArg, bool /*success*/)
// the message is 0 size control message to tell that command output is finished
// hence we don't put timeout, because it shouldn't increase queue size and shouldn't block
if (socket->putq(mb) == -1)
{
if (socket->putq(mb->duplicate()) == -1)
// getting here is bad, command can't be marked as complete
sLog->outDebug(LOG_FILTER_REMOTECOMMAND, "Failed to enqueue command end message. Error is %s", ACE_OS::strerror(errno));
mb->release();
}
mb->release();
socket->_commandExecuting = false;
}
@@ -57,6 +57,7 @@ class RASocket: public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
private:
/// Minimum security level required to connect
uint8 _minLevel;
ACE_Atomic_Op<ACE_Thread_Mutex, bool> _commandExecuting;
};
#endif
/// @}