diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index c8f724a17..d28478a97 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -120,7 +120,6 @@ namespace Logs { Loot, Expeditions, DynamicZones, - Group, MaxCategoryID /* Don't Remove this */ }; @@ -200,7 +199,6 @@ namespace Logs { "Loot", "Expeditions", "DynamicZones", - "Group", }; } diff --git a/common/servertalk.h b/common/servertalk.h index 816807b56..40be635ad 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -80,7 +80,6 @@ #define ServerOP_UpdateSpawn 0x003f #define ServerOP_SpawnStatusChange 0x0040 #define ServerOP_DropClient 0x0041 // DropClient -#define ServerOP_ChangeGroupLeader 0x0042 #define ServerOP_ReloadTasks 0x0060 #define ServerOP_DepopAllPlayersCorpses 0x0061 #define ServerOP_ReloadTitles 0x0062 @@ -862,7 +861,6 @@ struct ServerGroupLeave_Struct { uint16 instance_id; uint32 gid; char member_name[64]; //kick this member from the group - bool checkleader; }; struct ServerGroupJoin_Struct { @@ -872,20 +870,10 @@ struct ServerGroupJoin_Struct { char member_name[64]; //this person is joining the group }; -struct ServerGroupLeader_Struct { - uint32 zoneid; - uint16 instance_id; - uint32 gid; - char leader_name[64]; - char oldleader_name[64]; -}; - struct ServerForceGroupUpdate_Struct { uint32 origZoneID; uint16 instance_id; uint32 gid; - char leader_name[64]; - char oldleader_name[64]; }; struct ServerGroupChannelMessage_Struct { diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 58bd9f177..f09d08db1 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -277,14 +277,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { break; } - case ServerOP_ChangeGroupLeader: { - if (pack->size != sizeof(ServerGroupLeader_Struct)) { - break; - } - zoneserver_list.SendPacket(pack); //bounce it to all zones - break; - } - case ServerOP_RaidAdd: { if (pack->size != sizeof(ServerRaidGeneralAction_Struct)) break; diff --git a/zone/entity.cpp b/zone/entity.cpp index 6424407fb..cc531ca38 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4250,7 +4250,7 @@ void EntityList::ForceGroupUpdate(uint32 gid) } } -void EntityList::SendGroupLeave(uint32 gid, const char *name, bool checkleader) +void EntityList::SendGroupLeave(uint32 gid, const char *name) { auto it = client_list.begin(); while (it != client_list.end()) { @@ -4266,39 +4266,13 @@ void EntityList::SendGroupLeave(uint32 gid, const char *name, bool checkleader) gj->action = groupActLeave; strcpy(gj->yourname, c->GetName()); Mob *Leader = g->GetLeader(); - if (Leader) { + if (Leader) Leader->CastToClient()->GetGroupAAs(&gj->leader_aas); - } c->QueuePacket(outapp); safe_delete(outapp); - g->DelMemberOOZ(name, checkleader); - if (g->IsLeader(c) && c->IsLFP()) { + g->DelMemberOOZ(name); + if (g->IsLeader(c) && c->IsLFP()) c->UpdateLFP(); - } - } - } - } - ++it; - } -} - -void EntityList::SendGroupLeader(uint32 gid, const char *lname, const char *oldlname) -{ - auto it = client_list.begin(); - while (it != client_list.end()) { - if (it->second){ - Group *g = nullptr; - g = it->second->GetGroup(); - if (g) { - if (g->GetID() == gid) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; - gj->action = groupActMakeLeader; - strcpy(gj->membername, lname); - strcpy(gj->yourname, oldlname); - it->second->QueuePacket(outapp); - Log(Logs::Detail, Logs::Group, "SendGroupLeader(): Entity loop leader update packet sent to: %s .", it->second->GetName()); - safe_delete(outapp); } } } @@ -4321,9 +4295,9 @@ void EntityList::SendGroupJoin(uint32 gid, const char *name) gj->action = groupActJoin; strcpy(gj->yourname, it->second->GetName()); Mob *Leader = g->GetLeader(); - if (Leader) { + if (Leader) Leader->CastToClient()->GetGroupAAs(&gj->leader_aas); - } + it->second->QueuePacket(outapp); safe_delete(outapp); } diff --git a/zone/entity.h b/zone/entity.h index 5a93adf9d..b4855b42e 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -478,9 +478,8 @@ public: void CameraEffect(uint32 duration, uint32 intensity); Mob* GetClosestMobByBodyType(Mob* sender, bodyType BodyType); void ForceGroupUpdate(uint32 gid); - void SendGroupLeave(uint32 gid, const char *name, bool checkleader); + void SendGroupLeave(uint32 gid, const char *name); void SendGroupJoin(uint32 gid, const char *name); - void SendGroupLeader(uint32 gid, const char *lname, const char *oldlname); void SaveAllClientsTaskState(); void ReloadAllClientsTaskState(int task_id=0); diff --git a/zone/groups.cpp b/zone/groups.cpp index abc868460..4b8e25d09 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -59,12 +59,8 @@ Group::Group(uint32 gid) } if(gid != 0) { - if(!LearnMembers()) { + if(!LearnMembers()) SetID(0); - } - if(GetLeader() != nullptr) { - SetOldLeaderName(GetLeaderName()); - } } for(int i = 0; i < MAX_MARKED_NPCS; ++i) MarkedNPCs[i] = 0; @@ -82,8 +78,6 @@ Group::Group(Mob* leader) members[0] = leader; leader->SetGrouped(true); SetLeader(leader); - SetOldLeaderName(leader->GetName()); - Log(Logs::Detail, Logs::Group, "Group:Group() Setting OldLeader to: %s and Leader to: %s", GetOldLeaderName(), leader->GetName()); AssistTargetID = 0; TankTargetID = 0; PullerTargetID = 0; @@ -610,61 +604,39 @@ void Group::SendGroupJoinOOZ(Mob* NewMember) { } -bool Group::DelMemberOOZ(const char *Name, bool checkleader) { +bool Group::DelMemberOOZ(const char *Name) { - if (!Name) return false; + if(!Name) return false; - bool removed = false; // If a member out of zone has disbanded, clear out their name. - for (unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (!strcasecmp(Name, membername[i])) { + // + for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(!strcasecmp(Name, membername[i])) // This shouldn't be called if the member is in this zone. - if (!members[i]) { - if (!strncmp(GetLeaderName(), Name, 64)) { + if(!members[i]) { + if(!strncmp(GetLeaderName(), Name, 64)) + { //TODO: Transfer leadership if leader disbands OOZ. UpdateGroupAAs(); } - if (GroupCount() < 3) { + memset(membername[i], 0, 64); + MemberRoles[i] = 0; + if(GroupCount() < 3) + { UnDelegateMarkNPC(NPCMarkerName.c_str()); - if (GetLeader() && GetLeader()->IsClient() && - GetLeader()->CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoD) { - UnDelegateMainAssist(MainAssistName.c_str()); + if (GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoD) { + UnDelegateMainAssist(MainAssistName.c_str()); } ClearAllNPCMarks(); } - if (Name == mentoree_name) { + if (Name == mentoree_name) ClearGroupMentor(); - } - - memset(membername[i], 0, 64); - MemberRoles[i] = 0; - removed = true; - Log(Logs::Detail, Logs::Group, "DelMemberOOZ: Removed Member: %s", Name); - break; + return true; } - } } - if (GroupCount() < 2) { - DisbandGroup(); - return true; - } - - if (checkleader) { - Log(Logs::Detail, Logs::Group, "DelMemberOOZ: Checking leader..."); - if (strcmp(GetOldLeaderName(), Name) == 0 && GroupCount() >= 2) { - for (uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { - if (members[nl]) { - if (members[nl]->IsClient()) { - ChangeLeader(members[nl]); - break; - } - } - } - } - } - return removed; + return false; } bool Group::DelMember(Mob* oldmember, bool ignoresender) @@ -674,6 +646,16 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) return false; } + // TODO: fix this shit + // okay, so there is code below that tries to handle this. It does not. + // So instead of figuring it out now, lets just disband the group so the client doesn't + // sit there with a broken group and there isn't any group leader shuffling going on + // since the code below doesn't work. + if (oldmember == GetLeader()) { + DisbandGroup(); + return true; + } + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == oldmember) @@ -682,36 +664,44 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) membername[i][0] = '\0'; memset(membername[i],0,64); MemberRoles[i] = 0; - Log(Logs::Detail, Logs::Group, "DelMember: Removed Member: %s", oldmember->GetCleanName()); break; } } - if(GroupCount() < 2) + /* This may seem pointless but the case above does not cover the following situation: + * Group has Leader a, member b, member c + * b and c are out of zone + * a disconnects/quits + * b or c zone back in and disconnects/quits + * a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b) + * Ultimately we should think up a better solution to this. + */ + if(oldmember == GetLeader()) { - DisbandGroup(); - return true; + SetLeader(nullptr); } - // If the leader has quit and we have 2 or more players left in group, we want to first check the zone the old leader was in for a new leader. - // If a suitable replacement cannot be found, we need to go out of zone. If checkleader remains true after this method completes, another - // loop will be run in DelMemberOOZ. - bool checkleader = true; - if (strcmp(GetOldLeaderName(),oldmember->GetCleanName()) == 0 && GroupCount() >= 2) + //handle leader quitting group gracefully + if (oldmember == GetLeader() && GroupCount() >= 2) { for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { - if(members[nl]) + if(members[nl]) { if (members[nl]->IsClient()) { ChangeLeader(members[nl]); - checkleader = false; break; } } } } + + if (!GetLeaderName()) + { + DisbandGroup(); + return true; + } auto pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; @@ -719,7 +709,6 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) gl->zoneid = zone->GetZoneID(); gl->instance_id = zone->GetInstanceID(); strcpy(gl->member_name, oldmember->GetCleanName()); - gl->checkleader = checkleader; worldserver.SendPacket(pack); safe_delete(pack); @@ -811,7 +800,6 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) Bot::UpdateGroupCastingRoles(this); #endif - safe_delete(outapp); return true; } @@ -2342,16 +2330,17 @@ void Group::ChangeLeader(Mob* newleader) // this changes the current group leader, notifies other members, and updates leadship AA // if the new leader is invalid, do nothing - if (!newleader) { + if (!newleader || !newleader->IsClient()) return; - } + + Mob* oldleader = GetLeader(); auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; gu->action = groupActMakeLeader; strcpy(gu->membername, newleader->GetName()); - strcpy(gu->yourname, GetOldLeaderName()); + strcpy(gu->yourname, oldleader->GetName()); SetLeader(newleader); database.SetGroupLeaderName(GetID(), newleader->GetName()); UpdateGroupAAs(); @@ -2363,22 +2352,9 @@ void Group::ChangeLeader(Mob* newleader) members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName()); members[i]->CastToClient()->QueuePacket(outapp); - Log(Logs::Detail, Logs::Group, "ChangeLeader(): Local leader update packet sent to: %s .", members[i]->GetName()); } } safe_delete(outapp); - - Log(Logs::Detail, Logs::Group, "ChangeLeader(): Old Leader is: %s New leader is: %s", GetOldLeaderName(), newleader->GetName()); - - ServerPacket* pack = new ServerPacket(ServerOP_ChangeGroupLeader, sizeof(ServerGroupLeader_Struct)); - ServerGroupLeader_Struct* fgu = (ServerGroupLeader_Struct*)pack->pBuffer; - fgu->zoneid = zone->GetZoneID(); - fgu->gid = GetID(); - strcpy(fgu->leader_name, newleader->GetName()); - strcpy(fgu->oldleader_name, GetOldLeaderName()); - worldserver.SendPacket(pack); - - SetOldLeaderName(newleader->GetName()); } const char *Group::GetClientNameByIndex(uint8 index) diff --git a/zone/groups.h b/zone/groups.h index c27f9d59a..57dfdbfb6 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -37,8 +37,6 @@ public: GroupIDConsumer() { id = 0; } GroupIDConsumer(uint32 gid) { id = gid; } inline const uint32 GetID() const { return id; } - void SetOldLeaderName(const char* oldleader) { strcpy(oldleadername, oldleader); } - char* GetOldLeaderName() { return oldleadername; } protected: friend class EntityList; @@ -46,7 +44,6 @@ protected: inline void SetID(uint32 set_id) { id = set_id; } private: uint32 id; - char oldleadername[64]; // Keeps the previous leader name, so when the entity is destroyed we can still transfer leadership. }; class Group : public GroupIDConsumer { @@ -61,7 +58,6 @@ public: void SendLeadershipAAUpdate(); void SendWorldGroup(uint32 zone_id,Mob* zoningmember); bool DelMemberOOZ(const char *Name); - bool DelMemberOOZ(const char *Name, bool checkleader); bool DelMember(Mob* oldmember,bool ignoresender = false); void DisbandGroup(bool joinraid = false); void GetMemberList(std::list& member_list, bool clear_list = true); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 76b00398e..2793c3a2e 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -877,7 +877,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (gl->zoneid == zone->GetZoneID() && gl->instance_id == zone->GetInstanceID()) break; - entity_list.SendGroupLeave(gl->gid, gl->member_name, gl->checkleader); + entity_list.SendGroupLeave(gl->gid, gl->member_name); } break; } @@ -1114,17 +1114,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) break; } - case ServerOP_ChangeGroupLeader: { - ServerGroupLeader_Struct *fgu = (ServerGroupLeader_Struct *) pack->pBuffer; - if (zone) { - if (fgu->zoneid == zone->GetZoneID()) { - break; - } - entity_list.SendGroupLeader(fgu->gid, fgu->leader_name, fgu->oldleader_name); - } - break; - } - case ServerOP_OOZGroupMessage: { ServerGroupChannelMessage_Struct* gcm = (ServerGroupChannelMessage_Struct*)pack->pBuffer; if (zone) {