Spawn indexes in Player class now protected by mutex

Fix 
This commit is contained in:
image 2020-08-28 11:18:22 -04:00
parent cbb399fad4
commit 2ebc48c157
8 changed files with 208 additions and 82 deletions

View file

@ -40,7 +40,7 @@ void ClientPacketFunctions::SendHeroicOPUpdate(Client* client, HeroicOP* ho) {
PacketStruct* packet = configReader.getStruct("WS_HeroicOpportunity", client->GetVersion());
Spell* spell = 0;
if (packet) {
packet->setDataByName("id", client->GetPlayer()->player_spawn_reverse_id_map[client->GetPlayer()]);
packet->setDataByName("id", client->GetPlayer()->GetIDWithPlayerSpawn(client->GetPlayer()));
if (ho->GetWheel()) {
spell = master_spell_list.GetSpell(ho->GetWheel()->spell_id, 1);
if (!spell) {

View file

@ -114,6 +114,7 @@ Player::Player(){
pos_mutex.SetName("Player::pos_mutex");
vis_mutex.SetName("Player::vis_mutex");
info_mutex.SetName("Player::info_mutex");
index_mutex.SetName("Player::index_mutex");
m_playerSpawnQuestsRequired.SetName("Player::player_spawn_quests_required");
m_playerSpawnHistoryRequired.SetName("Player::player_spawn_history_required");
gm_vision = false;
@ -165,11 +166,13 @@ Player::~Player(){
DeleteMail();
world.RemoveLottoPlayer(GetCharacterID());
safe_delete(info);
index_mutex.writelock(__FUNCTION__, __LINE__);
player_spawn_index_map.clear();
player_spawn_map.clear();
player_spawn_reverse_id_map.clear();
player_removed_spawns.clear();
player_spawn_id_map.clear();
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
info_mutex.writelock(__FUNCTION__, __LINE__);
spawn_info_packet_list.clear();
@ -2932,11 +2935,13 @@ SpellEffects* Player::GetSpellEffects() {
}
void Player::ClearEverything(){
index_mutex.writelock(__FUNCTION__, __LINE__);
player_removed_spawns.clear();
player_spawn_map.clear();
player_spawn_index_map.clear();
player_spawn_id_map.clear();
player_spawn_reverse_id_map.clear();
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
map<int32, vector<int32>*>::iterator itr;
m_playerSpawnQuestsRequired.writelock(__FUNCTION__, __LINE__);
for (itr = player_spawn_quests_required.begin(); itr != player_spawn_quests_required.end(); itr++){
@ -3803,42 +3808,76 @@ void Player::CalculateLocation(){
}
Spawn* Player::GetSpawnByIndex(int16 index){
Spawn* spawn = 0;
index_mutex.readlock(__FUNCTION__, __LINE__);
if(player_spawn_map.count(index) > 0)
return player_spawn_map[index];
else
return 0;
spawn = player_spawn_map[index];
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
return spawn;
}
int16 Player::GetIndexForSpawn(Spawn* spawn){
int16 Player::GetIndexForSpawn(Spawn* spawn) {
int16 val = 0;
index_mutex.readlock(__FUNCTION__, __LINE__);
if(player_spawn_index_map.count(spawn) > 0)
return player_spawn_index_map[spawn];
else
return 0;
val = player_spawn_index_map[spawn];
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
return val;
}
bool Player::WasSpawnRemoved(Spawn* spawn){
bool wasRemoved = false;
index_mutex.readlock(__FUNCTION__, __LINE__);
if(player_removed_spawns.count(spawn) > 0)
return true;
else
return false;
wasRemoved = true;
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
return wasRemoved;
}
void Player::RemoveSpawn(Spawn* spawn)
{
LogWrite(PLAYER__DEBUG, 3, "Player", "Remove Spawn '%s' (%u)", spawn->GetName(), spawn->GetID());
info_mutex.writelock(__FUNCTION__, __LINE__);
pos_mutex.writelock(__FUNCTION__, __LINE__);
vis_mutex.writelock(__FUNCTION__, __LINE__);
index_mutex.writelock(__FUNCTION__, __LINE__);
player_removed_spawns[spawn] = 1;
if (player_spawn_index_map[spawn] && player_spawn_map.count(player_spawn_index_map[spawn]) > 0)
player_spawn_map.erase(player_spawn_index_map[spawn]);
if (player_spawn_index_map.count(spawn) > 0)
player_spawn_index_map.erase(spawn);
if (player_spawn_id_map.count(spawn->GetID()) && player_spawn_id_map[spawn->GetID()] == spawn)
player_spawn_id_map.erase(spawn->GetID());
if (player_spawn_reverse_id_map.count(spawn))
player_spawn_reverse_id_map.erase(spawn);
int32 id = spawn->GetID();
info_mutex.writelock(__FUNCTION__, __LINE__);
spawn_info_packet_list.erase(id);
if (spawn_info_packet_list.count(id))
spawn_info_packet_list.erase(id);
if (spawn_pos_packet_list.count(id))
spawn_pos_packet_list.erase(id);
if (spawn_vis_packet_list.count(id))
spawn_vis_packet_list.erase(id);
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
info_mutex.releasewritelock(__FUNCTION__, __LINE__);
pos_mutex.writelock(__FUNCTION__, __LINE__);
spawn_pos_packet_list.erase(id);
pos_mutex.releasewritelock(__FUNCTION__, __LINE__);
vis_mutex.writelock(__FUNCTION__, __LINE__);
spawn_vis_packet_list.erase(id);
vis_mutex.releasewritelock(__FUNCTION__, __LINE__);
}
@ -4524,8 +4563,10 @@ bool Player::CanReceiveQuest(int32 quest_id){
}
void Player::ClearRemovedSpawn(Spawn* spawn){
index_mutex.writelock(__FUNCTION__, __LINE__);
if(player_removed_spawns.count(spawn) > 0)
player_removed_spawns.erase(spawn);
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
}
bool Player::ShouldSendSpawn(Spawn* spawn){
@ -4896,10 +4937,13 @@ void Player::ResetSavedSpawns(){
spawn_pos_packet_list.clear();
pos_mutex.releasewritelock(__FUNCTION__, __LINE__);
index_mutex.writelock(__FUNCTION__, __LINE__);
player_spawn_reverse_id_map.clear();
player_spawn_id_map.clear();
player_spawn_map.clear();
player_spawn_index_map.clear();
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
m_playerSpawnQuestsRequired.writelock(__FUNCTION__, __LINE__);
player_spawn_quests_required.clear();
m_playerSpawnQuestsRequired.releasewritelock(__FUNCTION__, __LINE__);

View file

@ -569,22 +569,74 @@ public:
void ClearRemovedSpawn(Spawn* spawn);
bool ShouldSendSpawn(Spawn* spawn);
map<int16, Spawn*>* GetPlayerSpawnMap(){
return &player_spawn_map;
}
map<Spawn*, int16>* GetPlayerSpawnIndexMap(){
return &player_spawn_index_map;
}
Spawn* GetSpawnWithPlayerID(int32 id){
Spawn* spawn = 0;
index_mutex.readlock(__FUNCTION__, __LINE__);
if (player_spawn_id_map.count(id) > 0)
return player_spawn_id_map[id];
return 0;
spawn = player_spawn_id_map[id];
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
return spawn;
}
int32 GetIDWithPlayerSpawn(Spawn* spawn){
int32 id = 0;
index_mutex.readlock(__FUNCTION__, __LINE__);
if (player_spawn_reverse_id_map.count(spawn) > 0)
return player_spawn_reverse_id_map[spawn];
return 0;
id = player_spawn_reverse_id_map[spawn];
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
return id;
}
void SetSpawnMap(Spawn* spawn)
{
index_mutex.writelock(__FUNCTION__, __LINE__);
spawn_id += 1;
int32 tmp_id = spawn_id;
player_spawn_id_map[tmp_id] = spawn;
if(player_spawn_reverse_id_map.count(spawn))
player_spawn_reverse_id_map.erase(spawn);
player_spawn_reverse_id_map.insert(make_pair(spawn,tmp_id));
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
}
void SetSpawnMapIndex(Spawn* spawn, int16 index)
{
index_mutex.writelock(__FUNCTION__, __LINE__);
if (player_spawn_map.count(index))
player_spawn_map[index] = spawn;
else
player_spawn_map[index] = spawn;
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
}
int16 SetSpawnMapAndIndex(Spawn* spawn)
{
int16 new_index = 0;
index_mutex.writelock(__FUNCTION__, __LINE__);
spawn_index += 1;
if (spawn_index == 255)
spawn_index += 1; //just so we dont have to worry about overloading
new_index = spawn_index;
if (player_spawn_index_map.count(spawn))
player_spawn_index_map.erase(spawn);
player_spawn_index_map.insert(make_pair(spawn,new_index));
if (player_spawn_map.count(new_index))
player_spawn_map[new_index] = spawn;
else
player_spawn_map.insert(make_pair(new_index, spawn));
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
return new_index;
}
PacketStruct* GetQuestJournalPacket(bool all_quests, int16 version, int32 crc, int32 current_quest_id);
void RemoveQuest(int32 id, bool delete_quest);
vector<Quest*>* CheckQuestsChatUpdate(Spawn* spawn);
@ -602,10 +654,6 @@ public:
void AddHistoryRequiredSpawn(Spawn* spawn, int32 event_id);
int16 spawn_index;
int32 spawn_id;
map<Spawn*, int16> player_spawn_index_map;
map<int16, Spawn*> player_spawn_map;
map<int32, Spawn*> player_spawn_id_map;
map<Spawn*, int32> player_spawn_reverse_id_map;
map<int32, vector<int32>*> player_spawn_quests_required;
map<int32, vector<int32>*> player_spawn_history_required;
Mutex m_playerSpawnQuestsRequired;
@ -817,6 +865,7 @@ public:
Mutex info_mutex;
Mutex pos_mutex;
Mutex vis_mutex;
Mutex index_mutex;
void SetTempMount(int32 id) { tmp_mount_model = id; }
int32 GetTempMount() { return tmp_mount_model; }
@ -864,7 +913,6 @@ private:
map<Spawn*, bool> current_quest_flagged;
PlayerFaction factions;
map<int32, Quest*> completed_quests;
map<Spawn*, int8> player_removed_spawns;
bool charsheet_changed;
map<int32, string> spawn_vis_packet_list;
map<int32, string> spawn_info_packet_list;
@ -965,6 +1013,12 @@ private:
EQ2_Color tmp_mount_saddle_color;
bool gm_vision;
map<Spawn*, int16> player_spawn_index_map;
map<int16, Spawn*> player_spawn_map;
map<int32, Spawn*> player_spawn_id_map;
map<Spawn*, int32> player_spawn_reverse_id_map;
map<Spawn*, int8> player_removed_spawns;
};
#pragma pack()
#endif

View file

@ -198,7 +198,9 @@ void Spawn::InitializeHeaderPacketData(Player* player, PacketStruct* header, int
vector<Spawn*>::iterator itr;
int i = 0;
for (itr = spawn_group_list->begin(); itr != spawn_group_list->end(); itr++, i++){
header->setArrayDataByName("group_spawn_id", player->GetIDWithPlayerSpawn((*itr)), i);
int32 idx = 0;
idx = player->GetIDWithPlayerSpawn((*itr));
header->setArrayDataByName("group_spawn_id", idx, i);
}
MSpawnGroup->releasereadlock(__FUNCTION__, __LINE__);
}
@ -383,29 +385,21 @@ EQ2Packet* Spawn::spawn_serialize(Player* player, int16 version, int16 offset, i
((Player*)((NPC*)this)->GetOwner())->GetInfoStruct()->pet_id = player->spawn_id;
player->SetCharSheetChanged(true);
}
m_Update.writelock(__FUNCTION__, __LINE__);
int16 index;
if (player->player_spawn_index_map.count(this) > 0) {
index = player->player_spawn_index_map[this];
player->player_spawn_map[index] = this;
int16 index = 0;
if ((index = player->GetIndexForSpawn(this)) > 0) {
player->SetSpawnMapIndex(this, index);
}
else {
player->spawn_index++;
if (player->spawn_index == 255)
player->spawn_index++; //just so we dont have to worry about overloading
index = player->spawn_index;
player->player_spawn_index_map[this] = index;
player->player_spawn_map[index] = this;
index = player->SetSpawnMapAndIndex(this);
}
// Jabantiz - [Bug] Client Crash on Revive
if (player->player_spawn_reverse_id_map.count(this) == 0) {
int32 spawn_id = ++player->spawn_id;
player->player_spawn_id_map[spawn_id] = this;
player->player_spawn_reverse_id_map[this] = spawn_id;
if (player->GetIDWithPlayerSpawn(this) == 0) {
player->SetSpawnMap(this);
}
m_Update.writelock(__FUNCTION__, __LINE__);
PacketStruct* header = player->GetSpawnHeaderStruct();
header->ResetData();
InitializeHeaderPacketData(player, header, index);
@ -562,6 +556,7 @@ EQ2Packet* Spawn::spawn_serialize(Player* player, int16 version, int16 offset, i
}
if (offset > 0)
DumpPacket(part2, part2_size);
uchar tmp[1100];
bool reverse = (version > 283);
part2_size = Pack(tmp, part2, part2_size, 1100, version, reverse);
@ -631,7 +626,7 @@ EQ2Packet* Spawn::spawn_serialize(Player* player, int16 version, int16 offset, i
}
uchar* Spawn::spawn_info_changes(Player* player, int16 version){
int16 index = player->player_spawn_index_map[this];
int16 index = player->GetIndexForSpawn(this);
PacketStruct* packet = player->GetSpawnInfoStruct();
@ -688,7 +683,7 @@ uchar* Spawn::spawn_info_changes(Player* player, int16 version){
uchar* Spawn::spawn_vis_changes(Player* player, int16 version){
PacketStruct* vis_struct = player->GetSpawnVisStruct();
int16 index = player->player_spawn_index_map[this];
int16 index = player->GetIndexForSpawn(this);
player->vis_mutex.writelock(__FUNCTION__, __LINE__);
uchar* orig_packet = player->GetSpawnVisPacketForXOR(id);
@ -995,7 +990,7 @@ EQ2Packet* Spawn::spawn_update_packet(Player* player, int16 version, bool overri
}
uchar* Spawn::spawn_info_changes_ex(Player* player, int16 version) {
int16 index = player->player_spawn_index_map[this];
int16 index = player->GetIndexForSpawn(this);
PacketStruct* packet = player->GetSpawnInfoStruct();
@ -1059,7 +1054,7 @@ uchar* Spawn::spawn_info_changes_ex(Player* player, int16 version) {
uchar* Spawn::spawn_vis_changes_ex(Player* player, int16 version) {
PacketStruct* vis_struct = player->GetSpawnVisStruct();
int16 index = player->player_spawn_index_map[this];
int16 index = player->GetIndexForSpawn(this);
player->vis_mutex.writelock(__FUNCTION__, __LINE__);
@ -3744,4 +3739,11 @@ bool Spawn::SetPermissionToEntityCommand(EntityCommand* command, Player* player,
}
return false;
}
void Spawn::RemoveSpawnFromPlayer(Player* player)
{
m_Update.writelock(__FUNCTION__, __LINE__);
player->RemoveSpawn(this); // sets it as removed
m_Update.releasewritelock(__FUNCTION__, __LINE__);
}

View file

@ -298,6 +298,8 @@ public:
void RemovePrimaryEntityCommand(const char* command);
bool SetPermissionToEntityCommand(EntityCommand* command, Player* player, bool permissionValue);
void RemoveSpawnFromPlayer(Player* player);
void AddSecondaryEntityCommand(const char* name, float distance, const char* command, const char* error_text, int16 cast_time, int32 spell_visual){
secondary_command_list.push_back(CreateEntityCommand(name, distance, command, error_text, cast_time, spell_visual));
}

View file

@ -165,7 +165,7 @@ void TradeskillMgr::Process() {
PacketStruct* packet = configReader.getStruct("WS_UpdateCreateItem", client->GetVersion());
if (packet) {
packet->setDataByName("spawn_id", client->GetPlayer()->player_spawn_reverse_id_map[tradeskill->table]);
packet->setDataByName("spawn_id", client->GetPlayer()->GetIDWithPlayerSpawn(tradeskill->table));
packet->setDataByName("effect", effect);
packet->setDataByName("total_durability", tradeskill->currentDurability);
packet->setDataByName("total_progress", tradeskill->currentProgress);

View file

@ -1055,9 +1055,7 @@ void ZoneServer::CheckSpawnRange(Spawn* spawn){
}
void ZoneServer::PrepareSpawnID(Player* player, Spawn* spawn){
player->spawn_id++;
player->player_spawn_id_map[player->spawn_id] = spawn;
player->player_spawn_reverse_id_map[spawn] = player->spawn_id;
player->SetSpawnMap(spawn);
}
void ZoneServer::CheckSendSpawnToClient(Client* client, bool initial_login) {
@ -1071,24 +1069,24 @@ void ZoneServer::CheckSendSpawnToClient(Client* client, bool initial_login) {
Spawn* spawn = 0;
map<float, vector<Spawn*>* > closest_spawns;
if(spawn_range_map.count(client) > 0) {
if(initial_login || client->IsConnected()) {
if (spawn_range_map.count(client) > 0) {
if (initial_login || client->IsConnected()) {
MutexMap<int32, float >::iterator spawn_iter = spawn_range_map.Get(client)->begin();
while(spawn_iter.Next()) {
while (spawn_iter.Next()) {
spawn = GetSpawnByID(spawn_iter->first, true);
if(spawn && spawn->GetPrivateQuestSpawn()) {
if(!spawn->IsPrivateSpawn())
if (spawn && spawn->GetPrivateQuestSpawn()) {
if (!spawn->IsPrivateSpawn())
spawn->AddAllowAccessSpawn(spawn);
if(spawn->MeetsSpawnAccessRequirements(client->GetPlayer())) {
if(spawn->IsPrivateSpawn() && !spawn->AllowedAccess(client->GetPlayer()))
if (spawn->MeetsSpawnAccessRequirements(client->GetPlayer())) {
if (spawn->IsPrivateSpawn() && !spawn->AllowedAccess(client->GetPlayer()))
spawn->AddAllowAccessSpawn(client->GetPlayer());
}
else if(spawn->AllowedAccess(client->GetPlayer()))
else if (spawn->AllowedAccess(client->GetPlayer()))
spawn->RemoveSpawnAccess(client->GetPlayer());
}
if(spawn && spawn != client->GetPlayer() && client->GetPlayer()->ShouldSendSpawn(spawn)) {
if((!initial_login && spawn_iter->second <= SEND_SPAWN_DISTANCE) || (initial_login && (spawn_iter->second <= (SEND_SPAWN_DISTANCE/2) || spawn->IsWidget()))) {
if(closest_spawns.count(spawn_iter->second) == 0)
if (spawn && spawn != client->GetPlayer() && client->GetPlayer()->ShouldSendSpawn(spawn)) {
if ((!initial_login && spawn_iter->second <= SEND_SPAWN_DISTANCE) || (initial_login && (spawn_iter->second <= (SEND_SPAWN_DISTANCE / 2) || spawn->IsWidget()))) {
if (closest_spawns.count(spawn_iter->second) == 0)
closest_spawns[spawn_iter->second] = new vector<Spawn*>();
closest_spawns[spawn_iter->second]->push_back(spawn);
PrepareSpawnID(client->GetPlayer(), spawn);
@ -1098,15 +1096,19 @@ void ZoneServer::CheckSendSpawnToClient(Client* client, bool initial_login) {
}
vector<Spawn*>::iterator spawn_iter2;
map<float, vector<Spawn*>* >::iterator itr;
for(itr = closest_spawns.begin(); itr != closest_spawns.end(); itr++) {
for(spawn_iter2 = itr->second->begin(); spawn_iter2 != itr->second->end(); spawn_iter2++) {
for (itr = closest_spawns.begin(); itr != closest_spawns.end(); ) {
for (spawn_iter2 = itr->second->begin(); spawn_iter2 != itr->second->end(); spawn_iter2++) {
spawn = *spawn_iter2;
client->GetPlayer()->ClearRemovedSpawn(spawn);
SendSpawn(spawn, client);
if(client->ShouldTarget() && client->GetCombineSpawn() == spawn)
if (client->ShouldTarget() && client->GetCombineSpawn() == spawn)
client->TargetSpawn(spawn);
}
delete itr->second;
vector<Spawn*>* vect = itr->second;
map<float, vector<Spawn*>* >::iterator tmpitr = itr;
itr++;
closest_spawns.erase(tmpitr);
safe_delete(vect);
}
}
@ -1215,11 +1217,23 @@ void ZoneServer::DelayedSpawnRemoval(bool force_delete_all) {
void ZoneServer::AddPendingDelete(Spawn* spawn) {
MSpawnDeleteList.writelock(__FUNCTION__, __LINE__);
if(spawn_delete_list.count(spawn) == 0)
if (spawn_delete_list.count(spawn) == 0)
spawn_delete_list.insert(make_pair(spawn, Timer::GetCurrentTime2() + spawn_delete_timer)); //give other threads up to 30 seconds to stop using this spawn reference
MSpawnDeleteList.releasewritelock(__FUNCTION__, __LINE__);
}
void ZoneServer::RemovePendingDelete(Spawn* spawn) {
if (!spawn)
return;
MSpawnDeleteList.writelock(__FUNCTION__, __LINE__);
if (spawn_delete_list.count(spawn) > 0)
{
spawn_delete_list.erase(spawn);
}
MSpawnDeleteList.releasewritelock(__FUNCTION__, __LINE__);
}
void ZoneServer::DeleteSpawns(bool delete_all) {
MSpawnDeleteList.writelock(__FUNCTION__, __LINE__);
if(spawn_delete_list.size() > 0){
@ -2144,7 +2158,6 @@ Spawn* ZoneServer::ProcessSpawnLocation(SpawnLocation* spawnlocation, bool respa
if (!spawn)
{
LogWrite(ZONE__ERROR, 0, "Zone", "Error adding spawn to zone");
safe_delete(spawn);
continue;
}
@ -3672,12 +3685,10 @@ bool ZoneServer::SendRemoveSpawn(Client* client, Spawn* spawn, PacketStruct* pac
LogWrite(ZONE__DEBUG, 7, "Zone", "%s: Processing SendRemoveSpawn for spawn index %u (%s)...cur_id: %i, wasremoved:: %i", client->GetPlayer()->GetName(), index, spawn->GetName(), cur_id, wasRemoved);
if(packet && index > 0 && !wasRemoved)
{
packet->ResetData();
packet->setDataByName("spawn_index", index);
client->GetPlayer()->GetPlayerSpawnMap()->erase(index);
client->GetPlayer()->GetPlayerSpawnIndexMap()->erase(spawn);
client->GetPlayer()->player_spawn_id_map.erase(cur_id);
client->GetPlayer()->player_spawn_reverse_id_map.erase(spawn);
client->GetPlayer()->RemoveSpawn(spawn); // sets it as removed
spawn->RemoveSpawnFromPlayer(client->GetPlayer());
if(delete_spawn)
packet->setDataByName("delete", 1);
@ -3921,6 +3932,8 @@ void ZoneServer::RemoveSpawn(bool spawnListLocked, Spawn* spawn, bool delete_spa
safe_delete(packet);
bool alreadyDeletedSpawn = false;
if(respawn && !spawn->IsPlayer() && spawn->GetRespawnTime() > 0 && spawn->GetSpawnLocationID() > 0)
{
LogWrite(ZONE__DEBUG, 3, "Zone", "Handle NPC Respawn for '%s'.", spawn->GetName());
@ -3942,12 +3955,14 @@ void ZoneServer::RemoveSpawn(bool spawnListLocked, Spawn* spawn, bool delete_spa
spawn->GetRespawnTime(),spawn->GetZone()->GetInstanceID());
}
safe_delete(spawn);
alreadyDeletedSpawn = true;
}
else
{
int32 spawnLocationID = spawn->GetSpawnLocationID();
int32 spawnRespawnTime = spawn->GetRespawnTime();
safe_delete(spawn);
alreadyDeletedSpawn = true;
respawn_timers.Put(spawnLocationID, Timer::GetCurrentTime2() + spawnRespawnTime * 1000);
}
}
@ -3955,7 +3970,7 @@ void ZoneServer::RemoveSpawn(bool spawnListLocked, Spawn* spawn, bool delete_spa
// Do we really need the mutex locks and check to dead_spawns as we remove it from dead spawns at the start of this function
if (lock && !respawn)
MDeadSpawns.readlock(__FUNCTION__, __LINE__);
if(!respawn && delete_spawn && dead_spawns.count(spawn->GetID()) == 0)
if(!alreadyDeletedSpawn && !respawn && delete_spawn && dead_spawns.count(spawn->GetID()) == 0)
AddPendingDelete(spawn);
if (lock && !respawn)
MDeadSpawns.releasereadlock(__FUNCTION__, __LINE__);
@ -6277,12 +6292,18 @@ void ZoneServer::HidePrivateSpawn(Spawn* spawn) {
Client* client = 0;
Player* player = 0;
PacketStruct* packet = 0;
int32 packet_version = 0;
MutexList<Client*>::iterator itr = connected_clients.begin();
while (itr->Next()) {
client = itr->value;
player = client->GetPlayer();
if (player->WasSentSpawn(spawn->GetID()) && !player->WasSpawnRemoved(spawn)) {
packet = configReader.getStruct("WS_DestroyGhostCmd", client->GetVersion());
if (!packet || packet_version != client->GetVersion()) {
safe_delete(packet);
packet_version = client->GetVersion();
packet = configReader.getStruct("WS_DestroyGhostCmd", packet_version);
}
SendRemoveSpawn(client, spawn, packet);
if(spawn_range_map.count(client) > 0)
spawn_range_map.Get(client)->erase(spawn->GetID());
@ -6291,6 +6312,8 @@ void ZoneServer::HidePrivateSpawn(Spawn* spawn) {
player->SetTarget(0);
}
}
safe_delete(packet);
}
SpawnLocation* ZoneServer::GetSpawnLocation(int32 id) {

View file

@ -711,6 +711,7 @@ private:
void ReloadTransporters(); // never used outside zone server
void DeleteSpawns(bool delete_all); // never used outside zone server
void AddPendingDelete(Spawn* spawn); // never used outside zone server
void RemovePendingDelete(Spawn* spawn); // never used outside zone server
void ClearDeadSpawns(); // never used outside zone server
void RemoveChangedSpawn(Spawn* spawn); // never used outside zone server
void ProcessDrowning(); // never used outside zone server