diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 2f7e64b5..20947c99 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -286,6 +286,7 @@ + diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 121e0533..f39b87b5 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -1305,10 +1305,14 @@ namespace FFXIVClassic_Map_Server.Actors public void PartyLeave() { + SubPacket leavePacket = PartyLeavePacket.BuildPacket(playerSession, false); + QueuePacket(leavePacket); } public void PartyDisband() { + SubPacket disbandPacket = PartyLeavePacket.BuildPacket(playerSession, true); + QueuePacket(disbandPacket); } public void PartyPromote(uint actorId) diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/PartyLeavePacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/PartyLeavePacket.cs new file mode 100644 index 00000000..4251bc25 --- /dev/null +++ b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/PartyLeavePacket.cs @@ -0,0 +1,30 @@ +using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.Actors; +using FFXIVClassic_Map_Server.dataobjects; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group +{ + class PartyLeavePacket + { + public const ushort OPCODE = 0x1021; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket BuildPacket(Session session, bool isDisband) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt16)(isDisband ? 1 : 0)); + } + } + return new SubPacket(true, OPCODE, session.id, session.id, data); + } + + } +} diff --git a/FFXIVClassic World Server/DataObjects/Group/Party.cs b/FFXIVClassic World Server/DataObjects/Group/Party.cs index 3a5c132b..2447f1d6 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Party.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Party.cs @@ -94,11 +94,90 @@ namespace FFXIVClassic_World_Server.DataObjects.Group } //All good, remove - members.Remove(kickedMemberId); + Server.GetServer().GetWorldManager().GetPartyManager().RemoveFromParty(groupIndex, kickedMemberId); SendGroupPacketsAll(members); - Server.GetServer().GetWorldManager().SendPartySync(this); + Server.GetServer().GetWorldManager().SendPartySync(this); + + //Set the kicked guy to a new party + Session kickedSession = Server.GetServer().GetSession(kickedMemberId); + if (kickedSession != null) + { + Party kickedPlayersNewParty = Server.GetServer().GetWorldManager().GetPartyManager().CreateParty(kickedMemberId); + kickedPlayersNewParty.SendGroupPackets(kickedSession); + Server.GetServer().GetWorldManager().SendPartySync(kickedPlayersNewParty); + kickedPlayersNewParty.SendInitWorkValues(kickedSession); + } } - + + public void LeavePlayerRequest(Session requestSession) + { + uint leaver = requestSession.sessionId; + + //Check if party contains this person + if (!members.Contains(leaver)) + { + + return; + } + + //Send you are leaving messages + for (int i = 0; i < members.Count; i++) + { + Session session = Server.GetServer().GetSession(members[i]); + if (session == null) + continue; + + session.SendGameMessage(30431, 0x20, (Object)Server.GetServer().GetNameForId(leaver)); + } + + //All good, remove + Server.GetServer().GetWorldManager().GetPartyManager().RemoveFromParty(groupIndex, leaver); + SendGroupPacketsAll(members); + Server.GetServer().GetWorldManager().SendPartySync(this); + + //Set the left guy to a new party + if (requestSession != null) + { + Party kickedPlayersNewParty = Server.GetServer().GetWorldManager().GetPartyManager().CreateParty(leaver); + kickedPlayersNewParty.SendGroupPackets(requestSession); + Server.GetServer().GetWorldManager().SendPartySync(kickedPlayersNewParty); + kickedPlayersNewParty.SendInitWorkValues(requestSession); + } + + } + + public void DisbandPlayerRequest(Session requestSession) + { + uint disbander = requestSession.sessionId; + + //Check if leader + if (GetLeader() != disbander) + { + requestSession.SendGameMessage(30428, 0x20, Server.GetServer().GetNameForId(requestSession.sessionId)); + return; + } + + Server.GetServer().GetWorldManager().GetPartyManager().DeleteParty(groupIndex); + + //Send game messages and set new parties + for (int i = 0; i < members.Count; i++) + { + Session session = Server.GetServer().GetSession(members[i]); + if (session == null) + continue; + + session.SendGameMessage(30401, 0x20); + + //Set char to new party + Party newParty = Server.GetServer().GetWorldManager().GetPartyManager().CreateParty(members[i]); + newParty.SendGroupPackets(session); + Server.GetServer().GetWorldManager().SendPartySync(newParty); + newParty.SendInitWorkValues(session); + } + + Server.GetServer().GetWorldManager().SendPartySync(this); + } + public void SendLeaderWorkToAllMembers() { for (int i = 0; i < members.Count; i++) @@ -173,7 +252,6 @@ namespace FFXIVClassic_World_Server.DataObjects.Group } return groupMembers; } - } } diff --git a/FFXIVClassic World Server/PartyManager.cs b/FFXIVClassic World Server/PartyManager.cs index ae6cf642..a2e83145 100644 --- a/FFXIVClassic World Server/PartyManager.cs +++ b/FFXIVClassic World Server/PartyManager.cs @@ -38,7 +38,14 @@ namespace FFXIVClassic_World_Server if (mCurrentWorldGroupsReference.ContainsKey(groupId)) mCurrentWorldGroupsReference.Remove(groupId); if (mPartyList.ContainsKey(groupId)) + { + foreach (uint id in mPartyList[groupId].members) + { + if (mPlayerPartyLookup.ContainsKey(id)) + mPlayerPartyLookup.Remove(id); + } mPartyList.Remove(groupId); + } } public bool AddToParty(ulong groupId, uint charaId) diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs index 12eaab7c..0eeb92e2 100644 --- a/FFXIVClassic World Server/Server.cs +++ b/FFXIVClassic World Server/Server.cs @@ -221,6 +221,14 @@ namespace FFXIVClassic_World_Server break; //Party Resign or Disband case 0x1021: + PartyLeavePacket partyLeavePacket = new PartyLeavePacket(subpacket.data); + Party leavePt = mWorldManager.GetPartyManager().GetParty(subpacket.header.sourceId); + + if (!partyLeavePacket.isDisband) + leavePt.LeavePlayerRequest(GetSession(subpacket.header.sourceId)); + else + leavePt.DisbandPlayerRequest(GetSession(subpacket.header.sourceId)); + break; //Linkshell create request case 0x1025: diff --git a/FFXIVClassic World Server/WorldMaster.cs b/FFXIVClassic World Server/WorldMaster.cs index 7961dfda..66012213 100644 --- a/FFXIVClassic World Server/WorldMaster.cs +++ b/FFXIVClassic World Server/WorldMaster.cs @@ -221,7 +221,8 @@ namespace FFXIVClassic_World_Server } pt.SendGroupPackets(session); - SendPartySync(pt); + SendPartySync(pt); + mRetainerGroupManager.GetRetainerGroup(session.sessionId).SendGroupPackets(session); List linkshells = mLinkshellManager.GetPlayerLinkshellMembership(session.sessionId); foreach (Linkshell ls in linkshells)