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)